Jump to content

Calculate bulge of polyline arc segment


gsc

Recommended Posts

Hi,

 

I want to calculate the bulge of a polyline arc segment based on (Center) point, Angle1, Angle2 and Radius variables.

 

The formula I use is described on http://lee-mac.com/bulgeconversion.html

(Arc to Bulge)

 

This formula is based on an ARC object, which always returns a positive bulge.

But the bulge of an arc segment in a LWPOLYLINE has a either negative (clockwise) or positive (counter clockwise) value.

 

How can I, based on the variables, calculate whether this value should be negative or positive?

Link to comment
Share on other sites

How can I, based on the variables, calculate whether this value should be negative or positive?

 

With only a center, start point and end point, it is ambiguous as to whether the arc should traverse between the start & end point in a clockwise or anticlockwise direction - more information is required.

Link to comment
Share on other sites

I want to re-route a lwpolyline (red line), when it crosses a circle (cyan dashed), with a specified bend radius (green line). The lwpolyline is always located in the first quadrant, but the start/end point can be in any direction. The circle CP can be either left, right or on the lwpolyline. The bend radius line has to follow the shortest route around the circle. in the end the bend radius line needs to be added to the existing lwpolyline

 

I have managed to calculate the 4 vertex points (v1-v4), but i have problems calculating the correct bulges, since the direction of the lwpolyline affects the order of first angle and second angle to calculate the correct bulge (positive or negative)

 

attachment.php?attachmentid=62868&cid=1&stc=1

04fb25taDHQee6tv9KKveEx4ayiygPWQWUDy7H2XtfJp15+69+k+zFhZXDjR8mlVPZgHtIbOAwmu8mzV+aVJmAcHJLKATNP2fhjILCEtmAQBkQmYBAGRCZgEAZEJmAQBkQmYBAGRCZgEAZEJmAQBkQmYBAGRCZgEAZEJmAQBkQmYBAGTif6b73s9YnZW+AAAAAElFTkSuQmCCAA==

Case.jpg

Link to comment
Share on other sites

