Hi folks, been a while!
I have a client that wants to select a polyline (or multiple polylines) containing multiple curved segments and round all the radii of those segment to the nearest whole unit.
I've been looking around and have not found anything that addresses this specifically. Any help would be greatly appreciated.
Thanks as always!
-JP
This possibly contains a method but is line arc line. Using it redraws the arc so could set the radius.
(defun c:DyF (/ *error* _pnt AT:GetSel vl ov ent plst elst gr sp)
;; Dynamic Fillet
;; Alan J. Thompson, 03.07.11 / 03.09.11
(vl-load-com)
(defun *error* (msg)
(redraw)
(and vl (mapcar (function setvar) vl ov))
(and elst (mapcar (function redraw) elst '(4 4)))
(if (and msg (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*QUIT*,")))
(princ (strcat "\nError: " msg))
)
)
(defun _pnt (p) (trans (list (car p) (cadr p)) 0 1))
(defun AT:GetSel (meth msg fnc / ent)
;; meth - selection method (entsel, nentsel, nentselp)
;; msg - message to display (nil for default)
;; fnc - optional function to apply to selected object
;; Ex: (AT:GetSel entsel "\nSelect arc: " (lambda (x) (eq (cdr (assoc 0 (entget (car x)))) "ARC")))
;; Alan J. Thompson, 05.25.10
(setvar 'ERRNO 0)
(while
(progn (setq ent (meth (cond (msg)
("\nSelect object: ")
)
)
)
(cond ((eq (getvar 'ERRNO) 7) (princ "\nMissed, try again."))
((eq (type (car ent)) 'ENAME)
(if (and fnc (not (fnc ent)))
(princ "\nInvalid object!")
)
)
)
)
)
ent
)
(if (setq ent
(car
(AT:GetSel
entsel
"\nSelect arc: "
(lambda (x)
(if (eq "ARC" (cdr (assoc 0 (entget (car x)))))
(vl-every (function (lambda (p / ss)
(if (setq ss (ssget "_C" p p '((0 . "LINE"))))
(setq elst (cons (ssname ss 0) elst))
)
)
)
(setq plst (list (_pnt (vlax-curve-getStartPoint (car x)))
(_pnt (vlax-curve-getEndPoint (car x)))
)
)
)
)
)
)
)
)
(progn
(setq ov (mapcar (function getvar) (setq vl '("CMDECHO" "FILLETRAD"))))
(while
(progn
(setq gr (grread T 15 0))
(cond
((eq 5 (car gr))
(redraw)
(grdraw (setq sp (trans (vlax-curve-getStartPoint ent) 0 1)) (cadr gr) 1 -1)
(princ
(strcat "\rFillet radius: "
(rtos (setvar 'FILLETRAD (distance sp (cadr gr))))
" "
)
)
(if (vl-cmdf "_.fillet" (list (car elst) (car plst)) (list (cadr elst) (cadr plst)))
(progn (entdel ent) (setq ent (entlast)))
T
)
)
)
)
)
)
)
(*error* nil)
(princ)
)
Ditto what @ronjonp stated.
When you change the radius and retain the two segment endpoints, you have to change the radius point and delta, but the chord remains the same. The bulge must change as well, which is the key to your computation (for a bulge /= 0):
(setq delta (* 4 (atan (abs bulge)))
r (abs (/ chord 2 (sin (/ delta 2))))
)
You'll have to rearrange the formulas to compute the bulge from the radius.
Just be careful to keep the sign of the bulge the same. That is all you are changing per segment.
John F. Uhden
@john.uhden wrote:
.... When you change the radius and retain the two segment endpoints....
I certainly would not assume that part. @jpCADconsulting , is that what you want? Or do you want the adjacent line segments [I'm assuming the arc segments are flanked by line segments on both sides, but that's another question] to stay where they are path-wise but have their endpoints adjusted to suit the new radius, tangent to the adjusted arc segment, just as if you had used a FILLET command on them? A kind of extreme case to illustrate the difference:
[And it also raises the question of whether you're always dealing with arc segments that are tangent to the adjacent line segments, in Fillet-wise arrangement -- there are certainly lots of other possibilities.]
The difficulty is that AutoCAD does not store the radius of a Polyline arc segment as a piece of entity data. It stores a bulge factor, and the vertex locations at either end can be a very challenging computation if the adjacent line segments are not perpendicular. If you're talking about only rounded-corner 90° changes in direction, maybe not so difficult.
Fillet will change a pline radius but you need to work out the sequence is it, "segment arc segment" before applying. But like Kent this is a true tangent solution. Manually Fillet, pick the mid pt of the adjacent pline "line" segments.
Need to work out how read pline segment order say line arc line arc line line arc line.
((-1 . <Entity name: 659d51c0>) (0 . "LWPOLYLINE") (5 . "1DDD") (330 . <Entity name: 3d667520>) (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (370 . -1) (100 . "AcDbPolyline")
(90 . 6) ; 6 vertices
(70 . 0)
(43 . 0.0)
(38 . 0.0)
(39 . 0.0)
(10 -290.0 126.0) ; 1st point
(40 . 0.0)
(41 . 0.0)
(42 . 0.0) ; no bulge
(91 . 0)
(10 -256.667268683904 192.279044924515) ; 2nd point
(40 . 0.0)
(41 . 0.0)
(42 . -0.508204106875609) ; bulge value
(91 . 0)
(10 -159.189832703418 208.454364385618) ; 3rd point
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(91 . 0)
(10 -147.001442474056 196.494429027982)
(40 . 0.0)
(41 . 0.0)
(42 . 0.431880954930485) ; bulge
(91 . 0)
(10 -120.814586750271 197.527534827221) ; 5th point
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(91 . 0)
(10 -24.402170920898 308.345167019768) ; 6th point
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(91 . 0)
(210 0.0 0.0 1.0))
In the scenario below it won't have a rounded radius number arc, if the line segments beside the arc are parallel.
I doubt that @jpCADconsulting was expecting to have the new radius be tangent at both ends. I'm pretty sure that he meant exactly what he indicated... just to change the radius of the bulged segments:
I've been working on the code with help from Lee Mac. The procedure is to solve for the bulge given the chord and desired radius.
Do you want the new radius applied to all bulged segments, or to operate separately on each segment?
What about existing straight segments?
John F. Uhden
Those may not be exactly but certainly could be the same radius:
What would be your criteria for making one as opposed to the other?
@jpCADconsulting , we really need to know which variety of adjustment of arc segments you're after, or there could be a lot of time wasted pursuing the wrong goal.
@jpCADconsulting , we really need to know which variety of adjustment of arc segments you're after, or there could be a lot of time wasted pursuing the wrong goal.
How much of the consulting fee do you get for your time ( wasted or not )? 😂
As @ronjonp stated in previous post we need a lot more data to jump into finding solution.
Generally, problem is solvable in case when you have combination line-arc-line polyline segments. One would extract all arc segments and adjoin line segments and redefine radii by finding new tangents points for nearest integer radii (circle TTR). this would redefine arc segment start and end point, bulging will stay unchanged. In case of arc-arc polyline segment I don't find correct solution. But lets wait for @jpCADconsulting and his client.
Miljenko Hatlak
Out of curiosity I've been working on this challenge because I don't think I have ever had to compute the bulge from a radius, knowing only the chord distance as well. I've got the trigonometry figured out, but only if retaining the vertex locations, which will remove any tangency with the previous and next segments. Is that what you were hoping for, or must the vertices be moved to retain tangency?
John F. Uhden
Did you ever find a solution?
I have had the math all figured out for quite a while. Almost forgot about entirely. Just need a little time to put it together, that is if you still need it.
While I'm at it (if I am) do you want to select polylines one at a time, or by multiple selection, or by layer?
BTW, my thanks to @hak_vz and @pendean for finding the thread for me. I am historically challenged except that the Battle of Hastings was in 1066.
John F. Uhden
So, is there any update on this? I need to change the radii of arcs in polylines while holding field located points... I am just creating a fit polyline, exploding it and labeling the radii's and a decurved polyline under it to snap as I redraw it utilizing snaps, whole numbers and creating new tangencies or compound curves... having a button to do the math would be nice.
Maybe this is useful.
(defun c:DyF (/ *error* _pnt AT:GetSel vl ov ent plst elst gr sp)
;; Dynamic Fillet
;; Alan J. Thompson, 03.07.11 / 03.09.11
(vl-load-com)
(defun *error* (msg)
(redraw)
(and vl (mapcar (function setvar) vl ov))
(and elst (mapcar (function redraw) elst '(4 4)))
(if (and msg (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*QUIT*,")))
(princ (strcat "\nError: " msg))
)
)
(defun _pnt (p) (trans (list (car p) (cadr p)) 0 1))
(defun AT:GetSel (meth msg fnc / ent)
;; meth - selection method (entsel, nentsel, nentselp)
;; msg - message to display (nil for default)
;; fnc - optional function to apply to selected object
;; Ex: (AT:GetSel entsel "\nSelect arc: " (lambda (x) (eq (cdr (assoc 0 (entget (car x)))) "ARC")))
;; Alan J. Thompson, 05.25.10
(setvar 'ERRNO 0)
(while
(progn (setq ent (meth (cond (msg)
("\nSelect object: ")
)
)
)
(cond ((eq (getvar 'ERRNO) 7) (princ "\nMissed, try again."))
((eq (type (car ent)) 'ENAME)
(if (and fnc (not (fnc ent)))
(princ "\nInvalid object!")
)
)
)
)
)
ent
)
(if (setq ent
(car
(AT:GetSel
entsel
"\nSelect arc: "
(lambda (x)
(if (eq "ARC" (cdr (assoc 0 (entget (car x)))))
(vl-every (function (lambda (p / ss)
(if (setq ss (ssget "_C" p p '((0 . "LINE"))))
(setq elst (cons (ssname ss 0) elst))
)
)
)
(setq plst (list (_pnt (vlax-curve-getStartPoint (car x)))
(_pnt (vlax-curve-getEndPoint (car x)))
)
)
)
)
)
)
)
)
(progn
(setq ov (mapcar (function getvar) (setq vl '("CMDECHO" "FILLETRAD"))))
(while
(progn
(setq gr (grread T 15 0))
(cond
((eq 5 (car gr))
(redraw)
(grdraw (setq sp (trans (vlax-curve-getStartPoint ent) 0 1)) (cadr gr) 1 -1)
(princ
(strcat "\rFillet radius: "
(rtos (setvar 'FILLETRAD (distance sp (cadr gr))))
" "
)
)
(if (vl-cmdf "_.fillet" (list (car elst) (car plst)) (list (cadr elst) (cadr plst)))
(progn (entdel ent) (setq ent (entlast)))
T
)
)
)
)
)
)
)
(*error* nil)
(princ)
)
Can't find what you're looking for? Ask the community or share your knowledge.