Jump to content

Troubleshooting of Lisp routine


MichaelAllfire

Recommended Posts

Hi all,

 

I am having some problems with my lisp routine code. The goal is to pick two points and have an xline generated perpendicular to the angle between points, positioned based on a few calculation within the function. I am, however, getting some wonky angles and no real consistency. Any thoughts?

 

(defun c:aspacing () ;define function
(setq a (getpoint "\nFirst Point ")) ;first point
(setq b (getpoint "\nSecond Point ")) ;second point
(setq x (/ (distance a b) 4200)) ;divide distance from a to b by 4200
(setq y (fix (1+ x))) ;round up to next whole number
(setq z1 (/ (distance a b) y))	;value of S - divide distance a b by y
(setq z2 (/ (/ (distance a b) y) 2))	;value of half S
(setq ang (* (angle a b) 57.2958))	;set angle of distance
(setq a1 (polar a ang z2)) ;starting point for xline
(command "xline" a1 (polar a1 (+ ang 90) 100) "") ;xline at 90 degrees to a b angle
) ;end function
(princ) ;clean loading

 

Thanks very much in advance! :)

Link to comment
Share on other sites

Not sure about this, angle * 57.2958

 

(+ ang 90) Autocad will work angles often in radians so (+ ang (/ pi 2.0)) note the 2.0

 

(setq z2 (/ (/ (distance a b) y) 2.0)) to ensure real not integer answer just good house keeping.

Link to comment
Share on other sites

I'm not sure why you are multiplying the angle, but the following should set you on the right path:

(defun c:aspacing ( / a b d )
   (and (setq a (getpoint "\n1st point: "))
        (setq b (getpoint "\n2nd point: " a))
        (setq d (distance a b))
        (entmake
            (list
               '(000 . "XLINE")
               '(100 . "AcDbEntity")
               '(100 . "AcDbXline")
                (cons 10 (trans (polar a (angle a b) (/ d (fix (1+ (/ d 4200.0))) 2.0)) 1 0))
                (cons 11 (trans (list (- (cadr a) (cadr b)) (- (car b) (car a))) 1 0 t))
            )
        )
   )
   (princ)
)

Link to comment
Share on other sites

Not sure about this, angle * 57.2958

 

(+ ang 90) Autocad will work angles often in radians so (+ ang (/ pi 2.0)) note the 2.0

 

(setq z2 (/ (/ (distance a b) y) 2.0)) to ensure real not integer answer just good house keeping.

 

Hey Bigal, thanks for the reply!

 

The * 57.2958 was to convert the radians to degrees, but now, if I understand correctly, I see that I don't need to as the other parts of the code deal in radians as well. Does (+ ang (/ pi 2.0)) add 90 degrees to the angle?

 

The 2.0 for real is a good tip, thanks. Just started getting into this kind of programming, and learning good practices is helpful. Thanks heaps!

Link to comment
Share on other sites

I'm not sure why you are multiplying the angle, but the following should set you on the right path:
(defun c:aspacing ( / a b d )
   (and (setq a (getpoint "\n1st point: "))
        (setq b (getpoint "\n2nd point: " a))
        (setq d (distance a b))
        (entmake
            (list
               '(000 . "XLINE")
               '(100 . "AcDbEntity")
               '(100 . "AcDbXline")
                (cons 10 (trans (polar a (angle a b) (/ d (fix (1+ (/ d 4200.0))) 2.0)) 1 0))
                (cons 11 (trans (list (- (cadr a) (cadr b)) (- (car b) (car a))) 1 0 t))
            )
        )
   )
   (princ)
)

 

Hi Lee,

 

I am having a bit of trouble understanding some of the code. Is there any chance of a few comments on the different lines of code?

 

I don't quite understand yet how the and part works. My understanding is that it returns true if all arguments are true. What argument/s are being tested? I also don't understand the list or subsequent lines of code either.

 

I get lost once code gets more general, as I'm still trying to learn and get my head around it.

 

