Author Topic: Moving entities with code in different ucs.  (Read 8251 times)

0 Members and 1 Guest are viewing this topic.

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Moving entities with code in different ucs.
« on: November 15, 2005, 08:51:41 PM »
I'm trying to move (transform) and entity in code and try as I might I can't get this to work properly.

I think it has a lot to do with the points being returned with the user input are in current ucs and are being treated as world coord' points, i.e. when you try to move an object in the 'front' ucs upwards (y direction) the entity actually moves that amount in the world y direction and not the way you picked ???

Try loading it in and drawing a circle in world ucs and 'ment' it (the command is 'ment'), everything works ok. Change ucs to front, try to 'ment' the object up or down, sideways is of course the same as world 'x' anyway.

I've tried all sorts of transforms and matrices with seemingly no change (except my state of mind  :laugh:). Here it is in it's most basic form to start with, I bet it's something simple :)

Code: [Select]
[CommandMethod("ment", CommandFlags.Modal)]
public static void MoveEntity()
{
//Set up some tools we will need here
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
Transaction tr = db.TransactionManager.StartTransaction();
try
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

//get user input of insert point and entity to move
PromptEntityResult entity = ed.GetEntity("Pick entity to translate:\n");
PromptPointResult pnt1 = ed.GetPoint("Pick base point...");
PromptPointOptions ppo = new PromptPointOptions("Pick destination point...\n");
ppo.UseBasePoint = true;
ppo.BasePoint = pnt1.Value;
PromptPointResult pnt2 = ed.GetPoint(ppo);

//get the netity
Entity ent = (Entity)tr.GetObject(entity.ObjectId,OpenMode.ForWrite);

Matrix3d mat = new Matrix3d();
Vector3d vectrans = new Vector3d();
vectrans = pnt2.Value.GetAsVector().Subtract(pnt1.Value.GetAsVector());
mat = ed.CurrentUserCoordinateSystem;
vectrans.TransformBy(mat);
mat = Matrix3d.Displacement(vectrans);
ent.TransformBy(mat);

tr.Commit();
}
catch
{
}
finally
{
tr.Dispose();
}
}
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Moving entities with code in different ucs.
« Reply #1 on: November 15, 2005, 09:20:22 PM »
Hi Mick,
Do you have Jim Awe's MgdDbg sample ?

Do any of these help :
Utils.Db.TransformToWcs();
or  XformWcsOrigin() in ModifyEntTests.cs

Dont have time for a closer look, sorry.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: Moving entities with code in different ucs.
« Reply #2 on: November 15, 2005, 09:36:04 PM »
Ooh..forgot 'bout that! I haven't looked at it since 2006 wrappers came out, has he updated them for 2006?
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: Moving entities with code in different ucs.
« Reply #3 on: November 15, 2005, 09:40:37 PM »
Scratch that ^^^ found it. :)
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: Moving entities with code in different ucs.
« Reply #4 on: November 16, 2005, 04:28:59 PM »
Ok, after thumbing through Jim's code I worked out I basically tried the same things.

Here's what I've got now, if you read the output at the command line you will notice that the vector is not being tranformed ???

