Jump to content

Autocad inaccuracy and issues running lisp


MJLM

Recommended Posts

Hello folks,

 

I ve been using autolisp to extract data from a model I created inside autocad. The data has to do with line intersections and angles of them. It is basically a pipe network and according to the way is connected I get 'tees', 'elbows' etc.

 

The problem is that Autocad seems to introduce some inaccuracy when I copy the elements. Lets say I copy the same branch every 5 meters, something like a one direction array. Unfortunately when I run my lisp program it gives wrong results. The code is correct and give correct results if I dont copy the elements like that. That means copying by using osnaps (clicking manually every destination point) I get the results I am expecting.

 

Anyone encountered such issue? Any way to correct that somehow?

Thanks.

Link to comment
Share on other sites

Are you dividing with integers ?

 

Are you overriding / using osnaps in your code ?

 

As Tharwat suggests, posting code and sample are the best starting points.

 

-David

Link to comment
Share on other sites

try to set model to top view

 

I know that sometimes Autocad behaves better in top mode than 3D but that didn't make any difference. It is because like I said, the code is correct but the model seems to have some inaccuracy when inputing values instead of osnap points.

 

It is difficult to reproduce the whole issue cause it does not happen all the time.

 

I have noticed that the farther the copied member gets, the error can be greater. This means when selecting a line connected to a node and then copied every 5 units, something like a one directional array with a 5xn distance for each, the farthest it gets the most likely is that the point it sits is not exactly expected, for example not 15,5,10 rather 15.0000000000000000001. I guess it has to do with Autocad accuracy but some criteria in my lisp code do not work well because of that.

 

Has anyone encountered issues with Autocad accuracy?

 

As far as concern my code, it is lengthy and I dont think it makes sense for somebody looking through it but basically what I do is to parse the network on every node and make a selection set of lines on that node then looking for the angle between the two lines in the selection like that:

 

(setq A (distance (cdr (assoc 10 (entget (ssname s 0)))) (cdr (assoc 11 (entget (ssname s 0))))))
(setq B (distance (cdr (assoc 10 (entget (ssname s 1)))) (cdr (assoc 11 (entget (ssname s 1))))))
(setq C1 (distance (cdr (assoc 10 (entget (ssname s 0)))) (cdr (assoc 11 (entget (ssname s 1))))))
(setq C2 (distance (cdr (assoc 10 (entget (ssname s 0)))) (cdr (assoc 10 (entget (ssname s 1))))))
(setq C3 (distance (cdr (assoc 11 (entget (ssname s 0)))) (cdr (assoc 11 (entget (ssname s 1))))))
(setq C4 (distance (cdr (assoc 11 (entget (ssname s 0)))) (cdr (assoc 10 (entget (ssname s 1))))))
(setq C (max C1 C2 C3 C4))
(setq ang (* (/ 180 pi) (acos (/ (- (+ (* A A) (* B B)) (* C C)) (* 2 (* A B))))))

Link to comment
Share on other sites

It's not just autocad, but the way computers store REAL numbers. 15 significant digits ( not decimals ) are common

 

( rtos ) has this limit as to accuarcy even though you may speicfy 15 decimals (rtos c1 2 15) , it is estimating anything beyond the 15 significant digits

 

so 1234.56789012345 is about as accurate as is normally stored. The autolisp ( equal nnn nnn fuzz ) can be you best friend here.

 

So maybe a rounding function would help as well.

 

-David

Link to comment
Share on other sites

From the incomplete code snippet you provided it looks like you are trying to examine several distances between nodes and then calculate an angle as a function of distances A, B, and the largest of C1 thru c4. I assume the acos function is your custom function. Note that the acos function will produce more error for small angles. That is, as the acos approaches 1 (0°) a small change in the acos argument produces a larger difference in angle. For example, the change in angle from 0.0 for 0.1 is (90 - 84.26...) ~ 5.74° whereas the change from acos(.9) to acos(1) is a change of 25.84°. As you approach acos(1) the sensitivity increases.

In addition, the precision of the angles are also a function of the relative magnitude of the distances used in the calculation (the greater the distances the better) and the location of the lines relative to the WCS datum (0,0,0) (as you move away from the origin the precision is still 15 significant figures but the smallest step size is larger).

I suggest not using trig for your calculations and stick with vector calculations (the x, y, and z components of the vectors are essentially cosines). Perhaps just taking a dot product of vector AB and another vector will give you what you need.

A labeled picture of the points and what you are trying to determine would help me give you more detail if you want it.

~ lrm

Link to comment
Share on other sites