Thanks so much for your help so far!

Link to comment
Share on other sites

Hi Michael,

 

Firstly, here is a fully commented version of the program to assist with your analysis:

[color=GREEN];; Define function and declare local variables[/color]
([color=BLUE]defun[/color] c:aspacing ( [color=BLUE]/[/color] a b d )
   [color=GREEN];; Evaluate each of the following expressions until[/color]
   [color=GREEN];; an expression returns nil or no expressions remain[/color]
   ([color=BLUE]and[/color]
        [color=GREEN];; Prompt the user for the first point, assign result to local variable 'a'[/color]
        ([color=BLUE]setq[/color] a ([color=BLUE]getpoint[/color] [color=MAROON]"\n1st point: "[/color]))
        [color=GREEN];; Prompt the user for the second point (with rubber band to the first point)[/color]
        [color=GREEN];; Assign result to the local variable 'b'[/color]
        [color=GREEN];; Note that by virtue of the AND function being a Special Form, this expression[/color]
        [color=GREEN];; will not be evaluated in the event that the first point prompt returns nil.[/color]
        ([color=BLUE]setq[/color] b ([color=BLUE]getpoint[/color] [color=MAROON]"\n2nd point: "[/color] a))
        [color=GREEN];; Calculate linear distance between points a & b, assign result of calculation[/color]
        [color=GREEN];; to local variable 'd'[/color]
        ([color=BLUE]setq[/color] d ([color=BLUE]distance[/color] a b))
        [color=GREEN];; Append the following DXF data to the current drawing database[/color]
        ([color=BLUE]entmake[/color]
            [color=GREEN];; Construct a DXF list of dotted pairs to append to the database[/color]
            ([color=BLUE]list[/color]
                [color=GREEN];; DXF Group 0: Entity Type[/color]
                [color=GREEN];; Fixed data, so expressed as quoted literal dotted pair -[/color]
                [color=GREEN];; See http://bit.ly/18ftLyF for more information on this concept[/color]
               '(000 . [color=MAROON]"XLINE"[/color])
                [color=GREEN];; DXF Group 100: Subclass marker designating object type[/color]
               '(100 . [color=MAROON]"AcDbEntity"[/color])
                [color=GREEN];; DXF Group 100: Subclass marker designating entity type[/color]
               '(100 . [color=MAROON]"AcDbXline"[/color])
                [color=GREEN];; Construct a dotted pair from the following atoms:[/color]
                [color=GREEN];; See http://bit.ly/18ftLyF for more information on why this cannot be quoted as a literal[/color]
                ([color=BLUE]cons[/color]
                    [color=GREEN];; DXF Group 10: WCS Base point for XLine[/color]
                    10
                    [color=GREEN];; Translate the following point from UCS to WCS[/color]
                    ([color=BLUE]trans[/color]
                        [color=GREEN];; Calculate the position of a point relative to point 'a' based on given calculations[/color]
                        ([color=BLUE]polar[/color] a ([color=BLUE]angle[/color] a b) ([color=BLUE]/[/color] d ([color=BLUE]fix[/color] ([color=BLUE]1+[/color] ([color=BLUE]/[/color] d 4200.0))) 2.0))
                        1 0
                    ) [color=GREEN];; end trans[/color]
                ) [color=GREEN];; end cons[/color]
                [color=GREEN];; Construct a dotted pair from the following atoms:[/color]
                ([color=BLUE]cons[/color]
                    [color=GREEN];; DXF Group 11: WCS vector defining XLine direction[/color]
                    11
                    [color=GREEN];; Translate the following point from UCS to WCS, independent of UCS origin[/color]
                    ([color=BLUE]trans[/color]
                        [color=GREEN];; Calculate a UCS vector perpendicular to a->b[/color]
                        ([color=BLUE]list[/color] ([color=BLUE]-[/color] ([color=BLUE]cadr[/color] a) ([color=BLUE]cadr[/color] b)) ([color=BLUE]-[/color] ([color=BLUE]car[/color] b) ([color=BLUE]car[/color] a)))
                        1 0 [color=BLUE]t[/color]
                    ) [color=GREEN];; end trans[/color]
                ) [color=GREEN];; end cons[/color]
            ) [color=GREEN];; end list[/color]
        ) [color=GREEN];; end entmake[/color]
   ) [color=GREEN];; end and[/color]
   [color=GREEN];; Suppress the value returned by the last evaluated expression (AND returns t/nil)[/color]
   ([color=BLUE]princ[/color])
) [color=GREEN];; end defun[/color]

