Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Find the midpoint of a bulge in a polyline

24 REPLIES 24
SOLVED
Reply
Message 1 of 25
cncah
3500 Views, 24 Replies

Find the midpoint of a bulge in a polyline

Hello again. I was working on a lisp program this weekend that would automatically create the geometry necessary for milling parts on our CNC router. Thanks to a great amount of help from this forum I was able to obtain quite a bit of information. After getting the program to work on the part I was using as a template, I've now been trying it out on some other parts here at work and finding out that I will have to go a different route on comparing the vertex points and bulges to make the program work for multiple styles of parts instead of parts that match my template dwg. I'm wondering how to find the midpoint of a bulge arc? I've been looking online and seen how to get the chord length, but I'm needing to find the midpoint of the arc in each bulge of the polyline. Here is a picture of what I'm needing to find. I've placed the X,Y zero on the midpoint.I appreciate any help as always.

Polyline Bulge Midpoint.JPG

24 REPLIES 24
Message 21 of 25
Kent1Cooper
in reply to: cncah


@cncah wrote:

No, I would like the vertices. Just not needing to process the midpoints of the line segments.


Try this:

 

(defun dxflist (num); LIST of values associated with DXF number
  (mapcar 'cdr
    (vl-remove-if-not '(lambda (x) (= (car x) num)) pldata)
  ); mapcar
); defun
(defun vertdist (n); DISTance along Pline at VERTex
  (vlax-curve-getDistAtPoint pl (nth n verts))
); defun
(defun addpt (pt)
  (setq ptlist (cons pt ptlist))
); defun

 

(setq
  pl (car (entsel "\nSelect Polyline: ")); <--- add selection controls, or feed in from enclosing routine, or whatever...
  pldata (entget pl)
  verts (dxflist 10)
  bulges (dxflist 42)
  step 0
); setq
(repeat (1- (length verts))
  ;; because if open, don't check for bulge related to last vertex
  (addpt (nth step verts)); vertex at start of segment
  (if (/= (nth step bulges) 0); midpoint if arc segment
    (addpt
      (vlax-curve-getPointAtDist
        pl
        (/ (+ (vertdist step) (vertdist (1+ step))) 2)
      ); ...getPoint...
    ); addpt
  ); if
  (setq step (1+ step))
); repeat
(setq ptlist (cons (nth step verts) ptlist)); last vertex
(if (vlax-curve-isClosed pl)
  (progn ; then -- check for bulge in closing segment
    (if (/= (nth step bulges) 0.0)
      (addpt ; midpoint of closing arc segment
        (vlax-curve-getPointAtDist
          pl
          (/
            (+
              (vertdist step)
              (vla-get-length (vlax-ename->vla-object pl))
                ;; because getDistAtPoint using endpoint returns 0 if closed
            ); +
            2
          ); /
        ); ...getPoint...
      ); addpt
    ); if [bulge]
    (addpt (nth 0 verts)); back to start
  ); progn
); if [closed]
(reverse ptlist)

 

It uses distance rather than parameter methods, to prevent problems in case of Owen's quirkiness issue.  And I assume that if, in a closed Polyline, the closing segment is an arc, you would need all three of the start-, mid- and end-points of that, which is why it includes the starting vertex again at the end; likewise if it's a closing line segment, processing may need both ends of it.  If your procedure doesn't require [or doesn't want] that, it can easily be adjusted.

Kent Cooper, AIA
Message 22 of 25
cncah
in reply to: Kent1Cooper

Kent, your code works fine. It returns the Z coordinate on the bulges but not the vertices. Not a big deal, just didn't know if you knew that or not. I've been trying to finish the rest of my program using the code posted by ajilal.vijayan. His works great, but doesn't use the distance method like yours. Honestly, the quirkiness polyline issue isn't something I have ever had an issue with before but I will save the code you posted in case I need to use it when quirkiness rears it's ugly head. I appreciate all the help and work put in. This program will ultimately save the company and I hours upon hours of time when I finish it. As always, I got to learn quite a bit from the code provided and thank you for that. Here is what my final vertexBulgeList code ended up looking like:

