Author Topic: Draw polyline like autocad...  (Read 19798 times)

0 Members and 1 Guest are viewing this topic.

dann.boy.001

  • Guest
Draw polyline like autocad...
« on: June 19, 2009, 07:27:13 AM »
Hello

I try to solve one problem, but without sucess :-(.

I want to make progmaticaly drawing polyline (bulge=0) like autocad do with vb.net.

For each next picked point on polyline entity are added new segment.

I found on this forum example, but in that case only when we finish to draw
polyline is visible.

I need that polyline is visible while we draw.

Best regards

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel
Re: Draw polyline like autocad...
« Reply #1 on: June 19, 2009, 07:20:39 PM »
Have you tried using a jig?

dann.boy.001

  • Guest
Re: Draw polyline like autocad...
« Reply #2 on: June 19, 2009, 07:28:23 PM »
Have you tried using a jig?

Yes,

I solved it with jig, but when draw polyline flicking...
I want to reduce flick...

Thanks...

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Draw polyline like autocad...
« Reply #3 on: June 19, 2009, 07:36:23 PM »
Welcome to theSwamp Danijel :)
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.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Draw polyline like autocad...
« Reply #4 on: June 19, 2009, 07:38:06 PM »
Danijel,
Can you post the code you've used ?

Which ACAD Version are you using ?
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.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel

dann.boy.001

  • Guest
Re: Draw polyline like autocad...
« Reply #6 on: June 19, 2009, 07:55:47 PM »
Danijel,
Can you post the code you've used ?

Which ACAD Version are you using ?


Thank you Kerry :-)

I am using 2009.

Code is raw, I will post tomorow.

Best regards

dann.boy.001

  • Guest
Re: Draw polyline like autocad...
« Reply #7 on: June 19, 2009, 07:58:59 PM »
Also, have you tried this?

http://through-the-interface.typepad.com/through_the_interface/2006/11/advanced_jiggin.html

Yes, in that post Kean all polyline segments draw with jigs.

It is not good solution. Because for drawing time we can see
flick on drawing...

Autocad draw segment by segment...and jig only last segment
until user not pick next point...

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Draw polyline like autocad...
« Reply #8 on: June 19, 2009, 08:06:09 PM »

Danijel ,

For that type of dynamic situation you could :

Draw Lines Saving the 2dPoints, using a getpoint with a baspoint defined.
When the input is complete, delete the lines and draw the polyline from the saved point list

... perhaps ?

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

dann.boy.001

  • Guest
Re: Draw polyline like autocad...
« Reply #9 on: June 19, 2009, 08:15:45 PM »

Danijel ,

For that type of dynamic situation you could :

Draw Lines Saving the 2dPoints, using a getpoint with a baspoint defined.
When the input is complete, delete the lines and draw the polyline from the saved point list

... perhaps ?

/// kdub

It can be one of solutions, thank you...

Idea is good.

I will try to find some solution to
draw segment by segment of polyline.
Every next time to add next vertice...

But, If I dont find solution I will use
your method...

