Jump to content

Story-Booking idea for a LISP


Recommended Posts

I'm very new to creating LISPs but I want to learn.

We have parallel lines (Blue & Cyan). At some points on the Blue line there is a perpendicular Blue line. At that intersection, the Cyan line needs a V groove (Usually 90 degrees, but not always).

To story-book this LISP process:

Ask to select the Cyan Polyline

Ask to select the intersection point

Ask the angle (default to 90 degrees)

Capture2.JPG

 

I think we would have to take in intersection point (Blue) and extend to the Cyan line and measure the distance.

Then we add a point on the Cyan line (point 1).

Then we do the math of the angle (usually 90 degrees)

We take the distance * tan(.5(angle)) which give us the distance in either direction to add a point to the Cyan Polyline.

Then we move Point 1 on the Cyan to the intersection of the Blue lines

We'd also have to account for the angle and direction of the distance between the Blue and Cyan lines as this can occur on any side of a box.

 

Am I missing anything? Should I look out for anything? I know it's going to take me awhile but I want to learn.

Capture1.JPG

Link to post
Share on other sites
  • Replies 22
  • Created
  • Last Reply

Top Posters In This Topic

  • jonhite

    10

  • Jef!

    6

  • dlanorh

    3

  • BIGAL

    3

Top Posters In This Topic

Popular Posts

Few things is for sure: the code I posted might not be totally bullet proof, but it does work. Good news: I'm totally able to reproduce the result you describe: your current layer is off. We can take

That would be very complex to do, since when you break a line it creates a new one and you don't have any way to retrieve the entities to make the pline. One way would be to collect the coordinate fro

Posted Images

I'm very new to creating LISPs but I want to learn.

We have parallel lines (Blue & Cyan). At some points on the Blue line there is a perpendicular Blue line. At that intersection, the Cyan line needs a V groove (Usually 90 degrees, but not always).

To story-book this LISP process:

Ask to select the Cyan Polyline

Ask to select the intersection point

