Статьи > Тестирование статей

AutoCAD .NET API: Рассечение штриховки.

(1/2) > >>

alz:
Этот код позволяет разрезать штриховку кажущимся пересечением, образованным замкнутым контуром, то есть тем, который визуально отображается на мониторе, плоскости штриховки и контура могут не совпадать, главное что бы было визуальное их пересечение. Для создания кода использовалось достаточно много кода с этого сайта.

alz:
Ух блин, видимо какое то ограничение на длину сообщений. в предварительном просмотре все было нормально, а тут обрезало, надо делить на куски, как отредактировать не вижу :(

alz:
Первая часть кода


--- Код - C# [Выбрать] ---using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.EditorInput;using Autodesk.AutoCAD.Geometry;using Autodesk.AutoCAD.Runtime;using System;using System.Collections.Generic;using System.Reflection; namespace Trim_objects{    public class CurHatch    {            [CommandMethod("cut_hatch")]        public void c_hatch()        {            ObjectId plId = GetObjectId(new List<string> { "acdbpolyline", "acdbcircle" }, "Выберите замкнутый секущий контур");            if (plId == ObjectId.Null ) return;            ObjectId hId = GetObjectId(new List<string> { "acdbhatch" }, "Выберите разрезаемую штриховку");            if (hId == ObjectId.Null) return;            CutHatch(plId, hId);        }        /// <summary>        /// Основная команда, режет штриховку возвращает списко ObjectId полученных штриховок        /// </summary>        /// <param name="plId">ObjectId разрезающего контура</param>        /// <param name="hId">ObjectId разрезаемой штриховки</param>        public List<ObjectId> CutHatch(ObjectId plId, ObjectId hId)        {                List<ObjectId> result = new List<ObjectId>();            //работаем сразу в транзокции и таблице так как частенько придется что-то доставать или что-то записывать            using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())            {                using (BlockTableRecord ms = tr.GetObject(HostApplicationServices.WorkingDatabase.CurrentSpaceId, OpenMode.ForWrite, false, true) as BlockTableRecord)                {                    using (Hatch hatch = tr.GetObject(hId, OpenMode.ForWrite, false, true) as Hatch)                    {                        //получаем план штриховки                        Plane plane = hatch.GetPlane();                        //получаем вектор текущего вида                        Vector3d vector = GetViewVector();                        //проверяем на самопересечение и замкнутость                        using (Curve pl1 = tr.GetObject(plId, OpenMode.ForRead, false, true) as Curve)                        using (Curve pl = pl1.GetProjectedCurve(plane, vector))                        using (Curve3d pl3d = pl.GetGeCurve())                        using (CurveCurveIntersector3d cuin = new CurveCurveIntersector3d(pl3d, pl3d, vector))                        {                            if (cuin.NumberOfIntersectionPoints > 0 | !pl3d.IsClosed())                            {                                tr.Commit(); return new List<ObjectId> { ObjectId.Null };                            }                        }                        //получаем лупы из штриховки                        List<HatchLoop> loops = new List<HatchLoop>();                        for (int i = hatch.NumberOfLoops - 1; i >= 0; i--)                        {                            loops.Add(hatch.GetLoopAt(i));                        }                        //создаем кривые в чертеже для каждого лупа и записываем их в списки                        List<ObjectId> LoopCurve = new List<ObjectId>();                        foreach (HatchLoop loop in loops)                        {                            //получаем куски лупа                            LoopCurve.AddRange(GetCurveFromLoop(loop, plane, hatch));                        }                        //список удаляемых кривых лупов                        List<ObjectId> erList = new List<ObjectId>();                        //список добавляемых кривых в лупы                        List<ObjectId> addList = new List<ObjectId>();                        //список секущих точек                        List<Point3d> sPoints = new List<Point3d>();                        //разрезаем все контура в штриховке проекцией контура (которые контур рассекает)                        foreach (ObjectId id in LoopCurve)                        {                            //получаем кривую                            using (Curve cur = tr.GetObject(id, OpenMode.ForWrite, false, true) as Curve)                            {                                //получаем точки пересечения                                List<Point3d> points = IntersectPoints(plId, ObjectId.Null, null, cur.Clone() as Curve, plane, vector, false);                                //если точки есть то разрезаем кривую, добавляем куски в список и удаляем разрезанную                                if (points.Count > 0)                                {                                    sPoints.AddRange(points);                                    using (Point3dCollection collection = new Point3dCollection())                                    {                                        foreach (Point3d point in points) collection.Add(point);                                        using (DBObjectCollection objects = cur.GetSplitCurves(collection))                                        {                                            foreach (Object obj in objects)                                            {                                                using (Curve curve = obj as Curve)                                                {                                                    if (curve != null)                                                    {                                                        addList.Add(ms.AppendEntity(curve));                                                        tr.AddNewlyCreatedDBObject(curve, true);                                                    }                                                }                                            }                                        }                                    }                                    cur.Erase();                                    erList.Add(id);                                }                            }                        }                        //если пересечений не было значит штриховку можно не трогать                        if (erList.Count == 0)                        {                            DeleteObj(LoopCurve);                            tr.Commit();                            return new List<ObjectId> { ObjectId.Null };                        }                        //если были то обновляем список кривых в лупах                        foreach (ObjectId id in erList) LoopCurve.Remove(id);                        LoopCurve.AddRange(addList);                        //создаем списки распределения кривых (других по идее быть не должно)                        //внутри                        List<Curve> inner = new List<Curve>();                        //снаружи                        List<Curve> outer = new List<Curve>();                        //создаем список с кусками пересекающей кривой, которые будем добавлять в лупы                        List<ObjectId> kontPartLstId = new List<ObjectId>();                        List<Curve> kontPartLst = new List<Curve>();                        List<Curve> kontPartLstCopy = new List<Curve>();                        //получаем контур в виде проекции на плоскость штриховки                                            using (Curve pl1 = tr.GetObject(plId, OpenMode.ForRead, false, true) as Curve)                        using (Curve pl = pl1.GetProjectedCurve(plane, vector))                        {                            //распределяем куски лупов по спискам                            foreach (ObjectId id in LoopCurve)                            {                                Curve c = tr.GetObject(id, OpenMode.ForRead, false, true) as Curve;                                //после всех манипуляций тут должны быть только результаты 1 - 5                                //если встретится что-то другое то скорее всего произошла какая-то ошибка и просто прекращаем                                //если все нормально то все кривые распределятся по спискам кроме номера 3                                //он просто игнорируется и никуда не идет, его заменят если что части контура                                int res = PartIn(pl, c, plane, vector);                                if (res == 0 | res == 6)                                {                                    DeleteObj(LoopCurve);                                    tr.Commit();                                    return new List<ObjectId> { ObjectId.Null };                                }                                if (res == 1 | res == 4)                                {                                    inner.Add(c);                                    continue;                                }                                if (res == 2 | res == 5)                                {                                    outer.Add(c);                                    continue;                                }                                if (res == 3) continue;                            }                            //ищем куски разрезающей кривой                            //сортируем точки по разрезающей кривой                            sPoints = SortPoint(sPoints, pl);                            using (Point3dCollection collection = new Point3dCollection())                            {                                foreach (Point3d point in sPoints) collection.Add(point);                                using (DBObjectCollection objects = pl.GetSplitCurves(collection))                                {                                    foreach (Object obj in objects)                                    {                                        using (Curve curve = obj as Curve)                                        {                                            if (curve != null)                                            {                                                //проверяем находится ли кусок контура внутри штриховки                                                int res = CurveInCurves(curve, LoopCurve, plane, vector, null);                                                //если ошибка                                                if (res == 0)                                                {                                                    DeleteObj(LoopCurve);                                                    DeleteObj(kontPartLstId);                                                    tr.Commit();                                                    return new List<ObjectId> { ObjectId.Null };                                                }                                                //если внутри то добавляем на модель и в список                                                if (res == 1)                                                {                                                    kontPartLstId.Add(ms.AppendEntity(curve));                                                    tr.AddNewlyCreatedDBObject(curve, true);                                                }                                            }                                        }                                    }                                }                            }                            //получаем куски контура как кривые и создаем 2 списка для тех областей что внутри и для тех что снаружи                            List<ObjectId> nkontPartLstId = new List<ObjectId>();                            foreach (ObjectId objectId in kontPartLstId)                            {                                Curve curve = tr.GetObject(objectId, OpenMode.ForRead, false, true) as Curve;                                kontPartLst.Add(curve);                                //добавляем копию на модель и в список                                Curve curveCopy = curve.Clone() as Curve;                                nkontPartLstId.Add(ms.AppendEntity(curveCopy));                                tr.AddNewlyCreatedDBObject(curveCopy, true);                                kontPartLstCopy.Add(curveCopy);                            }                            //добавляем ObjectId копий в общий список для последующего удаления                            kontPartLstId.AddRange(nkontPartLstId);                            //анализируем списки и составляем из кусков новые лупы                            inner.AddRange(kontPartLstCopy);                            List<List<ObjectId>> loopsId = GetNewLoops(inner);                            if (loopsId != null) result.Add(NewHatch(tr, ms, loopsId, hatch));                            else                            {                                DeleteObj(LoopCurve);                                DeleteObj(kontPartLstId);                                tr.Commit();                                return new List<ObjectId> { ObjectId.Null };                            }                            outer.AddRange(kontPartLst);                            loopsId = GetNewLoops(outer);                            if (loopsId != null) result.Add(NewHatch(tr, ms, loopsId, hatch));                            else                            {                                DeleteObj(LoopCurve);                                DeleteObj(kontPartLstId);                                tr.Commit();                                return new List<ObjectId> { ObjectId.Null };                            }                        }                        hatch.Erase();                    }                }                                tr.Commit();            }            return result;        }        /// <summary>        /// создает новые лупы из списка кусков путем объединения в замкнутые контуры        /// возвращает список со списками ObjectId, объекты в которых образуют замкнутый контур        /// </summary>        /// <param name="cur"></param>        /// <returns></returns>        private List<List<ObjectId>> GetNewLoops(List<Curve> cur)        {            List<List<ObjectId>> loopsId = new List<List<ObjectId>>();                        int stop = 0;                        while (cur.Count > 0)            {                //на всякий случай выход из цикла                stop++;                if (stop > 2000)                {                   return null;                                    }                //создаем список контуров лупа                List<ObjectId> loop = new List<ObjectId>();                //проверяем списки и составляем лупы, пока все не очистим                     //берем первую кривую                Curve curve = cur[0];                loop.Add(curve.Id);                cur.RemoveAt(0);                //если она замкнута это готовый луп                //добавляем в список готовых лупов удаляем из списка обрабатываемых и переходим к следующему                if (curve.Closed == true | curve.StartPoint.Equals(curve.EndPoint))                {                    loopsId.Add(loop);                                        continue;                }                else                {                                       //получаем концы кривой                    Point3d k1 = curve.StartPoint;                    Point3d k2 = curve.EndPoint;                    //проходим по объектам пока не замкнем контур                    int stop2 = 0;                    while (!k1.Equals(k2))                    {                        //на всякий случай выход из цикла                        stop2++;                        if (stop2 > 2000)                        {                            return null;                        }                                 //проходим по контурам                        for (int i = 0; i < cur.Count; i++)                        {                            if (k1.Equals(cur[i].StartPoint))                            {                                loop.Add(cur[i].Id);                                                                k1 = cur[i].EndPoint;                                cur.RemoveAt(i);                                if (k1.Equals(k2))                                {                                    loopsId.Add(loop);                                    break;                                }                                                                    continue;                            }                             if (k1.Equals(cur[i].EndPoint))                            {                                loop.Add(cur[i].Id);                                                                k1 = cur[i].StartPoint;                                cur.RemoveAt(i);                                if (k1.Equals(k2))                                {                                    loopsId.Add(loop);                                    break;                                }                                continue;                            }                            if (k2.Equals(cur[i].StartPoint))                             {                                loop.Add(cur[i].Id);                                                                k2 = cur[i].EndPoint;                                cur.RemoveAt(i);                                if (k1.Equals(k2))                                {                                    loopsId.Add(loop);                                    break;                                }                                continue;                            }                            if (k2.Equals(cur[i].EndPoint))                             {                                loop.Add(cur[i].Id);                                                                k2 = cur[i].StartPoint;                                cur.RemoveAt(i);                                if (k1.Equals(k2))                                {                                    loopsId.Add(loop);                                    break;                                }                                                           }                                                   }                                            }                                    }            }            return loopsId;        }                /// <summary>        /// возвращает точку центра кривой         /// </summary>        /// <param name="ob"></param>        /// <returns></returns>        private Point3d GetCentr(Curve ob)        {            return ob.GetPointAtDist((ob.GetDistanceAtParameter(ob.StartParam) + ob.GetDistanceAtParameter(ob.EndParam)) / 2);        }        /// <summary>        /// строит штриховку из списка лупов в виде списков ObjecrId элементов используя как шаблон другую штриховку        /// возвращает ObjectId построенной штриховки если удалось        /// </summary>        /// <param name="tr"></param>        /// <param name="ms"></param>        /// <param name="loopsId"></param>        /// <param name="hatch"></param>        /// <returns></returns>        private ObjectId NewHatch(Transaction tr, BlockTableRecord ms, List<List<ObjectId>> loopsId, Hatch hatch)        {            ObjectId result = ObjectId.Null;            //переменная для фиксации результата            bool del = false;            using (Hatch h = new Hatch())            {                using (Transaction tr2 = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())                {                    result = ms.AppendEntity(h);                    tr2.AddNewlyCreatedDBObject(h, true);                    tr2.Commit();                }                //создаем новую штриховку                h.Normal = hatch.Normal;                h.Origin = hatch.Origin;                   h.Elevation = hatch.Elevation;                h.SetDatabaseDefaults();                h.VisualStyleId = hatch.VisualStyleId;                h.Color = hatch.Color;                //тут все сложно, что бы все масштабы корректно отобразились                 //после их установки надо прописать h.SetHatchPattern(HatchPatternType.PreDefined, hatch.PatternName);                //но если перед их установкой не прописать h.SetHatchPattern(hatch.PatternType, hatch.PatternName);                //то угол штриховки установить не получится так как видимо базовый тип не предусматривает установки угла, выдает исключение                h.SetHatchPattern(hatch.PatternType, hatch.PatternName);                h.PatternAngle = hatch.PatternAngle;                h.PatternScale = hatch.PatternScale;                                               h.PatternDouble = hatch.PatternDouble;                h.SetHatchPattern(HatchPatternType.PreDefined, hatch.PatternName);                        h.Layer = hatch.Layer;                h.Linetype = hatch.Linetype;                h.LineWeight = hatch.LineWeight;                h.LinetypeScale = hatch.LinetypeScale;                h.Transparency = hatch.Transparency;                                               //проходим по всем лупам в списке                foreach (List<ObjectId> loopId in loopsId)                {                    if (loopId.Count == 0) continue;                    //если ошибок не было то вставляем луп                    if (!del)                    {                        //создаем из списка коллекцию                        using (ObjectIdCollection lId = new ObjectIdCollection())                        {                            foreach (ObjectId curId in loopId) lId.Add(curId);                            //пробуем добавить коллекцию в штриховку                            try                            {                                h.AppendLoop(HatchLoopTypes.Default, lId);                            }                            catch                            {                                //если не удалось то удаляем штриховку и возвращаем ObjectId.Null                                del = true;                            }                        }                    }                    //удаляем куски лупа                    foreach (ObjectId curId in loopId)                         using (Curve cur = tr.GetObject(curId, OpenMode.ForWrite, false, true) as Curve)                             cur.Erase();                                    }                               //если произошла какая-то ошибка то удаляем штриховку                if (del)                 {                    h.Erase();                    return ObjectId.Null;                }                               }            return result;        }                /// <summary>        /// возвращает вектор текущего вида в wcs        /// </summary>        /// <returns></returns>        private Vector3d GetViewVector()        {            if (System.Convert.ToInt32(Application.GetSystemVariable("WORLDUCS")) == 0)            {                //если установлена ucs то получаем вектор из преобразованной точки                Point3d vpoint = (Point3d)Application.GetSystemVariable("VIEWDIR");                return vpoint.GetAsVector().TransformBy(Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem).GetNormal();            }            else            {                Point3d vpoint = (Point3d)Application.GetSystemVariable("VIEWDIR");                return vpoint.GetAsVector().GetNormal();            }        }        /// <summary>        /// сортирует точки находящиеся на кривой от начала кривой к концу        /// </summary>        /// <param name="result">список точек</param>        /// <param name="curve">кривая</param>        /// <returns></returns>        private List<Point3d> SortPoint(List<Point3d> result, Curve curve)        {            if (result.Count > 1)            {                List<Point3d> sorted_coll = new List<Point3d>();                while (result.Count > 0)                {                    Point3d? minPoint = null;                    double? min = null;                    for (int i = 0; i < result.Count; i++)                    {                        double dist = curve.GetDistAtPoint(result[i]);                        if (minPoint == null)                        {                            minPoint = result[i];                            min = dist;                        }                        else                        {                            if (dist < min.Value)                            {                                minPoint = result[i];                                min = dist;                            }                        }                    }                    result.Remove(minPoint.Value);                    sorted_coll.Add(minPoint.Value);                }                foreach (Point3d coll in sorted_coll)                {                    result.Add(coll);                }            }            return result;        }

alz:
Вторая часть кода


--- Код - C# [Выбрать] ---/// <summary>        /// возвращает список точек пересечения кривых на плане по вектору        /// Использовались части кода от Александра Ривилиса        /// </summary>        /// <param name="bCurId">ObjectId секущей кривой</param>        /// <param name="iCurId">ObjectId пересекаемой кривой </param>        /// <param name="bCur">секущая кривая</param>        /// <param name="iCur">пересекаемая кривая</param>        /// <param name="iBlock">Блок если пересекаемая кривая находится в блоке</param>        /// <param name="plane">план на котором ищутся пересечения</param>        /// <param name="vector">направление проецирования на план</param>        /// <param name="firstLast">возвращать точки пересечения на концах пересекаемой линии?</param>        /// <returns>список точек пересечения на пересекаемой кривой</returns>        private List<Point3d> IntersectPoints(ObjectId bCurId, ObjectId iCurId, Curve bCur, Curve iCur, Plane plane, Vector3d vector, bool firstLast)        {            List<Point3d> result = new List<Point3d>();            //если кривых нет то останавливаем            if ((bCurId == ObjectId.Null & bCur == null) | (iCurId == ObjectId.Null & iCur == null)) return result;            //если кривые заданы через ObjectId то получаем            if (bCur == null | iCur == null)            {                using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())                {                    if (bCur == null)                    {                        bCur = tr.GetObject(bCurId, OpenMode.ForRead, false, true) as Curve;                    }                    if (iCur == null)                    {                        iCur = tr.GetObject(iCurId, OpenMode.ForRead, false, true) as Curve;                    }                    tr.Commit();                }            }            //если вдруг что-то пошло не так и кривые мы все таки не получили то прекращаем            if (bCur == null | iCur == null) return result;                        //получаем проекции кривых на плоскость            using (Curve bCurPr = bCur.GetProjectedCurve(plane, vector))            using (Curve iCurPr = iCur.GetProjectedCurve(plane, vector))            {                //проверяем что проекции имеют длину                if ((bCurPr.GetDistanceAtParameter(bCurPr.StartParam) + bCurPr.GetDistanceAtParameter(bCurPr.EndParam)) == 0) return result;                if ((iCurPr.GetDistanceAtParameter(iCurPr.StartParam) + iCurPr.GetDistanceAtParameter(iCurPr.EndParam)) == 0) return result;                //получаем Curve3d                using (Curve3d bCurPr3d = bCurPr.GetGeCurve())                using (Curve3d iCurPr3d = iCurPr.GetGeCurve())                {                    //получаем точки пересечения кривых                    using (CurveCurveIntersector3d cInt = new CurveCurveIntersector3d(bCurPr3d, iCurPr3d, vector))                    {                        //если пересечения есть                        if (cInt.NumberOfIntersectionPoints > 0)                        {                            //получаем непроецированную кривую как Curve3d                            using (Curve3d iCur3d = iCur.GetGeCurve())                            {                                //проходим по пересечениям                                for (int i = 0; i < cInt.NumberOfIntersectionPoints; i++)                                {                                    //если касание пропускаем                                    if (cInt.IsTangential(i)) continue;                                    //получаем точку пересечения                                    Point3d point = cInt.GetIntersectionPoint(i);                                    //если это точка начала или конца и она не нужна то пропускаем                                    if (!firstLast)                                    {                                        if ((i == 0 | i == (cInt.NumberOfIntersectionPoints - 1)) & (point.Equals(iCurPr3d.StartPoint) | point.Equals(iCurPr3d.EndPoint))) continue;                                    }                                    //строим линию из этой точки и ищем реальную точку на непроецированной кривой                                    using (Line3d line = new Line3d(point, vector))                                    {                                        //получаем точки пересечения линии и непроецированной кривой                                        using (CurveCurveIntersector3d cits = new CurveCurveIntersector3d(iCur3d, line, vector))                                        {                                            if (cits.NumberOfIntersectionPoints > 0)                                            {                                                for (int j = 0; j < cits.NumberOfIntersectionPoints; j++)                                                {                                                    //если этой точки нет в списке то добавляем в список                                                    if (!result.Contains(cits.GetIntersectionPoint(j))) result.Add(cits.GetIntersectionPoint(j));                                                }                                                                                                }                                        }                                    }                                }                            }                        }                    }                }            }                    //возвращаем отсортированные точки            return SortPoint(result, iCur);        }        /// <summary>        /// Возвращает ObjectId кривых в лупе отрисованных в текущем пространстве        /// (немного доработанная функция от Александра Ривилиса)        /// </summary>        /// <param name="loop"></param>        /// <param name="plane"></param>        /// <param name="iBlock"></param>        /// <returns></returns>        private List<ObjectId> GetCurveFromLoop(HatchLoop loop, Plane plane, Hatch hatch)        {            List<ObjectId> result = new List<ObjectId>();            using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())            {                                using (BlockTableRecord ms = tr.GetObject(HostApplicationServices.WorkingDatabase.CurrentSpaceId, OpenMode.ForWrite, false, true) as BlockTableRecord)                {                    if (loop.IsPolyline)                    {                        using (Polyline poly = new Polyline())                        {                            int iVertex = 0;                            foreach (BulgeVertex bv in loop.Polyline)                            {                                poly.AddVertexAt(iVertex++, bv.Vertex, bv.Bulge, 0.0, 0.0);                            }                            poly.Normal = hatch.Normal;                            poly.Elevation = hatch.Elevation;                                                        result.Add(ms.AppendEntity(poly));                            tr.AddNewlyCreatedDBObject(poly, true);                        }                    }                    else                    {                        foreach (Curve2d cv in loop.Curves)                        {                            LineSegment2d line2d = cv as LineSegment2d;                            CircularArc2d arc2d = cv as CircularArc2d;                            EllipticalArc2d ellipse2d = cv as EllipticalArc2d;                            NurbCurve2d spline2d = cv as NurbCurve2d;                            if (line2d != null)                            {                                using (Line ent = new Line())                                {                                    ent.StartPoint = new Point3d(plane, line2d.StartPoint);                                    ent.EndPoint = new Point3d(plane, line2d.EndPoint);                                    result.Add(ms.AppendEntity(ent));                                    tr.AddNewlyCreatedDBObject(ent, true);                                }                            }                            else if (arc2d != null)                            {                                if (arc2d.IsClosed() || Math.Abs(arc2d.EndAngle - arc2d.StartAngle) < 1e-5)                                {                                    using (Circle ent = new Circle(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius))                                    {                                        result.Add(ms.AppendEntity(ent));                                        tr.AddNewlyCreatedDBObject(ent, true);                                    }                                }                                else                                {                                    if (arc2d.IsClockWise)                                    {                                        arc2d = arc2d.GetReverseParameterCurve() as CircularArc2d;                                    }                                    double angle = new Vector3d(plane, arc2d.ReferenceVector).AngleOnPlane(plane);                                    double startAngle = arc2d.StartAngle + angle;                                    double endAngle = arc2d.EndAngle + angle;                                    using (Arc ent = new Arc(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius, startAngle, endAngle))                                    {                                        result.Add(ms.AppendEntity(ent));                                        tr.AddNewlyCreatedDBObject(ent, true);                                    }                                }                            }                            else if (ellipse2d != null)                            {                                //-------------------------------------------------------------------------------------------                                // Bug: Can not assign StartParam and EndParam of Ellipse:                                // Ellipse ent = new Ellipse(new Point3d(plane, e2d.Center), plane.Normal,                                 //      new Vector3d(plane,e2d.MajorAxis) * e2d.MajorRadius,                                //      e2d.MinorRadius / e2d.MajorRadius, e2d.StartAngle, e2d.EndAngle);                                // ent.StartParam = e2d.StartAngle;                                 // ent.EndParam = e2d.EndAngle;                                // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.StartParam' cannot be assigned to -- it is read only                                // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.EndParam' cannot be assigned to -- it is read only                                //---------------------------------------------------------------------------------------------                                // Workaround is using Reflection                                //                                 using (Ellipse ent = new Ellipse(new Point3d(plane, ellipse2d.Center), plane.Normal,                                     new Vector3d(plane, ellipse2d.MajorAxis) * ellipse2d.MajorRadius,                                     ellipse2d.MinorRadius / ellipse2d.MajorRadius, ellipse2d.StartAngle, ellipse2d.EndAngle))                                {                                    ent.GetType().InvokeMember("StartParam", BindingFlags.SetProperty, null,                                      ent, new object[] { ellipse2d.StartAngle });                                    ent.GetType().InvokeMember("EndParam", BindingFlags.SetProperty, null,                                      ent, new object[] { ellipse2d.EndAngle });                                    result.Add(ms.AppendEntity(ent));                                    tr.AddNewlyCreatedDBObject(ent, true);                                }                             }                            else if (spline2d != null)                            {                                if (spline2d.HasFitData)                                {                                    NurbCurve2dFitData n2fd = spline2d.FitData;                                    using (Point3dCollection p3ds = new Point3dCollection())                                    {                                        foreach (Point2d p in n2fd.FitPoints) p3ds.Add(new Point3d(plane, p));                                        using (Spline ent = new Spline(p3ds, new Vector3d(plane, n2fd.StartTangent), new Vector3d(plane, n2fd.EndTangent),                                          /* n2fd.KnotParam, */  n2fd.Degree, n2fd.FitTolerance.EqualPoint))                                        {                                            result.Add(ms.AppendEntity(ent));                                            tr.AddNewlyCreatedDBObject(ent, true);                                        }                                    }                                }                                else                                {                                    NurbCurve2dData n2fd = spline2d.DefinitionData;                                    using (Point3dCollection p3ds = new Point3dCollection())                                    {                                        DoubleCollection knots = new DoubleCollection(n2fd.Knots.Count);                                        foreach (Point2d p in n2fd.ControlPoints) p3ds.Add(new Point3d(plane, p));                                        foreach (double k in n2fd.Knots) knots.Add(k);                                        double period = 0;                                        using (Spline ent = new Spline(n2fd.Degree, n2fd.Rational,                                                 spline2d.IsClosed(), spline2d.IsPeriodic(out period),                                                 p3ds, knots, n2fd.Weights, n2fd.Knots.Tolerance, n2fd.Knots.Tolerance))                                        {                                            result.Add(ms.AppendEntity(ent));                                            tr.AddNewlyCreatedDBObject(ent, true);                                        }                                    }                                }                            }                        }                    }                }                tr.Commit();            }            return result;        }        /// <summary>        /// выбор объекта на чертеже и возврат его ObjectId        /// </summary>        /// <param name="objTypes">список с типами допущенных для выбора объектов, пустой лист любого объекта</param>        /// <param name="soob">Выводимое сообщение при выборе</param>        /// <returns></returns>        private ObjectId GetObjectId(List<string> objTypes, string soob)        {            //повторяем пока не выбран нужный объект            while (true)            {                //Выбираем объект на чертеже                PromptEntityResult entRes = Application.DocumentManager.MdiActiveDocument.Editor.GetEntity("\n" + soob);                //Если объект не выбран то прекращаем программу                if (entRes.Status == PromptStatus.Cancel)                {                    return ObjectId.Null;                }                //проверка на тип объекта если выбранный объект корректен то выходим из цикла выбора                if (objTypes.Count == 0) return entRes.ObjectId;                foreach (string objType in objTypes)                     if (entRes.ObjectId.ObjectClass.Name.ToLower().Equals(objType.ToLower()))                         return entRes.ObjectId;                           }        }               /// <summary>        /// используется что бы определить положение объекта относительно других кривых        /// даст точный результат если объекты из списка образуют замкнутый контур        /// </summary>        /// <param name="cur">элемент который проверяется (кривая или точка)</param>        /// <param name="curvesId">список ObjectId кривых</param>        /// <param name="plane"></param>        /// <param name="vector"></param>        /// <param name="kontur">кривая если нужно передать уже открытую</param>        /// <returns>        /// 0 - ошибка исходных данных        /// 1 - внутри кривых        /// 2 - снаружи кривых         /// </returns>        private int CurveInCurves(Object cur, List<ObjectId> curvesId, Plane plane, Vector3d vector, Curve kontur)        {            if ((curvesId.Count == 0 & kontur == null) | cur == null ) return 0;            //счетчик общего числа пересечений             //создаем список точек что бы не задваивать пересечения            //если вдруг точка пересечения попадет в стык между двумя кривыми            //встречается часто если сечется прямоугольником так как вектор параллелен оси            List<Point3d> points = new List<Point3d>();            using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())            {                //строим луч из центра кривой в плане штриховки                using (Ray ray = new Ray())                {                                        //создаем луч из центра кривой                    if (cur is Curve) ray.BasePoint = GetCentr(cur as Curve);                    if (cur is Point3d) ray.BasePoint = (Point3d)cur;                    ray.UnitDir = plane.Normal.GetPerpendicularVector();                                        //проходим по всем кривым и ищем пересечения                    using (Curve3d ray3d = ray.GetGeCurve())                    {                        List<Curve> curves = new List<Curve>();                        foreach (ObjectId id in curvesId) curves.Add(tr.GetObject(id, OpenMode.ForRead, false, true) as Curve);                                               if (kontur != null) curves.Add(kontur);                        foreach (Curve curve in curves)                        {                            using (Curve3d loopCur3d = curve.GetGeCurve())                            using (CurveCurveIntersector3d cuin = new CurveCurveIntersector3d(ray3d, loopCur3d, vector))                            {                                if (cuin.NumberOfIntersectionPoints > 0)                                {                                    //ищем число пересечений не считая касательных                                                                            for (int i = 0; i < cuin.NumberOfIntersectionPoints; i++)                                        if (cuin.IsTransversal(i))                                                                                 {                                            if (!points.Contains(cuin.GetIntersectionPoint(i)))                                            {                                                 points.Add(cuin.GetIntersectionPoint(i));                                                                                           }                                        }                                   }                            }                        }                    }                }                tr.Commit();            }            //если число пересечений нечетное то точка изнутри, если четное или ноль то снаружи            if (points.Count % 2 != 0) return 1;                       else return 2;           }        /// <summary>        /// удаляет объекты из списка по id        /// </summary>        /// <param name="ids"></param>        private void DeleteObj(List<ObjectId> ids)        {            using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())            {                foreach (ObjectId id in ids)                {                    using (Entity c = tr.GetObject(id, OpenMode.ForWrite, false, true) as Entity)                    {                        c.Erase();                    }                }                tr.Commit();            }        }        /// <summary>        /// проверяет положение кривой part относительно кривой kontur        /// </summary>        /// <param name="kontur"></param>        /// <param name="part"></param>        /// <param name="iBlock"></param>        /// <returns>        /// 0 - ошибка исходных данных        /// 1 - внутри        /// 2 - снаружи        /// 3 - на границе            /// 4 - внутри и касается контура        /// 5 - снаружи и касается контура        /// 6 - пересекает контур                    /// </returns>        private int PartIn(Curve kontur, Curve part, Plane plane, Vector3d vector)        {            if (kontur == null | part == null) return 0;            //внутри контура            bool into = false;            //снаружи контура            bool outer = false;            //на границе контура            bool g = false;            //создаем список из трех точек            List<Point3d> points = new List<Point3d>            {                part.StartPoint,                part.EndPoint,                GetCentr(part)            };            //проверяем на пересечение            List<Point3d> per = IntersectPoints(ObjectId.Null, ObjectId.Null, kontur.Clone() as Curve, part.Clone() as Curve, plane, vector, false);            if (per.Count > 0) return 6;            foreach (Point3d point in points)            {                //проверяем на нахождение на контуре                //если проекция точки на контур совпадает с точкой то она на контуре                if (kontur.GetClosestPointTo(point, false).Equals(point))                {                    g = true;                    continue;                }                //если не на границе то пользуемся определением положения через луч                int res = CurveInCurves(point, new List<ObjectId>(), plane, vector, kontur);                                if (res == 1) into = true;                if (res == 2) outer = true;            }                                      //точки только внутри            if (into & !outer & !g)            {                return 1;            }            //точки только снаружи            if (!into & outer & !g)            {                return 2;            }            //точки только на границe            if (!into & !outer & g)            {                return 3;            }            //точки внутри и на границе            if (into & !outer & g)            {                return 4;            }            //точки снаружи и на границе            if (!into & outer & g)            {                return 5;            }            return 6;        }    }}

alz:
Потестировав этот вариант разрезания нашел нестандартное поведение получившихся элементов. Разрезанные этим методом штриховки невозможно разделить встроенным методом "Отдельные штриховки". Есть к у кого какие мысли, может быть я что-то не учел при создании новой штриховки?

Навигация

[0] Главная страница сообщений

[#] Следующая страница

Перейти к полной версии