/// <summary> /// Determines whether the specified PolylineSegment instances are considered equal. /// </summary> /// <param name="obj">The object to compare.</param> /// <returns>true if the objects are considered equal; otherwise, nil.</returns> public override bool Equals(object obj) { PolylineSegment seg = obj as PolylineSegment; if (seg == null) { return(false); } if (seg.GetHashCode() != this.GetHashCode()) { return(false); } if (!_startPoint.IsEqualTo(seg.StartPoint)) { return(false); } if (!_endPoint.IsEqualTo(seg.EndPoint)) { return(false); } if (_bulge != seg.Bulge) { return(false); } if (_startWidth != seg.StartWidth) { return(false); } if (_endWidth != seg.EndWidth) { return(false); } return(true); }
private void ResolveLineType(Point2d segPt1, Point2d segPt2, List <LineSegment2d> verticalLines, List <LineSegment2d> horizontalLines) { if (!segPt1.IsEqualTo(segPt2)) { List <Point2d> pts = new List <Point2d>() { segPt1, segPt2 }; Vector2d vector = segPt2 - segPt1; if (vector.IsParallelTo(Vector2d.YAxis)) { //Это вертикальная линия pts.Sort((p1, p2) => { return(p1.Y.CompareTo(p2.Y));//Сначала нижняя, потом верхняя }); verticalLines.Add(new LineSegment2d(pts[0], pts[1])); } else if (vector.IsParallelTo(Vector2d.XAxis)) { //Это горизонтальная линия pts.Sort((p1, p2) => { return(p1.X.CompareTo(p2.X));//Сначала левая, потом правая }); horizontalLines.Add(new LineSegment2d(pts[0], pts[1])); } } }
private int GetVisiblePt(HoleInfo hi) { //Обозначения точек согласно https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf Point2d M = hi.MaxXPt; Point2d I = Point2d.Origin; int[] edge = GetEdgeOnHorizontalRay(M, out I); if (edge == null) { throw new Exception("Ошибка при определении видимой точки. Не найдено ребро, пересекающееся с горизонтальным лучем"); } int vertexOnEdgeIndex = Polygon[edge[0]].X > Polygon[edge[1]].X ? edge[0] : edge[1]; Point2d P = GetPt2DAt(vertexOnEdgeIndex); if (P.IsEqualTo(I)) { //Если точки совпали return(vertexOnEdgeIndex); } List <int> reflexPtsIndices = GetReflexVertsInTriangle(M, I, P); if (reflexPtsIndices.Count > 0) { return(GetVisiblePtFromReflexPts(M, reflexPtsIndices)); } else { return(vertexOnEdgeIndex); } }
private bool IsEar(Point2d p1, Point2d p2, Point2d p3) { foreach (LinkedListNode <int> reflVertNode in reflexVerts) { Point2d reflVert = Utils.Point2DBy3D(this.polygon[reflVertNode.Value]); double lambda1, lambda2; if (!reflVert.IsEqualTo(p1) && !reflVert.IsEqualTo(p2) && !reflVert.IsEqualTo(p3) //Если одна из точек точно совпала с другой, значит это дублирующиеся точки, появившиеся при объединении с отверстиями //Эти точки не должны влиять отбор ear && Utils.BarycentricCoordinates(reflVert, p1, p2, p3, out lambda1, out lambda2)) { //Вогнутая вершина попала в треугольник. Это не Ear return(false); } } return(true); }
/// <summary> /// Gets a value indicating whether the specified point belongs to the collection. /// </summary> /// <param name="pts">The instance to which the method applies.</param> /// <param name="pt">The point to search.</param> /// <param name="tol">The tolerance to use in comparisons.</param> /// <returns>true if the point is found; otherwise, false.</returns> public static bool Contains(this Point2dCollection pts, Point2d pt, Tolerance tol) { for (var i = 0; i < pts.Count; i++) { if (pt.IsEqualTo(pts[i], tol)) { return(true); } } return(false); }
/// <summary> /// Gets a value indicating whether the specified point belongs to the collection. /// </summary> /// <param name="pts">The instance to which the method applies.</param> /// <param name="pt">The point to search.</param> /// <param name="tol">The tolerance to use in comparisons.</param> /// <returns>true if the point is found; otherwise, false.</returns> public static bool Contains([NotNull] this Point2dCollection pts, Point2d pt, Tolerance tol) { foreach (var t in pts) { if (pt.IsEqualTo(t, tol)) { return(true); } } return(false); }
/// <summary> /// Gets a value indicating whether the specified point belongs to the collection. /// </summary> /// <param name="source">The instance to which the method applies.</param> /// <param name="pt">The point to search.</param> /// <param name="tol">The tolerance to use in comparisons.</param> /// <returns>true if the point is found; otherwise, false.</returns> public static bool Contains(this Point2dCollection source, Point2d pt, Tolerance tol) { if (source == null) { throw new ArgumentNullException("source"); } for (int i = 0; i < source.Count; i++) { if (pt.IsEqualTo(source[i], tol)) { return(true); } } return(false); }
/// <summary> /// Определение граничных точек задающих тень по отношению к расчетной точке, среди всех точек /// </summary> private IIlluminationArea GetIllumShadow(List <Point2d> points) { IIlluminationArea ilum = null; // список точек и их углов к расчетной точке var angles = new List <Tuple <Point2d, double> >(); foreach (var iPt in points) { // угол к расчетной точке (от 0 по часовой стрелке) if (!ptCalc2d.IsEqualTo(iPt)) { var angle = values.GetInsAngleFromAcad((iPt - ptCalc2d).Angle); angles.Add(new Tuple <Point2d, double>(iPt, angle)); } } if (angles.Count > 1) { angles.Sort((p1, p2) => p1.Item2.CompareTo(p2.Item2)); ilum = CreateIllumShadow(angles[0], angles[angles.Count - 1]); } return(ilum); }
protected override SamplerStatus Sampler(JigPrompts prompts) { //throw new System.Exception("The method or operation is not implemented."); if (GetPoint) { JigPromptPointOptions jppo = new JigPromptPointOptions("Select Measeared jackpanel Position : \n"); jppo.UserInputControls = (UserInputControls.Accept3dCoordinates | UserInputControls.NullResponseAccepted | UserInputControls.NoNegativeResponseAccepted); PromptPointResult ppr = prompts.AcquirePoint(jppo); if (ppr.Status == PromptStatus.OK) { Point2d NewPoint = new Point2d(ppr.Value.X, ppr.Value.Y); if (NewPoint.IsEqualTo(BasePoint)) { //v2d = new Vector2d(0, 0); return(SamplerStatus.NoChange); } else { //v2d = BasePoint - NewPoint; BasePoint = new Point2d(ppr.Value.X, ppr.Value.Y); //ed.WriteMessage("POINT OK. \n"); return(SamplerStatus.OK); } } else { //v2d = new Vector2d(0, 0); return(SamplerStatus.Cancel); } } else if (GetAngle) { JigPromptAngleOptions jpao = new JigPromptAngleOptions("Select Measured jackpanel Angle : \n"); jpao.UseBasePoint = true; jpao.BasePoint = new Point3d(BasePoint.X, BasePoint.Y, 0); PromptDoubleResult pdr = prompts.AcquireAngle(jpao); if (pdr.Status == PromptStatus.OK) { if (pdr.Value == NewAngle) { return(SamplerStatus.NoChange); } else { NewAngle = pdr.Value;// -NewAngle; return(SamplerStatus.OK); } } else { return(SamplerStatus.Cancel); } } return(SamplerStatus.NoChange); }
/// <summary> /// point1과 point2가 tolerance 오차 내에서 같은지 반환합니다. /// </summary> /// <param name="point1">비교할 점1 입니다.</param> /// <param name="point2">비교할 점2 입니다.</param> /// <param name="tolerance">같다고 볼 오차범위 입니다.</param> /// <returns></returns> public static bool IsEqualPoint(Point2d point1, Point2d point2, double tolerance) { Tolerance oTol = new Tolerance(Tolerance.Global.EqualVector, tolerance); return(point1.IsEqualTo(point2, oTol)); }
/// <summary> /// Creates a new instance of PolylineSegmentCollection from an Ellipse. /// </summary> /// <param name="ellipse">An Ellipse instance.</param> public PolylineSegmentCollection(Ellipse ellipse) { // PolylineSegmentCollection figuring the closed ellipse double pi = Math.PI; Plane plane = new Plane(Point3d.Origin, ellipse.Normal); Point3d cen3d = ellipse.Center; Point3d pt3d0 = cen3d + ellipse.MajorAxis; Point3d pt3d4 = cen3d + ellipse.MinorAxis; Point3d pt3d2 = ellipse.GetPointAtParameter(pi / 4.0); Point2d cen = cen3d.Convert2d(plane); Point2d pt0 = pt3d0.Convert2d(plane); Point2d pt2 = pt3d2.Convert2d(plane); Point2d pt4 = pt3d4.Convert2d(plane); Line2d line01 = new Line2d(pt0, (pt4 - cen).GetNormal() + (pt2 - pt0).GetNormal()); Line2d line21 = new Line2d(pt2, (pt0 - pt4).GetNormal() + (pt0 - pt2).GetNormal()); Line2d line23 = new Line2d(pt2, (pt4 - pt0).GetNormal() + (pt4 - pt2).GetNormal()); Line2d line43 = new Line2d(pt4, (pt0 - cen).GetNormal() + (pt2 - pt4).GetNormal()); Line2d majAx = new Line2d(cen, pt0); Line2d minAx = new Line2d(cen, pt4); Point2d pt1 = line01.IntersectWith(line21)[0]; Point2d pt3 = line23.IntersectWith(line43)[0]; Point2d pt5 = pt3.TransformBy(Matrix2d.Mirroring(minAx)); Point2d pt6 = pt2.TransformBy(Matrix2d.Mirroring(minAx)); Point2d pt7 = pt1.TransformBy(Matrix2d.Mirroring(minAx)); Point2d pt8 = pt0.TransformBy(Matrix2d.Mirroring(minAx)); Point2d pt9 = pt7.TransformBy(Matrix2d.Mirroring(majAx)); Point2d pt10 = pt6.TransformBy(Matrix2d.Mirroring(majAx)); Point2d pt11 = pt5.TransformBy(Matrix2d.Mirroring(majAx)); Point2d pt12 = pt4.TransformBy(Matrix2d.Mirroring(majAx)); Point2d pt13 = pt3.TransformBy(Matrix2d.Mirroring(majAx)); Point2d pt14 = pt2.TransformBy(Matrix2d.Mirroring(majAx)); Point2d pt15 = pt1.TransformBy(Matrix2d.Mirroring(majAx)); double bulge1 = Math.Tan((pt4 - cen).GetAngleTo(pt1 - pt0) / 2.0); double bulge2 = Math.Tan((pt1 - pt2).GetAngleTo(pt0 - pt4) / 2.0); double bulge3 = Math.Tan((pt4 - pt0).GetAngleTo(pt3 - pt2) / 2.0); double bulge4 = Math.Tan((pt3 - pt4).GetAngleTo(pt0 - cen) / 2.0); _contents.Add(new PolylineSegment(pt0, pt1, bulge1)); _contents.Add(new PolylineSegment(pt1, pt2, bulge2)); _contents.Add(new PolylineSegment(pt2, pt3, bulge3)); _contents.Add(new PolylineSegment(pt3, pt4, bulge4)); _contents.Add(new PolylineSegment(pt4, pt5, bulge4)); _contents.Add(new PolylineSegment(pt5, pt6, bulge3)); _contents.Add(new PolylineSegment(pt6, pt7, bulge2)); _contents.Add(new PolylineSegment(pt7, pt8, bulge1)); _contents.Add(new PolylineSegment(pt8, pt9, bulge1)); _contents.Add(new PolylineSegment(pt9, pt10, bulge2)); _contents.Add(new PolylineSegment(pt10, pt11, bulge3)); _contents.Add(new PolylineSegment(pt11, pt12, bulge4)); _contents.Add(new PolylineSegment(pt12, pt13, bulge4)); _contents.Add(new PolylineSegment(pt13, pt14, bulge3)); _contents.Add(new PolylineSegment(pt14, pt15, bulge2)); _contents.Add(new PolylineSegment(pt15, pt0, bulge1)); // if the ellipse is an elliptical arc: if (!ellipse.Closed) { double startParam, endParam; Point2d startPoint = ellipse.StartPoint.Convert2d(plane); Point2d endPoint = ellipse.EndPoint.Convert2d(plane); // index of the PolylineSegment closest to the ellipse start point int startIndex = GetClosestSegmentIndexTo(startPoint); // start point on the PolylineSegment Point2d pt = _contents[startIndex].ToCurve2d().GetClosestPointTo(startPoint).Point; // if the point is equal to the PolylineSegment end point, jump the next segment in collection if (pt.IsEqualTo(_contents[startIndex].EndPoint)) { if (startIndex == 15) { startIndex = 0; } else { startIndex++; } startParam = 0.0; } // else get the 'parameter' at point on the PolylineSegment else { startParam = _contents[startIndex].GetParameterOf(pt); } // index of the PolylineSegment closest to the ellipse end point int endIndex = GetClosestSegmentIndexTo(endPoint); // end point on the PolylineSegment pt = _contents[endIndex].ToCurve2d().GetClosestPointTo(endPoint).Point; // if the point is equals to the PolylineSegment startPoint, jump to the previous segment if (pt.IsEqualTo(_contents[endIndex].StartPoint)) { if (endIndex == 0) { endIndex = 15; } else { endIndex--; } endParam = 1.0; } // else get the 'parameter' at point on the PolylineSegment else { endParam = _contents[endIndex].GetParameterOf(pt); } // if the parameter at start point is not equal to 0.0, calculate the bulge if (startParam != 0.0) { _contents[startIndex].StartPoint = startPoint; _contents[startIndex].Bulge = _contents[startIndex].Bulge * (1.0 - startParam); } // if the parameter at end point is not equal to 1.0, calculate the bulge if (endParam != 1.0) //(endParam != 0.0) { _contents[endIndex].EndPoint = endPoint; _contents[endIndex].Bulge = _contents[endIndex].Bulge * (endParam); } // if both points are on the same segment if (startIndex == endIndex) { PolylineSegment segment = _contents[startIndex]; _contents.Clear(); _contents.Add(segment); } else if (startIndex < endIndex) { _contents.RemoveRange(endIndex + 1, 15 - endIndex); _contents.RemoveRange(0, startIndex); } else { _contents.AddRange(_contents.GetRange(0, endIndex + 1)); _contents.RemoveRange(0, startIndex); } } }
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); } }
void HatchPerimeter(ObjectId entId) { Document activeDoc = Application.DocumentManager.MdiActiveDocument; Database db = activeDoc.Database; Editor ed = activeDoc.Editor; using (Transaction tr = db.TransactionManager.StartTransaction()) { Hatch hatch = tr.GetObject(entId, OpenMode.ForRead) as Hatch; int nLoops = hatch.NumberOfLoops; double totalExternalPerimeter = 0.0; double totalInternalPerimeter = 0.0; for (int i = 0; i < nLoops; i++) { double loopLength = 0.0; HatchLoopTypes hlt = hatch.LoopTypeAt(i); HatchLoop hatchLoop = hatch.GetLoopAt(i); if ((hatch.LoopTypeAt(i) & HatchLoopTypes.Polyline) == HatchLoopTypes.Polyline) { BulgeVertexCollection bulges = hatchLoop.Polyline; int nVertices = bulges.Count; Polyline testPoly = new Polyline(nVertices); for (int vx = 0; vx < bulges.Count; vx++) { BulgeVertex bv = bulges[vx]; testPoly.AddVertexAt(vx, bv.Vertex, bv.Bulge, 1.0, 1.0); } LineSegment3d ls = new LineSegment3d(); CircularArc3d cs = new CircularArc3d(); double d = 0.0, p1 = 0.0, p2 = 1.0; for (int ver = 0; ver < nVertices - 1; ver++) { d = testPoly.GetBulgeAt(ver); if (d <= 1e-5) { ls = testPoly.GetLineSegmentAt(ver); loopLength += ls.Length; } else { Point2d v1 = new Point2d(bulges[ver].Vertex.X, bulges[ver].Vertex.Y); Point2d v2 = new Point2d(bulges[ver + 1].Vertex.X, bulges[ver + 1].Vertex.Y); if (v1.IsEqualTo(v2) == false) { cs = testPoly.GetArcSegmentAt(ver); p1 = cs.GetParameterOf(cs.StartPoint); p2 = cs.GetParameterOf(cs.EndPoint); loopLength += cs.GetLength (p1, p2, Tolerance.Global.EqualPoint); } } } } else { Curve2dCollection curves = hatchLoop.Curves; if (curves != null) { foreach (Curve2d curve in curves) { if (hatchLoop.LoopType == HatchLoopTypes.External) { totalExternalPerimeter += curve.GetLength(0.0, 1.0); } else { totalInternalPerimeter += curve.GetLength(0.0, 1.0); } } } } if (nLoops > 1 && ((hlt & HatchLoopTypes.External) != HatchLoopTypes.External)) { totalInternalPerimeter += loopLength; } else { totalExternalPerimeter += loopLength; } } ed.WriteMessage(string.Format("\nExternal Perimeter : {0}", totalExternalPerimeter)); ed.WriteMessage(string.Format("\nInternal Perimeter : {0}", totalInternalPerimeter)); tr.Commit(); } }