Author Topic: Pick points to 2dpoints.  (Read 8141 times)

0 Members and 1 Guest are viewing this topic.

Bryco

  • Water Moccasin
  • Posts: 1883
Pick points to 2dpoints.
« on: December 18, 2007, 12:12:24 AM »
I'm having a bit of trouble figuring out planes.
I'm picking 3d points and I want to make them 2d for polyline coords.
I presume the plane needed is the
Plane pn = new Plane(db.Ucsorg, db.Ucsxdir.CrossProduct(db.Ucsydir));
as I want to add the pline in the current ucs.
Any combo of Point2d P = Res1.Value.Convert2d(pn); or
Point2d P = Res1.Value.TransformBy(ucs).Convert2d(pn); fails with a curly Ucs
In vba one translates the points to the plines ocs using the normal.
Is it the same in c#?
(I've tried Kean Walmsley's poly jig and that doesn't work either.)
some mess around code
Code: [Select]
[CommandMethod("Dp")]
        public void PlineDraw2()
        {
           
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            Polyline oPline = new Polyline(3);
            ObjectId id = ObjectId.Null;


            Plane pn = new Plane(db.Ucsorg, db.Ucsxdir.CrossProduct(db.Ucsydir));
            //Plane pn = new Plane(db.Ucsorg, new Vector3d(0,0,1));
            Transaction tr = null;
            Matrix3d ucs = ed.CurrentUserCoordinateSystem;
            Vector3d Norm = new Vector3d(0, 0, 1).TransformBy(ucs);
            oPline.Normal = Norm;
            //oPline.Elevation = db.Ucsorg.Z;
            //oPline.Elevation = -pn.Coefficients.D;
            //ed.WriteMessage("\nelev={0}", -pn.Coefficients.D);
            //Point3d O = db.Ucsorg;
            //ed.WriteMessage("\nucsOrigin={0},{1},{2}", O.X, O.Y,O.Z);
         
            PromptPointResult Res1 = ed.GetPoint("\nSpecify start point:");
            if (Res1.Status != PromptStatus.OK) return;
            ed.WriteMessage("\nP={0},{1},{2}", Res1.Value.X, Res1.Value.Y, Res1.Value.Z);
           // Point2d P = Res1.Value.Convert2d(pn);
            Point2d  P = new Point2d(Res1.Value.X, Res1.Value.Y);
            ed.WriteMessage("\nP={0},{1}", P.X, P.Y);


             //P = Res1.Value.TransformBy(ucs).Convert2d(pn);
            //Point2d P = Res1.Value.Convert2d(pn);
            ed.WriteMessage("\nP={0},{1}", P.X, P.Y);

            oPline.AddVertexAt(0, P, 0, 0, 0);
             
   

            Point3d BasePt = Res1.Value;//.TransformBy(ucs);

            PromptPointOptions PPO = new PromptPointOptions("\nSpecify next point or [Arc]:", "Arc");
            PPO.UseBasePoint = true;
            PPO.UseDashedLine = true;
            PPO.AllowNone = true;
            PPO.BasePoint = BasePt;
            PromptPointResult Res2 = ed.GetPoint(PPO);
            if (Res2.Status != PromptStatus.OK) return;




            //P = Res2.Value.TransformBy(ucs).Convert2d(pn);
            //ed.WriteMessage("\nP={0},{1}", P.X, P.Y);
             //P = Res2.Value.Convert2d(pn);
             P = new Point2d(Res2.Value.X, Res2.Value.Y);
            oPline.AddVertexAt(1, P, 0, 0, 0);


            try    //add verticies
            {
                using (tr = db.TransactionManager.StartTransaction())
                {
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                    btr.AppendEntity(oPline);
                    tr.AddNewlyCreatedDBObject(oPline, true);
                    tr.Commit();
                    id = oPline.ObjectId;
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nError: " + ex.Message);
                tr.Abort();
            }
            finally
            {
                if (tr != null) tr.Dispose();
            }


        }



T.Willey

  • Needs a day job
  • Posts: 5251
Re: Pick points to 2dpoints.
« Reply #1 on: December 18, 2007, 01:41:19 PM »
The problem might be with your AddVertexAt method calls.  Example
Code: [Select]
            oPline.AddVertexAt(0, P, 0, 0, 0);
I think it should be
Code: [Select]
            oPline.AddVertexAt(0, P, 0.0, 0.0, 0.0);
Since it wants 'double's in those locations.
Quote
public void AddVertexAt(int index, Point2d pt, double bulge, double startWidth, double endWidth);

Only thing I can see, without running the code.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Pick points to 2dpoints.
« Reply #2 on: December 18, 2007, 04:21:09 PM »
No it runs fine and works fine in world ucs or any world ucs that has been rotated about the z

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Pick points to 2dpoints.
« Reply #3 on: December 18, 2007, 06:00:50 PM »
Here is what worked for me (plus some stuff I tried).

Edit:  Now it is not working.  Back to the drawing board.
Code: [Select]
[CommandMethod("MyTestPline")]
public void MyTestPline() {
Document Doc = AcadApp.DocumentManager.MdiActiveDocument;
Database Db = Doc.Database;
Editor Ed = Doc.Editor;
PromptPointResult ppr01 = Ed.GetPoint("\nSelect first point: ");
PromptPointOptions ppo02 = new PromptPointOptions("\nSelect second point: ");
ppo02.UseBasePoint = true;
ppo02.BasePoint = ppr01.Value;
PromptPointResult ppr02 = Ed.GetPoint(ppo02);
PromptPointOptions ppo03 = new PromptPointOptions("\nSelect last point: ");
ppo03.UseBasePoint = true;
ppo03.BasePoint = ppr02.Value;
PromptPointResult ppr03 = Ed.GetPoint(ppo03);
Ed.WriteMessage("\n1 = {0}\n2 = {1}\n3 = {2}", ppr01.Value, ppr02.Value, ppr03.Value);
Vector3d vec = new Vector3d(0,0,1).TransformBy(Ed.CurrentUserCoordinateSystem);
Plane plane = new Plane(Db.Ucsorg,vec);
Ed.WriteMessage("\n{0}", vec);
//Point2d p01 = ppr01.Value.Convert2d(plane);
//Point2d p02 = ppr02.Value.Convert2d(plane);
//Point2d p03 = ppr03.Value.Convert2d(plane);
//Point3d p01 = ppr01.Value.TransformBy(Ed.CurrentUserCoordinateSystem);
//Point3d p02 = ppr02.Value.TransformBy(Ed.CurrentUserCoordinateSystem);
//Point3d p03 = ppr03.Value.TransformBy(Ed.CurrentUserCoordinateSystem);
//Ed.WriteMessage("\n1 = {0}\n2 = {1}\n3 = {2}", p01, p02, p03);
Polyline Pline = new Polyline(3);
//Pline.AddVertexAt(0, new Point2d(p01.X, p01.Y), 0.0, 0.0, 0.0);
//Pline.AddVertexAt(0, new Point2d(p02.X, p02.Y), 0.0, 0.0, 0.0);
//Pline.AddVertexAt(0, new Point2d(p03.X, p03.Y), 0.0, 0.0, 0.0);
//Pline.AddVertexAt(0, p01, 0.0, 0.0, 0.0);
//Pline.AddVertexAt(0, p02, 0.0, 0.0, 0.0);
//Pline.AddVertexAt(0, p03, 0.0, 0.0, 0.0);
Pline.AddVertexAt(0, new Point2d(ppr01.Value.X, ppr01.Value.Y), 0.0, 0.0, 0.0);
Pline.AddVertexAt(0, new Point2d(ppr02.Value.X, ppr02.Value.Y), 0.0, 0.0, 0.0);
Pline.AddVertexAt(0, new Point2d(ppr03.Value.X, ppr03.Value.Y), 0.0, 0.0, 0.0);
Pline.Normal = vec;
using (Transaction Trans = Db.TransactionManager.StartTransaction()) {
BlockTableRecord btr = (BlockTableRecord)Trans.GetObject(Db.CurrentSpaceId, OpenMode.ForWrite);
btr.AppendEntity(Pline);
Trans.AddNewlyCreatedDBObject(Pline, true);
Trans.Commit();
}

}
« Last Edit: December 18, 2007, 06:10:46 PM by T.Willey »
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Pick points to 2dpoints.
« Reply #4 on: December 18, 2007, 07:15:19 PM »
Thanks for trying Tim.
It seems like the easiest thing (I still hope it is) but there are so many variables.
I have everything working on the polyline jig but this (The 3d part), and I thought this would be the easiest.
Although for some reason the jig gives points in world just to totally confuse you.
Perhaps using a plane is a mistake.
Theoretically if you were to pick 4 points and the returns are in Ucs then using those numbers (say the z is 0)
to input as coordinates, make the pline and transform the whole pline with the ucsmatrix you would get the correct result (It sounds good I don't know.)
That transformation is a bit like , use the 2d points to make the pline, then set the normal and the elevation (if the ucs origin was 0,0,0 this may be the same)
The normal should be the ucs crossproduct, the elevation is probably the vector distance from the ucs origin to 0,0,0.
I think if you use ppr01.Value.Convert2d(plane); you are effectively getting the res value, converting it to world, converting that back to the same plane as the ucs.

I'll work some more on it tonight, as I said in vba I make an ocs but I haven't seen that used in C# so far.

Glenn R

  • Guest
Re: Pick points to 2dpoints.
« Reply #5 on: December 19, 2007, 06:27:15 AM »
Bryco,

Is this Kean's post you're referring to?

Cheers,
Glenn.

Glenn R

  • Guest
Re: Pick points to 2dpoints.
« Reply #6 on: December 19, 2007, 08:06:14 AM »
Bryco,

That post by Kean I linked above, seems to be doing, as they say over here, 'what it says on the tin', even with really squirly rotated and twisted UCS's. I used 'vpoint' to change the the view to something really funny, the did a 'ucs v' and it all looks ok...

Cheers,
Glenn.

Fatty

  • Guest
Re: Pick points to 2dpoints.
« Reply #7 on: December 19, 2007, 08:50:19 AM »
Here is similar on what you needed
but without jigg :)

Code: [Select]
Imports System
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.GraphicsInterface
Imports Autodesk.AutoCAD.ApplicationServices.Application
Imports AcadRT = Autodesk.AutoCAD.Runtime
Imports AcadED = Autodesk.AutoCAD.EditorInput
Imports AcadDB = Autodesk.AutoCAD.DatabaseServices
Imports AcadApp = Autodesk.AutoCAD.ApplicationServices.Application

Public Class PlineUtils
    <CommandMethod("TP")> _
    Public Sub InteractPline()
        Dim adoc As Autodesk.AutoCAD.ApplicationServices.Document = AcadApp.DocumentManager.MdiActiveDocument
        Dim db As Database = adoc.Database
        Dim ed As Editor = adoc.Editor

        Dim vec As Vector3d = New Vector3d(0, 0, 1).TransformBy(ed.CurrentUserCoordinateSystem)
        Dim plane As Plane = New Plane(db.Ucsorg, vec)
        Dim res1 As PromptPointResult = ed.GetPoint(ControlChars.CrLf & "Select first point: ")

        Dim bp As Point3d = New Point3d(res1.Value.X, res1.Value.Y, res1.Value.Z)
        Dim ar As ArrayList = New ArrayList
        ar.Add(bp.X)
        ar.Add(bp.Y)
        Dim res2 As PromptPointResult
        Dim n As Integer = 0

        Do
            Dim opt As PromptPointOptions = New PromptPointOptions(ControlChars.CrLf & "Select next point: ")

            opt.AppendKeywordsToMessage = True
            opt.UseBasePoint = True
            opt.BasePoint = bp
            opt.AllowArbitraryInput = True
            opt.SetMessageAndKeywords(ControlChars.CrLf & "Select next point: " & "Or Yes to Exit [Y/N]", "Yes No")
            res2 = ed.GetPoint(opt)
            bp = New Point3d(res2.Value.X, res2.Value.Y, res2.Value.Z)
            ar.Add(bp.X)
            ar.Add(bp.Y)
            n += 1
        Loop Until res2.Status = PromptStatus.Keyword

        Dim Pline As Polyline = New Polyline(n)
        For i As Integer = 0 To ar.Count - 1 Step 2
            Pline.AddVertexAt(0, New Point2d(ar(i), ar(i + 1)), 0.0, 0.0, 0.0)
        Next i

        Pline.Normal = vec
        Pline.RemoveVertexAt(0)

        Using tr As Transaction = db.TransactionManager.StartTransaction()
            Dim btr As BlockTableRecord = CType(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
            btr.AppendEntity(Pline)
            tr.AddNewlyCreatedDBObject(Pline, True)
            tr.Commit()
        End Using

    End Sub

~'J'~

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Pick points to 2dpoints.
« Reply #8 on: December 19, 2007, 11:15:38 AM »
Glenn, yes that one.
In the dwg enclosed, if you run mypoly and trce over the rectangle you will see it doesn't line up.  Actually it only needs the elevation set and adding the code below makes it work
Code: [Select]
// Create polyline, set defaults, add dummy vertex

                Polyline pline = Entity as Polyline;

                pline.SetDatabaseDefaults();

                pline.Normal = normal;

                Plane pn = new Plane         (ucs.CoordinateSystem3d.Origin,normal);///////////////////////
                pline.Elevation = -pn.Coefficients.D;//////////////////

                AddDummyVertex();

Perhaps this will help, but all the points given from the jig are in Wcs not Ucs.

Fatty, I don't have vb (the temptation was too great). I'll put that in C# tonight and see if it works

Glenn R

  • Guest
Re: Pick points to 2dpoints.
« Reply #9 on: December 19, 2007, 03:52:36 PM »
Yep. It created the polyline exactly as i thought it would. I listed the object you have previously drawn and it gives an extrusion direction - which immediately tells me, that it's not coplanar to the current UCS.

I think you're confusing the creation (programmatically) of a polyline (lightweight - which must have all points coplanar) and going tracing over that polyline which is NOT coplanar to the current UCS in your drawing.

If you wanted to trace over that polyline you have existing, then I think you would need a 3d poly or is it Polyline3d...can't remember.

Does that make sense?

Cheers,
Glenn.

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Pick points to 2dpoints.
« Reply #10 on: December 19, 2007, 05:27:16 PM »
Dang I posted the drawing with the wrong ucs. (Stomps foot)
This one has the ucs per object.

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Pick points to 2dpoints.
« Reply #11 on: December 19, 2007, 08:55:07 PM »
Fatty thanks for trying but if below is a correct translation, it doesn't do it either .
Code: [Select]
namespace Fatty
{
   
public class PlineUtils
{
    [CommandMethod("TP")]

    public void InteractPline()
    {
        Autodesk.AutoCAD.ApplicationServices.Document adoc= AcadApp.DocumentManager.MdiActiveDocument;
        Database db= adoc.Database;
        Editor ed= adoc.Editor;
       
        Vector3d vec= new Vector3d(0, 0, 1).TransformBy(ed.CurrentUserCoordinateSystem);
        Plane plane= new Plane (db.Ucsorg, vec);
        PromptPointResult res1= ed.GetPoint( "\nSelect first point: ");

        Point3d bp= new Point3d(res1.Value.X, res1.Value.Y, res1.Value.Z);
       
        ArrayList ar= new ArrayList();
        ar.Add(bp.X);
        ar.Add(bp.Y);
        PromptPointResult res2;
        int n  = 0;
       
        do
        {
            PromptPointOptions opt= new PromptPointOptions("Select next point: ");
            opt.AppendKeywordsToMessage = true;
            opt.UseBasePoint = true;
            opt.BasePoint = bp;
            opt.AllowArbitraryInput = true;
            opt.SetMessageAndKeywords( "Select next point: Or Yes to Exit [Y/N]", "Yes No");
            res2 = ed.GetPoint(opt);
            //bp = new Point3d(res2.Value.X, res2.Value.Y, res2.Value.Z);
            bp = res2.Value;
            ar.Add(bp.X);
            ar.Add(bp.Y);
            n ++;
       
        }
        while (res2.Status != PromptStatus.Keyword);

        Polyline Pline   =new Polyline(n);
        for(int i  = 0; i< ar.Count ; i+=2)
            Pline.AddVertexAt(0, new Point2d((double)ar[i], (double)ar[i + 1]), 0.0, 0.0, 0.0);

        Pline.Normal = vec;
        Pline.RemoveVertexAt(0);
        using ( Transaction tr = db.TransactionManager.StartTransaction())
        {
            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
            btr.AppendEntity(Pline);
            tr.AddNewlyCreatedDBObject(Pline, true);
            tr.Commit();
        }
    }

   
    }
}

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Pick points to 2dpoints.
« Reply #12 on: December 19, 2007, 10:31:09 PM »
Got it. Thanks for the help all.
1) Get the current ucs
            Matrix3d ucs = ed.CurrentUserCoordinateSystem;

 2) Get the ucs normal       
            Vector3d Norm = new Vector3d(0, 0, 1).TransformBy(ucs);

3) Make a plane using 0,0,0 as the origin
            Plane pn = new Plane(new Point3d(0, 0, 0), Norm);