Thanks...
In

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Draw polyline like autocad...
« Reply #10 on: June 24, 2009, 02:50:02 AM »
Code: [Select]
//Polylines/////////////////////////////////////////////////////////////////////////////


        public class PlineJiggy
    {

            public class PolyArcJiggy
            {

                public class PolyArcJig : EntityJig
                {
                    public Point2d startP, endP, SecondPt2d;
                    private Vector3d Norm, ViewDir, firstderiv;
                    private double Elev;
                    private Plane pn;
                    private Point3d BasePt, SecondPt, Cen3d;
                    public Point3d endP3d;
                    public double bulge;
                    public int i, iVertex;
                    private PromptPointResult dres;
                    private bool bCurve, bSecondPt;
                    private Matrix3d ucs;
                    private string jPrompts, keywords;
                    private Polyline oPline;

                    public PolyArcJig(double El, Vector3d norm, Point3d basept,
                        Point2d P, Matrix3d Ucs, Plane Pn, Vector3d Viewdir, Vector3d FirstDeriv,
                        string jigPrompts, string Keywords, bool BCurve, bool bSecond)
                        : base(new Polyline())
                    {
                        ucs = Ucs; pn = Pn; ViewDir = Viewdir;
                        Norm = norm; Elev = El;
                        jPrompts = jigPrompts; keywords = Keywords;
                        BasePt = basept; startP = P;
                        bCurve = BCurve;
                        bSecondPt = bSecond;
                        oPline = (Polyline)Entity;
                        oPline.Elevation = El;
                        oPline.Normal = norm;
                        oPline.AddVertexAt(0, startP, 0, 0, 0);
                        oPline.AddVertexAt(1, startP, 0, 0, 0);

                        if (bCurve)
                        {
                            firstderiv = FirstDeriv;
                            if (bSecondPt)
                            {
                                SecondPt = new Point3d(firstderiv.ToArray());
                                SecondPt2d = SecondPt.Convert2d(pn);
                            }
                        }
                    }


                    protected override SamplerStatus Sampler(JigPrompts prompts)
                    {

                        JigPromptPointOptions jigOpts = new JigPromptPointOptions();
                        jigOpts.UserInputControls = (UserInputControls.Accept3dCoordinates) |
                        UserInputControls.NullResponseAccepted;
                        if (bSecondPt | jPrompts == "\nSpecify end point of arc:")
                            jigOpts.Message = jPrompts;

                        else
                            jigOpts.SetMessageAndKeywords(jPrompts, keywords);
                        jigOpts.BasePoint = BasePt;

                        jigOpts.UseBasePoint = true;
                        dres = prompts.AcquirePoint(jigOpts);

                        if (dres.Status == PromptStatus.None)
                            return SamplerStatus.Cancel;
                        if (dres.Status == PromptStatus.Keyword)
                        {
                            return SamplerStatus.OK;
                        }

                        //CheckPoint(Elev, ucs, ViewDir, dres.Value.TransformBy(ucs.Inverse()), ref endP3d);
                        Point3d p3d = dres.Value;
                        double mult = (Elev - (p3d.X * Norm.X) - (p3d.Y * Norm.Y) - (p3d.Z * Norm.Z)) /
                                                   ((ViewDir.X * Norm.X) + (ViewDir.Y * Norm.Y) + (ViewDir.Z * Norm.Z));
                        endP3d = p3d.Add(ViewDir.MultiplyBy(mult));

                        Point2d endPointTemp = endP3d.Convert2d(pn);
                        if (endPointTemp != endP)
                        {
                            endP = endPointTemp;
                        }
                        else
                        {
                            return SamplerStatus.NoChange;
                        }
                        if (dres.Status == PromptStatus.Cancel)
                            return SamplerStatus.Cancel;
                        else
                            return SamplerStatus.OK;

                    }//End sampler



                    protected override bool Update()
                    {
                        try
                        {
                            if (bCurve)
                            {
                                Point2d Cen;
                                if (bSecondPt)
                                {
                                    Cen3d = Util.MyMath.CenterFrom3Pts(BasePt, SecondPt, endP3d);
                                    Cen = Cen3d.Convert2d(pn);
                                    double Ang = (startP - Cen).GetAngleTo(endP - Cen);
                                    int isCenterLeft = Util.MyMath.isLeft(startP, endP, Cen);
                                    int isSecondPtLeft = Util.MyMath.isLeft(startP, endP, SecondPt2d);
                                    ////-1 means P is right of the line (CCW)

                                    if (isCenterLeft == isSecondPtLeft)
                                        Ang = 2 * Math.PI - Ang;
                                        //arc angle > 180 deg
                                       
                                    bulge = Math.Tan( Ang / 4);
                                    if (isSecondPtLeft == 1) bulge = -bulge;
                                }
                                else
                                {
                                    Vector2d vCen = firstderiv.Convert2d(pn);
                                    double Ang = vCen.GetAngleTo(startP.GetVectorTo(endP));
                                    bulge = Math.Tan(Ang / 2);
                                    if (Util.MyMath.isLeft(startP, endP, startP.Add(vCen)) == 1)
                                        bulge = -bulge;
                                }
                                ((Polyline)Entity).SetBulgeAt(0, bulge);
                            }
                            ((Polyline)Entity).SetPointAt(1, endP);
                        }
                        catch (System.Exception)
                        {
                            return false;
                        }
                        return true;

                    }//End Update



                    public PromptPointResult Res()
                    {
                        return dres;
                    }


                    public int MinusPlus()
                    {
                        return -i;
                    }


                    public Entity GetEntity()
                    {
                        return Entity;
                    }

                }// class PolyArcJig



                public static bool CheckPoint(double Elev, Matrix3d ucs, Vector3d v, Point3d ucsPt, ref Point3d p3d)
                {
                    //Input the point in ucs and the byref output is in wcs
                    Point3d P = ucsPt;
                    if (Math.Abs(P.Z) < 0.000001)
                    {
                        P = new Point3d(P.X, P.Y, 0);
                        p3d = P.TransformBy(ucs);
                        return false;
                    }
                    p3d = ucsPt.TransformBy(ucs);
                    Vector3d Norm = ucs.CoordinateSystem3d.Zaxis;
                    double mult = (Elev - (p3d.X * Norm.X) - (p3d.Y * Norm.Y) - (p3d.Z * Norm.Z)) /
                                               ((v.X * Norm.X) + (v.Y * Norm.Y) + (v.Z * Norm.Z));
                    p3d = p3d.Add(v.MultiplyBy(mult));
                    return true;
                }




                #region Command Declarations

                [CommandMethod("DPl")]
                public void PlineDraw()
                {
                    Document doc = acadApp.DocumentManager.MdiActiveDocument;
                    Database db = doc.Database;
                    Editor ed = doc.Editor;
                    Matrix3d ucs = ed.CurrentUserCoordinateSystem;
                    CoordinateSystem3d cs = ucs.CoordinateSystem3d;
                    Vector3d Norm = cs.Zaxis;

                    Plane pn = new Plane(cs.Origin, Norm);
                    double Elev = -pn.Coefficients.D;
                    pn = new Plane(Point3d.Origin, Norm);
                    Polyline oPline = new Polyline();

                    ViewTableRecord vtr = ed.GetCurrentView();
                    Vector3d Viewdirection = vtr.ViewDirection.GetNormal();

                    double lastAngle = (double)acadApp.GetSystemVariable("LASTANGLE");
                    Vector3d FirstDeriv = new Vector3d(1, Math.Tan(lastAngle), 0);

                    //Get the first point
                    PromptPointResult Pres = ed.GetPoint("\nSpecify start point:");
                    if (Pres.Status != PromptStatus.OK) return;
                    Point3d BasePt = Pres.Value.TransformBy(ucs);
                    Point2d startP = BasePt.Convert2d(pn);
                    Point2d EndPt;
                    oPline.Normal = Norm;
                    oPline.Elevation = Elev;
                    oPline.AddVertexAt(0, startP, 0, 0, 0);
                    int iVertex = 1;
                    PromptResult res;
                    string prompt = "\nSpecify next point or [Arc]:";
                    string keywords = "Arc";

                    bool bCurve = false, bSecond = false;

                    ObjectId id = ObjectId.Null;
                    double Bulge = 0;
                    PolyArcJig jig;
                    Transaction tr = null;

                    do
                    {
                        jig = new PolyArcJig(Elev, Norm, BasePt, startP, ucs, pn,
                            Viewdirection, FirstDeriv, prompt, keywords, bCurve, bSecond);
                        res = ed.Drag(jig);
                        if (res.Status == PromptStatus.Cancel) return;
                        if (res.Status == PromptStatus.Keyword)
                        {
                            using (tr = db.TransactionManager.StartTransaction())
                            {
                                switch (res.StringResult)
                                {
                                    //case "Angle":
                                    //    //Todo
                                    //    break;
                                    case "Arc":
                                        prompt =
                                        "\nSpecify next point or [Close/Line/Second pt/Undo]:";
                                        keywords = "Close Line Second Undo";


                                        bCurve = true;
                                        if (iVertex > 1)
                                            FirstDeriv = oPline.GetFirstDerivative
                                                (oPline.NumberOfVertices - 1);
                                        break;

                                    case "Close":
                                        {
                                            oPline = (Polyline)tr.GetObject(id, OpenMode.ForWrite);
                                            if (oPline.GetPoint2dAt(0) == oPline.GetPoint2dAt(iVertex - 1))
                                            {
                                                iVertex = iVertex - 1;
                                                Bulge = oPline.GetBulgeAt(iVertex);
                                                oPline.RemoveVertexAt(iVertex);
                                            }
                                            else
                                                Bulge = 0;

                                            oPline.Closed = true;
                                            oPline.SetBulgeAt(iVertex - 1, Bulge);
                                            tr.Commit();
                                            return;
                                        }

                                    case "Second":
                                        prompt = "\nSpecify second point on arc:";
                                        bCurve = false;
                                        bSecond = true;
                                        break;

                                    case "Undo":

                                        oPline = (Polyline)tr.GetObject(id, OpenMode.ForWrite);
                                        if (oPline.NumberOfVertices > 2)
                                        {
                                            bCurve = oPline.GetBulgeAt(iVertex - 1) != 0;
                                            oPline.RemoveVertexAt(iVertex - 1);
                                            tr.Commit();
                                            iVertex = iVertex - 1;
                                            startP = oPline.GetPoint2dAt(iVertex - 1);
                                            BasePt = oPline.GetPoint3dAt(iVertex - 1);
                                            FirstDeriv = oPline.GetFirstDerivative
                                                (oPline.NumberOfVertices - 1);
                                        }
                                        else
                                        {
                                            iVertex = iVertex - 1;
                                        }
                                        goto Skip;
                                        //break;


                                    default:
                                        prompt = "\nSpecify next point or [Arc/Close/Second pt/Undo]:";
                                        keywords = "Arc Close Second Undo";
                                        bCurve = false;
                                        break;
                                }
                                tr.Commit();
                            }
                        }

                        if (res.Status == PromptStatus.OK)
                        {
                            if (bSecond)
                            {
                                prompt = "\nSpecify end point of arc:";
                                FirstDeriv = jig.endP3d.GetAsVector();
                                if (bCurve)
                                {
                                    prompt = "\nSpecify next point or [Close/Line/Second pt/Undo]:";
                                    keywords = "Close Line Second Undo";
                                    bSecond = false;
                                }
                                else
                                {
                                    //Util.AddEnt.Point(jig.endP3d,1);
                                    bCurve = true;
                                    goto Skip;
                                }
                            }

                            using (tr = db.TransactionManager.StartTransaction())
                            {
                                EndPt = jig.endP;
                                Bulge = jig.bulge;
                                if (iVertex == 1)
                                {
                                    oPline.AddVertexAt(1, EndPt, Bulge, 0, 0);
                                    oPline.SetBulgeAt(0, Bulge);
                                    BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                                    BlockTableRecord btr = tr.GetObject
                                        (db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                                    btr.AppendEntity(oPline);
                                    tr.AddNewlyCreatedDBObject(oPline, true);
                                    id = oPline.ObjectId;
                                    prompt =
                                        "\nSpecify next point or [Arc/Close/Line/Second pt/Undo]:";
                                    keywords = "Arc Close Line Second Undo";
                                    FirstDeriv = oPline.GetFirstDerivative(1);
                                }
                                else
                                {
                                    oPline = tr.GetObject(id, OpenMode.ForWrite) as Polyline;
                                    oPline.AddVertexAt(iVertex, EndPt, Bulge, 0, 0);
                                    oPline.SetBulgeAt(iVertex - 1, Bulge);
                                    FirstDeriv = oPline.GetFirstDerivative(oPline.NumberOfVertices - 1);
                                }
                                BasePt = oPline.GetPoint3dAt(iVertex);
                                startP = EndPt;

                                iVertex++;
                                tr.Commit();
                            }

                        }
                    Skip: ;

                    } while (res.Status == PromptStatus.OK || res.Status == PromptStatus.Keyword);





                }  //End PlineDraw

                #endregion
            }

}  //End PlineDraw

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Draw polyline like autocad...
« Reply #11 on: June 24, 2009, 02:57:19 AM »
Code: [Select]
        public static int isLeft(Point2d Startpoint, Point2d Endpoint, Point2d P)
        {
            return isLeftMath(Startpoint, Endpoint, P);
        }



        public static int isLeft(Point3d Startpoint, Point3d Endpoint, Point3d P)
        {
            Point2d Spt = new Point2d(Startpoint.X, Startpoint.Y);
            Point2d Ept = new Point2d(Endpoint.X, Endpoint.Y);
            Point2d Pt = new Point2d(P.X, P.Y);
            return isLeftMath(Spt, Ept, Pt);
        }

        public static int isLeftMath(Point2d Startpoint, Point2d Endpoint, Point2d P)
        {
            double Ans = ((Endpoint.X - Startpoint.X) * (P.Y - Startpoint.Y) -
              (P.X - Startpoint.X) * (Endpoint.Y - Startpoint.Y));
            if (Math.Abs(Ans) < 1.0e-8)
            { return 0; } //P is on the line
            else
            {
                if (Ans > 0)
                { return 1; } //P is left of the line (CW)
                else
                { return -1; } //P is right of the line (CCW)
            }
        }













 static public Point3d CenterFrom3Pts(Point3d P1, Point3d P2, Point3d P3)
                {
            //jheathc   http://discussion.autodesk.com/thread.jspa?messageID=406712
           
            double X1 = P1.X;double Y1 = P1.Y;double Z1 = P1.Z;
            double xba = P2.X - X1;
            double yba = P2.Y - Y1;
            double zba = P2.Z - Z1;
            double xca = P3.X - X1;
            double yca = P3.Y - Y1;
            double zca = P3.Z - Z1;
           
            // Calculate the squares of the lengths of the edges incident to x1-y1-Z1
           
            double balength = (xba * xba) + (yba * yba) + (zba * zba);
            double calength = (xca * xca) + (yca * yca) + (zca * zca);
            // Calculate the cross product of these edges. Take our chances with Intel
            //floating-point roundoff.
           
            double xcrossbc = (yba * zca) - (yca * zba);
            double ycrossbc = (zba * xca) - (zca * xba);
            double zcrossbc = (xba * yca) - (xca * yba);
           
            // Calculate the denominator of the formulae.
            double denominator = 0.5 / ((xcrossbc * xcrossbc) + (ycrossbc * ycrossbc) + (zcrossbc * zcrossbc));

            // Calculate offset from x1-y1-Z1 of the circumcenter.

            double xcirca = ((((balength * yca) - (calength * yba)) * zcrossbc) - (((balength * zca)
                     - (calength * zba)) * ycrossbc)) * denominator;
            double ycirca = ((((balength * zca) - (calength * zba)) * xcrossbc) - (((balength * xca)
                    - (calength * xba)) * zcrossbc)) * denominator;
            double zcirca = ((((balength * xca) - (calength * xba)) * ycrossbc) - (((balength *yca)
                    - (calength * yba)) * xcrossbc)) * denominator;
            // Calculate the absolute coordinates of the circumcircle center.
            Point3d Center=new Point3d(xcirca + X1,ycirca + Y1,zcirca + Z1);
           
           return Center;

        }

There's a bit of math involved

dann.boy.001

  • Guest
Re: Draw polyline like autocad...
« Reply #12 on: June 24, 2009, 06:40:59 AM »
Thanks Brico

I have similiar piece of code, it work well. But problem is because autocad do not jig
polyline in drawing proces.

Autocad jig only last segment of polyline, other segments not.

In your code you jig all segments of polyline, problem is because polyline on screen flicking.

Best regards
Danijel Ivankovic

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Draw polyline like autocad...
« Reply #13 on: June 24, 2009, 10:26:28 AM »
Odd, I don't see the flicker, in fact I don't see any difference than using the autocad pline command.
The code is making a new transaction opening the polyline for write and adding a new segment everytime a point (or 2 pts when making a curve) is picked.
« Last Edit: June 24, 2009, 10:36:23 AM by Bryco »

dann.boy.001

  • Guest
Re: Draw polyline like autocad...
« Reply #14 on: June 24, 2009, 10:39:03 AM »
Hello Bryco

I have trouble when compiling you code:

Cen3d = Util.MyMath.CenterFrom3Pts(BasePt, SecondPt, endP3d);

What is util? I am working on vb.net so I have problem to compile.

Best regards,
Danijel Ivankovic

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Draw polyline like autocad...
« Reply #15 on: June 24, 2009, 10:47:09 AM »
Util is the namespace I keep functions in and mymath is a class within that.
take the util.mymath out and you should be ok.
Danijel, I didn't want to spend 20 mins compiling this in a brand new project. That's the problem with functions, great to use but hard to find and post

dann.boy.001

  • Guest
Re: Draw polyline like autocad...
« Reply #16 on: June 24, 2009, 04:00:38 PM »
O.K.

Thank you very much on your code. It is exactly what I am looking... :-)

