Code Red => VB(A) => Topic started by: Bryco on April 26, 2006, 09:48:23 AM

Title: Picked point from getentity
Post by: Bryco on April 26, 2006, 09:48:23 AM
From help we have 
Variant (three-element array of doubles); output-only
A 3D WCS coordinate specifying the point that was selected

Code: [Select]
Sub GetEntPoint()
    Dim varPt As Variant, Po As AcadPoint
    Dim Ent As AcadEntity
    ThisDrawing.Utility.GetEntity Ent, varPt
    Set Po = ThisDrawing.ModelSpace.AddPoint(varPt)
    Po.Color = acMagenta
    varPt = ThisDrawing.Utility.TranslateCoordinates(varPt, acUCS, acWorld, False)
    Set Po = ThisDrawing.ModelSpace.AddPoint(varPt)
    Po.Color = acGreen
End Sub

If you run this code with a non zero origin the magenta point is not where you picked,
doesn't that mean the point is not WCS?
Title: Re: Picked point from getentity
Post by: Keith™ on April 26, 2006, 10:18:58 AM
It means that the point selected is referenced in the WCS, but the object is created in the current UCS
Title: Re: Picked point from getentity
Post by: Bryco on April 26, 2006, 11:40:19 AM
Thanks Keith
But if  I have to translate the point (the green point works) I think I'm getting a Ucs point not a Wcs.
It sure gets confusing.
Title: Re: Picked point from getentity
Post by: Keith™ on April 26, 2006, 11:51:09 AM
nope, you are getting a WCS point, but the object is placed interpreting the insertion point as a UCS point.

This is just another of the inconsistencies with the programming of AutoCAD. Try this for example ...

Set a UCS other than WCS and grab any point. That point will be WCS. Take that WCS point and apply it to a new (or edited) entity, the point you supply will be interpreted as relative to the UCS not the WCS. However, once the object is created you will find that the insertion point of the object no longer matches the WCS point as the previous point will be automatically converted to WCS upon reading from the entity.

In short, you must use UCS points when modifying or creating an insertion point, but when you read that insertion point from the object, it is read as WCS, thus the trans function
Title: Re: Picked point from getentity
Post by: Chuck Gabriel on April 26, 2006, 01:07:30 PM
I never noticed that before.  Output is in WCS.  Input is in UCS.  How ridiculous.  The worst part is the documentation for the AddPoint method is silent regarding the coordinate system for the input point (at least in 2000i).  I notice that several other methods (AddCircle for example) specify that the input point should be expressed in terms of the WCS.  I'm off now to see if the documentation is actually accurate.

Thanks for bringing that to my attention.
Title: Re: Picked point from getentity
Post by: Chuck Gabriel on April 26, 2006, 01:13:27 PM
Aha!  It is actually the documentation for GetEntity that is in error.  It does NOT return the point in WCS coordinates.  It returns it in UCS coordinates.

It's still pretty silly that input and output coordinates are not expressed using the same coordinate system.
Title: Re: Picked point from getentity
Post by: Bryco on April 26, 2006, 03:53:10 PM
Thanks guys.
I have a little pickpoint function that converts the point into a plines elevtion. I've just changed it from using the current viewport viewdirection (which requires a save to update) to using the viewdir setvar. It a was acting screwy so I had a hell of a time tracking down the problem. I thought it was in the twistangle. But now it seems to be working by feeding it the translated varpick. Am still tracking it down. This is in a class so there is plenty of cases where I can get the translations mixed up.