Ask the angle (default to 90 degrees

I think we would have to take in intersection point (Blue) and extend to the Cyan line and measure the distance.

Then we add a point on the Cyan line (point 1).

Then we do the math of the angle (usually 90 degrees)

We take the distance * tan(.5(angle)) which give us the distance in either direction to add a point to the Cyan Polyline.

Then we move Point 1 on the Cyan to the intersection of the Blue lines

We'd also have to account for the angle and direction of the distance between the Blue and Cyan lines as this can occur on any side of a box.

 

Am I missing anything? Should I look out for anything? I know it's going to take me awhile but I want to learn.

 

How would you draw it? This is always a good starting point.

 

 

I would do it in this order :

 

 

Ask for the angle (default to 90 degrees)

Convert angle to radians (autolisp works in radians)

 

Calculate half the angle (halfangle)

 

Ask to select the Cyan Polyline

Get Cyan Polylines entity name, layer and linetype (store in variables)

 

Convert entity name to object (cyan_polyline_obj)

 

Start a loop

 

Ask to select the intersection point [i_pt]

 

Use vlax-curve-getclosestpointto function to find perpendicular point on cyan line [p_pt] (these work on straight lines as well)

 

(setq p_pt (vlax-curve-getClosestPointTo cyan_polyline_obj i_pt))

 

Get distance via Autolisp distance function (distance i_pt p_pt)

Get Angle via Autolisp angle function (angle i_pt p_pt)

 

Calculate hypotenuse length = adjacent(distance i_pt p_pt)/Cos halfangle

 

Calc new angles (angle i_pt p_pt) + and minus halfangle

 

Use Autolisp function polar with hypotenuse length and new angles to get points on cyan polyline

 

Draw lines from i_pt to these two new points

 

Break polyline between these points

 

 

End loop

Link to post
Share on other sites

Ok, I've gone through the LISP tutorial on this site and learned some answers. But some parts are confusing. Here is how I jumbled things together. Can you guide me on some parts I've done wrong so that I can go back and figure out how to correct it? (First LISP by the way) Thanks!

(defun deg2rad (deg / )
 (/ (* deg 3.14159265359 ) 180)
)

;; rg for to make the Return Groove
(defun c:rg ( / ra rap cpn cyan_polyline_obj i_pt p_pt aa rra hyp)
 (setq ra (getangle "\nAngle of Groove "))
 (setq rap (/ (deg2rad ra) 2)
 

(princ "\nSelect CYAN Polyline: ")
		(setq SS (ssget (list (cons 0 "LWPOLYLINE"))))
(setq cpn (ssname)) ; Cyan Polyline Name
(setq cyan_polyline_obj (ssname)); Set as Object


Start Loop????

(setq i_pt (getpoint "\nSelect Insertion Point on Blue Line "))
(setq p_pt (vlax-curve-getClosestPointTo cyan_polyline_obj i_pt))
(setq aa (distance i_pt p_pt));Angle Adjacent Distance
(setq rra (angle i_pt p_pt)); I'm not sure how I'm getting an angle from 2 points?
(setq hyp (/ aa Cos)); Calculate Hypotenuse Length
(setq pt1 (polar hyp aa)); Calculates Point 1
(setq pt2 (polar hyp -aa)); Calculates Point 2
(command "line" i_pt pnt1 "")
(command "line" i_pt pnt2 "")
Break Polyline????
End Loop????

Link to post
Share on other sites

If your picking one at a time then use entsel. But it does not filter for correct object that is one advantage of ssget. You can though check the object name before proceeding. If the end users are experienced and understand what is expected entsel will work say 99%.

 

(princ "\nSelect CYAN Polyline: ")
		(setq SS (ssget (list (cons 0 "LWPOLYLINE"))))
(setq cpn (ssname)) ; Cyan Polyline Name
(setq cyan_polyline_obj (ssname)); Set as Object
v's
(setq cyan_polyline_obj  (car (entsel "\nPick cyan polyline")))

 

(setq hyp (/ aa Cos)) this will crash
Cos this function returns the cosine of angle 
(setq hyp (/ aa (Cos rra)))

 

(setq pt1 (polar hyp aa))
(setq pt1 (polar i_pt hyp aa )) ; not sure i_pt

 

(command "line" i_pt pnt1 "")
(command "line" i_pt pnt2 "")

(command "line" pnt2 i_pt pnt1 "")

Link to post
Share on other sites
Ok, I've gone through the LISP tutorial on this site and learned some answers. But some parts are confusing. Here is how I jumbled things together. Can you guide me on some parts I've done wrong so that I can go back and figure out how to correct it? (First LISP by the way) Thanks!

 

 

Try these : Green = substitute, add or change Red = remove

 

 

 

(defun deg2rad (deg / )
 (/ (* deg[color=seagreen] pi[/color]) 180)
)

;; rg for to make the Return Groove
(defun c:rg ( / ra rap [color=red]cpn[/color] cyan_polyline_obj i_pt p_pt aa rra hyp [color=seagreen]pt1 pt2[/color])
 (setq ra (getangle "\nAngle of Groove "))
 (setq rap (/ (deg2rad ra) 2)[color=seagreen])[/color]
 

([color=seagreen]prompt[/color] "\nSelect CYAN Polyline: ")[color=blue];IMO prompt is better than princ [/color]
           (setq SS (ssget [color=seagreen]"_:S"[/color] '((0 . "LWPOLYLINE"))))[color=blue];This ensures a single selection[/color]
[color=seagreen](setq cyan_polyline_obj (vlax-ename->vla-object (ssname ss 0)))[/color] [color=blue]; The entity name will be the first entry in the selection set (zero based). You must specify selection set and index with ssname[/color]
[color=red](setq cyan_polyline_obj (ssname)); Set as Object REMOVE THIS LINE COMBINED WITH ABOVE[/color]

[color=red]Start Loop????[/color]
[color=blue];while loop while you continue to select an insertion point. To finish just press enter or right click the mouse to provide a null. The loop will then exit      [/color]
[color=seagreen](while[/color] (setq i_pt (getpoint "\nSelect Insertion Point on Blue Line "))
(setq p_pt (vlax-curve-getClosestPointTo cyan_polyline_obj i_pt))
(setq aa (distance i_pt p_pt));Angle Adjacent Distance
(setq rra (angle i_pt p_pt)); I'm not sure how I'm getting an angle from 2 points?
[color=blue];;They are points but also coordinates. It calculates the angle from the coordinates[/color]


(setq hyp [color=seagreen](/ aa (cos rap))[/color]; Calculate Hypotenuse Length
(setq pt1 (polar hyp [color=seagreen](+ rra rap)[/color])); Calculates Point 1
(setq pt2 (polar hyp [color=seagreen](-rra rap)[/color])); Calculates Point 2
(command "line" i_pt [color=seagreen]pt1[/color] "")
(command "line" i_pt [color=seagreen]pt2[/color] "")
[color=seagreen](command "Break" "_F" pt1 pt2)[/color]
[color=seagreen]);end loop[/color]
[color=seagreen]);end_defun[/color]

It might be worth downloading Notepad++ as this has excellent parenthesis checking auto indenting and colour coding when set up for lisp (simple selection)

Link to post
Share on other sites

I've just realised that this won't work properly as breaking the polyline will change the entity. We may need to select the polyline before each break.

 

 

Remove the while from here:

 

[color=red](while [/color](setq i_pt (getpoint "\nSelect Insertion Point on Blue Line "))

 

 

and change these :

 

([color=seagreen]prompt[/color] "\nSelect CYAN Polyline: ")[color=blue];IMO prompt is better than princ[/color]
(setq SS (ssget [color=seagreen]"_:S"[/color] '((0 . "LWPOLYLINE"))))[color=blue];This ensures a single selection[/color] 
[color=seagreen](setq cyan_polyline_obj (vlax-ename->vla-object (ssname ss 0)))[/color] [color=blue]; The entity name will be the first entry in the selection set (zero based). You must specify selection set and index with ssname[/color] 

To :

 

[color=seagreen](while [/color](setq ss (car (entsel "\nSelect CYAN Polyline: "))) [color=seagreen]
[/color]
[color=seagreen](setq cyan_polyline_obj (vlax-ename->vla-object ss))[/color]

 

 

I also messed this up

 

(command "Break" [color=seagreen]ss[/color] "_F" pt1 pt2)

Link to post
Share on other sites

Its just me but get a piece of paper draw the same as cad look at each line of code and write on the paper what its doing write "I_pt" at the point of intersection etc then you will get a better visual idea of whats going on. When you get to remembering 20 point locations a sketch comes in handy.

Edited by BIGAL
Link to post
Share on other sites

I understand mostly what is happening, but it will help to see it in action. I loaded the lsp file from appload, but when I type rg it say that it is an unknown command. Any Ideas?

(defun deg2rad (deg / )
 (/ (* deg pi ) 180)
)

;; rg to make the Return Groove
(defun c:rg ( / ra rap cyan_polyline_obj i_pt p_pt aa rra hyp)
 (setq ra (getangle "\nAngle of Groove "))
 (setq rap (/ (deg2rad ra) 2)
 
(prompt "\nSelect CYAN Polyline: ")
		(setq SS (ssget "_:S" '(( 0 . "LWPOLYLINE"))))
(setq cyan_polyline_obj (vlax-ename->vla-object (ssname ss 0))) ; The entity name will be the first entry in the selection set (zero based). You must specify selection set and index with ssname

(while (setq ss (car (entsel "\nSelect CYAN Polyline: "))) 

(setq cyan_polyline_obj (vlax-ename->vla-object ss))
(setq i_pt (getpoint "\nSelect Insertion Point on Blue Line "))
(setq p_pt (vlax-curve-getClosestPointTo cyan_polyline_obj i_pt))
(setq aa (distance i_pt p_pt));Angle Adjacent Distance
(setq rra (angle i_pt p_pt)); getting an angle from 2 points
(setq hyp (/ aa (cos rap))); Calculate Hypotenuse Length
(setq pt1 (polar hyp (+ rra rap))); Calculates Point 1
(setq pt2 (polar hyp (- rra rap))); Calculates Point 2
(command "line" i_pt pt1 "")
(command "line" i_pt pt2 "")
(command "Break" ss "_F" pt1 pt2)
);end loop
);end_defun

Link to post
Share on other sites

You have a parenthesis mismatch (1 closing parenthesis missing) on the line

 

(setq rap (/ (deg2rad ra) 2)

 

This kind of thing is easy to find if you use the visual lisp editor... (type vlide to start it)

Link to post
Share on other sites

You can use Vlide to debug or as others have said if using notepad++ it will show you enclosed brackets or an oldy prior to notepad and VLIDE is chkbrk lisp that I wrote like 30 years ago a missing bracket is one of the most common mistakes the second for me is a missing "

 

Using notepad++ just click on the start of the line the end brackets will go red.

 

I tend to write and test as I go so you can copy 1 line at a time to the command line or more and make sure it works, whiles and repeats get a bit trickier. Dont paste ; remarks.

ScreenShot135.jpg

Link to post
Share on other sites

I'll start using Notepad++. At least I know what not having matching parenthesis does.

I ran the corrected LISP, here's what happened:

It ask's for the angle. I put 90

It asks to Select Objects. I assume (setq rap (/ (deg2rad ra) 2)) is calling for this? It won't let me proceed without selecting something so I select the blue line.

Then the asks to select the Cyan line. So I do.

Then it asks to Select Insertion Point on Blue Line. So I do.

Then nothing happens.

I don't know why and I wonder if it has to do with the "Select Objects" deg2red line.

Any ideas?

Link to post
Share on other sites

Hi there!

Quote

I assume (setq rap (/ (deg2rad ra) 2)) is calling for this?

Nope, this only transfer the angle from DEGrees to RADians.
The reason it prompts twice is because you ask twice, once with the

(prompt "\nSelect CYAN Polyline: ")
		(setq SS (ssget "_:S" '(( 0 . "LWPOLYLINE"))))

and another time in the while here

(while (setq ss (car (entsel "\nSelect CYAN Polyline: ")))

The 2nd time, in the while, just overrides the first selection made. If you look carefully on Dlanorh's post (kind of hard to see with the color tag/migration mess), in the while he doesn't ask for the cyan poly but rather for a point on the blue line

(while (setq i_pt (getpoint "\nSelect Insertion Point on Blue Line "))


Also I don't have cad here, so here's a shot in the dark, but isn't the "_f" oftion of break standing for the fence option?

(command "Break" ss "_F" pt1 pt2)

If so, it might not work as the fence overlaps perfectly the line tr break. To test you can try typing

(command "Break" ss "_F"

then look at the commandline if it is asking for a fence.

Link to post
Share on other sites
hanhphuc
On 8/15/2018 at 10:57 PM, jonhite said:

 

5 hours ago, jonhite said:

I'll start using Notepad++. At least I know what not having matching parenthesis does.

hi, Notepad++ has nice formatting environment but for LISP efficiency & debugging i still prefer powerful VLIDE 

FWIW, in VLIDE - matching parenthesis


Ctrl+M

 

 

 

Link to post
Share on other sites
14 hours ago, Jef! said:

If you look carefully on Dlanorh's post (kind of hard to see with the color tag/migration mess), in the while he doesn't ask for the cyan poly but rather for a point on the blue line


(while (setq i_pt (getpoint "\nSelect Insertion Point on Blue Line "))

 

Hi Jef,

In his next post, he says to use (while for the CYAN line.

I don't know if that is what is killing the LISP but once I make my selections, it just ends. No lines get drawn. I figure that is the next point to get to is to get the lines drawn on there.

Right now I have:

(while (setq ss (car (entsel "\nSelect CYAN Polyline: "))) 

(setq cyan_polyline_obj (vlax-ename->vla-object ss))
(setq i_pt (getpoint "\nSelect Insertion Point on Blue Line "))

Do I remove (while (setq ss (car (entsel "\nSelect CYAN Polyline: "))) ? and replace it with (while (setq i_pt (getpoint "\nSelect Insertion Point on Blue Line ")) ?

What about (setq i_pt (getpoint "\nSelect Insertion Point on Blue Line ")) ? Do I remove that?

Is there a way that I can get feedback from the LISP to know how far the code gets? Can I have it write in the command line when it has the Angle Distance, Hyp Length, Calculates pt1 & pt2?

Link to post
Share on other sites

Ok... Here's a list of exactly what is wrong with the code.

-Getangle returns a value in radians. Because of that...
-neither the deg2rad function nor further processing is required and should be removed
-Like previously stated, the first prompt/setq of cyan_poly is useless as it is overwritten immediately. You just need the part in the while
-The angle is the angle of the notch (lets take 90 degrees as an example), which means that you need to divide it in 2 right angle triangles (with the adjacent from p_pt to i_pt) to calculate hyp as an hypotenuse. What it means is that you need to divide the angle by 2.
-In the polar functions you have the first argument (point) missing. 
-Again in the polar function you swapped the 2 last arguments, hyp being the length. Polar is as follow (polar point angle distance)
-Same as hyp, in the polar the angle needed is half of the angle of the notch. 
-You have 1 too many argument in the break command, the "_F" that I suspected yesterday. By running it manually I get a "Invalid point.", so fence is not available (nor required)
-(EDIT) I just noticed that since we use the line command, we have to turn off the osmode. If we don't the lines will snap everywhere.
-(EDIT) Since we change a VAR, a error handler is required to restore the osmode to its previous state if the user hits escape (and he might because of the while)
-(EDIT) If you want to exit quietly you need to add (princ) at the end.

Basically this is all you need to know to make the code work, and you should try to fix it on your own... don't spoil the fun! Don't look!

(defun c:rg ( / ra cyan_polyline_obj i_pt p_pt aa rra hyp oldosmode)
  (defun *error* ( msg )
    (setvar 'osmode oldosmode)
     (if (not (member msg '("Function cancelled" "quit / exit abort")))
         (princ (strcat "\nError: " msg))
     )
         (princ)
  )
    
  (setq oldosmode (getvar 'osmode))
  (setvar 'osmode 0)
  (setq ra (getangle "\nAngle of Groove ")); (Jef! returns the angle in radians already!)
  (while (setq ss (car (entsel "\nSelect CYAN Polyline: ")))
         (setq cyan_polyline_obj (vlax-ename->vla-object ss))
         (setq i_pt (getpoint "\nSelect Insertion Point on Blue Line "))
         (setq p_pt (vlax-curve-getClosestPointTo cyan_polyline_obj i_pt))
         (setq aa (distance i_pt p_pt));Angle Adjacent Distance
         (setq rra (angle i_pt p_pt)); getting an angle from 2 points
         (setq hyp (/ aa (cos (/ ra 2)))); Calculate Hypotenuse Length  ; (Jef! The angle needed is HALF the angle of notch NOT "(/ aa (cos rap))")
         (setq pt1 (polar i_pt (+ rra (/ ra 2)) hyp)); Calculates Point 1 ; (Jef! NOT (polar hyp (+ rra rap))) missing argument (i_pt)in polar! (and polar args are pt ang dist, NOT pt dist ang)
         (setq pt2 (polar i_pt (- rra (/ ra 2)) hyp)); Calculates Point 2 ; (Jef! NOT (polar hyp (- rra rap))) missing argument(i_pt) in polar! (and polar args are pt ang dist, NOT pt dist ang)
         (command "line" i_pt pt1 "")
         (command "line" i_pt pt2 "")
         (command "Break" ss pt1 pt2); (Jef! No "_F"... not sure what it was, after ss it prompts for poit, so "_F" is an "Invalid point.")
   );end loop
  (setvar 'osmode oldosmode)
  (princ); exit quietly
)

You cheated! :)

Edited by Jef!
added the osmode change and the error handler
Link to post
Share on other sites

I tried to follow your description as a newbie but it didn't work. So I looked at your code and corrected my numerous mistakes. When I run your code this is what happens:

Choose angle: 90

Select the CYAN line

Select the insertion point on the blue line

It draws a line between the insertion point and the CYAN line and cuts the CYAN line. But never draws an angle.

I tried to modify your code with the idea at we can't get the angle from the 2 points until we have the points. We don't have the points until after they are calculated. I moved the line, and it won't even draw the first line (hyp) anymore. 

I'm learning a lot for my first LISP, but it's difficult when I can't get it to work correctly.

I really do appreciate your help, but what am I missing to get the angles to draw? Am I on the right track?

Link to post
Share on other sites

Never mind, you must have edited and corrected it. I pulled your 1st code from my e-mail.

It works. Next step is that I need to join the lines and make the CYAN 1 single polyline. I'll see if I can handle that.

I appreciate everyone's help on this. Much to learn!

Link to post
Share on other sites
Quote

It draws a line between the insertion point and the CYAN line and cuts the CYAN line. But never draws an angle.

Few things is for sure: the code I posted might not be totally bullet proof, but it does work. Good news: I'm totally able to reproduce the result you describe: your current layer is off. We can take care of it programmatically, as any other fail safes, of course the code will get more complex as we go. We will dig deeper on that.

Quote

we can't get the angle from the 2 points until we have the points

Actually we calculate the 2 points using the angle.

Ok, so now that we figured out that if the current layer is off, we need to choose what to do with it. When it is off, the result is still there and good, just not shown. The 3 options are A) We either do nothing and keep executing the code anyway. B) We just turn it on and leave it on or C) We turn it on just to see what we are doing and then restore it to its previous state. Good programming practice is to always leave the user environment exactly as it was before the execution of the code. Don't we hate when routines leave variables and settings changed after completion... but here, turning the layer back off might seems kind of strange. We also have the choice on how to do it. For beginners it might be easier to achieve things using command calls. I've localized the variables (ss pt1 pt2 and *error*, as well as tmp, a new one i created to keep track of the layer status). Here's the modified code.

(defun c:rg ( / *error* oldosmode ra ss cyan_polyline_obj i_pt p_pt aa rra hyp pt1 pt2 tmp)
  (defun *error* ( msg )
    (setvar 'osmode oldosmode)
    (if tmp (command "_layer" "_off" (getvar 'clayer) "_Y" "" ))
    (if (and msg
             (not (member msg '("Function cancelled" "quit / exit abort")))
        )
        (princ (strcat "\nError: " msg))
    )
    (princ)
  )
    
  (setq oldosmode (getvar 'osmode))
  (if (setq tmp (minusp (cdr (assoc 62 (tblsearch "layer" (getvar 'clayer))))))
      (command "_layer" "_on" (getvar 'clayer)"")
      (setq tmp nil)
  )
  (setq ra (getangle "\nAngle of Groove "))
  (while (setq ss (car (entsel "\nSelect CYAN Polyline: ")))
         (setq cyan_polyline_obj (vlax-ename->vla-object ss))
         (setq i_pt (getpoint "\nSelect Insertion Point on Blue Line "))
         (setq p_pt (vlax-curve-getClosestPointTo cyan_polyline_obj i_pt))
         (setq aa (distance i_pt p_pt));Angle Adjacent Distance
         (setq rra (angle i_pt p_pt)); getting an angle from 2 points
         (setq hyp (/ aa (cos (/ ra 2)))); Calculate Hypotenuse Length
         (setq pt1 (polar i_pt (+ rra (/ ra 2)) hyp)); Calculates Point 1
         (setq pt2 (polar i_pt (- rra (/ ra 2)) hyp)); Calculates Point 2
         (command "line" i_pt pt1 "")
         (command "line" i_pt pt2 "")
         (command "Break" ss pt1 pt2)
   );end loop
  (*error* nil)
)

 

  • Like 1
Link to post
Share on other sites

Never mind, you must have edited and corrected it. I pulled your 1st code from my e-mail.

It works. Next step is that I need to join the lines and make the CYAN 1 single polyline. I'll see if I can handle that.

I appreciate everyone's help on this. Much to learn!

Link to post
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
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...