示例#1
0
        public void DeleteAndSearchTest()
        {
            var tree = new RBush <Point>(maxEntries: 4);

            tree.BulkLoad(points);

            var len = points.Length;

            // Delete an existent point.
            bool resultExistent           = tree.Delete(points[0]);
            var  shouldFindPointsExistent = points
                                            .Skip(1)
                                            .OrderBy(x => x)
                                            .ToList();
            var foundPointsExistent = tree.Search()
                                      .OrderBy(x => x)
                                      .ToList();

            // Try to delete a non-existent point.
            bool resultNonExistent           = tree.Delete(new Point(1245, 1233, 1245, 1233));
            var  shouldFindPointsNonExistent = shouldFindPointsExistent;
            var  foundPointsNonExistent      = tree.Search()
                                               .OrderBy(x => x)
                                               .ToList();

            Assert.True(resultExistent);
            Assert.Equal(shouldFindPointsExistent, foundPointsExistent);
            Assert.False(resultNonExistent);
            Assert.Equal(shouldFindPointsNonExistent, foundPointsNonExistent);
        }
示例#2
0
        public void RunTestGroup(int maxEntries, int numberOfItems)
        {
            RBush <Item> rBush = new RBush <Item>(maxEntries);

            double             spaceScale = 50;
            IEnumerable <Item> items      = ItemListGenerator.GenerateItems(numberOfItems, spaceScale);

            Console.WriteLine("maxEntries = " + maxEntries);

            // Tests:

            RunTest("BulkLoad", numberOfItems, () => { rBush.BulkLoad(items); });

            RunTest("Search OLD", numberOfItems, () => { rBush.Search_Old(); });
            RunTest("Search NEW", numberOfItems, () => { rBush.Search(); });

            RunTest("Search envelope (Inf. bounds) OLD", numberOfItems, () => { rBush.Search_Old(Envelope.InfiniteBounds); });
            RunTest("Search envelope (Inf. bounds) NEW", numberOfItems, () => { rBush.Search(Envelope.InfiniteBounds); });

            RunTest("Iterate through IEnumerable [for comparison]", numberOfItems, () => { foreach (Item i in items)
                                                                                           {
                                                                                           }
                    });

            Console.ReadLine();
        }
示例#3
0
        public void TestSearch_AfterBulkLoadWithSplitRoot()
        {
            int maxEntries = 4;
            var tree       = new RBush <Point>(maxEntries);

            int      numFirstSet      = maxEntries * maxEntries + 2;    // Split-root will occur twice.
            var      firstSet         = points.Take(numFirstSet);
            Envelope firstSetEnvelope =
                new Envelope(
                    firstSet.Min(p => p.Envelope.MinX),
                    firstSet.Min(p => p.Envelope.MinY),
                    firstSet.Max(p => p.Envelope.MaxX),
                    firstSet.Max(p => p.Envelope.MaxY));

            tree.BulkLoad(firstSet);

            int      numExtraPoints         = 5;
            var      extraPointsSet         = points.TakeLast(numExtraPoints);
            Envelope extraPointsSetEnvelope =
                new Envelope(
                    extraPointsSet.Min(p => p.Envelope.MinX),
                    extraPointsSet.Min(p => p.Envelope.MinY),
                    extraPointsSet.Max(p => p.Envelope.MaxX),
                    extraPointsSet.Max(p => p.Envelope.MaxY));

            foreach (var p in extraPointsSet)
            {
                tree.Insert(p);
            }

            Assert.Equal(extraPointsSet.OrderBy(x => x), tree.Search(extraPointsSetEnvelope).OrderBy(x => x));
        }
示例#4
0
        public void BasicRemoveTest()
        {
            var tree = new RBush <Point>(maxEntries: 4);

            tree.BulkLoad(points);

            var len = points.Length;

            tree.Delete(points[0]);
            tree.Delete(points[1]);
            tree.Delete(points[2]);

            tree.Delete(points[len - 1]);
            tree.Delete(points[len - 2]);
            tree.Delete(points[len - 3]);

            var shouldFindPoints = points
                                   .Skip(3).Take(len - 6)
                                   .OrderBy(x => x)
                                   .ToList();
            var foundPoints = tree.Search()
                              .OrderBy(x => x)
                              .ToList();

            Assert.Equal(shouldFindPoints, foundPoints);
            Assert.Equal(shouldFindPoints.Count, tree.Count);
            Assert.Equal(
                shouldFindPoints.Aggregate(Envelope.EmptyBounds, (e, p) => e.Extend(p.Envelope)),
                tree.Envelope);
        }
示例#5
0
        public static IEnumerable <IPoint> Execute(IGeometry line1, IGeometry line2)
        {
            IDictionary <string, IPoint> unique = new Dictionary <string, IPoint>();
            IList <IPoint> intersections        = new List <IPoint>();

            RBush <Extensions.SpatialDataWrapper <Segment> > tree = new RBush <Extensions.SpatialDataWrapper <Segment> >();

            tree.BulkLoad(LineSegment.Execute(line2).Select(a => a.AsSpatialData <Segment>()));
            foreach (Segment segment in LineSegment.Execute(line1))
            {
                foreach (Extensions.SpatialDataWrapper <Segment> match in tree.Search(segment.BBox.AsEnvelope()))
                {
                    IPoint intersect = Intersects(segment.LineString, match.GetOriginalData <Segment>().LineString);
                    if (intersect != null)
                    {
                        var key = string.Join(",", intersect.X, intersect.Y);
                        if (!unique.ContainsKey(key))
                        {
                            unique.Add(key, intersect);
                            intersections.Add(intersect);
                        }
                    }
                }
            }

            return(intersections);
        }
示例#6
0
        public void TestSearchAfterInsertWithSplitRoot()
        {
            var maxEntries = 4;
            var tree       = new RBush <Point>(maxEntries);

            var numFirstSet = maxEntries * maxEntries + 2;              // Split-root will occur twice.
            var firstSet    = points.Take(numFirstSet);

            foreach (var p in firstSet)
            {
                tree.Insert(p);
            }

            var numExtraPoints         = 5;
            var extraPointsSet         = points.Skip(points.Length - numExtraPoints);
            var extraPointsSetEnvelope =
                extraPointsSet.Aggregate(Envelope.EmptyBounds, (e, p) => e.Extend(p.Envelope));

            foreach (var p in extraPointsSet)
            {
                tree.Insert(p);
            }

            // first 10 entries and last 5 entries are completely mutually exclusive
            // so searching the bounds of the new set should only return the new set exactly
            Assert.Equal(extraPointsSet.OrderBy(x => x), tree.Search(extraPointsSetEnvelope).OrderBy(x => x));
        }
