Author Topic: How to set Custom UCS to that of Object?  (Read 4385 times)

0 Members and 1 Guest are viewing this topic.

rmdw

  • Guest
How to set Custom UCS to that of Object?
« on: May 23, 2014, 01:41:53 PM »
Imagine a 3DFACE floating in some orientation in space.  If I wanted to draw a bunch of circles on the 3DFace I would simply go into the AutoCad Editor and do this from the Command Line:   UCS Object <select object>

From that point on, every circle I drew would then be aligned in the plane of the object.

I'd like to do the same thing programmatically in C#.  I've started following this article: http://docs.autodesk.com/ACD/2013/ENU/index.html?url=files/GUID-096085E3-5AD5-4454-BF10-C9177FDB5979.htm,topicNumber=d30e730706

It's getting me going BUT I can't figure out a simple way to just specify the object's EntityID to get the UCS set accordingly.

Hoping someone might have a solution!

Robert


rmdw

  • Guest
Re: How to set Custom UCS to that of Object?
« Reply #1 on: May 23, 2014, 02:08:32 PM »
Quick Update: I just tried doing this in my code: editor.CurrentUserCoordinateSystem = entity.Ecs;

It *seems* to make sense in that it appears to set the AutoCad Editor's Current UCS to the selected entity's UCS . . . but it doesn't work! :-(

gile

  • Gator
  • Posts: 2520
  • Marseille, France
Re: How to set Custom UCS to that of Object?
« Reply #2 on: May 23, 2014, 02:19:18 PM »
Hi,

While you're not calling AutoCAD commands, you do not need to define any UCS.