I don't quite understand yet how the and part works. My understanding is that it returns true if all arguments are true. What argument/s are being tested?

 

The use of the AutoLISP and function in this example is more of a convenience to yield concise code, but perhaps at the cost of readability. The example could also be written using a simple if statement, however, the progn function must also be used to enable multiple expressions to be evaluated as part of the single 'then' argument expression:

[color=GREEN];; Define function and declare local variables[/color]
([color=BLUE]defun[/color] c:aspacing ( [color=BLUE]/[/color] a b d )
   [color=GREEN];; If the following test expression returns a non-nil value[/color]
   ([color=BLUE]if[/color]
       [color=GREEN];; Evaluate each of the following expressions until[/color]
       [color=GREEN];; an expression returns nil or no expressions remain[/color]
       ([color=BLUE]and[/color]
           [color=GREEN];; Prompt the user for the first point, assign result to local variable 'a'[/color]
           ([color=BLUE]setq[/color] a ([color=BLUE]getpoint[/color] [color=MAROON]"\n1st point: "[/color]))
           [color=GREEN];; Prompt the user for the second point (with rubber band to the first point)[/color]
           [color=GREEN];; Assign result to the local variable 'b'[/color]
           [color=GREEN];; Note that by virtue of the AND function being a Special Form, this expression[/color]
           [color=GREEN];; will not be evaluated in the event that the first point prompt returns nil.[/color]
           ([color=BLUE]setq[/color] b ([color=BLUE]getpoint[/color] [color=MAROON]"\n2nd point: "[/color] a))
       ) [color=GREEN];; end and[/color]
       [color=GREEN];; Evaluate the following expressions as a single expression[/color]
       [color=GREEN];; constituting the 'then' argument for the IF function[/color]
       ([color=BLUE]progn[/color]
           [color=GREEN];; Calculate linear distance between points a & b, assign result of calculation[/color]
           [color=GREEN];; to local variable 'd'[/color]
           ([color=BLUE]setq[/color] d ([color=BLUE]distance[/color] a b))
           [color=GREEN];; Append the following DXF data to the current drawing database[/color]
           ([color=BLUE]entmake[/color]
               [color=GREEN];; Construct a DXF list of dotted pairs to append to the database[/color]
               ([color=BLUE]list[/color]
                   [color=GREEN];; DXF Group 0: Entity Type[/color]
                   [color=GREEN];; Fixed data, so expressed as quoted literal dotted pair -[/color]
                   [color=GREEN];; See http://bit.ly/18ftLyF for more information on this concept[/color]
                  '(000 . [color=MAROON]"XLINE"[/color])
                   [color=GREEN];; DXF Group 100: Subclass marker designating object type[/color]
                  '(100 . [color=MAROON]"AcDbEntity"[/color])
                   [color=GREEN];; DXF Group 100: Subclass marker designating entity type[/color]
                  '(100 . [color=MAROON]"AcDbXline"[/color])
                   [color=GREEN];; Construct a dotted pair from the following atoms:[/color]
                   [color=GREEN];; See http://bit.ly/18ftLyF for more information on why this cannot be quoted as a literal[/color]
                   ([color=BLUE]cons[/color]
                       [color=GREEN];; DXF Group 10: WCS Base point for XLine[/color]
                       10
                       [color=GREEN];; Translate the following point from UCS to WCS[/color]
                       ([color=BLUE]trans[/color]
                           [color=GREEN];; Calculate the position of a point relative to point 'a' based on given calculations[/color]
                           ([color=BLUE]polar[/color] a ([color=BLUE]angle[/color] a b) ([color=BLUE]/[/color] d ([color=BLUE]fix[/color] ([color=BLUE]1+[/color] ([color=BLUE]/[/color] d 4200.0))) 2.0))
                           1 0
                       ) [color=GREEN];; end trans[/color]
                   ) [color=GREEN];; end cons[/color]
                   [color=GREEN];; Construct a dotted pair from the following atoms:[/color]
                   ([color=BLUE]cons[/color]
                       [color=GREEN];; DXF Group 11: WCS vector defining XLine direction[/color]
                       11
                       [color=GREEN];; Translate the following point from UCS to WCS, independent of UCS origin[/color]
                       ([color=BLUE]trans[/color]
                           [color=GREEN];; Calculate a UCS vector perpendicular to a->b[/color]
                           ([color=BLUE]list[/color] ([color=BLUE]-[/color] ([color=BLUE]cadr[/color] a) ([color=BLUE]cadr[/color] b)) ([color=BLUE]-[/color] ([color=BLUE]car[/color] b) ([color=BLUE]car[/color] a)))
                           1 0 [color=BLUE]t[/color]
                       ) [color=GREEN];; end trans[/color]
                   ) [color=GREEN];; end cons[/color]
               ) [color=GREEN];; end list[/color]
           ) [color=GREEN];; end entmake[/color]
      ) [color=GREEN];; end progn[/color]
   ) [color=GREEN];; end if[/color]
   [color=GREEN];; Suppress the value returned by the last evaluated expression[/color]
   ([color=BLUE]princ[/color])
) [color=GREEN];; end defun[/color]