Like above I would not do this (/ 180 pi) but I would (/ 180.0 pi) this can help real/int calc problems.

 

Also I would do (setq pt1 (cdr (assoc 10 (entget (ssname s 0))))))) at start then (distance pt1 pt2)

Link to comment
Share on other sites

The AutoCAD database is double precision (15 significant digits) and AutoLISP is also double-precision so I don't think the "accuracy" problem is due to AutoCAD's precision but the method used in making the calculation. I would like more info on what the OP is trying to do.

 

BTW, mixed mode operations ( int / real ) are automatically converted to real math so although it is good practice to include a decimal point (/ 180.0 pi) it will not affect the computed result.

 

(setq a (/ 1 3 )) --> yields 0

(setq b (/ 1 3. )) --> yields 0.333333

(setq b (/ 1. 3. )) --> yields 0.333333

Link to comment
Share on other sites

  • 2 weeks later...

Here is a piece of code which creates all nodes of a chain created with lines. It also adds a text for each node.

 

(defun nodes (/ s ent i p a b)  

 (command "layer" "S" "0" "")

 (setq s (ssget "X" '((0 . "LINE"))))
  
 (setq plnod nil)
 (repeat (setq i (sslength s))
    (setq ent (entget (ssname s (setq i (1- i))))
            p (cdr (assoc 10 ent))
           plnod (if (not (member p plnod)) (cons p plnod) plnod)
            p (cdr (assoc 11 ent))
           plnod (if (not (member p plnod)) (cons p plnod) plnod)                                        
     )
  )

  (foreach p pl
     (mk_text p (itoa (+ (vl-position p pl) 2)) 0 0.05 0)
  )
  (command "layer" "S" "0" "")

  (princ)
)

(defun mk_text (p s j h r) 
  (entmakex
     (list (cons 0   "TEXT")         
           (cons 100 "AcDbEntity")          
           (cons 100 "AcDbText")    
           (cons 10 p)
           (cons 71 j)
           (cons 40 h)
           (cons 50 r)
           (cons  1 s)
     )
  )
)

But very often I found out that two texts in one node were created. See images below. The lines are created just like I say on my first post.

 

hc_007.jpg

 

hc_008.jpg

 

In this one below is the same as above, I only manually dragged the second text to make it clear.

hc_009.jpg

 

Therefore I understand that there is some short of micro misalignment? However if I type, either 'id' command and click the endpoint of each line or (entget (car (entsel))) picking any line or text and looking at the assoc 10 coordinates (or 11), it will always give the same result, the coordinates of the intersection point. No difference. This has implications on the way as other codes I have written do not interpret the nodes correctly giving wrong results. Any ideas why is it doing that?

hc_004.jpg

hc_005.jpg

hc_006.jpg

Link to comment
Share on other sites

I tried the code you posted and found a couple of typos. E.g., (Command "layer" ... should by "-layer" and two instances of pl should be plnod. Since the labeling error only occurs occasionally it is very difficult to debug without an actual example and the code you are using. Can you supply the code and example that produces the problem? My first thought was that perhaps there is an extra line. But, if this were the case you would have two extra text labels not just one as you have pictured. If you do a left-to-right select window that includes the labels 103, 104, 105 and the vertical line what do you get for an object count? You should get 4.

Link to comment
Share on other sites

I have given your accuracy concerns more thought and feel there may be a possibility that some noise could creep into the least significant digits of the coordinates you are retrieving and then examining with the member function. Another approach to try would be to do some rounding before building your list of coordinates. With 15 significant digits you should have some room for rounding.

 

First look at the largest coordinate that a node may have. Then determine what is the most precision you will need for a coordinate. I would add two orders of magnitude or more to compensate for rounding. So, if the extents of your model are +/- 1000 meters and you need a precision of 0.0001 you will need about 10 significant digits. I would try rounding node coordinates to 0.00001 before placing them in the list and doing the list search with the member function.

 

Consider using the following rounding functions posted by Lee Mac.

 

;; Round Up  -  Lee Mac
;; Rounds 'n' up to the nearest 'm'

(defun LM:roundup ( n m )
   (cond
       ((equal 0.0 (rem n m) 1e- n)
       ((< n 0) (- n (rem n m)))
       ((+ n (- m (rem n m))))
   )
)

;; Round Down  -  Lee Mac
;; Rounds 'n' down to the nearest 'm'

(defun LM:rounddown ( n m )
   (cond
       ((equal 0.0 (rem n m) 1e- n)
       ((< n 0) (- n (rem n m) m))
       ((- n (rem n m)))
   )
)

I hope this does it!

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