Anyway, a 3d face may have 4 vertices and not be planar (this is the reason why Plane.Ecs doesn't work), so a 3d face only insures defining a plane if it has only 3 edges (i.e. the 3rd vertex is equal to the 4th). If so, you can create a Plane instance using the first vertex as origin and the cross product of the vector from 1st vertex to 2nd one and the vector from the 1st vertex to the 3rd one. Then you can create circles and transform them using the TransformBy(Matrix3d.WorldToPlane) method with the Plane instance you created.
Speaking English as a French Frog

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: How to set Custom UCS to that of Object?
« Reply #3 on: May 23, 2014, 02:34:16 PM »
Essentially, get the normal vector for the plane formed by the Face object, yes?
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

gile

  • Gator
  • Posts: 2520
  • Marseille, France
Re: How to set Custom UCS to that of Object?
« Reply #4 on: May 23, 2014, 02:46:39 PM »
Essentially, get the normal vector for the plane formed by the Face object, yes?

Exactly, but as I said, to be safe it's needed to check if the Face object is planar. A triangular Face is always planar, a quadrangular Face may not be...
Speaking English as a French Frog

rmdw

  • Guest
Re: How to set Custom UCS to that of Object?
« Reply #5 on: May 23, 2014, 02:55:46 PM »
Thanks for your suggestions!  Here's the code I have so far:

Code: [Select]
    /// <summary>
    /// Creates a temporary UCS which is aligned to the specified entity.
    /// </summary>
    /// <param name="surfaceId"></param>
    /// <param name="editor"></param>
    /// <param name="dwg"></param>
    private void CreateUCSAlignedToEntity(ObjectId surfaceId, Editor editor, Database dwg)
    {
      // We're going to make an inquiry into the drawing DB so start a transaction
      Transaction trans = editor.Document.Database.TransactionManager.StartTransaction();
      try
      {
        // Change the Current UCS to that of the 'surface' we want to draw the panels on.
        Entity entity = (Entity)trans.GetObject(surfaceId, OpenMode.ForRead);
       
        // Gather the necessary data that defines the entity's unique coordinate system
        Point3d entityOrigin = entity.GeometricExtents.MinPoint;
        Vector3d entityXaxis = entity.Ecs.CoordinateSystem3d.Xaxis;
        Vector3d entityYaxis = entity.Ecs.CoordinateSystem3d.Yaxis;

        // Get the Active Viewport
        ViewportTableRecord viewportTableRecord = (ViewportTableRecord)trans.GetObject(editor.ActiveViewportId, OpenMode.ForWrite);
        viewportTableRecord.IconAtOrigin = true;
        viewportTableRecord.IconEnabled = true;

        // Debug: Neither of these two statements properly rotates the UCS in 3D space!
        //editor.CurrentUserCoordinateSystem = entity.Ecs;
        editor.CurrentUserCoordinateSystem = Matrix3d.AlignCoordinateSystem(Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis, entityOrigin, entityXaxis, entityYaxis, entityXaxis.CrossProduct(entityYaxis));

        viewportTableRecord.SetUcs(entityOrigin, entityXaxis, entityYaxis);
        editor.UpdateTiledViewportsFromDatabase();

        trans.Commit();
      }

      catch (Autodesk.AutoCAD.Runtime.Exception ex)
      {
        editor.WriteMessage("\nError: " + ex.Message);
      }

      finally
      {
        trans.Dispose();
      }
    }

It's VERY close to working!  It actually does correctly align the X,Y of the origin to the corner of the entity.  BUT it doesn't rotate the Z-axis in 3D-space.  Think of a sloped roof for example.

I'm attaching a sample drawing that I'm testing with.

Hopefully someone can spot the bug in my code!

Robert

rmdw

  • Guest
Re: How to set Custom UCS to that of Object?
« Reply #6 on: May 23, 2014, 03:07:21 PM »
I now realize what my problem is: The 'entityYaxis' is defined incorrectly!!!  It needs to be pointing up in a 3D manner.

With C#.NET in AutoCad, how can I calculate a Vector between two 3D points?

Robert

rmdw

  • Guest
Re: How to set Custom UCS to that of Object?
« Reply #7 on: May 23, 2014, 03:33:02 PM »
My code now *seems* to be working perfectly:

Code: [Select]
    /// <summary>
    /// Creates a temporary UCS which is aligned to the specified entity.
    /// </summary>
    /// <param name="surfaceId"></param>
    /// <param name="editor"></param>
    /// <param name="dwg"></param>
    private void CreateUCSAlignedToEntity(ObjectId surfaceId, Editor editor, Database dwg)
    {
      // We're going to make an inquiry into the drawing DB so start a transaction
      Transaction trans = editor.Document.Database.TransactionManager.StartTransaction();
      try
      {
        // Change the Current UCS to that of the 'surface' we want to draw the panels on.
        Entity entity = (Entity)trans.GetObject(surfaceId, OpenMode.ForRead);
       
        // Gather the necessary data that defines the entity's unique coordinate system
        Point3d entityOrigin = entity.GeometricExtents.MinPoint;
        Point3d entityUR = entity.GeometricExtents.MaxPoint;
        Vector3d entityXaxis = entity.Ecs.CoordinateSystem3d.Xaxis;

        Point3d entityUL = new Point3d(entityOrigin.X, entityUR.Y, entityUR.Z);  // Derive the upper-left corner from the coords of the origin & upper-right corner
        Vector3d entityYaxis = new Vector3d(0, entityUL.Y - entityOrigin.Y, entityUL.Z - entityOrigin.Z);  // Calculate the 3D Y-axis of the entity

        // Get the Active Viewport
        ViewportTableRecord viewportTableRecord = (ViewportTableRecord)trans.GetObject(editor.ActiveViewportId, OpenMode.ForWrite);
        viewportTableRecord.IconAtOrigin = true;
        viewportTableRecord.IconEnabled = true;

        // Set the CurrentUCS to that of the Entity's UCS
        editor.CurrentUserCoordinateSystem = Matrix3d.AlignCoordinateSystem(Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis, entityOrigin, entityXaxis, entityYaxis, entityXaxis.CrossProduct(entityYaxis));

        viewportTableRecord.SetUcs(entityOrigin, entityXaxis, entityYaxis);
        editor.UpdateTiledViewportsFromDatabase();

        trans.Commit();
      }

      catch (Autodesk.AutoCAD.Runtime.Exception ex)
      {
        editor.WriteMessage("\nError: " + ex.Message);
      }

      finally
      {
        trans.Dispose();
      }
    }
  }