Author Topic: Exception with GetPointAtDist  (Read 1786 times)

0 Members and 1 Guest are viewing this topic.

huiz

  • Swamp Rat
  • Posts: 845
  • Certified Prof C3D
Exception with GetPointAtDist
« on: March 19, 2013, 02:47:57 PM »
If I split a 3D Polyline with GetPointAtDist, and there are some double vertices at the same location (ie Vertex 1 and Vertex 2 are at the same location so there is a segment with distance zero), I get an exception eInvalidInput.

Why is this? The distance I want a point at is shorter than the length of the polyline. But as soon as there is a zerolength segment, I get this error.


The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

WILL HATCH

  • Bull Frog
  • Posts: 448
Re: Exception with GetPointAtDist
« Reply #1 on: March 19, 2013, 03:31:44 PM »
code?

BlackBox

  • King Gator
  • Posts: 3745
Re: Exception with GetPointAtDist
« Reply #2 on: March 19, 2013, 05:08:00 PM »
Perhaps this is because of the duplication of points; GetPointAtDist returns Point3d, and not Point3d[] (although, no exception is listed in Object Browser)... I wonder if GetParameterAtDistance, or GetPointAtParameter would behave any differently in this situation?
"How we think determines what we do, and what we do determines what we get."

TheMaster

  • Guest
Re: Exception with GetPointAtDist
« Reply #3 on: March 19, 2013, 07:08:07 PM »
If I split a 3D Polyline with GetPointAtDist, and there are some double vertices at the same location (ie Vertex 1 and Vertex 2 are at the same location so there is a segment with distance zero), I get an exception eInvalidInput.

Why is this? The distance I want a point at is shorter than the length of the polyline. But as soon as there is a zerolength segment, I get this error.

Not surprising. I think it's because polylines (all flavors) parameterize each segment distinctly as a simple curve, and add the parameter to the segment offset, so the midpoint of any segment will be (1.0*n)+0.5, where n is the index of the segment.

If there are zero-length segments, then what should GetParameterAtPoint() return given the start/end vertex of a zero-length segment?

I think the standard workaround is to detect and remove zero-length segments.

Here's a variation of some code I posted on Autodesk's discussion groups recently that attempts to tell if a Polyline can be used as a Region boundary. You might try adapting it to Polyline3d and see if it gives you some meaningful result that you can use to detect before-the-fact, if the polyline can be a problem with APIs like GetSplitCurves().

Code - C#: [Select]
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using Autodesk.AutoCAD.Geometry;
  7. using AcBr = Autodesk.AutoCAD.BoundaryRepresentation;
  8. using Autodesk.AutoCAD.Runtime;
  9.  
  10. namespace Autodesk.AutoCAD.DatabaseServices
  11. {
  12.    public static class PolylineExtensionMethods
  13.    {
  14.       /// <summary>
  15.       ///
  16.       /// Returns true if the given Polyline forms a
  17.       /// closed boundary and its Closed property is
  18.       /// false.
  19.       ///
  20.       /// The result is true if any of the
  21.       /// following conditions are true:
  22.       ///
  23.       /// 1.  Any segment intersects any other segment.
  24.       ///      Regardless of the value of the Closed property.
  25.       ///
  26.       /// 2.  Any vertex lies directly on any segment.
  27.       ///     or is coincident with any other vertex,
  28.       ///     including zero-length segments, regardless
  29.       ///     of the value of the Closed property
  30.       ///
  31.       /// 3.  If the first and last vertices are coincident,
  32.       ///     AND the PolyLine's Closed property is false,
  33.       ///     the polyline is considered effectively closed.
  34.       ///    
  35.       ///  4. A Closed polyline with < 3 vertices.
  36.       ///    
  37.       /// The test is intended to be consistent with the
  38.       /// REGION command's testing of boundary entities.
  39.       ///    
  40.       /// </summary>
  41.  
  42.       public static bool IsEffectivelyClosed( this Polyline pline )
  43.       {
  44.          int numverts = pline.NumberOfVertices;
  45.          if( numverts < 3 )
  46.             return pline.Closed;
  47.            
  48.          if( !pline.Closed && pline.StartPoint.IsEqualTo( pline.EndPoint ) )
  49.             return true;
  50.  
  51.          Point3dCollection points = new Point3dCollection();
  52.  
  53.          pline.IntersectWith( pline, Intersect.OnBothOperands, points,
  54.             IntPtr.Zero, IntPtr.Zero );
  55.  
  56.          if( !pline.Closed )
  57.             numverts -= 2;
  58.  
  59.          return points.Count != numverts;
  60.       }
  61.    }
  62. }
  63.  
  64.  
