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

0 Members and 1 Guest are viewing this topic.

MickD

  • Gator
  • Posts: 3411
  • (x-in)->[process]->(y-out)
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();
}
}
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

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.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

MickD

  • Gator
  • Posts: 3411
  • (x-in)->[process]->(y-out)
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?
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

MickD

  • Gator
  • Posts: 3411
  • (x-in)->[process]->(y-out)
Re: Moving entities with code in different ucs.
« Reply #3 on: November 15, 2005, 09:40:37 PM »
Scratch that ^^^ found it. :)
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

MickD

  • Gator
  • Posts: 3411
  • (x-in)->[process]->(y-out)
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 »
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

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 »
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

MickD

  • Gator
  • Posts: 3411
  • (x-in)->[process]->(y-out)
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.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

MP

  • Seagull
  • Posts: 17653
  • 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 • Programmer Analyst • CAD Specialist
Multi-Discipline • Design • Drafting • Document Control • Automation.
cadanalyst@gmail.comwww.linkedin.com/in/cadanalyst

MickD

  • Gator
  • Posts: 3411
  • (x-in)->[process]->(y-out)
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:
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

MickD

  • Gator
  • Posts: 3411
  • (x-in)->[process]->(y-out)
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]
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”