Author Topic: Problem getting an entity's ECS  (Read 355 times)

0 Members and 1 Guest are viewing this topic.

Pukawai

  • Mosquito
  • Posts: 2
Problem getting an entity's ECS
« on: January 14, 2024, 10:25:51 PM »
I wrote a little program that creates a circle on a face of a cube. To do that I need to get the ECS of the cube which Entity.ECS should do, but it just gives me WCS. I got the program to work by using Autocad to set the UCS to that of the cube entity, but I want to get the ECS directly from the entity in .net. In the attached image I've printed out the value of current UCS which was set to the cube entity, and then I print the value of the ECS i got using entity.ECS - Both these should be identical, but they're not!  Why does entity.ECS give me WCS or what am I missing here?

Code: [Select]
  <CommandMethod("testECS")>
  Public Sub testECS()
    Dim pnt1 As Point3d
    Dim cir As Circle
    Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
    Dim acCurDb As Database = acDoc.Database
    Dim ed As Editor = acDoc.Editor

    Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
      Try
        Dim acBlkTbl As BlockTable
        acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)
        Dim acBlkTblRec As BlockTableRecord
        acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite)

        Dim peo As PromptEntityOptions = New PromptEntityOptions("" & vbLf & "Select object : ")
        peo.SetRejectMessage("" & vbLf & "Invalid selection...")
        Dim pEntrs As PromptEntityResult = ed.GetEntity(peo)
        If (PromptStatus.OK <> pEntrs.Status) Then
          Return
        End If

        Dim cubeId As ObjectId = pEntrs.ObjectId
        Dim cubeEnt As Entity = CType(acTrans.GetObject(cubeId, OpenMode.ForRead), Entity)
        Dim curECS As Matrix3d = ed.CurrentUserCoordinateSystem
        Dim cubeECS As Matrix3d = cubeEnt.Ecs
        ed.WriteMessage(vbCrLf & "Current UCS: " & curECS.ToString)
        ed.WriteMessage(vbCrLf & "Cube UCS: " & cubeECS.ToString & vbCrLf)

        '' Create a circle
        pnt1 = New Point3d(0.6858, 0.6858, 0.0)
        cir = New Circle(pnt1, Vector3d.ZAxis, 0.5)
        cir.TransformBy(cubeECS)
        cir.TransformBy(curECS)
        acBlkTblRec.AppendEntity(cir)
        acTrans.AddNewlyCreatedDBObject(cir, True)
        acTrans.Commit()

      Catch ex As Exception
        ed.WriteMessage("Error: " & ex.Message)
        acTrans.Abort()
      End Try
    End Using
  End Sub

gile

  • Water Moccasin
  • Posts: 2493
  • Marseille, France
Re: Problem getting an entity's ECS
« Reply #1 on: January 15, 2024, 01:43:39 AM »
Hi,
It looks like you do not fully understand what is an ECS (or OCS). Only some 2D entities have an ECS/OCS which differ from WCS (see this topic).
I guess what you call a "cube" is a Solid3d which typically is not a 2D entity.
You'd rather explain what you want to achieve providing a DWG sample if you want some help.
Speaking English as a French Frog

Pukawai

  • Mosquito
  • Posts: 2
Re: Problem getting an entity's ECS
« Reply #2 on: January 15, 2024, 02:28:21 PM »
Thank you for your reply! Yes, you are right in that I don't fully understand ECS/OCS. I was aware of the topic you linked to that Autocad stores stores coordinates for some entities in its OCS, but on the other hand using the Autocad Command UCS | OBject will set the current UCS the that object's OCS. Since this command works for any type of entity, not just some, then every entity must have an OCS associated with it.

So what I'm trying to achieve is to get the 3D coordinate system in .net that I would get by manually using the UCS | OBject command.

Yes, the "cube" is a 3Dsolid, actually a solid inside of a block that was inserted using a GIS program to "drive" Autocad since the location and orientattion data was in GIS, but I don't have that data anymore and am trying to recreate it. The UCS | OBject command does the job, but I want to do it via .net without resorting to the brute force SendStringToExecute method  as there are hundreds of these cubes in my drawing.

gile

  • Water Moccasin
  • Posts: 2493
  • Marseille, France
Re: Problem getting an entity's ECS
« Reply #3 on: January 15, 2024, 05:27:36 PM »
Here's a command example to set the UCS on a planar face of a Solid3d.