« Last Edit: March 19, 2013, 07:44:04 PM by TT »

BlackBox

  • King Gator
  • Posts: 3745
Re: Exception with GetPointAtDist
« Reply #4 on: March 19, 2013, 07:24:00 PM »
If there are zero-length segments, then what should GetParameterAtPoint() return given the point at two or more coincident vertices ?

Methinks, that beith the problem... These Curve Methods are seemingly not equipped to handle such circumstances.

Does this mean that (as a generalization) one should iterate a given Curve for GetPointAtParameter to test for Zero length before continuing with one's own code, or perhaps instead simply catch this exception, and prompt the user to address this possibility?

Better still, am I completely overlooking a simpler solution (I am very much still learning the craft of development)?
"How we think determines what we do, and what we do determines what we get."

TheMaster

  • Guest
Re: Exception with GetPointAtDist
« Reply #5 on: March 19, 2013, 07:49:16 PM »
If there are zero-length segments, then what should GetParameterAtPoint() return given the point at two or more coincident vertices ?

Methinks, that beith the problem... These Curve Methods are seemingly not equipped to handle such circumstances.

Does this mean that (as a generalization) one should iterate a given Curve for GetPointAtParameter to test for Zero length before continuing with one's own code, or perhaps instead simply catch this exception, and prompt the user to address this possibility?

Better still, am I completely overlooking a simpler solution (I am very much still learning the craft of development)?

You can either catch the exception and tell the user something is wrong with the polyline, but you don't know exactly what it is, or you can interrogate the polyline before the fact, to try to determine if it will be rejected, and give the user a more meaningful  reason.

AutoCAD's Curve, Solid, and Region APIs are brain-dead in that regards, because they don't provide any clue about what is unacceptable or invalid given an object. If you look at the REGION command's behavior, you'll notice that it gives you details on what happened, or what objects were rejected and the reason why they were. We don't have access to those APIs, which unfortunately, seems to be the status-quo with plain vanilla AutoCAD APIs.

BlackBox

  • King Gator
  • Posts: 3745
Re: Exception with GetPointAtDist
« Reply #6 on: March 19, 2013, 08:36:06 PM »
If there are zero-length segments, then what should GetParameterAtPoint() return given the point at two or more coincident vertices ?

Methinks, that beith the problem... These Curve Methods are seemingly not equipped to handle such circumstances.

Does this mean that (as a generalization) one should iterate a given Curve for GetPointAtParameter to test for Zero length before continuing with one's own code, or perhaps instead simply catch this exception, and prompt the user to address this possibility?

Better still, am I completely overlooking a simpler solution (I am very much still learning the craft of development)?

You can either catch the exception and tell the user something is wrong with the polyline, but you don't know exactly what it is, or you can interrogate the polyline before the fact, to try to determine if it will be rejected, and give the user a more meaningful  reason.

AutoCAD's Curve, Solid, and Region APIs are brain-dead in that regards, because they don't provide any clue about what is unacceptable or invalid given an object. If you look at the REGION command's behavior, you'll notice that it gives you details on what happened, or what objects were rejected and the reason why they were. We don't have access to those APIs, which unfortunately, seems to be the status-quo with plain vanilla AutoCAD APIs.

For the first part of your reply, the latter option (when possible) is, or perhaps should be, an obvious preference.

