sublimation Posted October 29, 2019 Posted October 29, 2019 (edited) Part of my company's drawing standards are to make sure that all internal included corners of a profile are radius-ed. I am trying to avoid using any commands in my code and keep everything in VLA(X). My current logic for creating the fillets works fine for 2 of the 3 scenarios that I run into. I may be over complicating things, but I assume I need to calculate the point that the arc will make with my geometry. In the images; CYAN is the original geometry, GREEN & ORANGE are known, YELLOW can be calculated from the knowns, and RED is what I need to ascertain. Figure 1: Simply trig out d4 and use polar to find pt4 (same for d5 and pt5). Figure 2: Law of Cosines SAS to get a3 angle, polar the distance r3 to get pt5. Figure 3: HTF do I solve this?!?! I have been racking my brain for a week trying to find a solution. Any and all help is appreciated. Edited October 29, 2019 by sublimation Resize inline images Quote
dlanorh Posted October 29, 2019 Posted October 29, 2019 Read up on the visual lisp vlax-curve functions especially first and second deriv functions and the use of vla-getbulge, these will help. You are missing some calculable geometry in 3. The long chord (LC) pt2->pt3 is easy to calculate and LC/2 and r can be used to calculate the bulge factor for a given curve. Negative bulge factors denote clockwise curves and positive for ccw curves. Don't overlook using (vla-offset) or drawing other geometry (circles, xlines and rays) using their vla-add methods and using (vla-intersectwith) or the (vlax-invoke obj1 'intersectwith obj2 acextendnone) to get straight coords. All the add methods return the object created, so can be assigned variables and then deleted. A hint for 3 (assuming an arc). pt5 will lie on a line joining the centre points of the required arc (orange) and the arc described by pt2 pt5 pt3 Quote
BIGAL Posted October 30, 2019 Posted October 30, 2019 (edited) Something else to look at is doing a fillet yes this erases parts of lines and arcs, save the arc end points, center etc via lisp, THEN do a undo as required the lisp arc pt answers will still exist so let Autocad do the hard work. Much easier than doing all the maths. Solves 1 & 3. Not sure what your quite after in 2. (defun c:test ( / ) (setvar 'osmode 512) (setq pt1 (getpoint "pick 1st line away from int")) (setq pt2 (getpoint "pick 2nd line away from int")) (setvar 'osmode 0) (setvar 'filletrad (getreal "enter radius")) (vl-cmdf "_.fillet" pt1 pt2) (setq obj (vlax-ename->vla-object (entlast))) (setq end (vlax-get Obj 'EndPoint)) (setq start (vlax-get Obj 'startPoint)) (setq cen (vlax-get Obj 'center)) (command "undo" 1) (princ end)(princ start)(princ cen) ) (c:test) Edited October 30, 2019 by BIGAL Quote
hanhphuc Posted October 30, 2019 Posted October 30, 2019 (edited) 9 hours ago, sublimation said: I am trying to avoid using any commands in my code and keep everything in VLA(X). .... Figure 1: Simply trig out d4 and use polar to find pt4 (same for d5 and pt5). ... Respond to Figure 1 only p1->p2->p3 clockwise where p2 is an IP/vertex WCS only i prefer vanilla entmake here 3-point fillet if you like activeX just replace with vla-addarc method p/s: figure2 & 3 not sure should post drawing (defun c:test (/ tan foo p1 p2 p3 a r c l ls tp) ;hanhphuc 30.10.2019 (defun tan (x) (/ (sin x) (cos x))) (defun foo (a r) (list (abs (* (tan (* a 0.5)) r)) ;Tc (- (/ r (cos (* a 0.5))) r) ;Ec (* a r) ;Lc ) ) ;;; returns tangent length,external offset,curve Length ;;; (foo 1.5708 100.) ;--> '(100.0 41.4216 157.08) (if (and (setq p1 (getpoint "\nSpecify start point ")) (setq p2 (getpoint p1 "\nSpecify IP point ")) (setq p3 (getpoint p2 "\nSpecify End point ")) (setq r (getdist "\nEnter radius : ")) ) (progn (setq p (list p1 p2 p3) l (mapcar ''((a b) (angle a b)) p (cdr p)) a (apply '- (reverse l)) a (if (> a pi) (- (* 2. pi) a) a ) ls (foo a r) tp (mapcar ''((x f) (polar p2 x (f (car ls)))) (list (car l) (cadr l)) (list - +)) c (polar p2 (angle p2 (apply 'mapcar (cons ''((a b) (* 0.5 (+ a b))) tp))) (+ r (cadr ls))) ) (grdraw (car tp) (cadr tp) 2) (entmakex (vl-list* '(0 . "ARC") (cons 10 c) (cons 40 r) (mapcar ''((a b) (cons a (angle c b))) '(51 50) tp) ) ) ) (princ "\nOops.. Invalid point or input! ") ) (princ) ) Edited October 30, 2019 by hanhphuc syntax color Quote
Jamescalabut Posted October 30, 2019 Posted October 30, 2019 As you are drawing an arc from pt2 to pt3 , I assume you know it's Radius "R" and it's Center "C" (the center of the circumference). As the center of this circumference, the center of the circumference tangent to it and the point of tangence (pt5) are on the same line, it is very easy to find pt5, at a distance R from C. The point pt4 is the perpendicular to line pt1-pt2 from a1, which can be found via: (setq pt (getpoint))(setq obj (vlax-ename->vla-object (car (entsel "\nPick line"))))(setq pt2 (vlax-curve-getclosestpointto obj pt)) So now you know where pt4 is, you know d4. Quote
sublimation Posted October 30, 2019 Author Posted October 30, 2019 15 hours ago, dlanorh said: Read up on the visual lisp vlax-curve functions especially first and second deriv functions and the use of vla-getbulge, these will help. Don't overlook using (vla-offset) or drawing other geometry (circles, xlines and rays) using their vla-add methods and using (vla-intersectwith) or the (vlax-invoke obj1 'intersectwith obj2 acextendnone) to get straight coords. All the add methods return the object created, so can be assigned variables and then deleted. A hint for 3 (assuming an arc). pt5 will lie on a line joining the centre points of the required arc (orange) and the arc described by pt2 pt5 pt3 I will absolutely look at those vlax-curve functions! Thanks! Won't creating and deleting geometry be very taxing to the computer? I need to add these rads a minimum of 400 times in each drawing. Sorry, I left some things out because I didn't want to taint the ideas pool; since I didn't know what would be relevant to solving the problem. 10 hours ago, BIGAL said: Something else to look at is doing a fillet yes this erases parts of lines and arcs, save the arc end points, center etc via lisp, THEN do a undo as required the lisp arc pt answers will still exist so let Autocad do the hard work. Much easier than doing all the maths. Solves 1 & 3. Not sure what your quite after in 2. I failed to mention that I must do this at least 400 times in each drawing. So I must automate it. 9 hours ago, hanhphuc said: i prefer vanilla entmake here 3-point fillet if you like activeX just replace with vla-addarc method p/s: figure2 & 3 not sure should post drawing vla-addarc still requires that I calculate the 3 unknowns of the orange arc. Honestly, I don't think a drawing will be of any more help. It's really any random length line with a random arc and adding a radius between them. Quote
sublimation Posted October 30, 2019 Author Posted October 30, 2019 (edited) I am stoopid. I just noticed that I didn't specify that the orange arc is what I need to create. I don't know where the orange arc will exist. The angle, bulge, and radius are known, but not the location of the center point of the orange arc. Hence the need for the triangulation. Also, C1 in Figure 2 should be red. I apologize for the lack of clarity! Edited October 30, 2019 by sublimation Cause I'm stoopid twice. Quote
Jamescalabut Posted October 30, 2019 Posted October 30, 2019 Well, we know a bit more. In figure 3, c1 (not drawn, but the center of your circumference) will be the intersection of a line paralell to pt1-pt2 at a distance of r1 and a circumference with center in C and radius R+r1. So it's not difficult to locate c1 with vlax. After that, my last post applies to find the other points and distances. Quote
tombu Posted October 30, 2019 Posted October 30, 2019 Maybe oversimplification, but having the cyan geometry and knowing the radii I'd just use the fillet command. I used to do all this calculation stuff working in the field as a surveyor for 20 years before using AutoCAD. Haven't had to do much since especially since switching to Civil 3D. Quote
dlanorh Posted October 30, 2019 Posted October 30, 2019 1 hour ago, sublimation said: Won't creating and deleting geometry be very taxing to the computer? I need to add these rads a minimum of 400 times in each drawing. Sorry, I left some things out because I didn't want to taint the ideas pool; since I didn't know what would be relevant to solving the problem. You didn't say whether these were polylines or separate geometric items (lines and arcs). Creating Geometry may slow the lisp, but would you rather do it by hand. In figure 3, if cyan is a polyline, a simple offset by the radius will produce the centre point of the desired arc as the corresponding vertex (pt2) on the offset line, the "knack" is working out whether the offset distance should be positive or negative. When trying to solve these problems, try adding back as much "removed" geometry as you can. There are also loads of sub functions out there to help, just ask. 1 Quote
sublimation Posted October 30, 2019 Author Posted October 30, 2019 52 minutes ago, dlanorh said: Creating Geometry may slow the lisp, but would you rather do it by hand. In figure 3, if cyan is a polyline, a simple offset by the radius will produce the centre point of the desired arc as the corresponding vertex (pt2) on the offset line, the "knack" is working out whether the offset distance should be positive or negative. When trying to solve these problems, try adding back as much "removed" geometry as you can. There are also loads of sub functions out there to help, just ask. I would certainly rather create and delete geometry than do it by hand. I just figured that there has to be a way to do it mathematically. Quote
sublimation Posted October 30, 2019 Author Posted October 30, 2019 1 hour ago, tombu said: Maybe oversimplification, but having the cyan geometry and knowing the radii I'd just use the fillet command. I used to do all this calculation stuff working in the field as a surveyor for 20 years before using AutoCAD. Haven't had to do much since especially since switching to Civil 3D. I already do it by hand. The boring/tedious part is doing it 400+ times in each drawing. It eats up an entire day. Quote
dlanorh Posted October 30, 2019 Posted October 30, 2019 21 minutes ago, sublimation said: I would certainly rather create and delete geometry than do it by hand. I just figured that there has to be a way to do it mathematically. There is always a way to do it mathematically, however it is often easier to let autocad do it for you, it saves you replicating something it already has built in. The construction, processing and deletion of new geometry is not discernable on modern computers. There is only a problem if something errors between creation and deletion that a defined error handler cannot account for. 2 Quote
lrm Posted October 31, 2019 Posted October 31, 2019 There are two general mathematical approaches for calculating the center of the fillet radius (a1 in your figurer 3). One is to analytically solve for the intersection of a line and an arc. In this case the line will be a line offset from line pt1 pt2 by a distance r1 (the radius of the fillet). The center of the fillet will also be on an arc of radius equal to the fillet radius + given arc radius r = r1 + r2. This arc will have the same center as the given arc. Since a line may intersect an arc twice, part of the task is to determine which of the two possible solutions is the one you want. This can be done with a bias point determined from existing geometry or by the user specifying which solution is needed. Another method for finding the fillet center is to use numerical methods which use a sequence of systematic guesses to find a solution that is numerically satisfactory. I thought I'd have some fun with this problem and try a numerical solution. In the code below pt10 and pt 11 define the line offset from the line passing through pt1 pt2 by the distance r1. A unit vector perpendicular to line p1 p2 and pointing towards the arc center (ptctr) is used to determine the direction of the offset. The end of the offset line is used as an initial guess for the location of the center. This is the left most ptA. ptB is the intersection of the line from ptA to ptctr. ptB is then projected to line from pt10 to pt11> This defines a new ptA Step 1 above is repeated using the new ptA Step 2 is repeated to calculate a new ptB The process continues until the distance between the most recent values for ptA and ptB is less than a specified tolerance. I set this value to 0.00001 in the code below but it could be smaller or a percentage of some value (e.g., the extents). If a solution is not found in 100 tries the message "No Solution" is displayed. ; finds the center of a fillet given a line, arc, and fillet radius ; L. Minardi 10/30/2019 (defun c:ctrpoint (/) (command "_pdmode" "35" "") (setq osnp (getvar "osmode")) (setvar "osmode" 0) (setq r1 (getdist "\nEnter fillet radius") ss (entsel "\nSelect line") ed (entget (nth 0 ss)) pt1 (cdr (assoc 10 ed)) pt2 (cdr (assoc 11 ed)) ss (entsel "\nSelect arc") ed (entget (nth 0 ss)) ptctr (cdr (assoc 10 ed)) r2 (cdr (assoc 40 ed)) ; radius of arc perp12 (proj_pt pt1 pt2 ptctr) ; projection of arc center onto line uperp12 (normalize (mapcar '- ptctr perp12)) ; unit vector in direction of arc center pt10 (mapcar '+ pt1 (mapcar '* uperp12 (list r1 r1 r1))) ; offset line pt11 (mapcar '+ pt10 (mapcar '- pt2 pt1)) ptA pt10 ; start point for interation r (+ r1 r2) ; radius of arc with fillet center cont T ; while flag n 0 ; iteration counter ) ; ptB is at the intersetcion of the offset arc and line from ptA to arc center ; ptA is the projection of ptB onto the offset line. (while cont (setq ptB (mapcar '+ ptctr (mapcar '* (normalize (mapcar '- ptA ptctr)) (list r r r)) ) ) (setq ptA (proj_pt pt10 pt11 ptB)) (setq ptB (mapcar '+ ptctr (mapcar '* (normalize (mapcar '- ptA ptctr)) (list r r r)) ) ) (setq n (+ n 1)) (if (< (distance ptA ptB) 0.00001) (setq cont nil) ) ; end if (if (> n 100) (setq cont nil) ) ; end if ) ; end while (if (> n 100) (princ "\nNo Solution") (progn (princ "\fillet center = ") (princ ptB) (command "_point" ptB "") (princ "\iterations = ") (princ n) ) ) ; end if (setvar "osmode" osnp) ;reset osnap ;reset osnap (princ) ) ; end defun (defun normalize (p / d) ; normalize a vector (setq d (distance '(0 0 0) p)) (setq p (mapcar '/ p (list d d d))) ) ;;; calculates point of p projected to line defined by p1 and p2 (defun proj_pt (p1 p2 p / d u12 ) (setq d (distance p1 p2)) (setq u12 (mapcar '/ (mapcar '- p2 p1) (list d d d))) (setq d (dot u12 (mapcar '- p p1))) (setq pp (mapcar '+ p1 (mapcar '* u12 (list d d d)))) ) ;;; dot product of 2 vectors a and b (defun dot (a b / dd) (setq dd (mapcar '* a b)) (setq dd (+ (nth 0 dd) (nth 1 dd) (nth 2 dd))) ) 1 Quote
BIGAL Posted October 31, 2019 Posted October 31, 2019 We are all providing solutions but you say do 400 times what exactly are you doing ? Can you provide at least an image of what your doing, a dwg would be better. A step 1 step2 step 3 etc Quote
David Bethel Posted October 31, 2019 Posted October 31, 2019 While I don't fully understand your needs, here is a vanilla AutoLISP that creates the arc for a list 3 CCW Points and a specified radius. ;;;CREATE A FILLET ARC FROM A LIST OF 3 CCW POINTS AND RADIUS (defun f3p_fil3p (l ra / a1 a2 i1 d1 c1 c2 cn sa ea) (setq a1 (angle (nth 1 l) (nth 2 l)) a2 (angle (nth 1 l) (nth 0 l)) i1 (if (> a1 a2) (- (+ (* 2 pi) a2) a1) (- a2 a1)) d1 (abs (/ ra (/ (sin (* i1 0.5)) (cos (* i1 0.5))))) c1 (polar (nth 1 l) a1 d1) c2 (polar (nth 1 l) a2 d1) cn (inters c1 (polar c1 (+ a1 (* pi 0.5)) 1.0) c2 (polar c2 (+ a2 (* pi 0.5)) 1.0) nil) sa (angle cn c2) ea (angle cn c1)) (entmake (list (cons 0 "ARC") (cons 10 cn) (cons 40 ra) (cons 50 sa) (cons 51 ea)))) (defun LM:Clockwise-p ( p1 p2 p3 ) (< (* (- (car p2) (car p1)) (- (cadr p3) (cadr p1))) (* (- (cadr p2) (cadr p1)) (- (car p3) (car p1))))) ;************ TEST BED *************************************** (defun c:f3p (/ ra p1 p2 p3) (initget 7) (setq ra (getdist "\nFillet Radius: ")) (princ "\nSelect 3 CCW Pts: ") (initget 1) (setq p1 (getpoint "\nStart Pt - P1: ")) (initget 1) (setq p2 (getpoint p1 "\nVertex Pt - P2: ")) (grdraw p1 p2 1 3) (initget 1) (setq p3 (getpoint p2 "\nEnd Pt - P3: ")) (grdraw p2 p3 2 3) (if (LM:Clockwise-p p1 p2 p3) (alert "Ponts Are Not CCW") (f3p_fil3p (list p1 p2 p3) ra)) (prin1)) Basic error checking with Lee's CW test HTH -David Quote
sublimation Posted October 31, 2019 Author Posted October 31, 2019 9 hours ago, lrm said: There are two general mathematical approaches for calculating the center of the fillet radius (a1 in your figurer 3). One is to analytically solve for the intersection of a line and an arc. In this case the line will be a line offset from line pt1 pt2 by a distance r1 (the radius of the fillet). The center of the fillet will also be on an arc of radius equal to the fillet radius + given arc radius r = r1 + r2. This arc will have the same center as the given arc. Since a line may intersect an arc twice, part of the task is to determine which of the two possible solutions is the one you want. This can be done with a bias point determined from existing geometry or by the user specifying which solution is needed. Another method for finding the fillet center is to use numerical methods which use a sequence of systematic guesses to find a solution that is numerically satisfactory. I thought I'd have some fun with this problem and try a numerical solution. In the code below pt10 and pt 11 define the line offset from the line passing through pt1 pt2 by the distance r1. A unit vector perpendicular to line p1 p2 and pointing towards the arc center (ptctr) is used to determine the direction of the offset. The end of the offset line is used as an initial guess for the location of the center. This is the left most ptA. ptB is the intersection of the line from ptA to ptctr. ptB is then projected to line from pt10 to pt11> This defines a new ptA Step 1 above is repeated using the new ptA Step 2 is repeated to calculate a new ptB The process continues until the distance between the most recent values for ptA and ptB is less than a specified tolerance. I set this value to 0.00001 in the code below but it could be smaller or a percentage of some value (e.g., the extents). If a solution is not found in 100 tries the message "No Solution" is displayed. That does solve my third issue! Thank you. 8 hours ago, BIGAL said: We are all providing solutions but you say do 400 times what exactly are you doing ? Can you provide at least an image of what your doing, a dwg would be better. A step 1 step2 step 3 etc Unfortunately no. My company has very strict privacy/proprietary rules. Since this is also the first time in my life that I have a job that I enjoy, a company that respects me, and friendly co-workers, I won't even risk testing those waters. That being said, I can say that I design dies. Sorry I can't be more transparent and I greatly appreciate all the help everyone has given! 3 hours ago, David Bethel said: While I don't fully understand your needs, here is a vanilla AutoLISP that creates the arc for a list 3 CCW Points and a specified radius. Basic error checking with Lee's CW test HTH -David I appreciate all the work you put into that program, but my only issue is with solving Figure 3. Quote
hanhphuc Posted October 31, 2019 Posted October 31, 2019 (edited) 11 hours ago, sublimation said: I appreciate all the work you put into that program, but my only issue is with solving Figure 3. After i figured it out , there's a very simple solution could be done without hard coding. simply use command CIRCLE (Tan Tan Radius) then TRIM the residual i'm not sure this is how you do it manually Figure 3? (defun c:test nil (vl-cmdf "_.CIRCLE" "_T" "\\" "\\" (getvar 'filletrad) ) (vl-cmdf "_TRIM" "" "\\" "") (princ) ) On 10/30/2019 at 10:19 PM, sublimation said: I already do it by hand. The boring/tedious part is doing it 400+ times in each drawing. It eats up an entire day. Without actual drawing, this is what i imagine you are doing Figure 2 ? we don't understand whether you wanna label it or draw something export something else etc.. that's why @BIGAL was asking you sample drawing which he means was with automation maybe just few seconds to solve 400+ On 10/30/2019 at 10:17 PM, sublimation said: I would certainly rather create and delete geometry than do it by hand. I just figured that there has to be a way to do it mathematically. yes by law of cosines (defun acos (x /) (cond ((equal x 1.0 1.0e-16) 0.0) ((equal x -1.0 1.0e-16) pi) ((< (abs x) 1.0) (- (* pi 0.5) (atan (/ x (sqrt (- 1.0 (* x x))))))) (T nil) ) ) (defun cosine (a b c / sq) (setq sq '((x) (* x x))) (acos (/ (- (+ (sq a) (sq b)) (sq c)) (* 2.0 a b))) ) example: (cosine 3 4 5);1.5708 (cosine 4 5 3);0.643501 (cosine 5 3 4);0.927295 However since your task is solved, good luck Edited October 31, 2019 by hanhphuc demo GIF Quote
BIGAL Posted November 1, 2019 Posted November 1, 2019 Sublimation now we know a bit more I redid the code above as we really did not know what it was you were trying to do so image 1 & 3 solved. Arc no fillet, anf. Quote
Recommended Posts
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.