明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 2638|回复: 2

C#版几何约束编程实现

  [复制链接]
发表于 2014-11-24 10:08:53 | 显示全部楼层 |阅读模式
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[0]);
                         assoc2dConsGrp.AddConstrainedGeometry(edgeFullSubentity);
                         FullSubentityPath closetPtFullSubentity;
                         getClosetVertexSubentityOfEdge(fixedLine, fixedPt, edgeIds[0], 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[0]);
                                         assoc2dConsGrp.AddConstrainedGeometry(edgeFullSubentity);
                                         FullSubentityPath closetPtFullSubentity;
                                         getClosetVertexSubentityOfEdge(fixedLine, fixedPt, edgeIds[0], 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[0]));
                                         assoc2dConsGrp.AddConstrainedGeometry(new FullSubentityPath(new ObjectId[] { idPolyline }, edgeIds[edgeIds.Length - 1]));

                                         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[0]);
                         assoc2dConsGrp.AddConstrainedGeometry(edgeFullSubentity);
                         FullSubentityPath closetPtFullSubentity;
                         getClosetVertexSubentityOfEdge(fixedLine, fixedStartPt, edgeIds[0], out closetPtFullSubentity);
                         FullSubentityPath[] vertexFullSubentityPaths = new FullSubentityPath[] { closetPtFullSubentity };
                         assoc2dConsGrp.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, vertexFullSubentityPaths);

                         getClosetVertexSubentityOfEdge(fixedLine, fixedEndPt, edgeIds[0], 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[0]);
                                         assoc2dConsGrp.AddConstrainedGeometry(edgeFullSubentity);
                                         FullSubentityPath closetPtFullSubentity;
                                         getClosetVertexSubentityOfEdge(fixedLine, fixedStartPt, edgeIds[0], out closetPtFullSubentity);
                                         FullSubentityPath[] vertexFullSubentityPaths = new FullSubentityPath[] { closetPtFullSubentity };
                                         assoc2dConsGrp.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, vertexFullSubentityPaths);

                                         getClosetVertexSubentityOfEdge(fixedLine, fixedEndPt, edgeIds[0], 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) { }
         }
发表于 2019-8-29 15:15:38 | 显示全部楼层
支持一下分享!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 04:49 , Processed in 0.153720 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表