AutoCAD 2015 - в настоящее время я изучаю .NET API для создания геометрических ограничений (примечание: я не новичок в AutoCAD API в целом).Я работаю с примером кода, который я изучил на одном из курсов AutoDesk, и не могу понять, почему у меня возникает «ФАТАЛЬНАЯ ОШИБКА» и происходит сбой при попытке получить вершины объекта с помощью GetEdgeVertexSubentities(..)
,Исключение не выдается, Autocad просто выскакивает сообщение и вылетает.Try / Catch ничего не делает, поэтому не может проверить сообщение об исключении или стек вызовов.Если кто-то видел это раньше или имеет какие-то идеи, как то, на что я могу посмотреть или попробовать, это будет высоко оценено.
Это происходит с отладчиком и без него.Другими словами, такая же ошибка возникает при сборке релиза, запущенной с ярлыка.
Я пробовал использовать другой чертеж, другой компьютер и даже другую ОС (например, Win7, Win10), все с одинаковымиконечный результат.Приведенное ниже сообщение об ошибке и сбой.
Сообщение в окне вывода Visual Studio:
Исключение: 'System.AccessViolationException' в AcdbMgd.dll
Ивсплывающее сообщение об ошибке:
Вот полная команда теста.Оскверненная строка кода четко обозначена примерно на половине фрагмента кода.
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;
}