示例#7
0
        public void BasicRemoveTest()
        {
            var tree = new RBush <Point>(maxEntries: 4);

            tree.BulkLoad(points);

            var len = points.Length;

            tree.Delete(points[0]);
            tree.Delete(points[1]);
            tree.Delete(points[2]);

            tree.Delete(points[len - 1]);
            tree.Delete(points[len - 2]);
            tree.Delete(points[len - 3]);

            var shouldFindPoints = points
                                   .Skip(3).Take(len - 6)
                                   .OrderBy(x => x)
                                   .ToList();
            var foundPoints = tree.Search()
                              .OrderBy(x => x)
                              .ToList();

            Assert.Equal(shouldFindPoints, foundPoints);
        }
示例#8
0
        public void TestBulk()
        {
            var tree = new RBush <Point>();

            tree.BulkLoad(missingEnvelopeTestData);

            var envelope = new Envelope(
                minX: 34.73274678,
                minY: 31.87729923,
                maxX: 34.73274678,
                maxY: 31.87729923);

            Assert.Equal(
                expected: tree.Search().Where(p => p.Envelope.Intersects(envelope)).Count(),
                actual: tree.Search(envelope).Count);
        }
示例#9
0
        public void SearchReturnsEmptyResultIfNothingFound()
        {
            var tree = new RBush <Point>(maxEntries: 4);

            tree.BulkLoad(points);

            Assert.Equal(new Point[] { }, tree.Search(new Envelope(200, 200, 210, 210)));
        }
示例#10
0
        public void BulkLoadTestData()
        {
            var tree = new RBush <Point>();

            tree.BulkLoad(points);

            Assert.Equal(points.Length, tree.Count);
            Assert.Equal(points.OrderBy(x => x).ToList(), tree.Search().OrderBy(x => x).ToList());
        }
示例#11
0
        public void BulkLoadAfterDeleteTest2()
        {
            var pts       = GetPoints(20);
            var ptsDelete = pts.Take(4);
            var tree      = new RBush <Point>(maxEntries: 4);

            tree.BulkLoad(pts);

            foreach (var item in ptsDelete)
            {
                tree.Delete(item);
            }

            tree.BulkLoad(ptsDelete);

            Assert.Equal(pts.Count, tree.Search().Count);
            Assert.Equal(pts.OrderBy(x => x).ToList(), tree.Search().OrderBy(x => x).ToList());
        }
示例#12
0
        public void MissingEnvelopeTestInsertIndividually()
        {
            var tree = new RBush <Point>();

            foreach (var p in missingEnvelopeTestData)
            {
                tree.Insert(p);
            }

            var envelope = new Envelope(
                minX: 34.73274678,
                minY: 31.87729923,
                maxX: 34.73274678,
                maxY: 31.87729923);

            Assert.Equal(
                expected: tree.Search().Where(p => p.Envelope.Intersects(envelope)).Count(),
                actual: tree.Search(envelope).Count);
        }
示例#13
0
        public void InsertTestData()
        {
            var tree = new RBush <Point>();

            foreach (var p in points)
            {
                tree.Insert(p);
            }

            Assert.Equal(points.Length, tree.Count);
            Assert.Equal(points.OrderBy(x => x), tree.Search().OrderBy(x => x));
        }
示例#14
0
        public void InsertAfterDeleteTest1()
        {
            var pts       = GetPoints(20);
            var ptsDelete = pts.Take(18);
            var tree      = new RBush <Point>(maxEntries: 4);

            foreach (var item in pts)
            {
                tree.Insert(item);
            }

            foreach (var item in ptsDelete)
            {
                tree.Delete(item);
            }

            foreach (var item in ptsDelete)
            {
                tree.Insert(item);
            }

            Assert.Equal(pts.Count, tree.Search().Count);
            Assert.Equal(pts.OrderBy(x => x).ToList(), tree.Search().OrderBy(x => x).ToList());
        }
示例#15
0
文件: World.cs 项目: ckissane/IOGame
 public IEnumerable <Body> BodiesNear(Vector2 point, int maximumDistance = 0, bool offsetSize = false)
 {
     if (maximumDistance == 0)
     {
         return(this.Bodies);
     }
     else
     {
         return(RTree.Search(new Envelope(
                                 point.X - maximumDistance / 2,
                                 point.Y - maximumDistance / 2,
                                 point.X + maximumDistance / 2,
                                 point.Y + maximumDistance / 2
                                 )));
     }
 }
示例#16
0
        public void TestSearchAfterInsert()
        {
            var maxEntries = 9;
            var tree       = new RBush <Point>(maxEntries);

            var firstSet         = points.Take(maxEntries);
            var firstSetEnvelope =
                firstSet.Aggregate(Envelope.EmptyBounds, (e, p) => e.Extend(p.Envelope));

            foreach (var p in firstSet)
            {
                tree.Insert(p);
            }

            Assert.Equal(firstSet.OrderBy(x => x), tree.Search(firstSetEnvelope).OrderBy(x => x));
        }
示例#17
0
        public void InsertTestData()
        {
            var tree = new RBush <Point>();

            foreach (var p in points)
            {
                tree.Insert(p);
            }

            Assert.Equal(points.Length, tree.Count);
            Assert.Equal(points.OrderBy(x => x), tree.Search().OrderBy(x => x));

            Assert.Equal(
                points.Aggregate(Envelope.EmptyBounds, (e, p) => e.Extend(p.Envelope)),
                tree.Envelope);
        }
示例#18
0
        public void SearchReturnsMatchingResults()
        {
            var tree = new RBush <Point>(maxEntries: 4);

            tree.BulkLoad(points);

            var searchEnvelope   = new Envelope(40, 20, 80, 70);
            var shouldFindPoints = points
                                   .Where(p => p.Envelope.Intersects(searchEnvelope))
                                   .OrderBy(x => x)
                                   .ToList();
            var foundPoints = tree.Search(searchEnvelope)
                              .OrderBy(x => x)
                              .ToList();

            Assert.Equal(shouldFindPoints, foundPoints);
        }
示例#19
0
        public void AdditionalRemoveTest()
        {
            var tree      = new RBush <Point>();
            var numDelete = 18;

            foreach (var p in points)
            {
                tree.Insert(p);
            }

            foreach (var p in points.Take(numDelete))
            {
                tree.Delete(p);
            }

            Assert.Equal(points.Length - numDelete, tree.Count);
            Assert.Equal(points.Skip(numDelete).OrderBy(x => x), tree.Search().OrderBy(x => x));
        }
