What does (vla-getBulge) returned value represent?

What does (vla-getBulge) returned value represent?

Kent1Cooper
Consultant Consultant
2,032 Views
10 Replies
Message 1 of 11

What does (vla-getBulge) returned value represent?

Kent1Cooper
Consultant
Consultant

Can anyone explain the actual meaning  of the value returned by (vla-getBulge) at a parameter value on a LWPolyline, particularly on an arc segment?  I was assuming it would return the bulge factor of the segment, i.e. the (cdr (assoc 42 entitydata)) value associated with the vertex at the beginning of that segment.  But take a look at this:

 

vla-getBulge.PNG

 

The green is a simple LWPolyline of two equal arc segments.  They have the same bulge factors except for the sign [cyan at the top].  The red are the Parameter values along the Polyline.  Notice that the yellow values returned by (vla-getBulge) represent that entity-data bulge factor up to the midpoint of the first segment, but then the sign switches to negative  before it gets 3/4 of the way along that segment.  [It actually changes immediately  after half-way -- using parameter 0.501 returns -0.5.]  Then it stays the same across the vertex where the direction of curvature reverses.  And the -0.867... [I lopped off a few decimal places] happens to be the (assoc 42) value associated with the final vertex, whatever that may mean when there's no segment leading from it [it's not what it would be to close the Polyline -- that's -2.0].

 

The reason I want to know is that I was hoping to use (vla-getBulge) to determine, for a calculated [not User-picked] location that might fall anywhere along a LWPolyline, whether it's curved there, and if it is, whether the local direction of curvature is CW or CCW.  I don't need to know the degree  of curvature [the radius], just the direction, and at any location along the segment.  But it appears that's not something that can be determined by the sign of the returned value, as I was expecting.  Either or both of the numerical value and/or the sign can apparently change within a single segment.

 

Also, I experimented with changing the first segment to a line  [not shown], and even then, parameter values up to 0.5 return 0.0 as expected, but parameter 0.501 just past the midpoint of that segment returns -0.5 just as when it's an arc segment.  Searching for an answer in the Forums, I encountered routines that check whether (vla-getBulge) returns 0, on the assumption that a 0 return means you're on a line segment, but that is apparently not valid.

 

It looks like if you're within the first half of a segment, it returns the bulge factor for that segment, and if you're within the second half, it returns the bulge factor for the next  segment, as illogical as that seems.  [The latter seems rather pointless on the final segment of an open Polyline.]  Does anyone know whether that's always the case?  [Might it not be in a more complex Polyline than in the image?]  If not, what does the returned value really represent?

 

If that is  a reliable standard, I suspect one could check whether a parameter value is in the upper half of the range between integer values [within the second half of a segment], and if so, back it off by 0.5 and check (vla-getBulge) for that backed-off parameter value.  Does that seem valid?  I already have found that it's not quite  right for parameter 1.5 in the image -- by that standard, that location ought to still return -0.5.  Parameter 1.499 does, but it switches at  the halfway point in that segment, unlike what happens in the first segment, where it doesn't switch until just after  the midpoint.  Could that difference be related to its being the last  segment?

 

[All this ignores the possibility of a "quirky Polyline" -- Search for that phrase for discussions of quirky circumstances in which integer parameter values may not  fall at vertices.]

 

Any insights would be appreciated.

Kent Cooper, AIA
0 Likes
2,033 Views
10 Replies
Replies (10)
Message 2 of 11

john.uhden
Mentor
Mentor

Kent:

 

According to my ACAD2002 help, the index (parameter) provided to the getbulge method must always be an integer.  Therefor, I figure that you have uncovered a (perhaps) undocumented error, i.e. that the function returns a bogus value rather than an error when provided a real number greater than its whole.  I'd guess that the same is true for setbulge, though I haven't tried a non-integer index.

 

For all my VLisp life I have (fix)ed a parameter to obtain the bulge, or have just pulled the (assoc 42) values.  I think you had better stick to that.

John F. Uhden

0 Likes
Message 3 of 11

phanaem
Collaborator
Collaborator

Hi Kent

According to the ActiveX documentation, vla-getbulge argument must be an integer.

It seems like Vlisp is rounding the argument to the nearest integer, which explains the values in your sample.

 

Regarding the curvature, you can use vlax-curve-getsecondderiv. (0 0 0) means a straight segment, any other values means a curved segment.

I'm not sure about the curve direction (CW or CCW), but I guess you can use second deriv in conjunction with first deriv. At least for arcs, the cross product should give you an indication about the direction.

 

0 Likes
Message 4 of 11

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:

.... 

According to my ACAD2002 help, the index (parameter) provided to the getbulge method must always be an integer.  ....

 

For all my VLisp life I have (fix)ed a parameter to obtain the bulge....


There we have one of the problems with the AutoLisp Reference inexplicably not including vla-...  functions, though it does  include vl-...  and vlax-...  an vlr-...  functions.  I can't just look it up there to find what the argument should be.

 

Using (fix) is likely to serve my purpose -- I'll experiment [but not until at least tomorrow] and get back.

Kent Cooper, AIA
0 Likes
Message 5 of 11

Kent1Cooper
Consultant
Consultant

@phanaem wrote:

....

According to the ActiveX documentation, vla-getbulge argument must be an integer.

....

I'm not sure about the curve direction (CW or CCW....

 


I'm pretty sure the sign on the bulge factor, if I use (fix) on parameter values as @john.uhden suggested, will tell the story on the direction of curvature.  But I'll confirm that soon.

