cairunbin 发表于 2014-11-24 10:08:53

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) { }
         }

Leo1980 发表于 2019-8-29 15:15:38

支持一下分享!

天之如一 发表于 昨天 10:48

厉害。。。
页: [1]
查看完整版本: C#版几何约束编程实现