.NET

Reply
Active Contributor
absStructural
Posts: 36
Registered: ‎07-15-2010
Message 1 of 10 (478 Views)

Polyline3d GetClosestPointTo, GetObjectSnapPoints

478 Views, 9 Replies
12-15-2012 09:18 AM

I am trying to get a point on (or possibly extended from the end of) a 3D polyline closest to a specified point.  In the attached drawing, there is a 3D Polyline, and two nodes. 

 

In AutoCAD, if I draw a line from the node at 1239.817,994.9588,91.7498 perpendicular to the polyline, it snaps to (1239.8705, 999.9583, 91.6499) - which is the desired result.

 

The code below shows 3 methods of trying to obtain this result, but without success.  The output of this is:

 

pickedPt: (1239.8717322503,994.958757180007,91.7498303566326)
testPt1: (1234.21981294827,999.958333333333,91.7210574435876)
testPt2: (1239.87317003466,999.958333333333,92.2930159035884)
testPt3: (1234.21981294827,999.958333333333,91.7210574435876)
Snap Point Count: 503

 

So, the issue with Method 1 is that it does not extend the polyline.  Which led me to Method 2.

 

The issue with Method 2 is that it is not using the end of the polyline to determine the direction it should extend.

 

The issue with Method 3 is that it doesn't extend the polyline (the result is the same as Method 1).

 

Any suggestions?

 

public static void ClosestPl3dTest()
        {
            Document acDoc = Application.DocumentManager.MdiActiveDocument;
            Editor acEd = acDoc.Editor;

            PromptEntityResult per  = acEd.GetEntity("Select Polyline3d");
            if (per.Status == PromptStatus.OK)
            {
                Polyline3d pl = null;
                using (Transaction acTrans = acDoc.TransactionManager.StartTransaction())
                {
                    DBObject obj = acTrans.GetObject(per.ObjectId, OpenMode.ForRead);
                    if (obj is Polyline3d)
                    {
                        pl = (Polyline3d)obj;
                    }
                    acTrans.Commit();
                }
                if (pl != null)
                {
                    PromptPointResult ppr = acEd.GetPoint("Select point");
                    if (ppr.Status == PromptStatus.OK)
                    {
                        Point3d pickedPt = ppr.Value;

                        // Method 1
                        Point3d testPt1 = pl.GetClosestPointTo(pickedPt, false);

                        // Method 2
                        Point3d testPt2 = pl.GetClosestPointTo(pickedPt, true);
                        
                        // Method 3
                        Point3dCollection ptColl = new Point3dCollection();
                        IntegerCollection intColl = new IntegerCollection();
                        Matrix3d identity = Matrix3d.Identity;
                        pl.GetObjectSnapPoints(ObjectSnapModes.ModePerpendicular, 1, pickedPt, pickedPt, identity, ptColl, intColl);
                        
                        Point3d[] array = new Point3d[ptColl.Count];
                        ptColl.CopyTo(array, 0);

                        // return the closest result
                        Point3d testPt3 = array.OrderBy(pt => pt.DistanceTo(pickedPt)).First();

                        acEd.WriteMessage("\npickedPt: " + pickedPt.ToString() + "\n");
                        acEd.WriteMessage("testPt1: " + testPt1.ToString() + "\n");
                        acEd.WriteMessage("testPt2: " + testPt2.ToString() + "\n");
                        acEd.WriteMessage("testPt3: " + testPt3.ToString() + "\n");
                        acEd.WriteMessage("Snap Point Count: " + ptColl.Count + "\n");
                    }
                }
            }
        }

 

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 2 of 10 (463 Views)

Re: Polyline3d GetClosestPointTo, GetObjectSnapPoints

12-15-2012 11:31 AM in reply to: absStructural

Have not tested your code, just a guess, maybe you need to

convert the retrieved point to UCS

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Active Contributor
absStructural
Posts: 36
Registered: ‎07-15-2010
Message 3 of 10 (459 Views)

Re: Polyline3d GetClosestPointTo, GetObjectSnapPoints