示例#20
0
        public void BinarySerializeBasicTest()
        {
            RBush <Point> treeOriginal = new RBush <Point>(maxEntries: 4);

            treeOriginal.BulkLoad(points);
            Envelope searchEnvelope = new Envelope(20, 15, 60, 31);

            byte[]        byteArr          = treeOriginal.BinarySerialize();
            RBush <Point> treeDeserialized = byteArr.BinaryDeserialize() as RBush <Point>;

            Assert.True(treeOriginal.Count == treeDeserialized.Count);
            Assert.True(treeOriginal.Envelope == treeDeserialized.Envelope);
            IReadOnlyList <Point> treeOriginalSearchResult     = treeOriginal.Search(searchEnvelope);
            IReadOnlyList <Point> treeDeserializedSearchResult = treeDeserialized.Search(searchEnvelope);

            Assert.True(treeOriginalSearchResult.Count == treeDeserializedSearchResult.Count);
            Assert.True(treeOriginalSearchResult[0].Envelope == treeDeserializedSearchResult[0].Envelope);
        }
示例#21
0
        public void TestSearchAfterInsert()
        {
            int maxEntries = 9;
            var tree       = new RBush <Point>(maxEntries);

            var      firstSet         = points.Take(maxEntries);
            Envelope firstSetEnvelope =
                new Envelope(
                    firstSet.Min(p => p.Envelope.MinX),
                    firstSet.Min(p => p.Envelope.MinY),
                    firstSet.Max(p => p.Envelope.MaxX),
                    firstSet.Max(p => p.Envelope.MaxY));

            foreach (var p in firstSet)
            {
                tree.Insert(p);
            }

            Assert.Equal(firstSet.OrderBy(x => x), tree.Search(firstSetEnvelope).OrderBy(x => x));
        }
示例#22
0
        public void BulkLoadMergesTreesProperly()
        {
            var smaller = GetPoints(10);
            var tree1   = new RBush <Point>(maxEntries: 4);

            tree1.BulkLoad(smaller);
            tree1.BulkLoad(points);

            var tree2 = new RBush <Point>(maxEntries: 4);

            tree2.BulkLoad(points);
            tree2.BulkLoad(smaller);

            Assert.True(tree1.Count == tree2.Count);
            Assert.True(tree1.Root.Height == tree2.Root.Height);

            var allPoints = points.Concat(smaller).OrderBy(x => x).ToList();

            Assert.Equal(allPoints, tree1.Search().OrderBy(x => x).ToList());
            Assert.Equal(allPoints, tree2.Search().OrderBy(x => x).ToList());
        }
