| name | acad-polylines |
| description | Polyline, Polyline2d, Polyline3d — vertices, bulges, area, type conversion |
AutoCAD Polylines
Use this skill when creating, reading, or modifying polylines — lightweight polylines (Polyline / LWPOLYLINE), 2D polylines (Polyline2d), 3D polylines (Polyline3d), vertex manipulation, bulge values, and curve extraction.
Polyline (Lightweight / LWPOLYLINE)
Creating a Polyline
Polyline polyline = new Polyline();
polyline.Layer = layerName;
for (int i = 0; i < points.Count; i++)
{
Point2d pt = points[i];
double bulge = i < bulges.Count ? bulges[i] : 0.0;
polyline.AddVertexAt(i, pt, bulge, 0.0, 0.0);
}
polyline.ColorIndex = 256;
BlockTableRecord ms = (BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
ms.AppendEntity(polyline);
tr.AddNewlyCreatedDBObject(polyline, true);
Reading Vertices
Polyline pline = tr.GetObject(entityId, OpenMode.ForRead) as Polyline;
int count = pline.NumberOfVertices;
for (int i = 0; i < count; i++)
{
Point2d pt = pline.GetPoint2dAt(i);
Point3d pt3d = pline.GetPoint3dAt(i);
double bulge = pline.GetBulgeAt(i);
double startW = pline.GetStartWidthAt(i);
double endW = pline.GetEndWidthAt(i);
}
Modifying Vertices
pline.UpgradeOpen();
pline.SetPointAt(2, new Point2d(10.0, 20.0));
pline.SetBulgeAt(2, 0.5);
pline.SetStartWidthAt(2, 0.0);
pline.SetEndWidthAt(2, 1.0);
pline.AddVertexAt(3, new Point2d(15.0, 25.0), 0.0, 0.0, 0.0);
pline.RemoveVertexAt(3);
Bulge Values
The bulge value at vertex i defines the arc from vertex i to vertex i+1:
bulge = tan(includedAngle / 4)
| Bulge | Meaning |
|---|
0.0 | Straight segment |
> 0 | Counter-clockwise arc |
< 0 | Clockwise arc |
1.0 | Semicircle (180°) CCW |
-1.0 | Semicircle (180°) CW |
0.4142 | 90° arc CCW |
-0.4142 | 90° arc CW |
Calculating Bulge
double bulge = Math.Tan(includedAngle / 4.0);
double angle = 4.0 * Math.Atan(Math.Abs(bulge));
Polyline as Curve
Polyline inherits from Curve. All Curve methods are available.
Curve Methods
Point3d pt = pline.GetPointAtDist(50.0);
double dist = pline.GetDistAtPoint(pt);
Point3d closest = pline.GetClosestPointTo(testPoint, false);
Vector3d tangent = pline.GetFirstDerivative(pline.GetParameterAtPoint(pt));
Offset and Split
DBObjectCollection offsets = pline.GetOffsetCurves(2.5);
foreach (DBObject obj in offsets)
{
Entity offsetEnt = (Entity)obj;
ms.AppendEntity(offsetEnt);
tr.AddNewlyCreatedDBObject(offsetEnt, true);
}
DBObjectCollection pieces = pline.GetSplitCurves(
new Point3dCollection { splitPoint });
pline.ReverseCurve();
Segment-Level Access
for (int i = 0; i < pline.NumberOfVertices - 1; i++)
{
SegmentType segType = pline.GetSegmentType(i);
if (segType == SegmentType.Line)
{
LineSegment2d lineSeg = pline.GetLineSegment2dAt(i);
double length = lineSeg.Length;
}
else if (segType == SegmentType.Arc)
{
CircularArc2d arcSeg = pline.GetArcSegment2dAt(i);
double radius = arcSeg.Radius;
Point2d center = arcSeg.Center;
}
}
SegmentType Enum
SegmentType.Line — straight segment
SegmentType.Arc — arc segment
SegmentType.Coincident — zero-length segment (coincident vertices)
SegmentType.Point — degenerate segment
SegmentType.Empty — no segment
Polyline2d (Heavy / DXF "POLYLINE")
Polyline2d vertices are separate database objects (Vertex2d) owned by the polyline.
Creating Polyline2d
Point3dCollection pts = new Point3dCollection
{
new Point3d(0, 0, 0),
new Point3d(10, 0, 0),
new Point3d(10, 10, 0)
};
Polyline2d pline2d = new Polyline2d(Poly2dType.SimplePoly, pts, 0.0, false, 0.0, 0.0, null);
ms.AppendEntity(pline2d);
tr.AddNewlyCreatedDBObject(pline2d, true);
Iterating Polyline2d Vertices
Polyline2d pline2d = tr.GetObject(entityId, OpenMode.ForRead) as Polyline2d;
foreach (ObjectId vertexId in pline2d)
{
Vertex2d vertex = tr.GetObject(vertexId, OpenMode.ForRead) as Vertex2d;
if (vertex == null) continue;
Point3d position = vertex.Position;
double bulge = vertex.Bulge;
double startWidth = vertex.StartWidth;
double endWidth = vertex.EndWidth;
}
Polyline3d
Polyline3d vertices are separate database objects (PolylineVertex3d) with full 3D coordinates.
Creating Polyline3d
Point3dCollection pts = new Point3dCollection
{
new Point3d(0, 0, 0),
new Point3d(10, 0, 5),
new Point3d(20, 10, 10)
};
Polyline3d pline3d = new Polyline3d(Poly3dType.SimplePoly, pts, false);
ms.AppendEntity(pline3d);
tr.AddNewlyCreatedDBObject(pline3d, true);
Iterating Polyline3d Vertices
Polyline3d pline3d = tr.GetObject(entityId, OpenMode.ForRead) as Polyline3d;
foreach (ObjectId vertexId in pline3d)
{
PolylineVertex3d vertex = tr.GetObject(vertexId, OpenMode.ForRead) as PolylineVertex3d;
if (vertex == null) continue;
Point3d position = vertex.Position;
}
Handling All Polyline Types
When processing an entity that could be any polyline type, use a cascade pattern:
private static List<Point3d> GetVertices(Entity entity, Transaction tr)
{
List<Point3d> points = new List<Point3d>();
Polyline pline = entity as Polyline;
if (pline != null)
{
for (int i = 0; i < pline.NumberOfVertices; i++)
points.Add(pline.GetPoint3dAt(i));
}
else
{
Polyline2d pline2d = entity as Polyline2d;
if (pline2d != null)
{
foreach (ObjectId vId in pline2d)
{
Vertex2d v = tr.GetObject(vId, OpenMode.ForRead) as Vertex2d;
if (v != null) points.Add(v.Position);
}
}
else
{
Polyline3d pline3d = entity as Polyline3d;
if (pline3d != null)
{
foreach (ObjectId vId in pline3d)
{
PolylineVertex3d v = tr.GetObject(vId, OpenMode.ForRead) as PolylineVertex3d;
if (v != null) points.Add(v.Position);
}
}
}
}
return points;
}
Common Recipes
Join Polylines
pline.UpgradeOpen();
pline.JoinEntities(new Entity[] { otherPline1, otherPline2 });
Reverse Direction
pline.UpgradeOpen();
pline.ReverseCurve();
Convert Polyline to Point Collection
Point3dCollection points = new Point3dCollection();
for (int i = 0; i < pline.NumberOfVertices; i++)
points.Add(pline.GetPoint3dAt(i));
Spline Fit a Polyline2d
pline2d.UpgradeOpen();
pline2d.ConvertToPolyType(Poly2dType.CubicSplinePoly);
Gotchas
- Polyline (LWPOLYLINE) stores 2D vertices only — Z comes from the
Elevation property
- Polyline vertices are in OCS (object coordinate system), not WCS — convert with
Matrix3d.WorldToPlane(Normal) if the normal is not ZAxis
AddVertexAt index must be 0 to NumberOfVertices inclusive — index = NumberOfVertices appends
RemoveVertexAt on a polyline with only 2 vertices throws — erase the entity instead
- Polyline2d and Polyline3d vertices are separate database objects — must open each via transaction
- DXF name
"LWPOLYLINE" = Polyline class; "POLYLINE" = Polyline2d or Polyline3d — check the managed type to distinguish
GetOffsetCurves returns DBObjectCollection — results may not be Polyline (could be individual curves for complex offsets)
Area only works on closed polylines in a plane — throws for non-planar 3D polylines
- Bulge at vertex
i defines the arc from vertex i to vertex i+1 (not centered on vertex i)
Closed = true adds a segment from last to first vertex — does not duplicate the first point
JoinEntities requires contiguous endpoints within Application.DocumentManager.MdiActiveDocument.Database.EqualPoint tolerance
- Polyline2d
foreach yields ObjectIds of all sub-entities including fit/spline vertices — check VertexType to filter
ConvertToPolyType on Polyline2d is destructive — original vertices become control/fit points
Related Skills
acad-geometry — Point2d/Point3d construction, bulge math, CircularArc2d from arc segments
acad-editor-input — selecting polylines with GetEntity or selection filters (DxfCode.Start "LWPOLYLINE")
acad-layers — setting polyline layer, reading layer properties
acad-hatches — polylines as hatch boundary loops (AppendLoop with entity IDs or vertex+bulge arrays)