Code: [Select]
[CommandMethod("ment", CommandFlags.Modal)]
public static void MoveEntity()
{
//Set up some tools we will need here
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
Transaction tr = db.TransactionManager.StartTransaction();
try
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

//get user input of insert point and entity to move
//the problem here is the points are from the ucs coordinate
//system but when applied to objects in the db, the points are
//used as if they were world coordinates
PromptEntityResult entity = ed.GetEntity("Pick entity to translate:\n");
PromptPointResult pnt1 = ed.GetPoint("Pick base point...");
PromptPointOptions ppo = new PromptPointOptions("Pick destination point...\n");
ppo.UseBasePoint = true;
ppo.BasePoint = pnt1.Value;
PromptPointResult pnt2 = ed.GetPoint(ppo);

//get the netity
Entity ent = (Entity)tr.GetObject(entity.ObjectId,OpenMode.ForWrite);

//set up the current ucs items
Point3d ucsO = db.Ucsorg;
Vector3d ucsX, ucsY, ucsZ;
ucsX = db.Ucsxdir;
ucsY = db.Ucsydir;
ucsZ = ucsX.CrossProduct(ucsY);

//set up the world ucs (wcs) items
Point3d origin = new Point3d(0,0,0);
Vector3d wcsX = new Vector3d(1, 0, 0);
Vector3d wcsY = new Vector3d(0, 1, 0);
Vector3d wcsZ = new Vector3d(0, 0, 1);

Matrix3d mat = new Matrix3d();
mat = Matrix3d.AlignCoordinateSystem(/*from*/origin,wcsX,wcsY,wcsZ,
/ * to*/ucsO,ucsX,ucsY,ucsZ);

//create vector for displacement
Vector3d vectrans = new Vector3d();
vectrans = pnt2.Value.GetAsVector().Subtract(pnt1.Value.GetAsVector());
ed.WriteMessage("vectrans before xform = " + vectrans.ToString() + "\n");

//transform the vector from wcs to our ucs
vectrans.TransformBy(mat);
ed.WriteMessage("vectrans after xform = " + vectrans.ToString() + "\n");
ed.WriteMessage("mat before xform = " + mat.ToString() + "\n");
mat = Matrix3d.Displacement(vectrans);
ed.WriteMessage("mat after xform = " + mat.ToString() + "\n");
ent.TransformBy(mat);

tr.Commit();
}
catch
{
}
finally
{
tr.Dispose();
}
}

I'll have to dig deeper.
« Last Edit: November 16, 2005, 04:33:55 PM by MickD »
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Moving entities with code in different ucs.
« Reply #5 on: November 17, 2005, 06:50:27 AM »
Have a play with this Mick.
There is a lot more here than you need, but ... too bad :)

Note that there are a lot of verbose calls to explicit namespaces.class's that could be trimmed. I Used those 'cause they help my visualisation and understanding.

I have the solution split into 2 files, one for the problem, and one Utility Helper. .. as I mentioned there is more here than needed, so lurkers needn't get too frightened by the amount of code.

Some of the functionality is based on Jim's MgdDbg Samples.

This was developed in VSC#2005 and tested in AC2006
The solution seems to work for me ..

You will see that I have been separating the type declaration and initialiser onto separate lines .. similarly the Method declarations.
This is just a formatting preference to try and keep the displayed code block at about 80 characters wide.  .. just personal style, easily changed without affecting functionality ..

The Main :..
Code: [Select]
using System;
using System.Diagnostics;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;


using kwbAC.Utils;

public class TestXMent   
{
    [CommandMethod("xment", CommandFlags.Modal)]
    public static void
    MoveEntity()
    {
        //Set up some tools
        Editor
            ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
        try
        {
            //get user input

            PromptEntityResult
                entityRes = ed.GetEntity("Select entity to translate/move:\n");
            if (entityRes.Status != PromptStatus.OK)
                return;
            //----------------------------
            PromptPointResult
                fromPointRes = ed.GetPoint("Move From point...");
            if (fromPointRes.Status != PromptStatus.OK)
                return;
            //----------------------------

            PromptPointOptions
                PPOptions = new PromptPointOptions("\nTo point or <use first point as displacement>");
            PPOptions.UseBasePoint = true;
            PPOptions.BasePoint = fromPointRes.Value;
            PPOptions.UseDashedLine = true;
            PPOptions.AllowNone = true;

            PromptPointResult
                toPointRes = ed.GetPoint(PPOptions);

            Vector3d transVec = new Vector3d();

            if (toPointRes.Status == PromptStatus.OK)
                transVec = toPointRes.Value - fromPointRes.Value;
            else if (toPointRes.Status == PromptStatus.None)
                transVec = toPointRes.Value.GetAsVector();
            else
                return;
            //----------------------------


            OutputPoints(fromPointRes.Value, toPointRes.Value);

            Mover(entityRes.ObjectId, Matrix3d.Displacement(Db.UcsToWcs(transVec)));
       
        }
        catch (System.Exception ex)
        {
            // rethrow it for now
            throw ex;
        }
        finally
        {
           //
        }
    }