Given the lack of API exposure, would it be appropriate to employ a more LISP-like (linear?) solution, to interrogate the Curve and store each Param and Point to a hash table, etc. to see if there are any duplicate points? If one doesn't require the Param(s) as part of a hash table for later, then perhaps a List<Point3d> instead?

** Edit to add - I just saw that you've added some code to your earlier post. Thanks for that.
"How we think determines what we do, and what we do determines what we get."

huiz

  • Swamp Rat
  • Posts: 845
  • Certified Prof C3D
Re: Exception with GetPointAtDist
« Reply #7 on: March 20, 2013, 05:31:13 AM »
..
Not surprising. I think it's because polylines (all flavors) parameterize each segment distinctly as a simple curve, and add the parameter to the segment offset, so the midpoint of any segment will be (1.0*n)+0.5, where n is the index of the segment.

If there are zero-length segments, then what should GetParameterAtPoint() return given the start/end vertex of a zero-length segment?

I think the standard workaround is to detect and remove zero-length segments.

Here's a variation of some code I posted on Autodesk's discussion groups recently that attempts to tell if a Polyline can be used as a Region boundary. You might try adapting it to Polyline3d and see if it gives you some meaningful result that you can use to detect before-the-fact, if the polyline can be a problem with APIs like GetSplitCurves().

..

Thanks Tony. I've tested your code but it does not seem to do what it should do. Also 3D polylines that are correctly constructed without double vertices are sometimes marked as false. I'm not sure what the reason is.

At the moment I catch the exception and then I can remove the double points from that polyline.
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

huiz

  • Swamp Rat
  • Posts: 845
  • Certified Prof C3D
Re: Exception with GetPointAtDist
« Reply #8 on: March 20, 2013, 06:21:54 AM »
This is a function to remove double vertices.

Code: [Select]
  Private Sub RemoveDoubleVerticesFrom3DPoly(ePline As Polyline3d)

    Dim doc As acAppServ.Document = acAppServ.Application.DocumentManager.MdiActiveDocument
    Using db As Database = doc.Database
      Dim tr As Transaction = db.TransactionManager.StartTransaction
      Using tr

        Dim LastPt As New Point3d

        ' Loop vertices.
        For Each ObjID As ObjectId In ePline
          Dim v3D As PolylineVertex3d = tr.GetObject(ObjID, OpenMode.ForRead)
          If v3D.Position.IsEqualTo(LastPt) Then
            v3D.UpgradeOpen()
            v3D.Erase(True)
          Else
            LastPt = v3D.Position
          End If
        Next

        tr.Commit()

      End Using
    End Using

  End Sub

I actually don't catch the exception anymore, I just run the code on each polyline I have to split. There is not a noticable delay.
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

TheMaster

  • Guest
Re: Exception with GetPointAtDist
« Reply #9 on: March 21, 2013, 01:32:43 AM »
..
Not surprising. I think it's because polylines (all flavors) parameterize each segment distinctly as a simple curve, and add the parameter to the segment offset, so the midpoint of any segment will be (1.0*n)+0.5, where n is the index of the segment.

If there are zero-length segments, then what should GetParameterAtPoint() return given the start/end vertex of a zero-length segment?

I think the standard workaround is to detect and remove zero-length segments.

Here's a variation of some code I posted on Autodesk's discussion groups recently that attempts to tell if a Polyline can be used as a Region boundary. You might try adapting it to Polyline3d and see if it gives you some meaningful result that you can use to detect before-the-fact, if the polyline can be a problem with APIs like GetSplitCurves().

..

Thanks Tony. I've tested your code but it does not seem to do what it should do. Also 3D polylines that are correctly constructed without double vertices are sometimes marked as false. I'm not sure what the reason is.

At the moment I catch the exception and then I can remove the double points from that polyline.

I've never tried it on 3d polys, only 2d lightweight polys, so I wasn't sure what would happen there. It works for me with simple, 2d polylines though.