In routine, write and use bulges for one case... Then check for intersection of green lwpolyline and circle; if there are 3 points of intersection (use 'intersectwith method) which will always be true if bulges are opposite, you then switch bulge signs and the result should be like it was drawn in your picture... If intersectwith returns single point or equal points to apex quadrant point of circle, then sign assumptions are correct and routine should terminate without needing of switching bulge signs...

Link to comment
Share on other sites

Try the following:

([color=BLUE]defun[/color] c:bend ( [color=BLUE]/[/color] cir par ply rad )
   ([color=BLUE]if[/color] ([color=BLUE]and[/color] ([color=BLUE]setq[/color] ply (select [color=MAROON]"\nSelect 2D polyline: "[/color] [color=MAROON]"LWPOLYLINE"[/color]))
            ([color=BLUE]setq[/color] cir (select [color=MAROON]"\nSelect circle: "[/color]      [color=MAROON]"CIRCLE"[/color]))
            ([color=BLUE]setq[/color] par ([color=BLUE]vlax-curve-getparamatpoint[/color] ([color=BLUE]car[/color] ply) ([color=BLUE]vlax-curve-getclosestpointto[/color] ([color=BLUE]car[/color] ply) ([color=BLUE]trans[/color] ([color=BLUE]cadr[/color] ply) 1 0)))
                  cir ([color=BLUE]entget[/color] ([color=BLUE]car[/color] cir))
                  rad (bendradius [color=MAROON]"\nSpecify bend radius: "[/color] ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 40 cir)))
            )
       )
       ([color=BLUE]entmake[/color]
           ([color=BLUE]append[/color]
              '(   (000 . [color=MAROON]"LWPOLYLINE"[/color])
                   (100 . [color=MAROON]"AcDbEntity"[/color])
                   (100 . [color=MAROON]"AcDbPolyline"[/color])
                   (090 . 6)
                   (070 . 0)
               )
               (bend
                   ([color=BLUE]vlax-curve-getpointatparam[/color] ([color=BLUE]car[/color] ply) ([color=BLUE]fix[/color] par))
                   ([color=BLUE]vlax-curve-getpointatparam[/color] ([color=BLUE]car[/color] ply) ([color=BLUE]1+[/color] ([color=BLUE]fix[/color] par)))
                   ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 10 cir))
                   ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 40 cir))
                   rad
               )
           )
       )
   )
   ([color=BLUE]princ[/color])
)
([color=BLUE]defun[/color] select ( msg typ [color=BLUE]/[/color] sel )
   ([color=BLUE]while[/color]
       ([color=BLUE]progn[/color] ([color=BLUE]setvar[/color] 'errno 0) ([color=BLUE]setq[/color] sel ([color=BLUE]entsel[/color] msg))
           ([color=BLUE]cond[/color]
               (   ([color=BLUE]=[/color] 7 ([color=BLUE]getvar[/color] 'errno))
                   ([color=BLUE]princ[/color] [color=MAROON]"\nMissed, try again."[/color])
               )
               (   ([color=BLUE]null[/color] sel) [color=BLUE]nil[/color])
               (   ([color=BLUE]/=[/color] typ ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 0 ([color=BLUE]entget[/color] ([color=BLUE]car[/color] sel)))))
                   ([color=BLUE]princ[/color] [color=MAROON]"\nInvalid object selected."[/color])
               )
           )
       )
   )
   sel
)
([color=BLUE]defun[/color] bendradius ( msg rad [color=BLUE]/[/color] rtn )
   ([color=BLUE]while[/color]
       ([color=BLUE]and[/color]
           ([color=BLUE]progn[/color] ([color=BLUE]initget[/color] 6) ([color=BLUE]setq[/color] rtn ([color=BLUE]getdist[/color] msg)))
           ([color=BLUE]<[/color] rtn rad)
       )
       ([color=BLUE]princ[/color] ([color=BLUE]strcat[/color] [color=MAROON]"\nBend radius must be greater than or equal to "[/color] ([color=BLUE]rtos[/color] rad) [color=MAROON]"."[/color]))
   )
   rtn
)            
([color=BLUE]defun[/color] bend ( pt1 pt2 cpt crd brd [color=BLUE]/[/color] ang bu1 bu2 int pt3 pt4 pt5 pt6 pt7 vc1 )
   ([color=BLUE]setq[/color] vc1 (vx1 ([color=BLUE]mapcar[/color] '[color=BLUE]-[/color] pt2 pt1))
         pt3 ([color=BLUE]mapcar[/color] '[color=BLUE]+[/color] pt1 (vxs vc1 (vxv ([color=BLUE]mapcar[/color] '[color=BLUE]-[/color] cpt pt1) vc1)))
   )
   ([color=BLUE]cond[/color]
       (   ([color=BLUE]equal[/color] pt3 cpt 1e-
           ([color=BLUE]prompt[/color] [color=MAROON]"\nCircle center cannot lie on polyline."[/color])
       )
       (   ([color=BLUE]<=[/color] crd ([color=BLUE]distance[/color] cpt pt3))
           ([color=BLUE]prompt[/color] [color=MAROON]"\nCircle does not intersect polyline."[/color])
       )
       (   ([color=BLUE]setq[/color] ang ([color=BLUE]angle[/color] pt3 cpt)
                 pt4 ([color=BLUE]polar[/color] cpt ang ([color=BLUE]-[/color] brd crd))
                 pt5 ([color=BLUE]polar[/color] pt3 ang ([color=BLUE]-[/color] brd))
                 int (LM:inters-line-circle pt5 ([color=BLUE]mapcar[/color] '[color=BLUE]+[/color] pt5 vc1) pt4 ([color=BLUE]+[/color] brd brd))
                 pt6 ([color=BLUE]polar[/color] ([color=BLUE]car[/color]  int) ([color=BLUE]angle[/color] ([color=BLUE]car[/color]  int) pt4) brd)
                 pt7 ([color=BLUE]polar[/color] ([color=BLUE]cadr[/color] int) ([color=BLUE]angle[/color] ([color=BLUE]cadr[/color] int) pt4) brd)
                 bu1 (tan ([color=BLUE]/[/color] ([color=BLUE]-[/color] ang ([color=BLUE]angle[/color] ([color=BLUE]car[/color] int) pt4)) 4.0))
                 bu2 (tan ([color=BLUE]/[/color] ([color=BLUE]-[/color] ([color=BLUE]angle[/color] pt4 pt6) ([color=BLUE]angle[/color] pt4 pt7)) 4.0))
           )
           ([color=BLUE]list[/color]
               ([color=BLUE]cons[/color] 10 pt1)
              '(42 . 0.0)
               ([color=BLUE]cons[/color] 10 ([color=BLUE]polar[/color] ([color=BLUE]cadr[/color] int) ang brd))
               ([color=BLUE]cons[/color] 42 bu1)
               ([color=BLUE]cons[/color] 10 pt7)
               ([color=BLUE]cons[/color] 42 bu2)
               ([color=BLUE]cons[/color] 10 pt6)
               ([color=BLUE]cons[/color] 42 bu1)
               ([color=BLUE]cons[/color] 10 ([color=BLUE]polar[/color] ([color=BLUE]car[/color]  int) ang brd))
              '(42 . 0.0)
               ([color=BLUE]cons[/color] 10 pt2)
           )
       )
   )
)

[color=GREEN];; Line-Circle Intersection (vector version)  -  Lee Mac[/color]
[color=GREEN];; Returns the point(s) of intersection between an infinite line defined by[/color]
[color=GREEN];; points p,q and circle with centre c and radius r[/color]

([color=BLUE]defun[/color] LM:inters-line-circle ( p q c r [color=BLUE]/[/color] v s )
   ([color=BLUE]setq[/color] v ([color=BLUE]mapcar[/color] '[color=BLUE]-[/color] q p)
         s ([color=BLUE]mapcar[/color] '[color=BLUE]-[/color] p c)
   )
   ([color=BLUE]mapcar[/color] '([color=BLUE]lambda[/color] ( s ) ([color=BLUE]mapcar[/color] '[color=BLUE]+[/color] p (vxs v s)))
       (quad (vxv v v) ([color=BLUE]*[/color] 2 (vxv v s)) ([color=BLUE]-[/color] (vxv s s) ([color=BLUE]*[/color] r r)))
   )
)

[color=GREEN];; Quadratic Solution  -  Lee Mac[/color]
[color=GREEN];; Args: a,b,c - coefficients of ax^2 + bx + c = 0[/color]

([color=BLUE]defun[/color] quad ( a b c [color=BLUE]/[/color] d r )
   ([color=BLUE]cond[/color]
       (   ([color=BLUE]equal[/color] 0.0 ([color=BLUE]setq[/color] d ([color=BLUE]-[/color] ([color=BLUE]*[/color] b b) ([color=BLUE]*[/color] 4.0 a c))) 1e-
           ([color=BLUE]list[/color] ([color=BLUE]/[/color] b ([color=BLUE]*[/color] -2.0 a)))
       )
       (   ([color=BLUE]<[/color] 0 d)
           ([color=BLUE]setq[/color] r ([color=BLUE]sqrt[/color] d))
           ([color=BLUE]list[/color] ([color=BLUE]/[/color] ([color=BLUE]-[/color] r b) ([color=BLUE]*[/color] 2.0 a)) ([color=BLUE]/[/color] ([color=BLUE]-[/color] ([color=BLUE]-[/color] b) r) ([color=BLUE]*[/color] 2.0 a)))
       )
   )
)

[color=GREEN];; Vector Dot Product  -  Lee Mac[/color]
[color=GREEN];; Args: u,v - vectors in R^n[/color]

([color=BLUE]defun[/color] vxv ( u v )
   ([color=BLUE]apply[/color] '[color=BLUE]+[/color] ([color=BLUE]mapcar[/color] '[color=BLUE]*[/color] u v))
)

[color=GREEN];; Vector x Scalar  -  Lee Mac[/color]
[color=GREEN];; Args: v - vector in R^n, s - real scalar[/color]

([color=BLUE]defun[/color] vxs ( v s )
   ([color=BLUE]mapcar[/color] '([color=BLUE]lambda[/color] ( n ) ([color=BLUE]*[/color] n s)) v)
)

[color=GREEN];; Unit Vector  -  Lee Mac[/color]
[color=GREEN];; Args: v - vector in R^2 or R^3[/color]

([color=BLUE]defun[/color] vx1 ( v )
   (   ([color=BLUE]lambda[/color] ( n ) ([color=BLUE]if[/color] ([color=BLUE]equal[/color] 0.0 n 1e-10) [color=BLUE]nil[/color] ([color=BLUE]mapcar[/color] '[color=BLUE]/[/color] v ([color=BLUE]list[/color] n n n))))
       ([color=BLUE]distance[/color] '(0.0 0.0 0.0) v)
   )
)

[color=GREEN];; Tangent  -  Lee Mac[/color]
[color=GREEN];; Args: x - real[/color]

([color=BLUE]defun[/color] tan ( x )
   ([color=BLUE]if[/color] ([color=BLUE]not[/color] ([color=BLUE]equal[/color] 0.0 ([color=BLUE]cos[/color] x) 1e-10))
       ([color=BLUE]/[/color] ([color=BLUE]sin[/color] x) ([color=BLUE]cos[/color] x))
   )
)

([color=BLUE]princ[/color])

 

bend.gif

Link to comment
Share on other sites

@gsc... You can avoid bulges - you just need points...

 

(defun c:bend ( / acos li ci d c a r br ap1 ap2 ip apc1 apc2 ip1h ip2h an1 an2 ip1h1 ip1h2 ip2h1 ip2h2 s1 e1 s2 e2 apc11 apc12 apc21 apc22 sm1 em1 sm2 em2 )

 (defun acos ( x )
   (cond
     ((equal x 1.0 1e- 0.0)
     ((equal x 0.0 1e- (* 0.5 pi))
     ((equal x -1.0 1e- pi)
     ((and (minusp x) (equal x 0.0 1e-) (* 1.5 pi))
     ((atan (/ (sqrt (- 1 (* x x))) x)))
   )
 )

 (if
   (and
     (progn
       (while (or (not (setq li (car (entsel "\nPick line entity...")))) (if li (/= (cdr (assoc 0 (entget li))) "LINE")))
         (prompt "\nMissed or picked entity is not line enitity...")
       )
       t
     )
     (progn
       (while (or (not (setq ci (car (entsel "\nPick circle entity...")))) (if ci (/= (cdr (assoc 0 (entget ci))) "CIRCLE")))
         (prompt "\nMissed or picked entity is not circle enitity...")
       )
       t
     )
     (if (>= (setq d (distance (setq c (cdr (assoc 10 (entget ci)))) (inters c (polar c (+ (* 0.5 pi) (setq a (angle (cdr (assoc 10 (entget li))) (cdr (assoc 11 (entget li)))))) 1.0) (cdr (assoc 10 (entget li))) (cdr (assoc 11 (entget li))) nil))) (setq r (cdr (assoc 40 (entget ci)))))
       (progn
         (prompt "\nLine enitity does not pass through circle or don't have apparent intersections with circle or it is touching circle in single apex point... Quitting...")
         nil
       )
       t
     )
     (setq br (getdist "\nPick or specify bend radius : "))
     (progn
       (while (< br r)
         (prompt "\nBend radius must be larger than radius of circle (> ") (princ (rtos r 2 50)) (prompt ")")
         (setq br (getdist "\nPick or specify bend radius : "))
       )
       t
     )
   )
   (progn
     (setq ap1 (polar c (+ (* 0.5 pi) a) r) ap2 (polar c (- a (* 0.5 pi)) r))
     (setq ip (inters ap1 ap2 (cdr (assoc 10 (entget li))) (cdr (assoc 11 (entget li))) nil))
     (if (> (distance ip ap1) (distance ip ap2))
       (mapcar 'set '(ap1 ap2) (list ap2 ap1))
     )
     (setq apc1 (polar ap1 (angle ap1 ap2) br) apc2 (polar ap2 (angle ap2 ap1) br))
     (setq ip1h (mapcar '/ (mapcar '+ ip ap1) (list 2.0 2.0 2.0)) ip2h (mapcar '/ (mapcar '+ ip ap2) (list 2.0 2.0 2.0)))
     (setq an1 (acos (/ (distance apc1 ip1h) (distance apc1 ap1))) an2 (acos (/ (distance apc2 ip2h) (distance apc2 ap2))))
     (setq ip1h1 (polar apc1 (+ an1 (angle ap2 ap1)) br) ip1h2 (polar apc1 (- (angle ap2 ap1) an1) br))
     (setq ip2h1 (polar apc2 (+ an2 (angle ap1 ap2)) br) ip2h2 (polar apc2 (- (angle ap1 ap2) an2) br))
     (setq s1 (mapcar '+ ip1h1 (mapcar '- ip1h1 ap1)) e1 (mapcar '+ ip1h2 (mapcar '- ip1h2 ap1)))
     (setq s2 (mapcar '+ ip2h1 (mapcar '- ip2h1 ap2)) e2 (mapcar '+ ip2h2 (mapcar '- ip2h2 ap2)))
     (setq apc11 (mapcar '+ ip1h1 (mapcar '- ip1h1 apc1)) apc12 (mapcar '+ ip1h2 (mapcar '- ip1h2 apc1)))
     (setq apc21 (mapcar '+ ip2h1 (mapcar '- ip2h1 apc2)) apc22 (mapcar '+ ip2h2 (mapcar '- ip2h2 apc2)))
     (setq sm1 (polar apc11 (angle apc11 (mapcar '/ (mapcar '+ s1 ip1h1) (list 2.0 2.0 2.0))) br))
     (setq em1 (polar apc12 (angle apc12 (mapcar '/ (mapcar '+ e1 ip1h2) (list 2.0 2.0 2.0))) br))
     (setq sm2 (polar apc21 (angle apc21 (mapcar '/ (mapcar '+ s2 ip2h1) (list 2.0 2.0 2.0))) br))
     (setq em2 (polar apc22 (angle apc22 (mapcar '/ (mapcar '+ e2 ip2h2) (list 2.0 2.0 2.0))) br))
     (vl-cmdf "_.PLINE" "_non" s1 "_A" "_S" "_non" sm1 "_non" ip1h1 "_S" "_non" ap1 "_non" ip1h2 "_S" "_non" em1 "_non" e1 "")
     (vl-cmdf "_.PLINE" "_non" s2 "_A" "_S" "_non" sm2 "_non" ip2h1 "_S" "_non" ap2 "_non" ip2h2 "_S" "_non" em2 "_non" e2 "")
   )
 )
 (princ)
)

Regards, merry christmas!

Edited by marko_ribar
Link to comment
Share on other sites

I have tested both solutions succesfully, thanx for it, but I am focussing on Lee's code:

In my example I used a straight polyline (red line) with only 2 points as an example.

But this polyline can also have multiple vertices and possible tangent arc-segments.

In fact there can be multiple circles around the route of the polyline, which need to be avoided.

This means that there may be more vertex points than only PT1 and PT2 (in between or outside)

 

So I also need to:

 

  1. List the vertex points and bulges of the existing (red) polyline
  2. Figure out which vertex points are possibly between PT1 and PT2 and if there remove them from the list
  3. Insert the "Bend"
  4. Draw the new polyline
  5. Remove the old polyline

How do i approach step 2?

 

 

 

Other thing is, it does happen (small chance) that the CP circle is exactly on the polyline. This means that the user should have the choice to the re-route the polyline right or left from the circle.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...