Code: [Select]
Private Function PickPointToPolyElevation() As Variant

 'Ax+ By + Cz + d = 0 formula for a plane where d=-oPline.Elevation
 'pickpoint is line of sight to a ucs point w/ z=zero
    Dim v, N, Dir
    Dim newV(2) As Double
    Dim dist As Double
    Dim dViewtwist As Double
    Dim dOrigin As Variant
    N = oPline.Normal 'A 3D normal unit vector in WCS. Being a unit vector it's length=1
    v = VarPick
    addpt v, , 8
    Dir = ThisDrawing.GetVariable("viewdir")
    dist = (oPline.Elevation - (v(0) * N(0)) - (v(1) * N(1)) - (v(2) * N(2))) _
                        / ((Dir(0) * N(0)) + (Dir(1) * N(1)) + (Dir(2) * N(2)))
    newV(0) = v(0) + dist * Dir(0)
    newV(1) = v(1) + dist * Dir(1)
    newV(2) = v(2) + dist * Dir(2)
    PickPointToPolyElevation = newV
   ' dViewtwist = ThisDrawing.GetVariable("Viewtwist")
    'If dViewtwist <> 0 Then
   ' Dim dAng As Double
    'dAng = Tan
    'End If
End Function

Now I'm wondering if the entsel function should always translate the pickpoint
Title: Re: Picked point from getentity
Post by: MickD on April 26, 2006, 05:40:14 PM
Yes, this had me tricked for a bit. The returned picked point is always relevant to the current coordinate system, so this means that when adding objects to the drawing db they get added using this point which puts the object at this point related to the wcs.
This means you have to invert the current ucs matrix and push the point through it to get the true position in the world CS.
The real fun is when you get say 2 points picked in a different coordinate system with different 'z' values (to draws a line say) and get those points in the right spot - including the line's normal!
Title: Re: Picked point from getentity
Post by: Bryco on April 27, 2006, 12:53:55 AM
The real fun is when
Hehe if that's fun Mick, I reckon you're probably got a vector helper,
probably all the X's in that beer you drink.
Now where am I gonna get some of that.
Title: Re: Picked point from getentity
Post by: MickD on April 27, 2006, 01:42:51 AM
heh, yeah I have a few 'helpers' :)

here's some code for the problem I described, sorry it's in C# but you should be able to follow along. There is more coded than required for clarity -
Code: [Select]
public void RotateToWorld()
                        //some tools to work with the db:
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
Transaction tr = db.TransactionManager.StartTransaction();
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                        //here we go:
//get a couple of points:
PromptPointResult pnt1 = ed.GetPoint("Pick start point (LEFT end)...");
PromptPointOptions ppo = new PromptPointOptions("Pick the end point (RIGHT end):\n");
ppo.UseBasePoint = true;
ppo.BasePoint = pnt1.Value;
PromptPointResult pnt2 = ed.GetPoint(ppo);

//transform picked points to wcs:
Point3d startPoint = pnt1.Value;
Point3d endPoint = pnt2.Value;
Matrix3d newmat = new Matrix3d();
if(ed.CurrentUserCoordinateSystem != Matrix3d.Identity)
//current ucs
Point3d curOrigin = db.Ucsorg;
Vector3d xx, xy, xz;
xx = db.Ucsxdir;
xy = db.Ucsydir;
xz = db.Ucsxdir.CrossProduct(db.Ucsydir);

//trans ucs points to wcs matrix, as points are relevant to current
//ucs (ie. if plotted they would be relevant to wcs),
//they need to be xformed from wcs to current ucs picked positions:
newmat = Matrix3d.AlignCoordinateSystem(
/*from wcs(points really relative to ucs)*/
new Point3d(0.0,0.0,0.0),
/*to ucs position*/
//transform the picked points to 'proper' ucs positions:
startPoint = startPoint.TransformBy(newmat);
endPoint = endPoint.TransformBy(newmat);
//Build some vec's to help create the line:
Vector3d vec = new Vector3d();
vec = startPoint.GetVectorTo(endPoint);
Vector3d xAxis = vec.GetNormal(Tolerance.Global);
Vector3d zAxis = db.Ucsydir.CrossProduct(xAxis);

//create a line and add it to the db, we have already
//xformed our points, just need to assign proper normal:
Line line = new Line(startPoint,endPoint);
line.Normal = zAxis;
//add it to the db:


<edit - fixed zaxis calc>