Kent Cooper, AIA
0 Likes
Message 6 of 11

_gile
Consultant
Consultant

Hi,

 

From what I understood some times ago, the argument for vla-getbulge method should be an integer because it refers to a vertex.

 

With the .NET API, which is more strict, the corresponding method is: GetBulgeAt(index) where index must be an integer.

 

So, IMO, if the ActiveX GetBulge method accepts a real number as argument to specify an index, it's just a poor laxist implementation of the method.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 11

phanaem
Collaborator
Collaborator

@Kent1Cooper wrote:

@phanaem wrote:

....

According to the ActiveX documentation, vla-getbulge argument must be an integer.

....

I'm not sure about the curve direction (CW or CCW....

 


I'm pretty sure the sign on the bulge factor, if I use (fix) on parameter values as @john.uhden suggested, will tell the story on the direction of curvature.  But I'll confirm that soon.


 

My suggestion was to use second deriv, which, alone, doesn't give you any indication about the direction.

If vla-getbulge with the integer parameter is solving your problem, than, sure, forget about second deriv.

 

BTW, you can search the ActiveX documentation, acadauto.chm file. I found it in C:\Program Files\Common Files\Autodesk Shared\en-US folder.

I used to use a macro to open that file, but now, in AutoCAD 2018, Vlide is redirecting automatic to ActiveX Reference.

 

0 Likes
Message 8 of 11

ActivistInvestor
Mentor
Mentor

@_gile wrote:

Hi,

 

From what I understood some times ago, the argument for vla-getbulge method should be an integer because it refers to a vertex.

 

With the .NET API, which is more strict, the corresponding method is: GetBulgeAt(index) where index must be an integer.

 

So, IMO, if the ActiveX GetBulge method accepts a real number as argument to specify an index, it's just a poor laxist implementation of the method.


I believe it's a more-widely used convention, that was historically intended to allow values that exceed the range of a LISP and/or VBA integer. Or, put another way, it works for the same reason that this works:

 


(SSNAME (SSGET "X") 1.75)

 

0 Likes
Message 9 of 11

john.uhden
Mentor
Mentor

For the record, the sign of the bulge represents the direction of the arc segment only, not whether the polyline is traveling CW or CCW.  Apparently to be consistent with an arc, a positive bulge always represents a curve to the left and a negative bulge always represents a curve to the right.

 

The firstderiv can indicate the direction of the tangent at a point, but the secondderiv represents the rate of direction change, which would always be 1.0 for an arc, which is circular.  A spline or ellipse would exhibit  a non-consistent seconfderiv.

 

To determine if a polyline is traveling in a CW vs. CCw direction, one must sum the deflections from point to point to point.  A positive total deflection means CCW, and a negative total deflection means CW.  You can't presume that one CCW arc segment means the polyline is CCW.

John F. Uhden

Message 10 of 11

_gile
Consultant
Consultant

Here's a (quite old now) routine which returns the signed area of a polyline (it also works with arc segments).

A negative area means the polyline is clockwise.

 

;; PolylineSignedArea (gile)
;; Returns the algebraic area of the polyline
;; the area is negative if the polyline is clockwise
;;
;; Argument: a polyline ename

(defun PolylineSignedArea (pl / elst lst tot cen p0 area cen)
  (setq elst (entget pl))
  (while (setq elst (member (assoc 10 elst) elst))
    (setq lst  (cons (cons (cdar elst) (cdr (assoc 42 elst))) lst)
	  elst (cdr elst)
    )
  )
  (setq	lst (reverse lst)
	tot 0.0
	p0  (caar lst)
  )
  (if (/= 0 (cdar lst))
    (setq tot (PolyArcSignedArea (cdar lst) p0 (caadr lst))
    )
  )
  (setq lst (cdr lst))
  (if (equal (car (last lst)) p0 1e-9)
    (setq lst (reverse (cdr (reverse lst))))
  )
  (while (cadr lst)
    (setq tot (+ (TriangleSignedArea p0 (caar lst) (caadr lst)) tot))
    (if	(/= 0 (cdar lst))
      (setq tot (+ tot (PolyArcSignedArea (cdar lst) (caar lst) (caadr lst))))
    )
    (setq lst (cdr lst))
  )
  (if (/= 0 (cdar lst))
    (setq tot (+ tot (PolyArcSignedArea (cdar lst) (caar lst) p0)))
  )
  tot
)

;; TriangleSignedArea (gile)
;; Returns the algebraic area of the triangle defined by three 2d points
;; the area is negative if points are clockwise
;;
;; Arguments: three 2d points

(defun TriangleSignedArea (p1 p2 p3)
  (/ (-	(* (- (car p2) (car p1))
	   (- (cadr p3) (cadr p1))
	)
	(* (- (car p3) (car p1))
	   (- (cadr p2) (cadr p1))
	)
     )
     2.0
  )
)

;; PolyArcSignedArea (gile)
;; Returns the algebraic area of a 'polyarc'
;;
;; Arguments
;; bu : polyarc bulge
;; p1 : start point
;; p2 : end point

(defun PolyArcSignedArea (bu p1 p2 / ang rad)
  (setq	ang (* 2 (atan bu))
	rad (/ (distance p1 p2)
	       (* 2 (sin ang))
	    )
  )
  (/ (* rad rad (- (* 2 ang) (sin (* 2 ang)))) 2.0)
)


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 11 of 11

DannyNL
Advisor
Advisor

Too much to read through everything, but this is what I found in an old help file.

 

GetBulge.jpg

 

 

0 Likes