(setq pkt (ssget "x" '((0 . "LWPOLYLINE") (8 . "PktCutOut*"))))
  (setq pktcount (sslength pkt))
  (setq index1 0)

  (repeat pktcount

  (setq
  pktname (ssname pkt index1)
  plobj (vlax-ename->vla-object pktname)
  step 0
  vertexBulgeList (list)
  crlist (vlax-get-property plobj 'coordinates)
  crlist (vlax-safearray->list  (variant-value crlist))
  ); setq


  (defun mid (p1 p2)
     (mapcar '(lambda (x1 x2) (/ (+ x1 x2) 2.0)) p1 p2)
  ) ;;End defun

  (repeat ( / (length crlist) 2)
    (setq blg (vla-getbulge plobj step)) ;;Get the bulge value
      (if ( /= blg 0)
        (progn
    (setq pt1 (vlax-curve-getPointAtParam plobj step )) ;;Vertex @ bulge start
    (setq pt2 (vlax-curve-getPointAtParam plobj ( + step 1))) ;;Vertex @ bulge end
    (setq pt3 (mid pt1 pt2)) ;;Midpoint of pt1 and pt2
    (setq ang (angle pt1 pt2)) ;;Angle of pt1 and pt2
    (setq pt4 (polar pt3 ( - ang 1.570796326794897)  (*(distance pt1 pt3 )blg))) ;;Bulge midpoint
    (setq vertexBulgeList (cons pt1 vertexBulgeList))
    (setq vertexBulgeList (cons pt4 vertexBulgeList))
    (setq vertexBulgeList (cons pt2 vertexBulgeList))
        ) ;;End progn
       ) ;;End if
    (setq step ( + step 1))
      ) ;;End repeat

    (setq vertexBulgeList (reverse vertexBulgeList))

    (setq index1 (+ index1 1))

 Program continues on from here.

 
Message 23 of 25
Kent1Cooper
in reply to: cncah


@cncah wrote:

Kent, your code works fine. It returns the Z coordinate on the bulges but not the vertices. Not a big deal, just didn't know if you knew that or not. ....


Yeah -- that's because it gets the vertex points directly from the entity data, which for lightweight Polylines does not include Z coordiates, but it gets the arc-segment midpoints by looking for a position along the Polyline, which does include a Z coordinate.  The Z coordinates for the vertices are covered by the Polyline's elevation, and that could be tacked on to each point list if needed.  Or, it could use the point from the entity data to get the point along the Polyline for each vertex, which would bring in the Z coordinates -- like this:

 

(defun dxflist (num); LIST of values associated with DXF number
  (mapcar 'cdr
    (vl-remove-if-not '(lambda (x) (= (car x) num)) pldata)
  ); mapcar
); defun
(defun vertdist (n); DISTance along Pline at VERTex
  (vlax-curve-getDistAtPoint pl (nth n verts))
); defun
(defun addpt (pt)
  (setq ptlist (cons pt ptlist))
); defun
(defun ptZ (n); PoinT including Z coordinate at vertex
  (vlax-curve-getPointAtDist pl (vertdist n))
); defun

(setq
  pl (car (entsel "\nSelect Polyline: "))
  pldata (entget pl)
  verts (dxflist 10)
  bulges (dxflist 42)
  step 0
); setq
(repeat (1- (length verts))
  ;; because if open, don't check for bulge related to last vertex
  (addpt (ptZ step)); vertex at start of segment
  (if (/= (nth step bulges) 0); midpoint if arc segment
    (addpt
      (vlax-curve-getPointAtDist
        pl
        (/ (+ (vertdist step) (vertdist (1+ step))) 2)
      ); ...getPoint...
    ); addpt
  ); if
  (setq step (1+ step))
); repeat
(setq ptlist (cons (ptZ step) ptlist)); last vertex
(if (vlax-curve-isClosed pl)
  (progn ; then -- check for bulge in closing segment
    (if (/= (nth step bulges) 0.0)
      (addpt
        (vlax-curve-getPointAtDist
          pl
          (/
            (+
              (vertdist step)
              (vla-get-length (vlax-ename->vla-object pl))
                ;; ^-- because getDistAtPoint using endpoint returns 0 if closed
            ); +
            2
          ); /
        ); ...getPoint...
      ); addpt
    ); if [bulge]
    (addpt (ptZ 0)); back to start
  ); progn
); if [closed]
(reverse ptlist)

Kent Cooper, AIA
Message 24 of 25
cncah
in reply to: Kent1Cooper

Thanks Kent!

Message 25 of 25
Ajilal.Vijayan
in reply to: cncah


@cncah wrote:

I've been trying to finish the rest of my program using the code posted by ajilal.vijayan. His works great, but doesn't use the distance method like yours.

 

cncah,

I am glad to hear that the code works for you.Smiley Happy

 

 

This code I created based on the calcualtion shown in here.

 

s = c/2 * bulge

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost