Example #1
0
 public TriangleGraph(PolylineNesting polylineNesting, TinSurfaceTriangle triangle)
 {
     this.polylineNesting = polylineNesting;
     tinSurfaceTriangle   = triangle;
     verts[0]             = tinSurfaceTriangle.Vertex1;
     verts[1]             = tinSurfaceTriangle.Vertex2;
     verts[2]             = tinSurfaceTriangle.Vertex3;
     vert2dLocs[0]        = Utils.Point2DBy3D(tinSurfaceTriangle.Vertex1.Location);
     vert2dLocs[1]        = Utils.Point2DBy3D(tinSurfaceTriangle.Vertex2.Location);
     vert2dLocs[2]        = Utils.Point2DBy3D(tinSurfaceTriangle.Vertex3.Location);
     edgesLength[0]       = (vert2dLocs[1] - vert2dLocs[0]).Length;
     edgesLength[1]       = (vert2dLocs[1] - vert2dLocs[2]).Length;
     edgesLength[2]       = (vert2dLocs[2] - vert2dLocs[0]).Length;
     //Добавить узлы вершин треугольника
     new VertexGraphNode(this, 0);
     new VertexGraphNode(this, 1);
     new VertexGraphNode(this, 2);
 }
        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);
            }
        }