Code - C#: [Select]
  1.         [CommandMethod("SetUcsToFace")]
  2.         public static void SetUcsToFace()
  3.         {
  4.             var doc = Application.DocumentManager.MdiActiveDocument;
  5.             var db = doc.Database;
  6.             var ed = doc.Editor;
  7.  
  8.             // Select a sub entity of a solid 3d
  9.             var options = new PromptSelectionOptions();
  10.             options.MessageForAdding = "\nSelect face of a solid";
  11.             options.SingleOnly = true;
  12.             options.SinglePickInSpace = true;
  13.             options.ForceSubSelections = true;
  14.             var filter = new SelectionFilter(new[] { new TypedValue(0, "3DSOLID") });
  15.             var result = ed.GetSelection(options, filter);
  16.             if (result.Status != PromptStatus.OK)
  17.             {
  18.                 return;
  19.             }
  20.             var selectedObject = result.Value[0];
  21.             var subSelectedObject = selectedObject.GetSubentities()[0];
  22.             var subEntityType = subSelectedObject.FullSubentityPath.SubentId.Type;
  23.  
  24.             // Check if the sub entity is a face
  25.             if (subEntityType != SubentityType.Face)
  26.             {
  27.                 ed.WriteMessage($"\nSelected sub-entity is not a Face ({subEntityType})");
  28.                 return;
  29.             }
  30.             using (var tr = db.TransactionManager.StartTransaction())
  31.             {
  32.                 var solidId = selectedObject.ObjectId;
  33.                 var solid = (Solid3d)tr.GetObject(solidId, OpenMode.ForRead);
  34.                 var subentityId = subSelectedObject.FullSubentityPath.SubentId;
  35.                 var facePath = new FullSubentityPath(new [] { solid.ObjectId }, subentityId);
  36.                 var entityPath = new FullSubentityPath(new [] { solid.ObjectId }, new SubentityId(SubentityType.Null, IntPtr.Zero));
  37.                 using (var brep = new Brep(entityPath))
  38.                 {
  39.                     var face = brep.Faces.First(f => f.SubentityPath == facePath);
  40.  
  41.                     // Check if the face is planar
  42.                     var boundedSurface = (ExternalBoundedSurface)face.Surface;
  43.                     if (!boundedSurface.IsPlane)
  44.                     {
  45.                         ed.WriteMessage($"\nSelected Face is not planar");
  46.                         return;
  47.                     }
  48.                     var plane = (Plane)boundedSurface.BaseSurface;
  49.                     var faceCoordinateSystem = Matrix3d.PlaneToWorld(plane);
  50.                     ed.CurrentUserCoordinateSystem = faceCoordinateSystem;
  51.                 }
  52.                 tr.Commit();
  53.             }
  54.         }
Speaking English as a French Frog

gile

  • Water Moccasin
  • Posts: 2493
  • Marseille, France
Re: Problem getting an entity's ECS
« Reply #4 on: January 15, 2024, 05:35:18 PM »
Or, to draw a circle on the selected face:

Code - C#: [Select]
  1.         [CommandMethod("DrawCircleOnFace")]
  2.         public static void DrawCircleOnFace()
  3.         {
  4.             var doc = Application.DocumentManager.MdiActiveDocument;
  5.             var db = doc.Database;
  6.             var ed = doc.Editor;
  7.  
  8.             // Select a sub entity of a solid 3d
  9.             var options = new PromptSelectionOptions();
  10.             options.MessageForAdding = "\nSelect face of a solid";
  11.             options.SingleOnly = true;
  12.             options.SinglePickInSpace = true;
  13.             options.ForceSubSelections = true;
  14.             var filter = new SelectionFilter(new[] { new TypedValue(0, "3DSOLID") });
  15.             var result = ed.GetSelection(options, filter);
  16.             if (result.Status != PromptStatus.OK)
  17.             {
  18.                 return;
  19.             }
  20.             var selectedObject = result.Value[0];
  21.             var subSelectedObject = selectedObject.GetSubentities()[0];
  22.             var subEntityType = subSelectedObject.FullSubentityPath.SubentId.Type;
  23.  
  24.             // Check if the sub entity is a face
  25.             if (subEntityType != SubentityType.Face)
  26.             {
  27.                 ed.WriteMessage($"\nSelected sub-entity is not a Face ({subEntityType})");
  28.                 return;
  29.             }
  30.             using (var tr = db.TransactionManager.StartTransaction())
  31.             {
  32.                 var solidId = selectedObject.ObjectId;
  33.                 var solid = (Solid3d)tr.GetObject(solidId, OpenMode.ForRead);
  34.                 var subentityId = subSelectedObject.FullSubentityPath.SubentId;
  35.                 var facePath = new FullSubentityPath(new[] { solid.ObjectId }, subentityId);
  36.                 var entityPath = new FullSubentityPath(new[] { solid.ObjectId }, new SubentityId(SubentityType.Null, IntPtr.Zero));
  37.                 using (var brep = new Brep(entityPath))
  38.                 {
  39.                     var face = brep.Faces.First(f => f.SubentityPath == facePath);
  40.  
  41.                     // Check if the face is planar
  42.                     var boundedSurface = (ExternalBoundedSurface)face.Surface;
  43.                     if (!boundedSurface.IsPlane)
  44.                     {
  45.                         ed.WriteMessage($"\nSelected Face is not planar");
  46.                         return;
  47.                     }
  48.                     var plane = (Plane)boundedSurface.BaseSurface;
  49.                     var faceCoordinateSystem = Matrix3d.PlaneToWorld(plane);
  50.                     var circle = new Circle(Point3d.Origin, Vector3d.ZAxis, 0.5);
  51.                     circle.TransformBy(faceCoordinateSystem);
  52.                     var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  53.                     curSpace.AppendEntity(circle);
  54.                     tr.AddNewlyCreatedDBObject(circle, true);
  55.                 }
  56.                 tr.Commit();
  57.             }
  58.         }
Speaking English as a French Frog