    public static void
    OutputPoints(Point3d fromPoint, Point3d toPoint)
    {
        AUi.PrintToCmdLine("\nFrom Point in UCS: "
            + (AUi.PointToString(fromPoint)));
        AUi.PrintToCmdLine("\nFrom Point in WCS: "
            + (AUi.PointToString(Db.UcsToWcs(fromPoint))) + "\n");

        AUi.PrintToCmdLine("\nTo Point in UCS: "
            + (AUi.PointToString(toPoint)));
        AUi.PrintToCmdLine("\nTo Point in WCS: "
            + (AUi.PointToString(Db.UcsToWcs(toPoint))) + "\n");
    }

    public static void
    Mover(ObjectId id, Matrix3d m)
    {
        Database
            db = (id.Database);
        Autodesk.AutoCAD.DatabaseServices.TransactionManager
            tm = db.TransactionManager;
        using (Transaction
            tr = tm.StartTransaction())
        {
            Entity
                ent = (Entity)tm.GetObject(id, OpenMode.ForWrite, true);
            ent.TransformBy(m);
            tr.Commit();
        }
    }
}
The Helpers : ..
Code: [Select]
using System;
using System.Diagnostics;
using System.Collections;
using System.Text;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;


namespace kwbAC.Utils
{
    public class AUi
    {
        // User Interface Helper Constructor       
        AUi()
        {
        }
        //----------------------------         
        public static void
        PrintToCmdLine(string str)
        {
            Autodesk.AutoCAD.EditorInput.Editor
                ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
            ed.WriteMessage(str);
        }

        public static string
        PointToString(Point3d pt, DistanceUnitFormat unitType, int prec)
        {
            string x = Autodesk.AutoCAD.Runtime.Converter.DistanceToString(pt.X, unitType, prec);
            string y = Autodesk.AutoCAD.Runtime.Converter.DistanceToString(pt.Y, unitType, prec);
            string z = Autodesk.AutoCAD.Runtime.Converter.DistanceToString(pt.Z, unitType, prec);

            return string.Format("({0}, {1}, {2})", x, y, z);
        }

        public static string
        PointToString(Point3d pt)
        {
            return PointToString(pt, Autodesk.AutoCAD.Runtime.DistanceUnitFormat.Current, -1);
        }
    }
    //------------------------------------------------------------------------

    public class Db
    {
        // DataBase Helper Constructor
        public Db()
        {
        }
        //----------------------------
        public static Database
        GetCurDatabase()
        {
            Database
                db = AcadApp.DocumentManager.MdiActiveDocument.Database;
            return db;
        }

        public static Autodesk.AutoCAD.DatabaseServices.TransactionManager
        GetTransactionManager(Database db)
        {
            Autodesk.AutoCAD.DatabaseServices.TransactionManager
                tm = db.TransactionManager;
            return tm;
        }
        //----------------------------
       
        public static bool
        IsPaperSpace(Database db)
        {
            Debug.Assert(db != null);

            if (db.TileMode)
                return false;

            Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
            if (db.PaperSpaceVportId == ed.CurrentViewportObjectId)
                return true;

            return false;
        }

        public static Matrix3d
        GetUcsMatrix(Database db)
        {
            Debug.Assert(db != null);

            Point3d origin;
            Vector3d xAxis, yAxis, zAxis;

            if (IsPaperSpace(db))
            {
                origin = db.Pucsorg;
                xAxis = db.Pucsxdir;
                yAxis = db.Pucsydir;
            }
            else
            {
                origin = db.Ucsorg;
                xAxis = db.Ucsxdir;
                yAxis = db.Ucsydir;
            }

            zAxis = xAxis.CrossProduct(yAxis);

            return Matrix3d.AlignCoordinateSystem(Ge.kOrigin,
                Ge.kXAxis, Ge.kYAxis, Ge.kZAxis,
                origin, xAxis, yAxis, zAxis);
        }

        public static Point3d
        UcsToWcs(Point3d pt)
        {
            Matrix3d m = GetUcsMatrix(GetCurDatabase());

            return pt.TransformBy(m);
        }

        public static Vector3d
        UcsToWcs(Vector3d vec)
        {
            Matrix3d m = GetUcsMatrix(GetCurDatabase());

            return vec.TransformBy(m);
        }

        public static Point3d
        WcsToUcs(Point3d pt)
        {
            Matrix3d m = GetUcsMatrix(GetCurDatabase());

            return pt.TransformBy(m.Inverse());
        }
    }
    //------------------------------------------------------------------------
    public class Ge
    {
        // predefined constants for common angles
        public const double kPi = 3.14159265358979323846;
        public const double kHalfPi = 3.14159265358979323846 * 0.50;
        public const double kTwoPi = 3.14159265358979323846 * 2.00;

        public const double kRad0 = 0.0;
        public const double kRad45 = 3.14159265358979323846 * 0.25;
        public const double kRad90 = 3.14159265358979323846 * 0.50;
        public const double kRad135 = 3.14159265358979323846 * 0.75;
        public const double kRad180 = 3.14159265358979323846;
        public const double kRad270 = 3.14159265358979323846 * 1.5;
        public const double kRad360 = 3.14159265358979323846 * 2.0;

        // predefined values for common Points and Vectors
        public static readonly Point3d kOrigin = new Point3d(0.0, 0.0, 0.0);
        public static readonly Vector3d kXAxis = new Vector3d(1.0, 0.0, 0.0);
        public static readonly Vector3d kYAxis = new Vector3d(0.0, 1.0, 0.0);
        public static readonly Vector3d kZAxis = new Vector3d(0.0, 0.0, 1.0);

        // Geometry Helper Constructor
        public Ge()
        {
        }

        public static double
        RadiansToDegrees(double rads)
        {
            return rads * (180.0 / kPi);
        }

        public static double
        DegreesToRadians(double degrees)
        {
            return degrees * (kPi / 180.0);
        }
    }
}
« Last Edit: November 17, 2005, 07:29:29 AM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: Moving entities with code in different ucs.
« Reply #6 on: November 17, 2005, 04:04:57 PM »
Thanks Kerry, works good :)

Just have to find some time to sift through to find what works in your code and not in mine :D

I'll let you know as soon as I find out.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Moving entities with code in different ucs.
« Reply #7 on: November 17, 2005, 04:05:53 PM »
OT: Great sig Mick.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: Moving entities with code in different ucs.
« Reply #8 on: November 17, 2005, 05:54:30 PM »
It's all in the order of things.
This line in the code Kerry posted gave me the clue ( although I thought I was basically doing the same thing ??? )
Mover(entityRes.ObjectId, Matrix3d.Displacement(Db.UcsToWcs(transVec)));

I've replaced this-
Code: [Select]
vectrans = pnt2.Value.GetAsVector().Subtract(pnt1.Value.GetAsVector());

//transform the vector from wcs to our ucs
vectrans.TransformBy(mat);
mat = Matrix3d.Displacement(vectrans);
ent.TransformBy(mat);

with this -
Code: [Select]
Vector3d vectrans = p2.GetAsVector().Subtract(p1.GetAsVector());
ent.TransformBy(Matrix3d.Displacement(vectrans.TransformBy(mat)));

I knew it would be something simple  :roll:
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: Moving entities with code in different ucs.
« Reply #9 on: November 17, 2005, 06:46:42 PM »
OT: Great sig Mick.

Thanks MP.

I also like Se7en's -

Opportunity is missed by most people because it is dressed in overalls and looks like work. --Thomas Edison

[/OT]
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien