Jump to content

Recommended Posts

Posted

Hi,

 

I want to check for the width and height of a Rectangle.

 

I got this code

 

(defun getRect ()
    (if (setq rec (ssget "_X" (list '(0 . "LWPOLYLINE") '(8 . "LAYOUT") '(90 . 4) (cons 410 (getvar "ctab")) )))
        (progn
            (setq e (ssname rec 0))
            (setq coords (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget  e))))
          
            (setq height (distance (car coords) (nth 3 coords)))
            (setq width (distance (car coords) (nth 1 coords)))
        
            (if (= height 594.0)
                T
                (princ height)
             )
        
        )
      

    )
  (princ)
    
)

 

If I check for the Width it works and it returns T

But If I try to get the height it returns false and prints

594.0

 

Why does this not return True as well?

Posted (edited)

Copied and pasted stuff, try this:

 

(defun c:rectcoords ( / MyRect Coords MyCoords )
  (princ "\nSelect Rectangle")
  (if (setq MyRect (ssget "_+.:E:S" (list '(0 . "*POLYLINE") '(90 . 4) '(70 . 1)) )) ; Select single closed 4 line polyline
    (progn
      (setq Coords (vlax-get (vlax-ename->vla-object (ssname MyRect 0)) 'Coordinates) ) ; Get all coordinates
      (setq acount 0)
      (setq MyCoords (list))
      (while (< acount (length Coords)) ; split coords list into pairs
        (setq MyCoords (append MyCoords (list (list (nth acount Coords) (nth (+ acount 1) Coords)))))
        (setq acount (+ 2 acount))
      ) ; end while


      (setq height (distance (car MyCoords) (nth 3 MyCoords)))
      (setq width (distance (car MyCoords) (nth 1 MyCoords)))
      (if (= height 594.0)
        T
        (princ height)
      ) ; end if


    ) ; end progn
    (progn
      (princ "No Rectangle (4 vertex closed polyline) Selected")
    ) ; end progn
  ) ; end if
  (princ)
) ; end defun

 

Edited by Steven P
  • Thanks 1
Posted
32 minutes ago, Steven P said:

Copied and pasted stuff, try this:

 

(defun c:rectcoords ( / MyRect Coords MyCoords )
  (princ "\nSelect Rectangle")
  (if (setq MyRect (ssget "_+.:E:S" (list '(0 . "*POLYLINE") '(90 . 4) '(70 . 1)) )) ; Select single closed 4 line polyline
    (progn
      (setq Coords (vlax-get (vlax-ename->vla-object (ssname MyRect 0)) 'Coordinates) ) ; Get all coordinates
      (setq acount 0)
      (setq MyCoords (list))
      (while (< acount (length Coords)) ; split coords list into pairs
        (setq MyCoords (append MyCoords (list (list (nth acount Coords) (nth (+ acount 1) Coords)))))
        (setq acount (+ 2 acount))
      ) ; end while


      (setq height (distance (car MyCoords) (nth 3 MyCoords)))
      (setq width (distance (car MyCoords) (nth 1 MyCoords)))
      (if (= height 594.0)
        T
        (princ height)
      ) ; end if


    ) ; end progn
    (progn
      (princ "No Rectangle (4 vertex closed polyline) Selected")
    ) ; end progn
  ) ; end if
  (princ)
) ; end defun

 

Thank you for your help.

 

 I have not tested your code yet but I see you chnged a lot. Does this mean the way I was getting getting the coordinates was wrong?

I just don't understand why it would return false and print the same value (594.0) I was checking for in the if statement

Posted
3 hours ago, Brok said:

But If I try to get the height it returns false and prints

594.0

Why does this not return True as well?

 

When comparing reals (aka doubles) in AutoLISP, you should use the equal function with a small tolerance (e.g. 1e-8 = 0.00000001) in order to account for infinitesimal inaccuracies that are inevitably introduced at the limits of the precision of this format - two doubles are rarely ever exactly equal on a bitwise level.

 

As such, I would suggest changing:

(= height 594.0)

 

To:

(equal height 594.0 1e-8)

 

  • Like 1
  • Thanks 1
Posted
17 hours ago, Lee Mac said:

 

When comparing reals (aka doubles) in AutoLISP, you should use the equal function with a small tolerance (e.g. 1e-8 = 0.00000001) in order to account for infinitesimal inaccuracies that are inevitably introduced at the limits of the precision of this format - two doubles are rarely ever exactly equal on a bitwise level.

 

As such, I would suggest changing:

(= height 594.0)

 

To:

(equal height 594.0 1e-8)

 

 

Thank you Lee Mac. This worked perfectly

 

Posted

@Brok

Don't forget to locali(sz)e your variables: (/ coords e height rec width)

Posted
On 4/19/2023 at 11:55 AM, Brok said:

Thank you for your help.

 

 I have not tested your code yet but I see you chnged a lot. Does this mean the way I was getting getting the coordinates was wrong?

I just don't understand why it would return false and print the same value (594.0) I was checking for in the if statement

 

It was quicker for me to copy and paste stuff I know works than to work out what doesn't work... however as above, there are people out there who can spot these things instantly!

Posted
On 4/19/2023 at 2:08 PM, Lee Mac said:

 

When comparing reals (aka doubles) in AutoLISP, you should use the equal function with a small tolerance (e.g. 1e-8 = 0.00000001) in order to account for infinitesimal inaccuracies that are inevitably introduced at the limits of the precision of this format - two doubles are rarely ever exactly equal on a bitwise level.

 

As such, I would suggest changing:

(= height 594.0)

 

To:

(equal height 594.0 1e-8)

 

 

Lee, not sure if you'll get time to answer, but is there a global variable or setting that can be set to take account if these inaccuracies? Not something I have ever looked for yet though.

Posted (edited)
45 minutes ago, Steven P said:

Lee, not sure if you'll get time to answer, but is there a global variable or setting that can be set to take account if these inaccuracies? Not something I have ever looked for yet though.

 

No - such inaccuracies arise as an inherent consequence of the limited precision of the double-precision floating point format (for which the significand can represent decimal values to around 15-17 significant figures of precision).

 

Consider how some numbers cannot be perfectly represented in base10 (decimal) - e.g. multiples of 1/3 represented in decimal would require a infinite number of decimal places to be represented exactly; whereas, these same numbers can be represented exactly in other bases - e.g. 1/3 in base3 (ternary) is exactly 0.1. The same applies to binary values, where other rational numbers cannot be represented exactly, but must instead be approximated to the precision afforded by the amount of memory allocated to the format used to store the value (in this case 64-bits used by the double-precision floating point format).

 

As such, rounding will inevitably occur at the limit of precision following arithmetic operations, which then introduces infinitesimal differences and can result in a calculated value not being exactly equal to its literal counterpart - you can observe these differences directly using the rtos function to display all available decimal places:

 

_$ (rtos x 2 16)
"0.8000000000000000"
_$ (* x x)
0.64
_$ (rtos (* x x) 2 16)
"0.6400000000000002"
_$ (= 0.64 (* x x))
nil
_$ (equal 0.64 (* x x) 1e-8)
T

 

Edited by Lee Mac
  • Like 1
Posted

Thanks Lee, 

 

 

As always a good explanation why calculations can be inaccurate

 

 

 

 

(The way I look at this, using 1/3 as an  example

1/3 = 0.333333333333333 to 15 decimal places

3x 0.333333333333333 =  0.999999999999999

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