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); } }