Challenge 01/23

Challenge 01/23

Sea-Haven
Mentor Mentor
1,890 Views
34 Replies
Message 1 of 35

Challenge 01/23

Sea-Haven
Mentor
Mentor

This has been on my to do list for years the simple do a fillet between two arcs or circles, yes Circle TTR gives a result but draws a circle rather than an arc. So this is arc option 1 if can be done better please do so, there are 4 possible options for a new arc. 

 

You just pick the 2 circles and the top approx new arc center point. It drawa the arc based on a left to right method.

SeaHaven_0-1672962266890.png

 

; 2 circle add arc. downwards between 2 circle or arcs
; BY alanH Jan 2023


(defun C:A1 ( / ent1 ent2 cen1 cen2 obj1 obj2 obj3 obj4)
(vl-load-com)
(setq oldsnap (getvar 'osmode))
(setvar 'osmode 0)
(setq ent1 (vlax-ename->vla-object (car  (entsel "Pick circle 1 (L) "))))
(setq ent2 (vlax-ename->vla-object (car  (entsel "Pick circle 2 (R) "))))
(setq cen1 (vlax-get ent1 'center))
(setq cen2 (vlax-get ent2 'center))
(setq rad1 (vlax-get ent1 'radius))
(setq rad2 (vlax-get ent2 'radius))
(setq rad3 (getreal "\nEnter radius "))
(command "circle" cen1 (+ rad1 rad3))
(setq obj1 (vlax-ename->vla-object  (entlast)))
(command "circle" cen2 (+ rad2 rad3))
(setq obj2 (vlax-ename->vla-object  (entlast)))
(setq intpt (vlax-invoke obj2 'intersectWith obj1 acExtendThisEntity))
(setq pt1 (list (car intpt)(cadr intpt) 0.0))
(setq pt2 (list (nth 3 intpt)(nth 4 intpt) 0.0))
(vla-delete obj1)
(vla-delete obj2)
(setq cenpt (getpoint "\npick near arc point center "))
(setq d1 (distance pt1 cenpt)
	    d2 (distance pt2 cenpt)
)
(if (> d1 d2)
    (progn
    (setq temp pt1)
    (setq pt1 pt2)
    (setq pt2 temp)
    )
)
(command "line" pt1 cen1 "")
(setq obj3 (vlax-ename->vla-object (entlast)))
(setq arcpt1 (vlax-invoke ent1 'intersectWith obj3 acExtendThisEntity))
(command "line" pt1 cen2 "")
(setq obj4 (vlax-ename->vla-object (entlast)))
(setq arcpt2 (vlax-invoke ent2 'intersectWith obj4 acExtendThisEntity))
(vla-delete obj3)
(vla-delete obj4)
(command "arc" "s" arcpt1 "E" arcpt2 "R" rad3)
(princ)
)
(C:a1)

 

So what about an external arc ?

0 Likes
Accepted solutions (1)
1,891 Views
34 Replies
Replies (34)
Message 21 of 35

john.uhden
Mentor
Mentor

@dbroad 

BTW, @phanaem counted 16 variations.  How did you arrive at 14?

John F. Uhden

0 Likes
Message 22 of 35

dbroad
Mentor
Mentor

16 is probably correct.  I knew there were at least 14.

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 23 of 35

Sea-Haven
Mentor
Mentor

I was avoiding using 

(command "_.circle" "_ttr" "_tan" p1 "_tan" p2 r)

 

The idea being to have multiple arc defuns that cover the most common arcs required. And not rely on trim.

 

 

0 Likes
Message 24 of 35

john.uhden
Mentor
Mentor

@Sea-Haven ,

Well put.  Understood.

John F. Uhden

0 Likes
Message 25 of 35

dbroad
Mentor
Mentor

Yes but I demonstrated a single function that could do all 16 cases without any more input from the user.  If you don't want to actually select the circle, just point, p3 could be generated instead based on the general direction. It does use trim but vlax-invoke ... 'intersectwith and deleting the circle and redrawing the arc does essentially the same work as the trim.

 

I tried your first one but needed to change 

(getreal "\nEnter radius ")

to

(getdist "\nEnter radius ")

in order to make it like fillet and circle ttr.

and I had to change

(command "arc" "s" arcpt1 "E" arcpt2 "R" rad3)

to

(command "arc" arcpt1 "E" arcpt2 "R" rad3)

because arc won't accept an "s" keyword.

I also tried your second code post but since it was part of a code fragment rather than a complete program, I couldn't get it to work.  

I did expand my code later, for fun, to add constraints automatically so that the user could change the radii and maintain the tangencies.

 

I will keep looking at the thread to see what comes up.  Good coding.

 

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 26 of 35

leeminardi
Mentor
Mentor

Some of you olde timers may remember that back in the pre-CAD days a "fillet" was an arc in an internal corner that was tangent to the adjacent lines and/or arcs.  This is an example of a fillet.

leeminardi_0-1673711760955.png

A "radius" or "round" was an arc on an external corner.  For example,

leeminardi_1-1673711819756.png

BTW, neither should be confused with a filet as in a McDonald's Filet-O-Fish

 

I don't believe that the following was ever considered as a fillet.  I'll name this a "silly-fillet".

leeminardi_2-1673712047609.png

 

The popularization of CAD removed the distinction of a fillet and radius (round).

 

For the case of creating a fillet between two circles I believe the correct definition is that there are potentially  up to 8 arc options.  If you believe that silly-fillets are valid then there are 16 possible arcs. 

 

The AutoCAD fillet command only generates two of the eight options.  The green arcs in the image below.

leeminardi_3-1673712396770.png

 

I've always used circle with the Tan Tan Radius option get the fillets that the fillet command will not generate.  But, it requires that annoying step of trimming the result.

 

Of the solutions provided, @CADaSchtroumpf program (post #11) is pretty good but will yield silly-fillets in certain situations (the point show where the user picked the circles).   E.g.,

leeminardi_4-1673712818104.png

 @dbroad 's code (#19) is better than using circle ttr as it streamlines the trimming aspect but I think it could be enhanced to create the legit fillet (as opposed to the silly fillet) without the need of the user to pick which arc is wanted by assuming the desired arc is the one of less than 180°. 

 

 

lee.minardi
Message 27 of 35

marko_ribar
Advisor
Advisor

@leeminardi 

As how you drawn them, I suppose you can code for it... So it's up to you, dear Lee...

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 28 of 35

phanaem
Collaborator
Collaborator
Accepted solution

For circle/circle only, this will allow to draw any of the 16 possible arcs.

Selecting the desired arc is a little bit counterintuitive. After selecting the 2 circles and the radius, move the mouse to see the available solutions. The arc with the middle point closest to the current position, is selected, so you need to know where it might be.

(defun c:cfillet ( / *error* acobj acdoc
                  e1 e2 c1 c2 r1 r2 d a a1 a2
                  lst enter g r p e
                 )
  
  (vl-load-com)
  (setq acobj (vlax-get-acad-object)
        acdoc (vla-get-activedocument acobj))

  
  (if
    (= 8 (logand (getvar 'undoctl) 8))
    (vla-endundomark acdoc)
  )
  (vla-startundomark acdoc)

  (defun *error* (msg)
    (and msg
      (not (wcmatch (strcase msg) "*CANCEL*,*QUIT*,*BREAK*,*EXIT*"))
      (princ (strcat "\nError: " msg))
    )
    (foreach x lst (vl-catch-all-apply 'vla-delete (list x)))
    (if
      (= 8 (logand (getvar 'undoctl) 8))
      (vla-endundomark acdoc)
    )
    (princ)
  )

  (or *rad* (setq *rad* 1.0))
  (if
    (and
      (princ "\nSelect first circle or arc: ")
      (setq e1 (ssget "_+.:S" '((0 . "CIRCLE"))))
      (setq e1 (ssname e1 0))
      (progn
        (while
          (progn
            (redraw e1 3)
            (princ "\nSelect second circle: ")
            (setq e2 (ssget "_+.:S" '((0 . "CIRCLE"))))
            (redraw e1 4)
            (if
              (and e2 (eq e1 (setq e2 (ssname e2 0))))
              (princ "Select a different circle or arc: ")
            )
          )
        )
        e2
      )
      (setq *rad* (cond
                    ((progn
                       (initget 6)
                       (getdist (strcat "\nSpecify fillet radius <" (rtos *rad*) ">: "))
                     )
                    )
                    (*rad*)
                  )
      )
    )
    (progn
      (mapcar 'set '(c1 r1) (circle_def e1))
      (mapcar 'set '(c2 r2) (circle_def e2))
      (setq d (distance c1 c2)
            a (angle c1 c2)
      )
      (foreach f '(+ -)
        (foreach g '(+ -)
          (foreach p (circle_inters d
                       (abs ((eval f) r1 *rad*))
                       (abs ((eval g) r2 *rad*))
                     )
            (setq p (mapcar '+ c1 (rot p a))
                  a1 (if
                       (and
                         (< (distance p c1) r1)
                         (< *rad* r1)
                       )
                       (angle c1 p)
                       (angle p c1)
                     )
                  a2 (if
                       (and
                         (< (distance p c2) r2)
                         (< *rad* r2)
                       )
                       (angle c2 p)
                       (angle p c2)
                     )
                  lst (append
                        (mapcar
                         '(lambda (a1 a2)
                            (vlax-ename->vla-object
                              (entmakex
                                (list
                                 '(0 . "ARC")
                                 '(60 . 1)
                                  (cons 10 p)
                                  (cons 40 *rad*)
                                  (cons 50 a1)
                                  (cons 51 a2)
                                )
                              )
                            )
                          )
                          (list a1 a2)
                          (list a2 a1)
                        )
                        lst
                      )
            )
          )
        )
      )
      (setq enter nil)
      (if lst
        (while (not enter)
          (setq g (grread 't 15 0)
                r (car  g)
                p (cadr g)
          )
          (princ "\rSelect Arc to keep.")
          (cond
            ((or (member r '(11 12 25)) (= p 13) (= p 32))
             (setq enter t)
            ) 
            ((= r 5)
             (setq p (trans p 1 0))
             (if e (vla-put-visible e :vlax-false))
             (setq e (car
                       (vl-sort
                         lst
                         '(lambda (a b)
                            (<
                              (distance p
                                (vlax-curve-getpointatdist a
                                  (/
                                    (vlax-curve-getdistatparam a
                                      (vlax-curve-getendparam a)
                                    )
                                    2.0
                                  )
                                )
                              )
                              (distance p
                                (vlax-curve-getpointatdist b
                                  (/
                                    (vlax-curve-getdistatparam b
                                      (vlax-curve-getendparam b)
                                    )
                                    2.0
                                  )
                                )
                              )
                            )
                          )
                        )
                      )
             )
             (vla-put-visible e :vlax-true)
            )
            ((= r 3)
             (setq lst (vl-remove e lst))
             (setq enter t)
            )
          )
        )
      )
    )
  )
  (*error* nil)
  (princ)
)

(defun circle_inters (d r1 r2 / x y)
  (if
    (<= (abs (- r1 r2)) d (+ r1 r2))
    (progn
      (setq x (/ (+ (* d d) (* r1 r1) (* -1 r2 r2)) (* 2.0 d)))
      (setq y (sqrt (- (* r1 r1) (* x x))))
      (if
        (< 0 y)
        (list (list x y) (list x (- y)))
        (list (list x y))
      )
    )
  )
)

(defun rot (p a)
  (list
    (- (* (car p) (cos a)) (* (cadr p) (sin a)))
    (+ (* (car p) (sin a)) (* (cadr p) (cos a)))
  )
)

(defun circle_def (e)
  (setq e (entget e))
  (list
    (cdr (assoc 10 e))
    (cdr (assoc 40 e))
  )
)

 For arc/arc or arc/circle, I suggest FILLET command. It's working pretty nice.

 

 

0 Likes
Message 29 of 35

leeminardi
Mentor
Mentor

@marko_ribar   I've modified the code of @CADaSchtroumpf (post 11) to ensure only the fillet of less than or equal to 180° is added.  His code explicitly calculates the two tangent points.  That's why I chose his code to modify.  I would prefer that the code did not depend on the use of the Circle TTR command as adding an object and then deleting it slows computation.   I think Lee Mac's 2-circle intersection code could be used to determine the center of the tangent circle but prior calculations would be needed  to determine if r1 and r2 should be added or subtracted from the fillet radius to determine the radius of the two circles to feed to his code.

I've done some testing and it seems to avoid the "silly" solutions.  I understand that some users may want those arcs.

(vl-load-com)
; creates one filet between two circle given the approximate location of
; the tangents and the radius of the fillet
; original code by CADaSchtroumpf ,  modified by L. Minardi to ensure the
; fillet added has an arc angle <= 180°  1/14/2023
(defun C:filletnew ( / p1 e1 t1 p2 e2 t2 rad cx  a1 a2 abig asm tsm tbig)
  (setvar "cmdecho" 0)
  (while (not (setq e1 (nentsel "\n1st point of tangency: ")))
  )
  (setq p1 (cadr e1))
  (setq t1 (osnap p1 "_near"))
  (while (not (setq e2 (nentsel "\n2nd point of tangency: ")))
  )
  (setq p2 (cadr e2))
  (setq t2 (osnap p2 "_near"))
  (cond
    ((and t1 t2)
     (initget 7)
     (setq rad (getreal "\nRadius?: "))
     (command "_.circle" "_Ttr" t1 t2 rad)
     (setq cx (entlast))
     (setq t1
	    (vlax-invoke
	      (vlax-ename->vla-object cx)
	      'IntersectWith
	      (vlax-ename->vla-object (car e1))
	      acextendotherentity
	    )
     )
     (setq t2
	    (vlax-invoke
	      (vlax-ename->vla-object cx)
	      'IntersectWith
	      (vlax-ename->vla-object (car e2))
	      acextendotherentity
	    )
     )
     (setq cx (cdr (assoc 10 (entget cx))))
     (entdel (entlast))
     (if (and t1 t2)
	(progn
	 (setq a1 (angle cx t1)
	       a2 (angle cx t2)
	 )
	 ; determine which arc is <= 180°
	(if (> a2 a1) (setq abig a2 asm a1 tbig t2 tsm t1) (setq abig a1 asm a2 tbig t1 tsm t2 ))
	 (if (< (- abig asm) pi)
	     (command "_.arc" "_none" (trans tsm 0 1) "_ce" "_none" (trans cx 0 1) "_none" (trans tbig 0 1))
	     (command "_.arc" "_none" (trans tbig 0 1) "_ce" "_none" (trans cx 0 1) "_none" (trans tsm 0 1))
	 )
	)	; end progn
      (princ "\nNo solution!")
     ) ;end if
    )
  )
  (setvar "cmdecho" 1)
  (prin1)
)

lee.minardi
0 Likes
Message 30 of 35

Sea-Haven
Mentor
Mentor

Ok to me the original idea was to have a image dcl with the choices or a ribbon option with flyouts. These would show a single arc choice.

 

If you look at post 10 you will see 3 arc choices, as mentioned arc 1 has a solution with a second variation being go through a pt, so that leaves 2 more desired in the simplest way possible if it involves TTR that may be the simplest way rather than approx centre that I used for my Arc 1, there is geometry solutions if you draw enough tangent/ line/ to centres.

 

I appreciate we are at like 14 or is 16 choices, but I want first 3. Using a pick left then right circles this will reduce to 7 or 8 options.

 

I will do the front end dcl when I get a chance to busy fishing at moment as on holidays.

0 Likes
Message 31 of 35

Kent1Cooper
Consultant
Consultant

@Sea-Haven wrote:

,,,, If you look at post 10 you will see 3 arc choices ....


Clarify what is wanted with Arc 3.  Arc 1 has both original Circles on the outside of the Arc, and Arc 2 has both on the inside.  Arc 3 has one Circle on the outside and the other on the inside.  Is there a reason for which is which?  Your Arc 3 is what is green in my image in Message 9, but my blue Arcs are the other option with one Circle inside the Arc and the other outside.  Do you always want the one for which the smaller Circle is inside and the larger one outside?  [What if the Circles are the same size?]  Or always the left Circle inside and the right one outside?  [What if they're not in a horizontal relationship?]   Or is there some other criterion?

Kent Cooper, AIA
0 Likes
Message 32 of 35

john.uhden
Mentor
Mentor

@leeminardi ,

How about fillet mignon?

I think Doug's "pick a point..." purpose was not for silly fillets but for picking which of two arcs you want to keep, discarding the other.  But then that doesn't help when picking which side of crossing arcs.  Probably better to create both and let the user erase the unwanted one.  After all, I think we were just trying to find a way to do what the AutoCAD FILLET command doesn't.

John F. Uhden

Message 33 of 35

Sea-Haven
Mentor
Mentor

Thanks for comments and a quick answer circle dia has nothing to do with it, its circle/arc1 and circle/arc2. With a connecting arc of a particular style like arc1 and arc2 can be looked at as inside and outside arc solutions.

 

The arc3 yes may be more to be implied than just what I have shown, a more start tangent on top 1st circle go to tangent at bottom second circle. This would be 2 solutions again or maybe only 1 using pick order.

 

Like John's comment After all, I think we were just trying to find a way to do what the AutoCAD FILLET command doesn't. Fillet1 fillet2 fillet3 and so on.

 

 

 

0 Likes
Message 34 of 35

CADaSchtroumpf
Advisor
Advisor

@leeminardi  a écrit :

Of the solutions provided, @CADaSchtroumpf program (post #11) is pretty good but will yield silly-fillets in certain situations (the point show where the user picked the circles).   E.g.,

leeminardi_4-1673712818104.png


This happens if the selected points are counterclockwise

You won't have the same result if you first select the left circle at the designated points (like your screenshot)

You will have the correct solution if you first select the circle on the right at the designated point, then the one on the left.


In the DXF definition of the arc 50 will always be the first angle and 51 the second angle in counterclockwise

 

Message 35 of 35

Sea-Haven
Mentor
Mentor

Getting somewhere if you want to try, realised need 2x4 dcl will update the code by Cadaschtroumpf covers 2 situations. The top 2 work, will implement more.

SeaHaven_0-1674365535530.png

 

Just save the slides to a support directory.

 

 

0 Likes