示例#23
0
文件: World.cs 项目: yahyaguzide/daud
 public IEnumerable <Body> BodiesNear(Envelope searchArea)
 {
     return(RTreeDynamic.Search(searchArea)
            .Union(RTreeStatic.Search(searchArea)));
 }
        public void SurfaceMeshByBoundary()
        {
            Document adoc = Application.DocumentManager.MdiActiveDocument;

            if (adoc == null)
            {
                return;
            }

            Database db = adoc.Database;

            DB = db;

            Editor ed = adoc.Editor;

            ED = ed;

            CivilDocument cdok = CivilDocument.GetCivilDocument(adoc.Database);


            try
            {
                Color currColor = db.Cecolor;
                if (!currColor.IsByLayer)//Если текущий слой не по слою, то расчитать более темный цвет для границ участков
                {
                    Color dimmerColor = Utils.GetDimmerColor(currColor, BORDER_DIM_MULTIPLIER);

                    ColorForBorder = dimmerColor;
                }
                else
                {
                    ColorForBorder = Color.FromColorIndex(ColorMethod.ByAci, 256);
                }


                if (!TinSurfIdIsValid())
                {
                    //Выбрать поверхность
                    if (!PickTinSurf(ed))
                    {
                        return;//Если выбор не успешен, прервать выполнение
                    }
                }
                //Подсветить поверхность
                HighlightTinSurf(true);


                //Запрос ключевых слов
                while (true)
                {
                    const string kw1 = "ПОВерхность";
                    const string kw2 = "ВОЗвышение";
                    const string kw3 = "ОТКлонкниеОтДуг";
                    const string kw4 = "СОЗдаватьГраницы";

                    PromptKeywordOptions pko = new PromptKeywordOptions("\nЗадайте параметры или пустой ввод для продолжения");
                    pko.Keywords.Add(kw1);
                    pko.Keywords.Add(kw2);
                    pko.Keywords.Add(kw3);
                    pko.Keywords.Add(kw4);
                    pko.AllowNone = true;
                    PromptResult pr = ed.GetKeywords(pko);
                    if (pr.Status == PromptStatus.Cancel)
                    {
                        return;
                    }

                    if (String.IsNullOrEmpty(pr.StringResult))
                    {
                        break;
                    }

                    switch (pr.StringResult)
                    {
                    case kw1:
                        if (!PickTinSurf(ed))
                        {
                            return;
                        }
                        break;

                    case kw2:
                        if (!GetMeshElevation(ed))
                        {
                            return;
                        }
                        break;

                    case kw3:
                        if (!GetApproxParam(ed))
                        {
                            return;
                        }
                        break;

                    case kw4:
                        if (!GetCreateBorders(ed))
                        {
                            return;
                        }

                        break;
                    }
                }


                //Проверка текущего набора выбора
                acSSet = null;
                PromptSelectionResult acSSPrompt;
                acSSPrompt = ed.SelectImplied();
                if (acSSPrompt.Status == PromptStatus.OK)
                {
                    acSSet = acSSPrompt.Value;
                }
                else
                {
                    //Множественный выбор блоков
                    TypedValue[] tv = new TypedValue[]
                    {
                        new TypedValue(0, "INSERT")
                    };
                    SelectionFilter flt = new SelectionFilter(tv);


                    PromptSelectionOptions pso = new PromptSelectionOptions();
                    pso.MessageForAdding = "\nВыберите блоки участков";

                    acSSPrompt = adoc.Editor.GetSelection(pso, flt);
                    if (acSSPrompt.Status == PromptStatus.OK)
                    {
                        acSSet = acSSPrompt.Value;
                    }
                }

                if (acSSet != null)
                {
                    Common.Timer timerMain = new Common.Timer();
                    timerMain.Start();
                    foreach (SelectedObject acSSObj in acSSet)
                    {
                        string       blockName = null;
                        Common.Timer timer     = new Common.Timer();
                        timer.Start();
                        try
                        {
                            if (acSSObj != null)
                            {
                                //полилинии внутри блока
                                List <ObjectId> polylines      = new List <ObjectId>();
                                BlockReference  blockReference = null;
                                ObjectId        btrId          = ObjectId.Null;
                                using (Transaction tr = db.TransactionManager.StartTransaction())
                                {
                                    //блок внутри набора выбора
                                    blockReference = tr.GetObject(acSSObj.ObjectId, OpenMode.ForRead) as BlockReference;
                                    tr.Commit();
                                }
                                Matrix3d transform = Matrix3d.Identity;
                                if (blockReference != null)
                                {
                                    //трансформация из системы координат блока в мировую систему координат
                                    transform = blockReference.BlockTransform;

                                    //Перебор всех объектов внутри блока
                                    //Найти все правильные полилинии в блоке
                                    using (Transaction tr = db.TransactionManager.StartTransaction())
                                    {
                                        btrId = blockReference.BlockTableRecord;
                                        BlockTableRecord blockTableRecord = tr.GetObject(btrId, OpenMode.ForRead) as BlockTableRecord;

                                        if (blockTableRecord.XrefStatus == XrefStatus.NotAnXref)
                                        {
                                            blockName = blockTableRecord.Name;
                                            foreach (ObjectId id in blockTableRecord)
                                            {
                                                using (Polyline poly = tr.GetObject(id, OpenMode.ForRead) as Polyline)
                                                {
                                                    if (poly != null &&
                                                        (poly.Closed || poly.GetPoint2dAt(0).Equals(poly.GetPoint2dAt(poly.NumberOfVertices - 1))) &&//Полилиния замкнута
                                                        !Utils.PolylineIsSelfIntersecting(poly) &&//Не имеет самопересечений
                                                        poly.Visible == true &&//Учет многовидовых блоков
                                                        poly.Bounds != null
                                                        )
                                                    {
                                                        polylines.Add(id);
                                                    }
                                                }

                                                AcadDb.Entity ent = tr.GetObject(id, OpenMode.ForRead) as AcadDb.Entity;
                                                if (ent is Polyline)
                                                {
                                                    Polyline poly = ent as Polyline;
                                                }
                                            }


                                            if (polylines.Count > 0)
                                            {
                                                //Проверить все линии на пересечение друг с другом. Удалить из списка те, которые имеют пересечения
                                                HashSet <ObjectId> polylinesWithNoIntersections = new HashSet <ObjectId>(polylines);
                                                //Сделать RBush для всех полилиний
                                                RBush <SpatialEntity> polylinesTree   = new RBush <SpatialEntity>();
                                                List <SpatialEntity>  spatialEntities = new List <SpatialEntity>();
                                                foreach (ObjectId polyId in polylines)
                                                {
                                                    spatialEntities.Add(new SpatialEntity(polyId));
                                                }
                                                polylinesTree.BulkLoad(spatialEntities);

                                                foreach (SpatialEntity se in spatialEntities)
                                                {
                                                    //Нахождение всех объектов, расположенных в пределах BoundingBox для этой полилинии
                                                    IReadOnlyList <SpatialEntity> nearestNeighbors = polylinesTree.Search(se.Envelope);
                                                    if (nearestNeighbors.Count > 1)
                                                    {
                                                        Polyline thisPoly = tr.GetObject(se.ObjectId, OpenMode.ForRead) as Polyline;

                                                        foreach (SpatialEntity n in nearestNeighbors)
                                                        {
                                                            if (!n.Equals(se))//Всегда будет находиться та же самая полилиния
                                                            {
                                                                Polyline          otherPoly = tr.GetObject(n.ObjectId, OpenMode.ForRead) as Polyline;
                                                                Point3dCollection pts       = new Point3dCollection();
                                                                thisPoly.IntersectWith(otherPoly, Intersect.OnBothOperands, pts, IntPtr.Zero, IntPtr.Zero);
                                                                if (pts.Count > 0)
                                                                {
                                                                    polylinesWithNoIntersections.Remove(thisPoly.Id);
                                                                    polylinesWithNoIntersections.Remove(otherPoly.Id);
                                                                    break;
                                                                }
                                                            }
                                                        }
                                                    }
                                                }

                                                //Аппроксимация всех полилиний, которые имеют кривизну
                                                List <Polyline> polylinesToProcess = new List <Polyline>();
                                                foreach (ObjectId polyId in polylinesWithNoIntersections)
                                                {
                                                    using (Polyline poly = tr.GetObject(polyId, OpenMode.ForRead) as Polyline)
                                                    {
                                                        polylinesToProcess.Add(ApproximatePolyBulges(poly, approxParam));//Какой допуск оптимален?
                                                    }
                                                }

                                                //Удалить все повторяющиеся подряд точки полилинии
                                                foreach (Polyline poly in polylinesToProcess)
                                                {
                                                    for (int i = 0; i < poly.NumberOfVertices;)
                                                    {
                                                        Point2d curr      = poly.GetPoint2dAt(i);
                                                        int     nextIndex = (i + 1) % poly.NumberOfVertices;
                                                        Point2d next      = poly.GetPoint2dAt(nextIndex);

                                                        if (next.IsEqualTo(curr, new Tolerance(0.001, 0.001)))//Прореживать точки, расположенные слишком близко//TODO: Учесть масштабирование блока
                                                        {
                                                            poly.RemoveVertexAt(nextIndex);
                                                        }
                                                        else
                                                        {
                                                            i++;
                                                        }
                                                    }
                                                }


                                                //Построение дерева вложенности полилиний
                                                using (TinSurface tinSurf = tr.GetObject(tinSurfId, OpenMode.ForRead) as TinSurface)
                                                {
                                                    using (PolylineNesting polylineNesting = new PolylineNesting(tinSurf))
                                                    {
                                                        foreach (Polyline poly in polylinesToProcess)
                                                        {
                                                            poly.TransformBy(transform);
                                                            polylineNesting.Insert(poly);
                                                        }

                                                        //Расчет полигонов
                                                        polylineNesting.CalculatePoligons();

                                                        //Построение сети
                                                        using (SubDMesh sdm = polylineNesting.CreateSubDMesh())
                                                        {
                                                            List <Line> lines = new List <Line>();
                                                            if (createBorders)
                                                            {
                                                                //Создание 3d линий по границе
                                                                lines = polylineNesting.CreateBorderLines();
                                                            }

                                                            //Объекты постоены в координатах пространства модели
                                                            if (sdm != null)
                                                            {
                                                                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForWrite);
                                                                if (btr.GetBlockReferenceIds(true, false).Count > 1)
                                                                {
                                                                    //Если у блока несколько вхождений, то создавать объекты в пространстве модели
                                                                    BlockTable       bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
                                                                    BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                                                                    ms.AppendEntity(sdm);
                                                                    tr.AddNewlyCreatedDBObject(sdm, true);

                                                                    foreach (Line line in lines)
                                                                    {
                                                                        ms.AppendEntity(line);
                                                                        tr.AddNewlyCreatedDBObject(line, true);
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    //Если у блока только одно вхождение, то создавать сеть внутри блока
                                                                    sdm.TransformBy(transform.Inverse());
                                                                    btr.AppendEntity(sdm);
                                                                    tr.AddNewlyCreatedDBObject(sdm, true);

                                                                    foreach (Line line in lines)
                                                                    {
                                                                        line.TransformBy(transform.Inverse());
                                                                        btr.AppendEntity(line);
                                                                        tr.AddNewlyCreatedDBObject(line, true);
                                                                    }
                                                                }
                                                            }

                                                            foreach (Line line in lines)
                                                            {
                                                                line.Dispose();
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }

                                        tr.Commit();
                                    }
                                }
                            }
                        }
                        catch (System.Exception ex)
                        {
                            string message = "Возникла ошибка при обработке одного из выбранных объектов";
                            if (!String.IsNullOrEmpty(blockName))
                            {
                                message = "Возникла ошибка при обработке вхождения блока " + blockName;
                            }
                            Utils.ErrorToCommandLine(ed, message, ex);
                        }
                        timer.TimeOutput(blockName);
                    }

                    ed.WriteMessage("\n" +
                                    timerMain.TimeOutput("Затрачено времени (параметр аппроксимации - " + approxParam + ")")
                                    );

                    ed.Regen();
                }
            }
            catch (System.Exception ex)
            {
                CommonException(ex, "Ошибка при создании сетей по участкам поверхности");
            }
            finally
            {
                HighlightTinSurf(false);
            }
        }
        private void Create3dProfile(object arg)
        {
            try
            {
                if (doc != null)
                {
                    List <ObjectId> toHighlight = new List <ObjectId>();

                    using (doc.LockDocument())
                    {
                        Editor   ed = doc.Editor;
                        Database db = doc.Database;

                        using (Transaction tr = db.TransactionManager.StartTransaction())
                        {
                            //найти координату X начала профиля (крайнюю левую)
                            double          minx        = double.PositiveInfinity;
                            List <ObjectId> allSelected = new List <ObjectId>(soilHatchIds);
                            foreach (ObjectId id in allSelected)
                            {
                                Entity ent = null;
                                try
                                {
                                    ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
                                }
                                catch (Autodesk.AutoCAD.Runtime.Exception) { continue; }
                                Extents3d?ext = ent.Bounds;
                                if (ext != null)
                                {
                                    Point3d minPt = ext.Value.MinPoint;
                                    if (minx > minPt.X)
                                    {
                                        minx = minPt.X;
                                    }
                                }
                            }


                            //Штриховки должны быть заранее раскиданы по слоям в соответствии с ИГЭ!

                            //пересчет всех точек штриховок в координаты:
                            //X - положение отностиельно начала профиля с учетом горизонтального масштаба профиля,
                            //Y - отметка расчитанная согласно базовой отметке с учетом вертикального масштаба профиля
                            Matrix2d transform =
                                new Matrix2d(new double[]
                            {
                                HorScaling, 0, 0,
                                0, VertScaling, 0,
                                0, 0, 1
                            })
                                * Matrix2d.Displacement(new Vector2d(-minx, -ElevBasePoint.Value.Y + ElevationInput / VertScaling));

                            C5.IntervalHeap <HatchEvent> eventQueue            = new C5.IntervalHeap <HatchEvent>();
                            List <HatchData>             allHatchData          = new List <HatchData>();
                            List <Point2dCollection>     selfintersectingLoops = new List <Point2dCollection>();
                            foreach (ObjectId id in soilHatchIds)
                            {
                                //получить все точки штриховок с учетом возможных дуг, сплайнов и проч
                                //Для каждой штриховки создается набор композитных кривых, состоящих из линейных сегментов
                                Hatch hatch = null;
                                try
                                {
                                    hatch = (Hatch)tr.GetObject(id, OpenMode.ForRead);
                                }
                                catch (Autodesk.AutoCAD.Runtime.Exception) { continue; }
                                List <CompositeCurve2d>  boundaries   = new List <CompositeCurve2d>();
                                List <Extents2d>         extends      = new List <Extents2d>();
                                List <Point2dCollection> ptsCollList  = new List <Point2dCollection>();
                                List <List <double> >    ptParamsList = new List <List <double> >();
                                for (int i = 0; i < hatch.NumberOfLoops; i++)
                                {
                                    HatchLoop hl = hatch.GetLoopAt(i);
                                    if (!hl.LoopType.HasFlag(HatchLoopTypes.SelfIntersecting) &&
                                        !hl.LoopType.HasFlag(HatchLoopTypes.Textbox) &&
                                        !hl.LoopType.HasFlag(HatchLoopTypes.TextIsland) &&
                                        !hl.LoopType.HasFlag(HatchLoopTypes.NotClosed))
                                    {
                                        List <Curve2d>   curves = Utils.GetHatchLoopCurves(hl);
                                        List <Curve2d>   compositeCurveElems = new List <Curve2d>();
                                        double           _minx         = double.PositiveInfinity;
                                        double           _miny         = double.PositiveInfinity;
                                        double           _maxx         = double.NegativeInfinity;
                                        double           _maxy         = double.NegativeInfinity;
                                        Action <Point2d> updateExtends = new Action <Point2d>(p =>
                                        {
                                            _minx = p.X < _minx ? p.X : _minx;
                                            _miny = p.Y < _miny ? p.Y : _miny;
                                            _maxx = p.X > _maxx ? p.X : _maxx;
                                            _maxy = p.Y > _maxy ? p.Y : _maxy;
                                        });

                                        Point2dCollection ptsColl   = new Point2dCollection();
                                        List <double>     ptParams  = new List <double>();
                                        double            currParam = 0;
                                        foreach (Curve2d c in curves)
                                        {
                                            if (!(c is LineSegment2d))
                                            {
                                                Interval         interval  = c.GetInterval();
                                                PointOnCurve2d[] samplePts = c.GetSamplePoints(interval.LowerBound, interval.UpperBound, 0.02);

                                                Point2d[] pts = samplePts.Select(p => transform * p.Point).ToArray();
                                                for (int n = 0; n < pts.Length - 1; n++)
                                                {
                                                    LineSegment2d lineSeg = new LineSegment2d(pts[n], pts[n + 1]);
                                                    compositeCurveElems.Add(lineSeg);

                                                    ptsColl.Add(pts[n]);
                                                    ptParams.Add(currParam);
                                                    updateExtends(pts[n]);
                                                    currParam += lineSeg.Length;
                                                }
                                            }
                                            else
                                            {
                                                LineSegment2d lineSeg = (LineSegment2d)c;
                                                lineSeg.TransformBy(transform);
                                                compositeCurveElems.Add(lineSeg);

                                                ptsColl.Add(lineSeg.StartPoint);
                                                ptParams.Add(currParam);
                                                updateExtends(lineSeg.StartPoint);
                                                currParam += lineSeg.Length;
                                            }
                                        }


                                        CompositeCurve2d boundary = new CompositeCurve2d(compositeCurveElems.ToArray());
                                        Extents2d        ext      = new Extents2d(_minx, _miny, _maxx, _maxy);
                                        boundaries.Add(boundary);
                                        ptsCollList.Add(ptsColl);
                                        ptParamsList.Add(ptParams);
                                        extends.Add(ext);
                                    }
                                }

                                //контуры штриховок не могут иметь самопересечений!
                                #region Проверка на пересечения
                                //проверка на самопересечения
                                //bool badBoundaries = false;
                                HashSet <int> badBoundaries   = new HashSet <int>();
                                HashSet <int> splitBoundaries = new HashSet <int>();//Если 2 контура в одной штриховке пересекаются, то разносить их по разным штриховкам
                                //List<HatchData> decomposeHatchData = new List<HatchData>();//TODO: самопересекающиеся полигоны нужно разбить на отдельные по количеству самопересечний.

                                for (int i = 0; i < boundaries.Count; i++)
                                {
                                    CompositeCurve2d        b           = boundaries[i];
                                    CurveCurveIntersector2d intersector = new CurveCurveIntersector2d(b, b);
                                    if (intersector.NumberOfIntersectionPoints > 0)
                                    {
                                        //если происходит только наложение???
                                        badBoundaries.Add(i);
                                        selfintersectingLoops.Add(ptsCollList[i]);
                                    }
                                }

                                if (boundaries.Count > 1)
                                {
                                    //проверка на взаимные пересечения.
                                    //Исп RBush для того чтобы избежать проверки на пересечение каждого с каждым и квадратичной сложности
                                    //(работает только если контуры разнесены)
                                    //Не брать в расчет пересечения по касательной
                                    RBush <Spatial> boundariesRBush = new RBush <Spatial>();
                                    List <Spatial>  spatialData     = new List <Spatial>();
                                    for (int i = 0; i < extends.Count; i++)
                                    {
                                        spatialData.Add(new Spatial(extends[i], i));
                                    }
                                    boundariesRBush.BulkLoad(spatialData);
                                    foreach (Spatial s in spatialData)
                                    {
                                        IReadOnlyList <Spatial> nearestNeighbors = boundariesRBush.Search(s.Envelope);
                                        if (nearestNeighbors.Count > 1)
                                        {
                                            CompositeCurve2d thisCurve = boundaries[(int)s.Obj];
                                            foreach (Spatial n in nearestNeighbors)
                                            {
                                                if (!s.Equals(n))
                                                {
                                                    CompositeCurve2d        otherCurve = boundaries[(int)n.Obj];
                                                    CurveCurveIntersector2d intersector
                                                        = new CurveCurveIntersector2d(thisCurve, otherCurve);
                                                    if (intersector.NumberOfIntersectionPoints > 0 ||
                                                        intersector.OverlapCount > 0)
                                                    {
                                                        bool matches = false;
                                                        //Проверить, что кривые не накладываются друг на друга по всей длине (то есть полностью совпадают)
                                                        if (intersector.OverlapCount > 0)
                                                        {
                                                            //сумма длин всех интервалов перекрытия равна общей длине кривой
                                                            double thisCurveOverlapLength  = 0;
                                                            double otherCurveOverlapLength = 0;
                                                            for (int i = 0; i < intersector.OverlapCount; i++)
                                                            {
                                                                Interval[] intervals           = intersector.GetOverlapRanges(i);
                                                                Interval   thisOverlapInterval = intervals[0];
                                                                thisCurveOverlapLength += thisOverlapInterval.Length;
                                                                Interval otherOverlapInterval = intervals[1];
                                                                otherCurveOverlapLength += otherOverlapInterval.Length;
                                                            }

                                                            Interval thisCurveInterval  = thisCurve.GetInterval();
                                                            Interval otherCurveInterval = otherCurve.GetInterval();

                                                            if (Utils.LengthIsEquals(thisCurveOverlapLength, thisCurveInterval.Length) &&
                                                                Utils.LengthIsEquals(otherCurveOverlapLength, otherCurveInterval.Length))
                                                            {
                                                                matches = true;
                                                            }
                                                        }

                                                        if (!matches)
                                                        {
                                                            splitBoundaries.Add((int)s.Obj);
                                                            splitBoundaries.Add((int)n.Obj);
                                                        }
                                                        else
                                                        {
                                                            badBoundaries.Add((int)s.Obj);
                                                            badBoundaries.Add((int)n.Obj);
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }

                                splitBoundaries.ExceptWith(badBoundaries);
                                List <HatchData> splitHatchData = new List <HatchData>();
                                if (badBoundaries.Count > 0 || splitBoundaries.Count > 0)
                                {
                                    List <CompositeCurve2d>  boundariesClear   = new List <CompositeCurve2d>();
                                    List <Extents2d>         extendsClear      = new List <Extents2d>();
                                    List <Point2dCollection> ptsCollListClear  = new List <Point2dCollection>();
                                    List <List <double> >    ptParamsListClear = new List <List <double> >();

                                    for (int i = 0; i < boundaries.Count; i++)
                                    {
                                        if (!badBoundaries.Contains(i) && !splitBoundaries.Contains(i))
                                        {
                                            boundariesClear.Add(boundaries[i]);
                                            extendsClear.Add(extends[i]);
                                            ptsCollListClear.Add(ptsCollList[i]);
                                            ptParamsListClear.Add(ptParamsList[i]);
                                        }
                                    }

                                    foreach (int index in splitBoundaries)
                                    {
                                        splitHatchData.Add(new HatchData(
                                                               new HatchNestingNode(
                                                                   boundaries[index],
                                                                   extends[index],
                                                                   ptsCollList[index],
                                                                   ptParamsList[index], hatch)));
                                    }


                                    boundaries   = boundariesClear;
                                    extends      = extendsClear;
                                    ptsCollList  = ptsCollListClear;
                                    ptParamsList = ptParamsListClear;
                                }
                                #endregion

                                //определяется вложенность контуров штриховки
                                //ЕСЛИ ШТРИХОВКА СОСТОИТ ИЗ 2 И БОЛЕЕ КОНТУРОВ, КОТОРЫЕ НЕ ВЛОЖЕНЫ ДРУГ В ДРУГА,
                                //ТО ЭТИ КОНТУРЫ ДОЛЖНЫ РАССМАТРИВАТЬСЯ КАК ОТДЕЛЬНЫЕ ШТРИХОВКИ!!!
                                HatchNestingTree hatchNestingTree
                                    = new HatchNestingTree(boundaries, extends, ptsCollList, ptParamsList, hatch);
                                List <HatchData> currHatchData = hatchNestingTree.GetHatchData();
                                currHatchData.AddRange(splitHatchData);//добавить контуры, полученные из взаимно пересекающихся контуров
                                //currHatchData.AddRange(decomposeHatchData);

                                allHatchData.AddRange(currHatchData);

                                //Каждая штриховка имеет диапазон по X от начала до конца по оси.
                                //В общую очередь событий сохраняются события начала и конца штриховки
                                foreach (HatchData hd in currHatchData)
                                {
                                    hd.AddEventsToQueue(eventQueue);
                                }
                            }



                            //Трассу разбить на отрезки, на которых будут вставлены прямолинейные сегменты штриховок
                            Polyline alignmentPoly = null;
                            try
                            {
                                alignmentPoly = (Polyline)tr.GetObject(AlignmentPolyId, OpenMode.ForRead);
                            }
                            catch (Autodesk.AutoCAD.Runtime.Exception)
                            {
                                return;
                            }
                            int segments = alignmentPoly.NumberOfVertices - 1;
                            List <AlignmentSegment>   alignmentSegments   = new List <AlignmentSegment>();
                            Action <Point2d, Point2d> addAlignmentSegment = new Action <Point2d, Point2d>((p0, p1) =>
                            {
                                double start = alignmentPoly.GetDistAtPoint(new Point3d(p0.X, p0.Y, 0));
                                double end   = alignmentPoly.GetDistAtPoint(new Point3d(p1.X, p1.Y, 0));
                                if (Math.Abs(start - end) > Tolerance.Global.EqualPoint)//TODO: Это спорный момент - ведь может быть большое множество очень коротких участков подряд!
                                {
                                    Vector2d startDir = p1 - p0;
                                    alignmentSegments.Add(new AlignmentSegment(start, end, p0, startDir));
                                }
                            });
                            for (int i = 0; i < segments; i++)
                            {
                                SegmentType segmentType = alignmentPoly.GetSegmentType(i);
                                Point2d     startLoc    = alignmentPoly.GetPoint2dAt(i);
                                Point2d     endLoc      = alignmentPoly.GetPoint2dAt(i + 1);
                                switch (segmentType)
                                {
                                case SegmentType.Line:
                                    addAlignmentSegment(startLoc, endLoc);
                                    break;

                                case SegmentType.Arc:
                                    CircularArc2d    arc       = new CircularArc2d(startLoc, endLoc, alignmentPoly.GetBulgeAt(i), false);
                                    Interval         interval  = arc.GetInterval();
                                    PointOnCurve2d[] samplePts = arc.GetSamplePoints(interval.LowerBound, interval.UpperBound, 0.1);
                                    for (int n = 0; n < samplePts.Length - 1; n++)
                                    {
                                        addAlignmentSegment(samplePts[n].Point, samplePts[n + 1].Point);
                                    }
                                    break;
                                }
                            }


                            //проход по каждому отрезку трассы (диапазон отрезка - диапазон длины полилинии)
                            HashSet <HatchData> currentHatchData = new HashSet <HatchData>();
                            foreach (AlignmentSegment alignmentSegment in alignmentSegments)
                            {
                                if (eventQueue.Count == 0)
                                {
                                    break;                       //штриховки закончились
                                }
                                //Получить те штриховки, диапазон по X которых пересекается с диапазоном текущего отрезка
                                //(СКАНИРУЮЩАЯ ЛИНИЯ: события - начало, конец штриховки)
                                HashSet <HatchData> intervalHatchData = new HashSet <HatchData>(currentHatchData);//штриховки пришедшие из предыдущего участка остаются все

                                //Собрать все события до конца сегмента
                                //Если при проходе от начала до конца сегмента какая-то штриховка проходится полностью от начала до конца, то
                                //все ее контуры без изменений должны быть переданы для создания М-полигона!!! (для них обход графа не нужен!)
                                HashSet <HatchData> startedInsideInterval           = new HashSet <HatchData>();
                                List <HatchData>    hatchesCompletelyInsideInterval = new List <HatchData>();
                                while (eventQueue.Count > 0)
                                {
                                    HatchEvent nextEvent = eventQueue.FindMin();
                                    if (nextEvent.Position > alignmentSegment.End)
                                    {
                                        break;
                                    }
                                    else if (nextEvent.Start)
                                    {
                                        //добавить штриховку в текущий набор
                                        HatchData hd = eventQueue.DeleteMin().HatchData;
                                        currentHatchData.Add(hd);
                                        //добавлять в набор текущего интервла только в том случае,
                                        //если сканирующая линия еще не дошла до конца интервала
                                        if (nextEvent.Position < alignmentSegment.End &&
                                            !Utils.LengthIsEquals(nextEvent.Position, alignmentSegment.End))   //Допуск нужен
                                        {
                                            startedInsideInterval.Add(hd);
                                            intervalHatchData.Add(hd);
                                        }
                                    }
                                    else
                                    {
                                        //убрать штриховку из текущего набора
                                        HatchData hd = eventQueue.DeleteMin().HatchData;
                                        currentHatchData.Remove(hd);

                                        if (startedInsideInterval.Contains(hd))
                                        {
                                            hatchesCompletelyInsideInterval.Add(hd);
                                        }
                                    }
                                }

                                foreach (HatchData hd in hatchesCompletelyInsideInterval)
                                {
                                    HatchSegmentData hsd = new HatchSegmentData(hd);
                                    alignmentSegment.HatchSegmentData.Add(hsd);

                                    hsd.Polygons = hd.GetAllBoundaries();
                                }


                                intervalHatchData.ExceptWith(hatchesCompletelyInsideInterval);
                                foreach (HatchData hd in intervalHatchData)
                                {
                                    HatchSegmentData hsd = new HatchSegmentData(hd);
                                    alignmentSegment.HatchSegmentData.Add(hsd);
                                    //для каждой штриховки выполнить построение и обход графа сегмента штриховки
                                    HatchSegmentGraph graph = new HatchSegmentGraph(alignmentSegment.Start, alignmentSegment.End, hd, doc.Editor);

                                    //сохранить наборы полигонов для текущего диапазона
                                    hsd.Polygons = graph.Result;
                                }
                            }



                            //для каждого диапазона создать полученные полигоны в 3d
                            BlockTable       bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
                            BlockTableRecord ms
                                = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                            BlockTableRecord btr = new BlockTableRecord();//Каждый профиль в отдельный блок
                            btr.Name = Guid.NewGuid().ToString();
                            ObjectId btrId = bt.Add(btr);
                            tr.AddNewlyCreatedDBObject(btr, true);

                            foreach (AlignmentSegment alignmentSegment in alignmentSegments)
                            {
                                List <Entity> flatObjs = new List <Entity>();

                                foreach (HatchSegmentData hsd in alignmentSegment.HatchSegmentData)
                                {
                                    //PlaneSurface
                                    hsd.GetNesting();
                                    Dictionary <Point2dCollection, List <Point2dCollection> > bwhs = hsd.GetBoundariesWithHoles();
                                    foreach (KeyValuePair <Point2dCollection, List <Point2dCollection> > bwh in bwhs)
                                    {
                                        //создать Region
                                        Region region = null;
                                        using (Polyline poly = new Polyline())
                                        {
                                            for (int i = 0; i < bwh.Key.Count; i++)
                                            {
                                                poly.AddVertexAt(i, bwh.Key[i], 0, 0, 0);
                                            }
                                            poly.Closed = true;
                                            DBObjectCollection coll = new DBObjectCollection();
                                            coll.Add(poly);
                                            try
                                            {
                                                DBObjectCollection regionColl = Region.CreateFromCurves(coll);
                                                foreach (DBObject dbo in regionColl)
                                                {
                                                    region = (Region)dbo;
                                                    break;
                                                }
                                            }
                                            catch { }
                                        }

                                        //из Region создать PlaneSurface
                                        if (region != null)
                                        {
                                            using (PlaneSurface planeSurface = new PlaneSurface())
                                            {
                                                planeSurface.CreateFromRegion(region);
                                                planeSurface.LayerId    = hsd.Hatch.LayerId;
                                                planeSurface.ColorIndex = 256;



                                                ObjectId planeSurfaceId = ms.AppendEntity(planeSurface);
                                                tr.AddNewlyCreatedDBObject(planeSurface, true);


                                                //вырезать отверстия в PlaneSurface

                                                foreach (Point2dCollection holePts2d in bwh.Value)
                                                {
                                                    if (holePts2d.Count < 3)
                                                    {
                                                        continue;
                                                    }

                                                    using (Polyline poly = new Polyline())
                                                    {
                                                        for (int i = 0; i < holePts2d.Count; i++)
                                                        {
                                                            poly.AddVertexAt(i, holePts2d[i], 0, 0, 0);
                                                        }
                                                        poly.Closed = true;

                                                        ObjectIdCollection trimPolyColl = new ObjectIdCollection();
                                                        trimPolyColl.Add(ms.AppendEntity(poly));
                                                        tr.AddNewlyCreatedDBObject(poly, true);

                                                        List <Point2d> ptsList  = new List <Point2d>(holePts2d.ToArray());
                                                        Point2d        pickPt2d = Utils.GetAnyPointInsidePoligon(ptsList,
                                                                                                                 Utils.DirectionIsClockwise(ptsList));

                                                        try
                                                        {
                                                            AcadDB.Surface.TrimSurface(planeSurfaceId, new ObjectIdCollection(), trimPolyColl,
                                                                                       new Vector3dCollection()
                                                            {
                                                                Vector3d.ZAxis
                                                            }, new Point3d(pickPt2d.X, pickPt2d.Y, 0),
                                                                                       -Vector3d.ZAxis, false, false);
                                                        }
                                                        catch /*(Exception ex)*/
                                                        {
                                                            //Вывод в командную строку
                                                            Utils.ErrorToCommandLine(doc.Editor,
                                                                                     "Ошибка при попытке вырезания отверстия в поверхности" /*, ex*/);
                                                        }

                                                        //Удалить все объекты, добавленные в чертеж!
                                                        poly.Erase();
                                                    }
                                                }


                                                flatObjs.Add((Entity)planeSurface.Clone());

                                                //Удалить все объекты, добавленные в чертеж!
                                                planeSurface.Erase();
                                            }
                                            region.Dispose();
                                        }
                                    }
                                }



                                foreach (Entity ent in flatObjs)
                                {
                                    ent.TransformBy(alignmentSegment.Transform);
                                    /*ms*/
                                    btr.AppendEntity(ent);
                                    tr.AddNewlyCreatedDBObject(ent, true);
                                    ent.Dispose();
                                }
                            }

                            BlockReference br = new BlockReference(Point3d.Origin, btrId);
                            ms.AppendEntity(br);
                            tr.AddNewlyCreatedDBObject(br, true);


                            if (selfintersectingLoops.Count > 0)
                            {
                                Utils.ErrorToCommandLine(doc.Editor,
                                                         "Отбраковано самопересекающихся контуров штриховок - " + selfintersectingLoops.Count + " (отмечены на профиле)");

                                ObjectId layerId = Utils.CreateLayerIfNotExists("САМОПЕРЕСЕКАЮЩИЙСЯ КОНТУР ШТРИХОВКИ", db, tr,
                                                                                color: Color.FromColorIndex(ColorMethod.ByAci, 1), lineWeight: LineWeight.LineWeight200);
                                Matrix2d returnTransform = transform.Inverse();
                                foreach (Point2dCollection pts in selfintersectingLoops)
                                {
                                    using (Polyline selfIntersectingPoly = new Polyline())
                                    {
                                        selfIntersectingPoly.LayerId    = layerId;
                                        selfIntersectingPoly.ColorIndex = 256;
                                        for (int i = 0; i < pts.Count; i++)
                                        {
                                            Point2d pt = pts[i].TransformBy(returnTransform);
                                            selfIntersectingPoly.AddVertexAt(i, pt, 0, 0, 0);
                                        }

                                        toHighlight.Add(ms.AppendEntity(selfIntersectingPoly));
                                        tr.AddNewlyCreatedDBObject(selfIntersectingPoly, true);

                                        //selfIntersectingPoly.Highlight();
                                    }
                                }
                            }


                            tr.Commit();
                        }
                    }
                    ps.Visible = false;

                    if (toHighlight.Count > 0)
                    {
                        using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
                        {
                            foreach (ObjectId id in toHighlight)
                            {
                                Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
                                ent.Highlight();
                            }
                            tr.Commit();
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                GeologyConvertationCommand.ClosePalette(null, null);
                CommonException(ex, "Ошибка при создании 3d профиля геологии");
            }
        }