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

From help we have
PickedPoint
Variant (threeelement array of doubles); outputonly
A 3D WCS coordinate specifying the point that was selected
.
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?

It means that the point selected is referenced in the WCS, but the object is created in the current UCS

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.

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

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.

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.

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.
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

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!

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.

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 
[CommandMethod("MYLINE")]
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:
try
{
//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),
Vector3d.XAxis,
Vector3d.YAxis,
Vector3d.ZAxis,
/*to ucs position*/
curOrigin,
xx,
xy,
xz);
//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:
btr.AppendEntity(line);
tr.AddNewlyCreatedDBObject(line,true);
tr.Commit();
}
catch
{
ed.WriteMessage("\nOoops!...");
}
finally
{
tr.Dispose();
}
}
<edit  fixed zaxis calc>