Jump to content

3D Circle Fit LISP no longer works correctly after changing unit settings


jeremyw

Recommended Posts

Hey everyone, we currently use a 3D Circle Fit LISP in C3D2016 to report on surveyed flange faces, but have noticed that since we modified our template unit settings to read clockwise from north, the circle fit routine no longers functions as expected and draws the circle at the correct size, but at a seemingly random angle.

 

I'm not sure where this file came from as it's not included in the code, can't be found online anymore and outdates any of the CAD staff working for us. It's quite possible this file was developed in-house, as we've got other older programs there were written in-house. 

 

If someone could please take a look and see if they can see what would be causing it; or even point us to a different circle fit LISP, it would be much appreciated. I can't see what would be casuing it, as I'm not aware of a connection between the angular units settings and UCS, and it seems like this program just draws multiple circles at various UCS to fit each 3 point circle, then averages those circles out to get the best fit circle.

 

(defun rtd (r) 
  (/ (* r 180.0) pi))
(defun dtr (d)
  (/ (* d pi) 180.0))

(defun c:3dcf (/ OSM) 
  (setvar "cmdecho" 0)
  (setq OSM (getvar "osmode"))
  (setvar "osmode" 8)
  (command "ucs" "w") 
  (setq all_pn nil)
    (while (setq cir_pn(getpoint "\nGet circle points (Enter when finished): "))
         (setq all_pn(append all_pn(list cir_pn)))
    )
  (setvar "osmode" 0)
  (command "ucsicon" "off") 
  (setq loop_pn all_pn)
  (setq radii nil)
  (setq verts nil)
  (setq wcents nil)
  (setq len_all (length all_pn))
  (repeat len_all  ; Draw circles from each set of 3 points in list
     (setq w1_p (car loop_pn))
     (setq w2_p (cadr loop_pn))
     (setq w3_p (caddr loop_pn))
     (setq w3_pall (cddr loop_pn))
     (command "ucs" "3P" w1_p w2_p w3_p)                            
     (setq u1_p (trans w1_p 0 1)) ; Convert each to local ucs.
     (setq u2_p (trans w2_p 0 1))
     (setq u3_p (trans w3_p 0 1))
     (command "circle" "3p" u1_p u2_p u3_p)
     (setq circ_1 (entlast))
     (command "ucs" "w")
     (command "ucs" "za" w1_p w2_p)
     (setq l1_p (trans w1_p 0 1))
     (setq l2_p (trans w2_p 0 1))
     (setq l3_p (trans w3_p 0 1))
     (command "ucs" "z" l1_p l3_p)
     (setq uc1_p (trans w1_p 0 1))
     (setq uc2_p (trans w2_p 0 1))
     (setq u3_pall nil)
     (foreach wp_n w3_pall
       (setq ucs_t (trans wp_n 0 1))
       (setq u3_pall (append u3_pall (list ucs_t)))
     )
     (setq u3_angs nil)
     (foreach a3 u3_pall
       (setq ucs_a3 (rtd (angle uc1_p a3)))
       (cond
	  ((>= ucs_a3 270)(setq ucs_a3 (- ucs_a3 360))) 
          ((and (>= ucs_a3 90)(< ucs_a3 270))(setq ucs_a3 (- ucs_a3 180)))
       )
       (setq u3_angs (append u3_angs (list ucs_a3)))
     )
     (setq u3_len  (length u3_angs))
     (setq u3_mean (/ (apply '+ u3_angs) u3_len))
     (command "rotate" circ_1 "" uc1_p u3_mean) 
       (setq st_circ (entget circ_1))
       (setq v1 (cdr(assoc 210 st_circ)))        
       (setq v_pl1 v1) 
       (setq verts (append verts(list v_pl1)))   
       (setq c1 (cdr(assoc 10 st_circ)))          
       (setq c1w (trans c1 v1 0))                   
       (setq wcents (append wcents(list c1w)))     
       (setq r1 (cdr(assoc 40 st_circ)))        
       (setq radii (append radii(list r1)))
      (command "erase" "last" "")
      (command "ucs" "world")
     (setq 1st_loop (car loop_pn))
     (setq rest_loop (cdr loop_pn))     
     (setq loop_pn (append rest_loop (list 1st_loop)))
  )
   (setq divi (list len_all len_all len_all))
   (setq new_rad (/ (apply'+ radii) len_all))
  (setq v1_b (car verts))
  (setq verts_1 verts)
  (setq cvt_2 (list 0 0 0)) 
  (setq mis_1 (list -1 -1 -1))
  (repeat len_all
    (setq v1_n (car verts_1))
    (setq v1_d (mapcar'- v1_n v1_b))
    (setq v1_d1 (car v1_d))
    (setq v1_d2 (cadr v1_d))
    (setq v1_d3 (caddr v1_d))
     (cond
       ((> v1_d1 1.0)(setq v1_n(mapcar'* v1_n mis_1)))
       ((< v1_d1 -1.0)(setq v1_n(mapcar'* v1_n mis_1)))
       ((> v1_d2 1.0)(setq v1_n(mapcar'* v1_n mis_1)))
       ((< v1_d2 -1.0)(setq v1_n(mapcar'* v1_n mis_1)))
       ((> v1_d3 1.0)(setq v1_n(mapcar'* v1_n mis_1)))
       ((< v1_d3 -1.0)(setq v1_n(mapcar'* v1_n mis_1)))
     )
    (setq cvt_2 (mapcar'+ v1_n cvt_2))
    (setq verts_1 (cdr verts_1))
  )
  (setq new_ver (mapcar'/ cvt_2 divi))
  (setq wcents_1 wcents)
  (setq wct_2 (list 0 0 0)) 
  (repeat len_all
    (setq wct_1 (car wcents_1))
    (setq wct_2 (mapcar'+ wct_1 wct_2))
    (setq wcents_1 (cdr wcents_1))
  )
  (setq new_cenw (mapcar'/ wct_2 divi))
  (command "vpoint" new_ver)
  (command "ucs" "view")
  (command "zoom" "previous")
  (setq new_cenuc(trans new_cenw 0 1))
  (command "circle" new_cenuc new_rad)
  (command "ucs" "world")
   (setq circ_2 (entlast))
   (setq lcirc_2 (entget circ_2))
   (command "ucs" "object" "last")
   (setq all_errs nil)
     (foreach wp_er all_pn
       (setq ucs_er (trans wp_er 0 1))
       (setq all_errs (append all_errs (list ucs_er)))
     ) 
     (foreach zer all_errs
     (princ (cddr zer))
     ) 
     (setq err_cen (list 0 0 0))
       (foreach den all_errs
         (princ (fix (- (distance err_cen den) new_rad)))
       ) 

   (command "ucs" "w")
   (command "ucsicon" "on")
   (setvar "cmdecho" 1)
   (setvar "osmode" OSM)
   (princ "3dcf" )
)

3DCF.LSP

Edited by jeremyw
Link to comment
Share on other sites

5 hours ago, jeremyw said:

... I can't see what would be causing it, as I'm not aware of a connection between the angular units settings and UCS, and it seems like this program just draws multiple circles at various UCS to fit each 3 point circle, then averages those circles out to get the best fit circle.

 

Its using translate to calculate new points.

(setq u1_p (trans w1_p 0 1)) ; Convert each to local ucs.

 

looks like these points are then used to calculate angles and change the UCS for further calculations

 

Quote

we modified our template unit settings to read clockwise from north

 

Didn't run the code but think the error is in this bit of code with the new clockwise from north (90 ?)    maybe upload a sample drawing of what its suppose to do vs what its doing now.

 

(setq u3_angs nil)
(foreach a3 u3_pall
  (setq ucs_a3 (rtd (angle uc1_p a3)))
  (cond
    ((>= ucs_a3 270)
     (setq ucs_a3 (- ucs_a3 360))
    ) 
    ((and (>= ucs_a3 90)(< ucs_a3 270))
      (setq ucs_a3 (- ucs_a3 180))
    )
  )
  (setq u3_angs (append u3_angs (list ucs_a3)))
)

 

might need to add or subtract 90 from these conditional statements to fix it.

Link to comment
Share on other sites

I thought that section might be the issue, but don't quite know enough LISP to have known for sure.

 

I've uploaded a DWG with the red circle being the circle generated with default unit settings and cyan being what I get with it set to our templates direction and 0° position.

 

Circle Fit Exmple.png

3D_Circle_Fit_Example.dwg

Link to comment
Share on other sites

I ended up just addding a pair of commands at the start to set ANG BASE and ANGDIR to default values, and then resetting it back to our values at the end. Seems to work, but would be nice to figure out the "correct" solution rather than just a work-around.

 

  • Like 1
Link to comment
Share on other sites

I consider that a working solution. often times I set osnap or change other system variables before running a lisp to then revert the settings back after its done.

 

If you have to set a lot at one time best to use mapcar.

;;---------------------------------------------------------------;;
(setq vars '(ANGBASE ANGDIR)  ;list of variables
      vals  (mapcar 'getvar vars)      ;store old values
)
(mapcar 'setvar vars '(0 0)) ;set new values

....


(mapcar 'setvar vars vals) ;set old values before exit of lisp

 

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...