Thanks so much for your help so far!

 

You're most welcome - feel free to ask if you have further questions surrounding the posted code.

Link to comment
Share on other sites

Once it gets into the entmake and list part of the code, it ends up going way over my head. I guess I don't have a good enough understanding of these parts of Lisp programming. I will have to go and do some more research! I'll check out the tutorials on your website, any others you could recommend as well? Thanks for your help!

 

Continuing on from the actual functionality of the code - I want to add something to this command, but don't know how to go about it. I am hoping to have the first xline offset a number of times, so that the total number of xlines = the rounded up value of d/4200. The xlines need to have equal distance between them, but half that distance between the end lines and the two points chosen. Does that make sense?

 

Can this be achieved with something like a simple offset command (again, me not knowing a lot of basics, this is my only real thought) to be 2 x the distance from the first point to the second point?

 

I have more things I want to add, but baby steps at this stage. Thanks heaps!

Link to comment
Share on other sites

If your struggling with a entmake and knowing the dxf codes can be daunting go back to old fashioned for now.

 

(defun c:aspacing ( / a b d )
   (and (setq a (getpoint "\n1st point: "))
        (setq b (getpoint "\n2nd point: " a))
        (setq d (distance a b))
        (setq pt1 (trans (polar a (angle a b) (/ d (fix (1+ (/ d 4200.0))) 2.0)) 1 0))
        (setq pt2 (trans (list (- (cadr a) (cadr b)) (- (car b) (car a))) 1 0 t))
        (command "XLINE" pt1 pt2 "") 
   )
   (princ)
)

 

Please post an imgage or dwg of what you want so its clear.

Link to comment
Share on other sites

Hi Bigal,

 

The structuring of your code seems similar to my initial post. It seems more straight forward (at least to me) following a one-after-another sort of approach. At least that's the way it appears to me. Thanks for your reply!

 

I have quite a large overall plan for this command. Attached below is an image of what I am trying to achieve for this part of the command.Capture.jpg

 

The xlines (supposed to be yellow in the image, not quite yellow) are the part that I want the command to draw, I don't need any of the dimensions, text, circles or grey line, just the xlines.

 

Does that make sense in regards to the previous posts? The number of xlines needs to be

(fix (1+ (/ d 4200.0)))

