Reputation: 1532
I'm trying to manipulate some lines that I've drawn using the Autocad-API with c#. I usually work with Revit, but now I'm exploring AutoCAD's API.
Long story short, I have some polyline rectangles I've split up, converted to Line2D
and now I'm trying to add them to another list however their information is not coming with them. The new list shows they are there but they have no startpoints or endpoints and this error occurs:
Exception thrown: 'System.InvalidOperationException' in AcdbMgd.dll
An exception of type 'System.InvalidOperationException' occurred in AcdbMgd.dll but was not handled in user code
Additional information: Operation is not valid due to the current state of the object.
I think it might have something to do with the block table record or perhaps having objects open for read? I am not sure. I've looked around for a bit but haven't found anyinformation on it. Also information on the BlockTableRecord seems to be....sparse in terms of how its used. I've only found this link which did a moderate job at explaining it with usage examples
Any and all help is appreciated.
Here is a shot of my 3dLineList:
Here is a shot of my new 2dLinelist:
here is my code:
// Get the current document and database, and start a transaction
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database acCurDb = doc.Database;
using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = tr.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
// Open the Block table record Model space for read
BlockTableRecord acBlkTblRec;
acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
List<Line> lineList3d = new List<Line>();
doc.Editor.WriteMessage("\nModel space objects: ");
// Step through each object in Model space and
// display the type of object found
foreach (ObjectId objId in acBlkTblRec)
{
doc.Editor.WriteMessage("\n" + objId.ObjectClass.DxfName);
if (objId.ObjectClass.DxfName == "LWPOLYLINE")
{
Polyline polyline = (Polyline)tr.GetObject(objId, OpenMode.ForRead);
for (int i = 0; i < polyline.NumberOfVertices; i++)
{
if (i != polyline.NumberOfVertices - 1)
{
Point3d pt1 = polyline.GetPoint3dAt(i);
Point3d pt2 = polyline.GetPoint3dAt(i + 1); // TODO: getting index out of range here. fix it.
UnitsConverter.GetConversionFactor(UnitsValue.Inches, UnitsValue.Feet);
var lineSegment = new Line(pt1, pt2);
lineList3d.Add(lineSegment);
}
else if (i == polyline.NumberOfVertices - 1)
{
Point3d pt1 = polyline.GetPoint3dAt(i);
Point3d pt2 = polyline.GetPoint3dAt(0);
UnitsConverter.GetConversionFactor(UnitsValue.Inches, UnitsValue.Feet);
var lineSegment = new Line(pt1, pt2);
lineList3d.Add(lineSegment);
}
}
}
else if (objId.ObjectClass.DxfName == "LINE")
{
Line line = (Line)tr.GetObject(objId, OpenMode.ForRead);
lineList3d.Add(line);
}
}
// find the other side of the wall
List<Line2d> lineList2d = new List<Line2d>();
foreach (Line xLine3d in lineList3d)
{
// convert 3dline to line2d
Plane linePlane = xLine3d.GetPlane();
Point2d line1pt1 = xLine3d.StartPoint.Convert2d(linePlane);
Point2d line1pt2 = xLine3d.EndPoint.Convert2d(linePlane);
Line2d line2d = new Line2d(line1pt1, line1pt2);
lineList2d.Add(line2d);
Debug.WriteLine("line2d: " + line2d.StartPoint); // <-- Crash occurs here
}
}
Upvotes: 1
Views: 1618
Reputation: 2493
Autodesk.AutoCAD.Geometry.Line2d represents an unbounded line (without start and end points). If you need a list of 2d linear segments (LineSegement2d), you can get them directly by using the Polyline.GetLineSegment2dAt() method.
// Get the current document and database, and start a transaction
var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
var ed = doc.Editor;
var db = doc.Database;
using (var tr = db.TransactionManager.StartTransaction())
{
// Open the Block table record for read
var bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// Open the Block table record Model space for read
var btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
var segments = new List<LineSegment2d>();
doc.Editor.WriteMessage("\nModel space objects: ");
// Step through each object in Model space and
// display the type of object found
foreach (ObjectId id in btr)
{
ed.WriteMessage("\n" + id.ObjectClass.DxfName);
if (id.ObjectClass.DxfName == "LWPOLYLINE")
{
var polyline = (Polyline)tr.GetObject(id, OpenMode.ForRead);
for (int i = 0; i < polyline.NumberOfVertices; i++)
{
if (i != polyline.NumberOfVertices - 1)
{
if (polyline.GetSegmentType(i) == SegmentType.Line)
segments.Add(polyline.GetLineSegment2dAt(i));
}
}
}
else if (id.ObjectClass.DxfName == "LINE")
{
var line = (Line)tr.GetObject(id, OpenMode.ForRead);
var linePlane = line.GetPlane();
segments.Add(new LineSegment2d(line.StartPoint.Convert2d(linePlane), line.EndPoint.Convert2d(linePlane)));
}
}
// find the other side of the wall
foreach (var segment in segments)
{
Debug.WriteLine("line2d: " + segment.StartPoint); // <-- Crash occurs here
}
Upvotes: 2
Reputation: 1532
Turns out I should have been using LineSegment2d
instead of Line2d
¯_(ツ)_/¯
Upvotes: 1