Auto edit bulge radius pline to even-odd ?

Auto edit bulge radius pline to even-odd ?

Anonymous
Not applicable
3,729 Views
16 Replies
Message 1 of 17

Auto edit bulge radius pline to even-odd ?

Anonymous
Not applicable

Hi all,

 

Can someone have lisp edit bulge radius pline to even-odd.

Pls see attached photo.

Capture.JPG

Thanks

0 Likes
Accepted solutions (2)
3,730 Views
16 Replies
Replies (16)
Message 2 of 17

Kent1Cooper
Consultant
Consultant

That seems possible by altering bulge factors in entity data, but I notice one of the odd ones is rounded up and the other down -- more criteria would be needed on which to determine the desired results.  And I assume you're aware that true tangency between arc segments would be lost, though with values like these they would remain very close to tangent.

 

[And I confess to being curious about what such a thing could possibly be needed for....]

Kent Cooper, AIA
0 Likes
Message 3 of 17

Anonymous
Not applicable

Thank you for repply.

 

That is for Lanscape pline.  Only need radius bulge to even-odd 0 or 5. Example: 7863 --> 7865, 7862->7860

Capture.JPG

 

0 Likes
Message 4 of 17

_gile
Consultant
Consultant

Hi,

 

It seems to me you cannot both change radii of successive tangent arcs and keep the tangency between them.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 17

Anonymous
Not applicable

Hi Gile,

 

Yes i dont need tangent arcs and keep the tangency between them. Dont need keep exactly tangency between them. Only change radius.

 

0 Likes
Message 6 of 17

_gile
Consultant
Consultant

You can try the following routine doing: (editPline (car (entsel "\nSelect Polyline: ")))

The operation will fail if rounding a radius make it smaller than half the arc chord.

 

(defun editPline (pline / roundTo5 asin roundBulge editPlineList elst)

  (defun roundTo5 (x)
    (* 5.
       (fix ((if (minusp x)
	       -
	       +
	     )
	      (/ x 5.)
	      0.5
	    )
       )
    )
  )
(defun asin (n) (cond ((equal n 1. 1e-9) (/ pi 2.)) ((equal n -1. 1e-9) (/ pi -2.)) ((< -1. n 1.) (atan n (sqrt (- 1 (expt n 2)))) ) ) ) (defun tan (a) (/ (sin a) (cos a))) (defun roundBulge (chord bulge) (tan (/ (asin (/ chord (* 2. (roundTo5 (/ chord (* 2. (sin (* 2 (atan bulge)))) ) ) ) ) ) 2. ) ) ) (defun editPlineList (lst start) (cond ((null lst) nil) ((= (caar lst) 10) (vl-list* (car lst) (cadr lst) (caddr lst) (cons 42 (roundBulge (distance (cdar lst) (cond ((cdar (vl-member-if '(lambda (x) (= (car x) 10)) (cdr lst)))) ((cdr start)) ) ) (cdr (cadddr lst)) ) ) (editPlineList (cddddr lst) (cond (start) ((car lst)) ) ) ) ) (T (cons (car lst) (editPlineList (cdr lst) start))) ) ) (if (= "LWPOLYLINE" (cdr (assoc 0 (setq elst (entget pline))))) (if (vl-catch-all-error-p (vl-catch-all-apply 'entmod (list (editPlineList elst nil))) ) (alert "Invalid operation") ) ) )


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 17

_gile
Consultant
Consultant
Accepted solution

The upper code is wrong with bulges greater then 1 or lower than -1.

Use the following one instead.

 

(defun editPline (pline / roundTo5 asin roundBulge editPlineList elst)

  (defun roundTo5 (x)
    (* 5.
       (fix ((if (minusp x)
	       -
	       +
	     )
	      (/ x 5.)
	      0.5
	    )
       )
    )
  )
  (defun asin (n)
    (cond
      ((equal n 1. 1e-9) (/ pi 2.))
      ((equal n -1. 1e-9) (/ pi -2.))
      ((< -1. n 1.)
       (atan n (sqrt (- 1 (expt n 2))))
      )
    )
  )

  (defun tan (a) (/ (sin a) (cos a)))
  
  (defun roundBulge (chord bulge / alpha result)
    (setq alpha (asin
	      (/ chord
		 (* 2.
		    (roundTo5
		      (/ chord
			 (* 2. (sin (* 2 (atan bulge))))
		      )
		    )
		 )
	      )
	    )
	 )
    (if	(< 1 (abs bulge))
      (setq alpha (+ pi alpha))
    )
    (setq result (tan (/ alpha 2.)))
    (if	(or (< result 0 bulge) (< bulge 0 result))
      (- result)
      result
    )
  )

  (defun editPlineList (lst start)
    (cond
      ((null lst) nil)
      ((= (caar lst) 10)
       (vl-list*
	 (car lst)
	 (cadr lst)
	 (caddr lst)
	 (cons
	   42
	   (if (zerop (cdr (cadddr lst)))
	     0.
	     (roundBulge
	       (distance
		 (cdar lst)
		 (cond
		   ((cdar (vl-member-if '(lambda (x) (= (car x) 10)) (cdr lst))))
		   ((cdr start))
		 )
	       )
	       (cdr (cadddr lst))
	     )
	   )
	 )
	 (editPlineList
	   (cddddr lst)
	   (cond (start)
		 ((car lst))
	   )
	 )
       )
      )
      (T (cons (car lst) (editPlineList (cdr lst) start)))
    )
  )

  (if (= "LWPOLYLINE" (cdr (assoc 0 (setq elst (entget pline)))))
    (if	(vl-catch-all-error-p
	  (vl-catch-all-apply 'entmod (list (editPlineList elst nil)))
	)
      (alert "Invalid operation")
    )
  )
)


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 8 of 17

Anonymous
Not applicable

Your code exactly what i mean. Very usefull for me.

 

Thank you so much Gile. Heart

 

One more point: that is for 1 unit = 1 mm. If 1unit = 1m then i must /1000. Where i modify in your code ? 

 

 

 

0 Likes
Message 9 of 17

phanaem
Collaborator
Collaborator
Accepted solution

Try this

(defun c:test ( / e q a b c r x)
  (if
    (and
      (setq e (ssget "_+.:S:L" '((0 . "LWPOLYLINE") (-4 . "<>") (42 . 0.0))))
      (progn
        (initget 6)
        (setq q (getdist "\nSpecify rounding number: "))
      )
    )
    (progn
      (setq e (vlax-ename->vla-object (ssname e 0))
            a (vlax-curve-getstartparam e)
            c (vlax-curve-getendparam   e)
      )
      (while (< a c)
        (setq b (vla-getbulge e a))
        (if
          (> (setq r (distance '(0.0 0.0 0.0) (vlax-curve-getsecondderiv e a))) (/ q 2.0))
          (progn
            (setq x (/
                      (* q (fix (+ 0.5 (/ r q))))
                      (distance
                        (vlax-curve-getpointatparam e a)
                        (vlax-curve-getpointatparam e (+ 1.0 a))
                      )
                      0.5
                    )
            )
            (vla-setbulge e a
              (*
                ((if (< (abs b) 1) - +) x (sqrt (- (* x x) 1.0)))
                (if (minusp b) -1 1)
              )
            )
          )
        )
        (setq a (1+ a))
      )
    )
  )
  (princ)
)
Message 10 of 17

Anonymous
Not applicable

Okey phanaem,

your code very userfull. Smiley Happy

 

Thank you so much.

0 Likes
Message 11 of 17

_gile
Consultant
Consultant

@phanaem, nice code.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 12 of 17

phanaem
Collaborator
Collaborator

@_gilewrote:

@phanaem, nice code.


Thanks Gile.

I noticed the most programmers take the bulge definition literally, which is "the tangent of 1/4 of the included angle for the arc between the selected vertex and the next vertex".  Take a look at this picture. The angle b is half of the arc MB, which is half of the arc AB = a. So the angle b is exactly a/4 and the tangent of b (which is the bulge value) is the distance MC divided by AC. It is much easier to calculate the bulge this way, no need for the trigonometric functions.

acad_2018-04-15_20-36-47.png

0 Likes
Message 13 of 17

_gile
Consultant
Consultant

Yes, I know what you show here.

The thing I didn't give enough attention is the second derivative at some parameter of a polyline.

 

You provided a nice trick anyway.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 14 of 17

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... 

That is for Lanscape pline.  Only need radius bulge to even-odd 0 or 5. Example: 7863 --> 7865, 7862->7860


So now it occurs to me -- It would be far  simpler to round the text content  of the Dimensions to the nearest multiple of .0005 [or of .05 in the original image], rather than change the Polyline routings.  There are lots of number-rounding routines on these Forums, and imposing the rounded result on the Dimensions is easy.  Would that serve the purpose as well?

 

Yes, if you do something to alter the shape of the Polyline, the Dimensions' text content wouldn't update automatically.  But with the forced-bulge-factor approach, an altered associative Dimension's updated radius value isn't [except by very rare coincidence] going to be to the right rounding, anyway.  So that "drawback" isn't really a disadvantage -- in either case you'd need to run some  routine again, either to re-alter the shape of the Polyline, or to re-override the text content of the Dimension.

Kent Cooper, AIA
0 Likes
Message 15 of 17

Anonymous
Not applicable

Yep i know that.

That is process convert sketch (jpg concept) to drawing of architects. She's draw curve by a lot of pline. So she can not draw exactly right now because very slow, only draw approach. If you draw exactly one by one cuver then slowly. When finish just use lisp @phanaem fix exactly valua radius by one command (i modifed for multi object). Quickly and exactly. Smiley Happy 

Thanks for your solution.

 

0 Likes
Message 16 of 17

_gile
Consultant
Consultant

@Kent1Cooper wrote:

@Anonymous wrote:

.... 

That is for Lanscape pline.  Only need radius bulge to even-odd 0 or 5. Example: 7863 --> 7865, 7862->7860


So now it occurs to me -- It would be far  simpler to round the text content  of the Dimensions to the nearest multiple of .0005 [or of .05 in the original image], rather than change the Polyline routings.  There are lots of number-rounding routines on these Forums, and imposing the rounded result on the Dimensions is easy.  Would that serve the purpose as well?

 

Yes, if you do something to alter the shape of the Polyline, the Dimensions' text content wouldn't update automatically.  But with the forced-bulge-factor approach, an altered associative Dimension's updated radius value isn't [except by very rare coincidence] going to be to the right rounding, anyway.  So that "drawback" isn't really a disadvantage -- in either case you'd need to run some  routine again, either to re-alter the shape of the Polyline, or to re-override the text content of the Dimension.


This could be easily done without forcing the dimension text.

You can simply define a dimension style with DIMDEC = 0 and DIMRND = 5



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 17 of 17

Kent1Cooper
Consultant
Consultant

@_gile wrote:

@Kent1Cooper wrote:

 


So now it occurs to me -- It would be far  simpler to round the text content  of the Dimensions to the nearest multiple of .0005 [or of .05 in the original image], rather than change the Polyline routings.  ....


This could be easily done without forcing the dimension text.

You can simply define a dimension style with DIMDEC = 0 and DIMRND = 5


True -- I think I was over-hastily picturing rounding only being able to go to any number at each decimal place, so that you could round to 2 decimal places and get X.04 or X.05 or X.06, but couldn't limit it to just 0 and 5 endings.  But yes, you can.

 

They would want DIMDEC = 2 and DIMRND = 0.05 in one example, and DIMDEC = 4 and DIMRND = 0.0005 in the other.  Unless there's some reason they actually need the Polyline bulges to be truly at those rounded radii [hard to imagine for the example situation], that's the no-code-necessary solution.

Kent Cooper, AIA
0 Likes