4) Set the pline normal           
            oPline.Normal = Norm;

5 )Set the pline elevation using the distance of the current ucs from (0,0,0)
            Plane pn2 = new Plane(ucs.CoordinateSystem3d.Origin, Norm);
            oPline.Elevation = -pn2.Coefficients.D;

6) Convert the picked point to wcs then convert it to a 2d point
            Point2d   P = Res1.Value.TransformBy(ucs).Convert2d(pn);
       

Glenn R

  • Guest
Re: Pick points to 2dpoints.
« Reply #13 on: December 20, 2007, 05:03:08 AM »
Nice one Bryco, but how on earth did you come up with it?

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Pick points to 2dpoints.
« Reply #14 on: December 20, 2007, 07:53:03 AM »
There's no math in vba as you know, so I have done this before, but I didn't know how net does it. As far as really understanding it I don't.
I wrote a sub to give  the rectangle a normal of 0,0,1 and that has the coordinates I need to put in.
Since normals and elevations are all related to 0,0,0 it makes sense to use 0,0,0 as the origin.
To check things I wrote the following
Code: [Select]
    [CommandMethod("rep")]
        public void PlineDraw4()
        {

            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptEntityResult E = ed.GetEntity("Poly");
            ObjectId id = E.ObjectId;
            Point2dCollection P = new Point2dCollection();
            Vector3d Norm = new Vector3d();
            Point2d d = new Point2d();
            double el;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {

                Polyline oPline = (Polyline)tr.GetObject(id, OpenMode.ForRead);
                Norm = oPline.Normal;
                el = oPline.Elevation;
                for (int i = 0; i < oPline.NumberOfVertices; i++)
                {
                    P.Add(oPline.GetPoint2dAt(i));
                    d = oPline.GetPoint2dAt(i);
                    ed.WriteMessage("\nP1={0},{1}", d.X, d.Y);
                }
                tr.Abort();
            }
           
            Polyline P2 = new Polyline(3);
         

            for (int i = 0; i < P.Count; i++)
            {
                P2.AddVertexAt(i, P[i], 0, 0, 0);

            }
            P2.Closed = true;
            P2.Normal = Norm;
            P2.Elevation = el;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {

                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                btr.AppendEntity(P2);
                tr.AddNewlyCreatedDBObject(P2,true);
             
                tr.Commit();
            }

        }

The 2d points (GetPoint2dAt(i)) that this prints out when you run it on the drawing provided are the same as those listed in the property box (set the ucs to wcs for this) for the rectangle with the 0,0,1 normal. Whereas the property box gives a lying ass reading for the rectangle as drawn. The 2d points should read the same no matter what the normal or elevation is.

So with a plane that cuts through 0,0,0 we have effectively layed the rectangle onto a world plane (but up or down in the z by it's elevation) so the 2d points will be true.
Ax+ By + Cz + d = 0 formula for a plane where d=-oLWP.Elevation
So the .Coefficients.D looked like the ticket.