I had problem with transaction in my code, to add vertex to polyline...now
I can solve my problem using your code...

Best regards,
Danijel Ivankovic

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Draw polyline like autocad...
« Reply #17 on: June 24, 2009, 08:36:31 PM »
Glad to help, Danijel.
The thing that's tough with jigs is trying to debug them. They refuse.

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2139
  • class keyThumper<T>:ILazy<T>
Re: Draw polyline like autocad...
« Reply #18 on: June 24, 2009, 10:09:04 PM »
Bryco ,

well done.

I'll bookmark this to look at later :)

// kdub
Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

dann.boy.001

  • Guest
Re: Draw polyline like autocad...
« Reply #19 on: June 25, 2009, 10:49:37 AM »
Bryco,

I am very thankful. Last night I solve my problem using you idea  :mrgreen:.

I will share my code on this forum, next week.

My comments are on croatian, but I think that code my be useful for
someone how is beginer in .net for autocad.

Best regards
Danijel Ivankovic


Bryco

  • Water Moccasin
  • Posts: 1883
Re: Draw polyline like autocad...
« Reply #20 on: June 25, 2009, 02:25:04 PM »
Thanks guys, the checkpoint function looks insane, but I put that in as sometimes in an iso-view the chosen pt isnt on the ucs plane. We all know this is impossible so??? It's there if you need it.