12-15-2012 11:45 AM in reply to: Hallex

This was just written as a small test - and it is assumed the UCS is World (which it was when I tested it).  Agreed, though, in a complete solution - this would be done.

Active Contributor
absStructural
Posts: 36
Registered: ‎07-15-2010
Message 4 of 10 (430 Views)

Re: Polyline3d GetClosestPointTo, GetObjectSnapPoints

12-17-2012 05:27 AM in reply to: absStructural

Any other thoughts?

Active Contributor
absStructural
Posts: 36
Registered: ‎07-15-2010
Message 5 of 10 (422 Views)

Re: Polyline3d GetClosestPointTo, GetObjectSnapPoints

12-17-2012 08:19 AM in reply to: absStructural

It would also appear that all of the 503 points that are populated in GetObjectSnapPoints are just vertices of the Polyline3d.  This doesn't seem right.

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 6 of 10 (405 Views)

Re: Polyline3d GetClosestPointTo, GetObjectSnapPoints

12-18-2012 12:44 AM in reply to: absStructural

Not sure about what is your goal,

try to change snap mode like this

pl.GetObjectSnapPoints(ObjectSnapModes.ModeNear, 1, pickedPt, pickedPt, identity, ptColl, intColl);

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Active Contributor
absStructural
Posts: 36
Registered: ‎07-15-2010
Message 7 of 10 (400 Views)

Re: Polyline3d GetClosestPointTo, GetObjectSnapPoints

12-18-2012 05:35 AM in reply to: Hallex

As stated in my original post:

 

In AutoCAD, if I draw a line from the node at 1239.817,994.9588,91.7498 perpendicular to the polyline, it snaps to (1239.8705, 999.9583, 91.6499) - which is the desired result.

 

So, that's the goal.

 

This point is off the end of the Polyline - which is what I want.  Using OSnap near would not make any sense.

ADN Support Specialist
fenton.webb
Posts: 352
Registered: ‎07-24-2007
Message 8 of 10 (353 Views)

Re: Polyline3d GetClosestPointTo, GetObjectSnapPoints

01-03-2013 03:00 PM in reply to: absStructural

It looks like the API version doesn't extend the Pline to gain the perp point like the Ui does. I suggest you either extend the ends of the in memory polyline and then carry out the GetObjectSnapPoints(), or used acedComand() to emulate the UI.





Fenton Webb

Developer Technical Services

Autodesk Developer Network


Valued Mentor
DiningPhilosopher
Posts: 370
Registered: ‎05-06-2012
Message 9 of 10 (343 Views)

Re: Polyline3d GetClosestPointTo, GetObjectSnapPoints

01-04-2013 06:31 AM in reply to: absStructural

GetOsnapPoints() wasn't really intended to be used directly, it was designed to be called by AutoCAD in the process of interactively acquiring an object snap point. While it's possible to set up the parameters to those required to use the method, that isn't as simple as it may appear.

 

For your objective, this should be all you need:

 

   Autodesk.AutoCAD.EditorInput.Editor.Snap( string modes, Point3d point );

 

It is the managed wrapper for the LISP (osnap) function. For PERP and TAN osnap modes, you need to first set the LASTPOINT system variable to the point that those two modes use as a parameter.

Active Contributor
absStructural
Posts: 36
Registered: ‎07-15-2010
Message 10 of 10 (337 Views)

Re: Polyline3d GetClosestPointTo, GetObjectSnapPoints

01-04-2013 08:14 AM in reply to: DiningPhilosopher

That method works; but with two issues I can see. 

 

1. The polyline has to be in the database (not just in memory) - though I'm okay with that.

2. This method doesn't guaranty that the desired polyline will be snapped to.  If there is another entity close by, it could very well snap to it.

 

What I ended up doing is getting a point using polyline.GetClosestPointTo(point, false).  If that point is the start point or end point of the polyline, then I create a line (in memory) from the start or end using the first derivative vector.  I then use line.GetClosestPointTo(point, true).

 

Is it clean?  No.  Do I like it?  Not really.  But, it works.

Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.