Calling all Math Wiz's - vlax-curve-getfirstderiv

Discussion in 'AutoCAD' started by Darren J. Young, Apr 23, 2004.

  1. Darren J. Young

    John Uhden Guest

    Belatedly, here's a little function to help you "see" what the SecondDeriv
    represents...
    (defun c:2nd ( / @2D Object Start End Param P2 P2 Ang)
    (redraw)
    (defun @2D (p)(list (car p)(cadr p)))
    (and
    (setq Object (car (entsel)))
    (setq Object (vlax-ename->vla-object Object))
    (not (vl-catch-all-error-p (setq Start (vl-catch-all-apply
    'vlax-curve-GetStartParam (list Object)))))
    (setq End (vlax-curve-GetEndParam Object))
    (setq Param Start)
    (while (< Param End)
    (setq P1 (vlax-curve-getpointatparam Object Param))
    (setq Ang (apply 'atan (reverse (@2d (vlax-curve-getSecondDeriv Object
    Param)))))
    (print Ang)
    (setq P2 (polar P1 Ang (* 0.1 (getvar "viewsize"))))
    (setq Param (+ Param 0.5))
    (grdraw P1 P2 1)
    1
    )
    )
    )
    You could change it to observe 1stDerivs as well.
     
    John Uhden, May 17, 2004
    #21
  2. Darren J. Young

    David Kozina Guest

    COOL!
    Thanks, John.
    Putting on my 2nd derivative goggles now...
    Best regards,
    David Kozina
     
    David Kozina, May 17, 2004
    #22
  3. Darren J. Young

    David Kozina Guest

    OK, perhaps all of you already know this, but here are my findings so far
    with respects to parameters and LWPolylines... (You know, it would be nice
    if the help files were a little more robust/obvious regarding this).

    *Please* provide corrections if I've got anything mixed up here...

    **In the case of LW/Polylines**

    Parameter 0.0 is at the First Vertex
    Parameter 0.5 is midway along segment between First & Second Vertices
    Parameter 1.0 is at the Second Vertex
    ....
    Parameter N.0 is at Vertex (N+1)

    vlax-curve-getStartParam = 0.0
    vlax-curve-getEndParam = (total number of vertices - 1.0)

    Since Parameter values here need not correspond in any way to distances,
    this explains why additional curve functions are necessary to access that
    information:

    ....DistAtParam 0.0 = 0.0
    ....DistAtParam 0.5 = 1/2 Length of First segment
    ....DistAtParam 1.0 = Length of First segment
    ....DistAtParam N.0 = Total Length of first N segments

    If, for example
    ....ParamAtDist 2.0 = 4.35, you know that the point 35% of the way along the
    Fifth Segment is 2.0 units away from the Start Point (along the curve) - and
    ....PointAtParam 4.35 will returns that location - and said point fed back to
    ....ParamAtPoint will return 4.35


    If the above is sound - I've got two more questions, perhaps related to each
    other:

    ~
    /
    |<-- Dist X -->| ,Obj /
    + +================+
    A_pt Start_pt 2nd Vertex
    (Parameter 0.0) (Parameter 1.0)

    Is there any way with these function to extrapolate points, such as A_pt?
    Or must I now resort to the older standbys: polar, ang, and dist?

    Should I want to use vector calculations to accomplish the above, what is
    the best way to find the *unit* direction and *unit* normal vectors?
    (Start_pt to 2nd Vertex could be at any angle)

    It appears that
    (vlax-curve-getFirstDeriv Obj 0.0) returns a vector with length equal to
    length of first segment.

    How could this be converted to a unit vector? Like so?:

    (setq 1stDeriv_vec
    (vlax-curve-getFirstDeriv Obj 0.0)
    )

    (setq Norm
    (distance '(0 0) 1stDeriv_vec)
    )

    (setq Unit_Vec
    (mapcar
    '(lambda (ord)
    (/ ord Norm)
    )
    1stDeriv_vec
    )
    )

    This seems to work in my limited testing - but I'd appreciate some
    kibbitzing before I do a Wiley Coyote and step out over the precipice...

    Any comments would be most appreciated.

    Best regards,
    David Kozina
     
    David Kozina, May 18, 2004
    #23
  4. Can it be simplified to say that the parameter value
    of a point is the vertex index + the distance from
    the start of the vertex expressed as a percentage of
    the overall length of the vertex?

    There's little use of the parameter in the problem you
    describe, because solving that only requires you to
    know the direction of a straight segment, which you can
    derive from nothing but the adjacent vertices.

    For more general computations of coordinates that lie
    on a line (e.g., a straight lwpolyline segment), you
    can use the parametric equation of the line in WCS.

    Using the parametric equation, you can solve for any
    number of points that lie on the extended vertex, using
    pythagorian theorm.


    http://www.caddzone.com

    AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005
    http://www.acadxtabs.com
     
    Tony Tanzillo, May 18, 2004
    #24
  5. Darren J. Young

    Owen Wengerd Guest

    David:
    I've preached about this before, but it bears repeating: parameters are
    opaque real numbers by design, and you should not infer anything about their
    relationship to points on an entity. The relationship of parameters to
    points is a function of the PointAtParam functions. Trying to establish
    relationships empirically is perilous at best. The relationship may change
    at any time at the discretion of the implementor, and in any case, it's
    impossible to be certain that any empirical relationships hold true in all
    cases.

    To reiterate: the parameters are opaque and their meaning and relationship
    to points on the entity are defined completely by the DistAtParam()
    function. By the same token, the first and second derivatives are simply
    that, and I think it's dangerous to try to look for and potentially rely on
    any "extraneous" relationships those have to the entity. Interesting
    perhaps, but dangerous nonetheless. :)
     
    Owen Wengerd, May 18, 2004
    #25
  6. Darren J. Young

    David Kozina Guest

    Oh, sure.
    <throwing pencil over shoulder>
    NOW you tell me... :)

    So, IOW, <to be safe>, I ought to round-file the curve functions for this
    project, and just extract the vertex info via the vl property functions, and
    then extrapolate additional points from those - correct? (Those curve
    functions are rather interesting, though - and I'm not a bit sorry I got to
    play around with them some.)

    Of course, this raises more questions...

    Is it preferred to calculate/extrapolate/interpolate points (assuming
    straight segments) with vector calculations or with polar/angle
    calculations? Seems like I've read that using polar/angle calculations
    quickly leads to rounding/spatial errors, whereas vector calculations tend
    to remain more accurate.

    Also, with regards to the 'opaque' parameters in the curve functions, I
    guess I am at a loss to understand just how (or for what purpose) the
    functions should properly be used... Would you say that the "most critical"
    function is ParamAtPoint - since that is the only way you can be sure that
    you have the correct parameter to feed the other functions?

    Thanks,
    David Kozina
     
    David Kozina, May 18, 2004
    #26
  7. Darren J. Young

    John Uhden Guest

    Owen:

    Are you saying that the "evident" relationship between parameters and vertices
    of polylines is not necessarily consistent now? Or are you saying that such
    "evident" relationship is likely to change? Or maybe both? Have you been
    cleaning your crystal ball? I still have a lot of old lisp code that figures
    out geometry by basic trigonometric procedures applied to DXF values. Are you
    suggesting to stick with same? Then again, there have been rumors that AutoLisp
    functions such as (entget) may be retired. One might deduce that by design,
    developers will have to resort to ARX if either ActiveX methods will become
    inconsistent or certain AutoLisp functions are retired. Certainly VBA, to my
    limited knowledge, has no ability to derive the all the actual vertices of a
    complex polyline.

    Please expound.
     
    John Uhden, May 19, 2004
    #27
  8. Darren J. Young

    Owen Wengerd Guest

    In all honesty, I've forgotten what the original goal was. Assuming the
    goal is to find midpoints of vertex segments, then essentially yes, scrap
    the reliance on parameter relationships. That doesn't mean the parameter
    functions are useless or should be ignored. For example you could get the
    parameter of the midpoint of any segement, curved or straight(*1), by
    finding the parameter of the segment endpoint vertices, querying the
    distance to each endpoint with DistAtParam, then averaging the two
    distances, then calculating the parameter of the midpoint with ParamAtDist,
    then converting that parameter to coordinates with PointAtParam.

    * The beauty of using parameters here instead of your own geometry functions
    is that your code won't need to care what kind of shape the segment is. The
    segment could be a Euclidean spiral for all you care. And *that* is the
    beauty of parameters: they work for any curve of any shape, and you can
    write code that is "curve-independent" if you utilize parameters.

    Does that make sense? :)
     
    Owen Wengerd, May 19, 2004
    #28
  9. Darren J. Young

    Owen Wengerd Guest

    Are you saying that the "evident" relationship between parameters and
    I'm saying both. I'm fairly confident that the behavior of the built-in
    lightweight polyline object won't change any time soon, but...

    1) Third party developers are already able to make their own
    AcDbPolyline-derived objects that don't necessarily use the same
    relationships that Autodesk chose, and

    2) I wouldn't be a bit surprised to see new possibilities beyond line and
    arc for polyline segments sometime in the future (i.e. complex curves like
    the Euclidean spiral example I used in my reply to David, although that
    specific example is admittedly far-fetched).

    No, not at all. I'm not suggesting that parameters should be ignored; see
    my other reply to David.

    Really? If this is true, then "proper technique" is out the window and
    hacking is the only option. :)
     
    Owen Wengerd, May 19, 2004
    #29
  10. Darren J. Young

    David Kozina Guest

    OK, now I've got another question... :)
    (see below)



    This seems to be a CATCH-22 (to me), since I'm not understanding how you
    would do this without making *some* sort of assumption regarding the
    relationships of parameters to vertices (which you say is a no-no).

    Say, for example, you want to find the midpoint of segment #1 of some
    Object, and **you don't know** if you're dealing with a line or lwpolyline
    or arc or some other oddity. (I say this because you say below that it
    shouldn't matter what type of 'curve' it is) How would I take this first
    step and determine the parameters of the segment endpoint vertices in this
    case? Sorry for being so dense about this.


    OK, I follow the rest of what you're saying, and it makes good sense - just
    not the first part above. I really appreciate you're taking time to try and
    explain this in an understandable way.


    Well... almost. Thanks, Owen.

    Best regards,
    David Kozina
     
    David Kozina, May 19, 2004
    #30
  11. Darren J. Young

    Doug Broad Guest

    John,

    Polylines and 3dpolylines have a property called coordinates.
    The coordinates are the locations of the verticies of the polylines.

    There is no analog, however for the vlax-curve functions,
    AFAIK in VBA.

    Regards,
    Doug
     
    Doug Broad, May 19, 2004
    #31
  12. Darren J. Young

    David Kozina Guest

    I'm pretty sure this is one of the things Tony has provided in his AcadX
    extension.
    (Which is one of the reasons I'd like to understand their use better here
    and now, should I eventually move on to VBA).

    Best regards,
    David Kozina
     
    David Kozina, May 19, 2004
    #32
  13. Darren J. Young

    Owen Wengerd Guest

    David:
    First of all, if you introduce the concept of segments then the object
    must be a form of polyline, otherwise there are no segments to deal with.
    What I meant with my earlier comment is that parameters allow you to deal
    with *polyline* segments of any type, not just arcs and lines. (Yes, they
    do allow you to deal with any sort of curve object in a generic way, but
    only polylines have segments, and therefore only polyline objects are of
    interest for an example of using parameters with segments.)

    What I meant by my earlier comment about any kind of curve is that you can
    (and should IMO) write your code to deal with polyline segments *of any
    type*, not limited to arcs and lines. Imagine a polyline with a parabolic
    segment, or maybe one with a sinusoidal segment. These are possible to make
    today by implementing a custom polyline-derived object, and it's conceivable
    that Autodesk might add such possibilities to the core polyline objects in a
    future version of AutoCAD.

    Now then, to find the midpoint of the first segment of a polyline, your
    code barely needs to directly work with parameters at all (watch wrap):

    <PRE>
    (defun c:getmid (/ lwpline)
    (if
    (and
    (setq lwpline (car (entsel "\nSelect a polyline entity")))
    (= (cdr (assoc 0 (entget lwpline))) "LWPOLYLINE")
    (setq lwpline (vlax-ename->vla-object lwpline))
    )
    (progn (princ "\n") (princ (getmid lwpline)))
    )
    (princ)
    )

    (defun getmid (lwpline / vertex0 vertex1 v1dist v2dist midptdist midptparam)
    (setq vertex0 (append (vlax-safearray->list (vlax-variant-value
    (vla-get-coordinate lwpline 0))) '(0))
    vertex1 (append (vlax-safearray->list (vlax-variant-value
    (vla-get-coordinate lwpline 1))) '(0)))
    (setq v1dist (vlax-curve-getdistatpoint lwpline vertex0)
    v2dist (vlax-curve-getdistatpoint lwpline vertex1)
    midptdist (/ (+ v1dist v2dist) 2.0)
    midptparam (vlax-curve-getparamatdist lwpline midptdist))
    (vlax-curve-getpointatparam lwpline midptparam)
    )
    </PRE>
     
    Owen Wengerd, May 19, 2004
    #33
  14. Darren J. Young

    David Kozina Guest

    Owen,

    I think I get it now. Thanks for the more detailed explanation.

    So, then, you *do* need to know/determine what kind of *object* you're
    working with, then go from there. That clears up the CATCH-22 I was
    tripping over.

    But now, if I may, another question relating to polylines... (forgive me) :)
    Is there any good/foolproof way to determine, with, say, input from a user
    pick, what *segment* of a polyline one is dealing with? (Since I should not
    rely on ParamAtPoint to help determine this). (I guess one needs to assume
    the user won't be picking some self-intersecting point, should one exist -
    <but, then again, what would happen in that case?>)

    Note: I don't have to deal with this situation currently, but I'm curious
    as to how this could be determined unambiguously.

    Best regards,
    David Kozina
     
    David Kozina, May 19, 2004
    #34
  15. Darren J. Young

    David Kozina Guest

    Luis,



    If I understood Owen correctly, the above 3 setq lines [which, btw, is the
    approach I would've taken, too] are exactly what he said we **shouldn't**
    do/assume with regards to
    parameter<->vertex relationships. (Hence my last question).

    Best regards,
    David Kozina
     
    David Kozina, May 19, 2004
    #35
  16. Darren J. Young

    Owen Wengerd Guest

    David:
    Yes, there are several ways. You can use (vlax-curve-getClosestPointTo)
    to find the closest point on the polyline, then covert that point to a
    distance with (vlax-curve-getDistAtPoint), then step through the vertices
    comparing distances at each vertex until you reach a vertex whose distance
    is greater than the selected point. That vertex will then be the end vertex
    of the segment containing the picked point.

    You can also do it with (ssget ":N") and (ssnamex), but I don't have a
    ready example of the code. :)
     
    Owen Wengerd, May 19, 2004
    #36
  17. Darren J. Young

    Owen Wengerd Guest

    Luis:
    Your code relies on the empirically determined relationship of a point's
    parameter to the segment containing the point, which is exactly what I've
    been preaching about *not* doing. :)
     
    Owen Wengerd, May 19, 2004
    #37
  18. While it's true that the parameter is opaque, I'd hardly
    call interpreting an lwpolyline's parameter as a means of
    determining which vertex a given point is on, perilous.

    That goes double in a non-object-oriented language where
    there are no classes or overridden virtual methods, and
    where objects are typically not dealt with in a class-wise
    manner.

    For example, LISP programmers generally don't manipulate
    buches of curves of various base/derived classes with
    indifference, as would be the case when calling virtual
    methods of AcDbCurve-based objects in C++, by code that
    knows nothing about the specific class of the objects it
    is working with.

    In fact, from LISP you can't even determine if a given
    object is a derivative of AcDbCurve, without going to
    such a rediculous extreme as invokng a vlax-curve-* method
    on it, and trapping the error that occurs (and even that
    does not necessarily indicate anything). There is no
    AcDbCurve subclass data to look at in the (entget) list,
    so we are not dealing with curve objects in the way that
    a C++ programmer might.

    When I'm working with native AcDbCurve based objects in
    LISP, it is usually implied that our code assumes it is
    dealing with an object of a specific type/class, not
    some object that happens to be derived from that class.

    For that reason, I think that while your comments are
    valid in terms of C++/OOP concepts, I also think they
    don't translate very well to practicle LISP programming.

    If a LISP programmer encounters some custom AcDbCurve-
    based object (assuming they can determine that), then of
    course, it would be foolish at best, to interpret its
    parameter in any way.

    So while I do agree in theory, in practicle terms,
    and WRT native objects like LWPOLYLINEs, I don't agree
    entirely. As far as a change to the meaning of the
    parameter, that may be likely with custom objects, but
    seriously doubt it will ever happen to an LWPOLYLINE.

    Thanks, but I'll keep using vlax-curve-getParamAtPoint
    to determine what vertex a given point is on, especially
    considering the alternatives. I think the line between
    theoretical and practicle needs to be taken into account
    here.
     
    Tony Tanzillo, May 19, 2004
    #38
  19. Darren J. Young

    David Kozina Guest

    Owen,

    OK, NOW it makes sense. Thanks very much for explaining this.

    Rather more complicated (than a 'simple assumption'), but I see how you can
    do it.

    Best regards,
    David Kozina
     
    David Kozina, May 19, 2004
    #39
  20. Darren J. Young

    Doug Broad Guest

    Hi Owen,
    Can you give me a concrete example of where,
    given that you know the object is a lwpolyline
    that the point selected in this case:

    (initget 1)
    (vlax-curve-getparamatpoint object
    (trans (osnap (getpoint "\nSelect point on object: ") "nea") 1 0)
    )

    and which returns 1.67823 is not on the second segment?

    Certainly the method you show is foolproof. I'm just looking
    for an example where the above would not work. Sometimes
    we can make things more complicated than necessary.

    Thanks.

    Regards,
    Doug
     
    Doug Broad, May 19, 2004
    #40
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.