if that makes sense. (the rounded up value of distance/4200)

 

Thanks for you help as well!

Link to comment
Share on other sites

Maybe I should add what my plans are for the rest of the command.

 

I want the command to basically repeat itself a second time after the xlines are drawn, but in a different direction.

 

On the second run through, it needs to -

Get the distance between the two points of the second direction (value 0)

Get the distance between two of the existing xlines. (value 1)

Divide 12000 by value 1. (value 2)

Multiply value 2 by 1000 (value 3)

Divide value 0 by value 3 (value 4)

Round value 4 up to nearest whole number (value 5)

Use value 5 as the number of xlines to space in the second direction, keeping half x at the ends.

 

Basically, if I can repeat the command in a second direction, it will allow me to create a grid like in the image below, where the grid rectangles don't go over 12 square metres.

 

Capture2.jpg

 

I hope this makes sense.

Link to comment
Share on other sites

So I have continued tinkering in my spare time, mostly to get a bit better with lisp coding, and have come up with this code.

 

(defun c:aspacing ()						;define function
(setq a (getpoint "\nFirst Point ")) 	;first point
(setq b (getpoint "\nSecond Point " a)) ;second point
(setq x (/ (distance a b) 4200))		;divide distance from a to b by 4200
(setq y (fix (1+ x)))					;round up to next whole number
(setq z1 (/ (distance a b) y))			;value of S - divide distance a b by whole number
(setq z2 (/ (/ (distance a b) y) 2))	;value of half S
(setq ang (angle a b))					;set angle of distance
(setq a1 (polar a ang z2))				;starting point for xline
(command "xline" a1 (polar a1 (+ ang 1.570795765134617) 100)"")		;draw xline perpendicular to ab
(command "offset" z1 a1 "m" (repeat y(b)) "" "") 		;offset y number of times
)											;end function
(princ) 									;clean loading

 

I am having an issue with the (command "offset" ...) line. I am using point b as the direction of offset, but I need it to repeat y number of times. I have no idea how to make repeat work in this situation. Thoughts?

Link to comment
Share on other sites

Hi Bigal! Thanks for that, works perfectly. I have updated my code to add a second run through, to make a grid like in a previous post of mine. It seems to work pretty well, even though my code feels a bit rudimentary. It currently looks like this.

 

(defun c:aspacing ()													
(setq a (getpoint "\nFirst Point ")) 								
(setq b (getpoint "\nSecond Point " a)) 							
(setq d (/ (distance a b) 4200))									
(setq y (fix (1+ d)))												
(setq y1 (fix d))													
(setq s (/ (distance a b) y))										
(setq halfS (/ (/ (distance a b) y) 2))								
(setq ang (angle a b))												
(setq x (polar a ang halfS))										
(command "xline" x (polar x (+ ang 1.570795765134617) 100)"")		
(command "offset" s x "m" (repeat y1(command b))) 					
(setq a2 (getpoint "\nFirst Point ")) 								
(setq b2 (getpoint "\nSecond Point " a2))				 			
(setq h (* (/ 12000 s) 1000))										
(setq h1 (/ (distance a2 b2) h))									
(setq y2 (fix (1+ h1)))												
(setq y3 (fix h1))													
(setq s2 (/ (distance a2 b2) y2))									
(setq halfS2 (/ (/ (distance a2 b2) y2) 2))							
(setq ang2 (angle a2 b2))											
(setq x2 (polar a2 ang2 halfS2))									
(command "xline" x2 (polar x2 (+ ang2 1.570795765134617) 100)"")	
(command "offset" s2 x2 "m" (repeat y3(command b2)) "" "") 			

)																		
(princ) 		

 

It works great when selecting random points on my drawing, but as soon as I use, say, the corners of a rectangle or the end points of a line, it gets stuck waiting for me to input a through point for my xline. The base point of the xline is always the first point I clicked. Thoughts? Is this a quirk of the xline command that I might not know about?

 

Any other comments on my code?

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