C#版几何约束编程实现
ObjectARX的几何约束功能,有时候还是很有用。在网上找不到.Net版本的几何约束源码。我根据C++的代码,自己写了几个C#版的几何约束方法。
方法实现的约束功能很简单,复杂的约束可以根据这个代码进一步扩展。
代码在AutoCAD2014及2015下测试过,其它版本未经测试。
源代码如下:
class geometricalConstraints
{
static public void createFixedConstraintOnMidPt4line(Line fixedLine, Database curDB, Assoc2dConstraintGroup assoc2dConsGrp)
{
Point3d fixedPt = new Point3d((fixedLine.StartPoint.X + fixedLine.EndPoint.X) / 2, (fixedLine.StartPoint.Y + fixedLine.EndPoint.Y) / 2, (fixedLine.StartPoint.Z + fixedLine.EndPoint.Z) / 2);
AssocPersSubentityIdPE pe = AssocPersSubentityIdPE.Create(fixedLine.QueryX(AssocPersSubentityIdPE.GetClass(typeof(AssocPersSubentityIdPE))), false) as AssocPersSubentityIdPE;
SubentityId[] edgeIds = pe.GetAllSubentities(fixedLine, SubentityType.Edge);
FullSubentityPath edgeFullSubentity = new FullSubentityPath(new ObjectId[] { fixedLine.ObjectId }, edgeIds);
assoc2dConsGrp.AddConstrainedGeometry(edgeFullSubentity);
FullSubentityPath closetPtFullSubentity;
getClosetVertexSubentityOfEdge(fixedLine, fixedPt, edgeIds, out closetPtFullSubentity);
FullSubentityPath[] vertexFullSubentityPaths = new FullSubentityPath[] { closetPtFullSubentity };
assoc2dConsGrp.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, vertexFullSubentityPaths);
}
static public void createFixedConstraintOnMidPt4line(ObjectId idFixedLine, Database curDB)
{
using (Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.LockDocument())
{
ObjectId consGrpId = getConstraintGroup();
if (consGrpId.IsNull) return;
using (Transaction trans = curDB.TransactionManager.StartTransaction())
{
Assoc2dConstraintGroup assoc2dConsGrp = trans.GetObject(consGrpId, OpenMode.ForWrite) as Assoc2dConstraintGroup;
if (assoc2dConsGrp == null)
{
return;
}
Line fixedLine = trans.GetObject(idFixedLine, OpenMode.ForRead) as Line;
Point3d fixedPt = new Point3d((fixedLine.StartPoint.X + fixedLine.EndPoint.X) / 2, (fixedLine.StartPoint.Y + fixedLine.EndPoint.Y) / 2, (fixedLine.StartPoint.Z + fixedLine.EndPoint.Z) / 2);
AssocPersSubentityIdPE pe = AssocPersSubentityIdPE.Create(fixedLine.QueryX(AssocPersSubentityIdPE.GetClass(typeof(AssocPersSubentityIdPE))), false) as AssocPersSubentityIdPE;
SubentityId[] edgeIds = pe.GetAllSubentities(fixedLine, SubentityType.Edge);
FullSubentityPath edgeFullSubentity = new FullSubentityPath(new ObjectId[] { idFixedLine }, edgeIds);
assoc2dConsGrp.AddConstrainedGeometry(edgeFullSubentity);
FullSubentityPath closetPtFullSubentity;
getClosetVertexSubentityOfEdge(fixedLine, fixedPt, edgeIds, out closetPtFullSubentity);
FullSubentityPath[] vertexFullSubentityPaths = new FullSubentityPath[] { closetPtFullSubentity };
assoc2dConsGrp.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, vertexFullSubentityPaths);
ObjectId idNetWork = AssocNetwork.GetInstanceFromDatabase(curDB, true, "");
if (!idNetWork.IsValid) return;
AssocNetwork network = trans.GetObject(idNetWork, OpenMode.ForWrite) as AssocNetwork;
speAssocEvaluationCallback callback = new speAssocEvaluationCallback();
network.Evaluate(callback);
trans.Commit();
}
}
}
static public void createFixedConstraintsOnPolylineStartAndEndPt(ObjectId idPolyline, Database curDB)
{
using (Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.LockDocument())
{
ObjectId consGrpId = getConstraintGroup();
if (consGrpId.IsNull) return;
using (Transaction trans = curDB.TransactionManager.StartTransaction())
{
Assoc2dConstraintGroup assoc2dConsGrp = trans.GetObject(consGrpId, OpenMode.ForWrite) as Assoc2dConstraintGroup;
if (assoc2dConsGrp == null)
{
return;
}
Polyline thePolyline = trans.GetObject(idPolyline, OpenMode.ForRead) as Polyline;
Point3d fixedStartPt = thePolyline.GetPoint3dAt(0);
Point3d fixedEndPt = thePolyline.GetPoint3dAt(thePolyline.NumberOfVertices - 1);
AssocPersSubentityIdPE pe = AssocPersSubentityIdPE.Create(thePolyline.QueryX(AssocPersSubentityIdPE.GetClass(typeof(AssocPersSubentityIdPE))), false) as AssocPersSubentityIdPE;
SubentityId[] vertexIds = pe.GetAllSubentities(thePolyline, SubentityType.Vertex);
SubentityId[] edgeIds = pe.GetAllSubentities(thePolyline, SubentityType.Edge);
FullSubentityPath startPtFullSubentity;
getClosetVertexFullSubentity(thePolyline, fixedStartPt, vertexIds, out startPtFullSubentity);
FullSubentityPath endPtFullSubentity;
getClosetVertexFullSubentity(thePolyline, fixedEndPt, vertexIds, out endPtFullSubentity);
assoc2dConsGrp.AddConstrainedGeometry(new FullSubentityPath(new ObjectId[] { idPolyline }, edgeIds));
assoc2dConsGrp.AddConstrainedGeometry(new FullSubentityPath(new ObjectId[] { idPolyline }, edgeIds));
assoc2dConsGrp.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, new FullSubentityPath[] { startPtFullSubentity });
assoc2dConsGrp.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, new FullSubentityPath[] { endPtFullSubentity });
ObjectId idNetWork = AssocNetwork.GetInstanceFromDatabase(curDB, true, "");
if (!idNetWork.IsValid) return;
AssocNetwork network = trans.GetObject(idNetWork, OpenMode.ForWrite) as AssocNetwork;
speAssocEvaluationCallback callback = new speAssocEvaluationCallback();
network.Evaluate(callback);
trans.Commit();
}
}
}
static public void createFixedLine(Line fixedLine, Database curDB, Assoc2dConstraintGroup assoc2dConsGrp)
{
Point3d fixedStartPt = fixedLine.StartPoint;
Point3d fixedEndPt = fixedLine.EndPoint;
AssocPersSubentityIdPE pe = AssocPersSubentityIdPE.Create(fixedLine.QueryX(AssocPersSubentityIdPE.GetClass(typeof(AssocPersSubentityIdPE))), false) as AssocPersSubentityIdPE;
SubentityId[] edgeIds = pe.GetAllSubentities(fixedLine, SubentityType.Edge);
FullSubentityPath edgeFullSubentity = new FullSubentityPath(new ObjectId[] { fixedLine.ObjectId }, edgeIds);
assoc2dConsGrp.AddConstrainedGeometry(edgeFullSubentity);
FullSubentityPath closetPtFullSubentity;
getClosetVertexSubentityOfEdge(fixedLine, fixedStartPt, edgeIds, out closetPtFullSubentity);
FullSubentityPath[] vertexFullSubentityPaths = new FullSubentityPath[] { closetPtFullSubentity };
assoc2dConsGrp.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, vertexFullSubentityPaths);
getClosetVertexSubentityOfEdge(fixedLine, fixedEndPt, edgeIds, out closetPtFullSubentity);
vertexFullSubentityPaths = new FullSubentityPath[] { closetPtFullSubentity };
assoc2dConsGrp.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, vertexFullSubentityPaths);
}
static public void createFixedLine(ObjectId idFixedLine, Database curDB)
{
using (Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.LockDocument())
{
ObjectId consGrpId = getConstraintGroup();
if (consGrpId.IsNull) return;
using (Transaction trans = curDB.TransactionManager.StartTransaction())
{
Assoc2dConstraintGroup assoc2dConsGrp = trans.GetObject(consGrpId, OpenMode.ForWrite) as Assoc2dConstraintGroup;
if (assoc2dConsGrp == null)
{
return;
}
Line fixedLine = trans.GetObject(idFixedLine, OpenMode.ForRead) as Line;
Point3d fixedStartPt = fixedLine.StartPoint;
Point3d fixedEndPt = fixedLine.EndPoint;
AssocPersSubentityIdPE pe = AssocPersSubentityIdPE.Create(fixedLine.QueryX(AssocPersSubentityIdPE.GetClass(typeof(AssocPersSubentityIdPE))), false) as AssocPersSubentityIdPE;
SubentityId[] edgeIds = pe.GetAllSubentities(fixedLine, SubentityType.Edge);
FullSubentityPath edgeFullSubentity = new FullSubentityPath(new ObjectId[] { idFixedLine }, edgeIds);
assoc2dConsGrp.AddConstrainedGeometry(edgeFullSubentity);
FullSubentityPath closetPtFullSubentity;
getClosetVertexSubentityOfEdge(fixedLine, fixedStartPt, edgeIds, out closetPtFullSubentity);
FullSubentityPath[] vertexFullSubentityPaths = new FullSubentityPath[] { closetPtFullSubentity };
assoc2dConsGrp.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, vertexFullSubentityPaths);
getClosetVertexSubentityOfEdge(fixedLine, fixedEndPt, edgeIds, out closetPtFullSubentity);
vertexFullSubentityPaths = new FullSubentityPath[] { closetPtFullSubentity };
assoc2dConsGrp.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, vertexFullSubentityPaths);
ObjectId idNetWork = AssocNetwork.GetInstanceFromDatabase(curDB, true, "");
if (!idNetWork.IsValid) return;
AssocNetwork network = trans.GetObject(idNetWork, OpenMode.ForWrite) as AssocNetwork;
speAssocEvaluationCallback callback = new speAssocEvaluationCallback();
network.Evaluate(callback);
trans.Commit();
}
}
}
/// <summary>
/// 在给定的edge Subentity中,搜索距离pt最近的Vertex Subentity
/// </summary>
/// <param name="fixedLine"></param>
/// <param name="pt"></param>
/// <param name="edgeSubentity"></param>
static public void getClosetVertexSubentityOfEdge(Entity fixedLine, Point3d pt, SubentityId edgeSubentity, out FullSubentityPath closetPtFullSubentity)
{
List<SubentityId> vertexSubentityIds = new List<SubentityId>(4);
AssocPersSubentityIdPE pe = AssocPersSubentityIdPE.Create(fixedLine.QueryX(AssocPersSubentityIdPE.GetClass(typeof(AssocPersSubentityIdPE))),
false) as AssocPersSubentityIdPE;
SubentityId startVertexSubentId = SubentityId.Null; ;
SubentityId endVertexSubentId = SubentityId.Null;
SubentityId[] otherVertexSubentIds = null;
pe.GetEdgeVertexSubentities(fixedLine, edgeSubentity, ref startVertexSubentId, ref endVertexSubentId, ref otherVertexSubentIds);
vertexSubentityIds.Add(startVertexSubentId);
vertexSubentityIds.Add(endVertexSubentId);
vertexSubentityIds.AddRange(otherVertexSubentIds);
double minDist = -1.0;
SubentityId closestId = SubentityId.Null;
foreach (var vertexSubent in vertexSubentityIds)
{
Point3d vertexPos;
vertexPos = pe.GetVertexSubentityGeometry(fixedLine, vertexSubent);
double dist = vertexPos.DistanceTo(pt);
if (minDist < 0 || dist < minDist)
{
minDist = dist;
closestId = vertexSubent;
}
}
closetPtFullSubentity = new FullSubentityPath(new ObjectId[] { fixedLine.ObjectId }, closestId);
}
static public void getClosetVertexFullSubentity(Entity entity, Point3d pt, SubentityId[] vertexSubentityIds, out FullSubentityPath closetPtFullSubentity)
{
AssocPersSubentityIdPE pe = AssocPersSubentityIdPE.Create(entity.QueryX(AssocPersSubentityIdPE.GetClass(typeof(AssocPersSubentityIdPE))), false) as AssocPersSubentityIdPE;
double minDist = -1.0;
SubentityId closestId = SubentityId.Null;
foreach (var vertexSubent in vertexSubentityIds)
{
Point3d vertexPos;
vertexPos = pe.GetVertexSubentityGeometry(entity, vertexSubent);
double dist = vertexPos.DistanceTo(pt);
if (minDist < 0 || dist < minDist)
{
minDist = dist;
closestId = vertexSubent;
}
}
closetPtFullSubentity = new FullSubentityPath(new ObjectId[] { entity.ObjectId }, closestId);
}
/// <summary>
/// 获取Assoc2dConstraintGroup对象。该对象位于当前活动文档的当前坐标系的oxy平面内
/// </summary>
/// <returns></returns>
static public ObjectId getConstraintGroup()
{
ObjectId idConsGrp = ObjectId.Null;
try
{
Editor activeEditor = AutoCadDatabaseOperate.m_activeDocument.Editor;
CoordinateSystem3d cs3d = activeEditor.CurrentUserCoordinateSystem.CoordinateSystem3d;
Plane currentPlane = new Plane(cs3d.Origin, cs3d.Xaxis, cs3d.Yaxis);
Database curDB = HostApplicationServices.WorkingDatabase;
//ObjectId spaceId = curDB.CurrentSpaceId;
ObjectId idNetWork = AssocNetwork.GetInstanceFromDatabase(curDB, true, "");
if (!idNetWork.IsValid) return ObjectId.Null;
using (Transaction trans = curDB.TransactionManager.StartTransaction())
{
AssocNetwork assocNetWork = trans.GetObject(idNetWork, OpenMode.ForWrite) as AssocNetwork;
foreach (ObjectId idAction in assocNetWork.GetActions)
{
if (!idAction.IsValid)
{
continue;
}
Assoc2dConstraintGroup action = trans.GetObject(idAction, OpenMode.ForRead) as Assoc2dConstraintGroup;
if (action == null) continue;
if (action.WorkPlane.IsCoplanarTo(currentPlane))
{
return idAction;
}
}
Assoc2dConstraintGroup consGrp = new Assoc2dConstraintGroup(currentPlane);
idConsGrp = curDB.AddDBObject(consGrp);
trans.AddNewlyCreatedDBObject(consGrp, true);
assocNetWork.AddAction(idConsGrp, true);
trans.Commit();
}
return idConsGrp;
}
catch
{
return idConsGrp;
}
}
}
/// <summary>
/// 几何约束执行类
/// </summary>
internal class speAssocEvaluationCallback : AssocEvaluationCallback
{
public override void BeginActionEvaluation(AssocAction action) { }
public override void BeginActionEvaluationUsingObject(AssocAction pAction, ObjectId objectId, bool objectIsGoingToBeUsed, bool objectIsGoingToBeModified, DBObject substituteObject) { }
public override bool CancelActionEvaluation()
{
return false;
}
public override void EndActionEvaluation(AssocAction action) { }
public override void EndActionEvaluationUsingObject(AssocAction action, ObjectId objectId, DBObject obj) { }
public override void SetActionEvaluationErrorStatus(AssocAction action, Autodesk.AutoCAD.Runtime.ErrorStatus errorStatus, ObjectId objectId, DBObject obj, System.IntPtr errorInfo) { }
} 支持一下分享! 厉害。。。
页:
[1]