【发布时间】:2018-11-23 08:47:57
【问题描述】:
AutoCAD 2015 - 我目前正在学习用于创建几何约束的 .NET API(注意:我一般对 AutoCAD API 并不陌生)。我正在使用从 AutoDesk 课程之一中获得的代码示例以供学习,我似乎无法弄清楚为什么在尝试使用 GetEdgeVertexSubentities(..) 检索实体的顶点时出现“致命错误”并崩溃.没有抛出异常,Autocad 只是弹出消息并崩溃。 Try/Catch 不执行任何操作,因此无法检查异常消息或调用堆栈。如果有人以前看过这个或者有一些我可以查看或尝试的想法,将不胜感激。
无论是否附加调试器,都会发生这种情况。换句话说,从快捷方式启动的发布版本也会发生同样的错误。
我尝试过使用不同的绘图、不同的计算机,甚至不同的操作系统(即 Win7、Win10),都具有相同的最终结果。下面的错误消息和崩溃。
Visual Studio 输出窗口消息:
抛出异常:AcdbMgd.dll 中的“System.AccessViolationException”
并且弹出错误信息:
这是完整的测试命令。有问题的代码行被清楚地标记,大约在代码 sn-p 的一半处。
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
[CommandMethod("TESTFIXED")]
public static void testFixedCommand()
{
Database db = Application.DocumentManager.MdiActiveDocument.Database;
Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = db.TransactionManager;
using (Transaction transaction = tm.StartTransaction())
{
// Create DB resident line
BlockTable blockTable = (BlockTable)transaction.GetObject(db.BlockTableId, OpenMode.ForRead, false);
BlockTableRecord modelSpace = (BlockTableRecord)transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false);
Entity entity = new Line(new Point3d(12, 5, 0), new Point3d(15, 12, 0));
modelSpace.AppendEntity(entity);
transaction.AddNewlyCreatedDBObject(entity, true);
AssocPersSubentityIdPE subentityIdPE;
RXClass protocolClass = AssocPersSubentityIdPE.GetClass(typeof(AssocPersSubentityIdPE));
IntPtr pSubentityIdPE = entity.QueryX(protocolClass);
if (pSubentityIdPE == IntPtr.Zero)
{
return;
}
subentityIdPE = AssocPersSubentityIdPE.Create(pSubentityIdPE, false) as AssocPersSubentityIdPE;
if (subentityIdPE == null)
{
return;
}
// Now we have the PE, we query the subentities
// First we retrieve a list of all edges (a line has one edge)
SubentityId[] edgeSubentityIds = null;
edgeSubentityIds = subentityIdPE.GetAllSubentities(entity, SubentityType.Edge);
SubentityId test = edgeSubentityIds[0];
SubentityId startSID = SubentityId.Null;
// Now we retrieve the vertices associated with the first edge in our array.
// In this case we have one edge, and the edge has three vertices - start, end and middle.
SubentityId endSID = SubentityId.Null;
SubentityId[] other = null;
//****** This next line is the offender ********
subentityIdPE.GetEdgeVertexSubentities(entity, test, ref startSID, ref endSID, ref other);
//************************************************
// The PE returns a SubEntId. We want a FullSubentityPath
FullSubentityPath subentPathEdge = new FullSubentityPath(new ObjectId[1] { entity.ObjectId }, edgeSubentityIds[0]); // The line edge
FullSubentityPath subentPath1 = new FullSubentityPath(new ObjectId[1] { entity.ObjectId }, startSID); // The edge's startpoint.
// We call a helper function to retrieve or create a constraints group
ObjectId constraintGroupID = getConstraintGroup(true);
using (Assoc2dConstraintGroup constraintGroup = (Assoc2dConstraintGroup)transaction.GetObject(constraintGroupID, OpenMode.ForWrite, false))
{
// Pass in geometry to constrain (the line edge)
ConstrainedGeometry constraintedGeometry = constraintGroup.AddConstrainedGeometry(subentPathEdge);
// Now create the constraint, a Fixed constraint applied to the line's startpoint.
FullSubentityPath[] paths = new FullSubentityPath[1] { subentPath1 };
GeometricalConstraint newConstraint = constraintGroup.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, paths);
}
// Evaluate the network to update the parameters of the constrained geometry
String temp = "";
ObjectId networkId = AssocNetwork.GetInstanceFromDatabase(db, true, temp);
using (AssocNetwork network = (AssocNetwork)transaction.GetObject(networkId, OpenMode.ForWrite, false))
{
AssocEvaluationCallback callBack = null;
network.Evaluate(callBack);
}
transaction.Commit();
}
}
要运行该命令,您还需要此辅助方法。下面的代码没有已知问题,只需复制粘贴即可。
// Helper function to retrieve (or create) constraint group
internal static ObjectId getConstraintGroup(bool createIfDoesNotExist)
{
// Calculate the current plane on which new entities are added by the editor
// (A combination of UCS and ELEVATION sysvar).
Editor editor = Application.DocumentManager.MdiActiveDocument.Editor;
Matrix3d ucsMatrix = editor.CurrentUserCoordinateSystem;
Point3d origin = ucsMatrix.CoordinateSystem3d.Origin;
Vector3d xAxis = ucsMatrix.CoordinateSystem3d.Xaxis;
Vector3d yAxis = ucsMatrix.CoordinateSystem3d.Yaxis;
Vector3d zAxis = ucsMatrix.CoordinateSystem3d.Zaxis;
origin = origin + Convert.ToDouble(Application.GetSystemVariable("ELEVATION")) * zAxis;
Plane currentPlane = new Plane(origin, xAxis, yAxis);
// get the constraint group from block table record
ObjectId ret = ObjectId.Null;
Database database = HostApplicationServices.WorkingDatabase;
ObjectId networkId = AssocNetwork.GetInstanceFromObject(SymbolUtilityServices.GetBlockModelSpaceId(database), createIfDoesNotExist, true, "");
if (!networkId.IsNull)
{
// Try to find the constraint group in the associative network
using (Transaction transaction = database.TransactionManager.StartTransaction())
{
using (AssocNetwork network = transaction.GetObject(networkId, OpenMode.ForRead, false) as AssocNetwork)
{
if (network != null)
{
// Iterate all actions in network to find Assoc2dConstraintGroups
ObjectIdCollection actionsInNetwork = network.GetActions;
for (int nCount = 0; nCount <= actionsInNetwork.Count - 1; nCount++)
{
ObjectId idAction = actionsInNetwork[nCount];
if (idAction == ObjectId.Null)
{
continue;
}
// Is this action a type of Assoc2dConstraintGroup?
if (idAction.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Assoc2dConstraintGroup))))
{
using (AssocAction action = (AssocAction)transaction.GetObject(idAction, OpenMode.ForRead, false))
{
if (action == null)
{
continue;
}
Assoc2dConstraintGroup constGrp = action as Assoc2dConstraintGroup;
// Is this the Assoc2dConstraintGroup for our plane of interest?
if (constGrp.WorkPlane.IsCoplanarTo(currentPlane))
{
// If it is then we've found an existing constraint group we can use.
ret = idAction;
break;
}
}
}
}
}
}
// If we get to here, a suitable contraint group doesn't exist, create a new one if that's what calling fn wanted.
if (ret.IsNull && createIfDoesNotExist)
{
using (AssocNetwork network = (AssocNetwork)transaction.GetObject(networkId, OpenMode.ForWrite, false))
{
// Create construction plane
Plane constraintPlane = new Plane(currentPlane);
// If model extent is far far away from origin then we need to shift
// construction plane origin within the model extent.
// (Use Pextmin, PExtmax in paper space)
Point3d extmin = database.Extmin;
Point3d extmax = database.Extmax;
if (extmin.GetAsVector().Length > 100000000.0)
{
Point3d originL = extmin + (extmax - extmin) / 2.0;
PointOnSurface result = currentPlane.GetClosestPointTo(originL);
constraintPlane.Set(result.GetPoint(), currentPlane.Normal);
}
// Create the new constraint group and add it to the associative network.
using (Assoc2dConstraintGroup constGrp = new Assoc2dConstraintGroup(constraintPlane))
{
ret = database.AddDBObject(constGrp);
}
network.AddAction(ret, true);
}
}
transaction.Commit();
}
}
return ret;
}
【问题讨论】:
标签: c# autocad autocad-plugin