LISP TO MAKE A LINE WITH PREDEFINED DISTANCE AND USING THE ANGLE OF 2 VERTEX

LISP TO MAKE A LINE WITH PREDEFINED DISTANCE AND USING THE ANGLE OF 2 VERTEX

MEAN28
Participant Participant
1,462 Views
16 Replies
Message 1 of 17

LISP TO MAKE A LINE WITH PREDEFINED DISTANCE AND USING THE ANGLE OF 2 VERTEX

MEAN28
Participant
Participant

"Hi everyone!

I'm new to this field, and I'd love your help building this Lisp. I'm trying to reduce the number of clicks I have to make while doing this work. I’m very new to Lisp and don’t yet know how to code, but I’m eager to learn. Building it myself has been much harder than I expected.

The Lisp I'm working on involves creating a line with a predefined distance, using the angle between two vertices. If possible, I'd also like to loop the command so that I don't have to re-enter the distance each time. It would be great if, for example, I accidentally hit Esc, and when I run the command again, it remembers the last distance I entered.

Your help would be greatly appreciated. THANK YOU! 😊"

0 Likes
Accepted solutions (1)
1,463 Views
16 Replies
Replies (16)
Message 2 of 17

MEAN28
Participant
Participant

One more thing: if you know a faster way to achieve this output than what I have in mind, that would be great— as long as the result is the same. Thanks!

0 Likes
Message 3 of 17

ВeekeeCZ
Consultant
Consultant

You gotta express somehow what you have in mind - you forget to post your LISP?

0 Likes
Message 4 of 17

Moshe-A
Mentor
Mentor

@MEAN28  hi,

 

First welcome to AutoLISP world 😀

explain what do you mean by 'using angle between two vertices' ? supply an example

 

Here is CUSL (Custom Line) command for you to test. it is a bit pro but i added comments where possible

the main code is on lines 65-68 preformed by loop to draw the line if points is still coming.

the real code is done in (pause_for_input) local function, there you pick points and specify Distance and Angle

 

the command starts on line 49

on line 53 i define a default variable for distance

on line 59 i define a default variable for angle

 

the whole code is wrapped inside (defun c:cusl ()    on line 3

below is 3 local functions which also declared on line 3

 

enjoy

Moshe

 

 

 

 

; Custom line

(defun c:cusl (/ askdist askangle pause_for_input ; local functions
	         dist ang p1 ;| local variables |;)

 (defun askdist (def / ask)
  (initget (+ 2 4)) ; prevent respond with zero / negative values
  (if (not (setq ask (getdist (strcat "\nSpecify line length <" (rtos def 2) ">: "))))
   (setq ask def)
   (setq def ask)
  )
 ); askdist


 (defun askangle (def / ask)
  (if (not (setq ask (getangle (strcat "\nRotation angle <" (angtos def 0) ">: "))))
   (setq ask def)
   (setq def ask)
  )
 ); askangle


 (defun pause_for_input (/ pt)
  (setq pt "") ; reset pt to null string
  (while (eq (type pt) 'STR)
   ;  present user with current settings...
   (prompt (strcat "\nCurrent setting: Distance = " (rtos dist 2) ", Angle = " (angtos ang 0)))
   (initget "Distance Angle") ; allow keyword input (e.g Distance Angle)
   (setq pt (getpoint "\nSpecify start point or [Distance/Angle]: ")) ; pause for input

   (cond
    ((not pt)
     pt ; user press enter to exit command
    ); case
    ((eq (type pt) 'LIST)
     pt ; user pcked point
    ); case
    ((eq pt "Distance")
     (setvar "userr1" (setq dist (askdist dist)))
    ); case
    ((eq pt "Angle")
     (setvar "userr2" (setq ang (askangle ang)))
    ); case
   ); cond
  ); while
 ); pause_for_input


 ; here start c:cusl
 (setvar "cmdecho" 0)   	; disable command echo
 (command "._undo" "_begin")	; start undo group
  
 ; set line length default value
 (if (= (getvar "userr1") 0)
  (setq dist (setvar "userr1" 10.0))
  (setq dist (getvar "userr1"))
 )

 ; set line angle default value
 (if (= (getvar "userr2") 0)
  (setq ang (setvar "userr2" 0.0))
  (setq ang (getvar "userr2"))
 )

 ; loop as long points are coming in
 (while (setq p1 (pause_for_input))
  (command "._line" "_None" p1 "_None" (polar p1 ang dist) "")
 )

 (command "._undo" "_end")   ; end undo group
 (setvar "cmdecho" 1)	     ; restore command echo
 (princ)	
); c:cusl

 

0 Likes
Message 5 of 17

Kent1Cooper
Consultant
Consultant

I was going to suggest simply Offsetting the yellow outline and using it as a cutting boundary in TRIM, with Fence selection of all the white Polylines to cut off.  But I see the blue Lines in some cases are longer than the Polyline segment that defines their direction.  Is that really what you want?

Kent Cooper, AIA
0 Likes
Message 6 of 17

Kent1Cooper
Consultant
Consultant

If you are willing to be required to pick on a Polyline [or Line or whatever you want the new Line to get its direction from] near a particular end [in your case, near the end that touches the yellow outline], I can imagine a pretty easy way to do this.  Is that an acceptable limitation?

Kent Cooper, AIA
0 Likes
Message 7 of 17

komondormrex
Mentor
Mentor

hey,

check this one

 

(defun c:mark_neighbours (/ mark_length host_pline host_vertices neighbour_data segment_point segment_point_param- segment_point-
			    segment_point+ start_point angle_
			 )
  (if (null mark_length_saved) (setq mark_length_saved 33.862)) 
  (setq mark_length (getreal (strcat "\nEnter mark length <" (rtos mark_length_saved) ">: "))  
	host_pline (car (entsel "\nPick host pline: "))
	host_vertices (mapcar 'cdr (vl-remove-if-not '(lambda (group) (= 10 (car group))) (entget host_pline))) 
  )
  (if (null mark_length) (setq mark_length mark_length_saved) (setq mark_length_saved mark_length))  
  (while (setq neighbour_data (entsel "\nPick neighbour pline segment to draw mark: "))
    (setq segment_point (vlax-curve-getclosestpointto (car neighbour_data) (cadr neighbour_data))
	  segment_point_param- (fix (vlax-curve-getparamatpoint (car neighbour_data) segment_point))
	  segment_point- (mapcar '+ '(0 0) (vlax-curve-getpointatparam (car neighbour_data) segment_point_param-))  
	  segment_point+ (mapcar '+ '(0 0) (vlax-curve-getpointatparam (car neighbour_data) (1+ segment_point_param-)))
    )
    (if (or (vl-some '(lambda (vertex) (equal (setq start_point vertex) segment_point- 1e-3)) host_vertices)
	    (vl-some '(lambda (vertex) (equal (setq start_point vertex) segment_point+ 1e-3)) host_vertices)
	)
      	(progn
      		(setq angle_ (angle start_point segment_point))
		(vla-put-color (vla-addline (vla-get-block (vla-get-activelayout (vla-get-activedocument (vlax-get-acad-object))))
					    (vlax-3d-point start_point)
					    (vlax-3d-point (polar start_point angle_ mark_length))
			       )
			       5
		)
	)
    )
  )
  (princ)
)

 

0 Likes
Message 8 of 17

MEAN28
Participant
Participant

Thank you for your reply. This is my Lisp.

 

The problem is that if the reference line is longer than the distance input, the endpoint seems to always be at the midpoint of the reference line. However, there’s no issue with shorter reference lines.

0 Likes
Message 9 of 17

Kent1Cooper
Consultant
Consultant

@MEAN28 wrote:

.... if the reference line is longer than the distance input, the endpoint seems to always be at the midpoint of the reference line. However, there’s no issue with shorter reference lines.


Do you have running Object Snap modes on?

Whether that's the issue or not, there's a simpler way to get your pt-end location, and you don't even need to save it into a variable.  Try eliminating the calculation of that entirely, and drawing the Line this way:

(command "_.LINE" "_non" pt-start "_non" (polar pt-start ang dist) "")

Kent Cooper, AIA
0 Likes
Message 10 of 17

MEAN28
Participant
Participant

Thank you for your reply.

That was fast! I'm amazed 😮, and my brain is melting 😅.

What I meant by using the angle between two vertices is this: Before explaining that part, let me clarify the function of my Lisp. First, you run the command "adj," then input or select the distance. After that, you select the first point, then the second point. Now, these two points form an angle, right? That’s what I meant. So, we’re not actually going to input the angle manually. To be clear, the angle depends on the two points/vertices selected.

The issue with my Lisp is that if the reference line is longer than the distance input, the endpoint seems to always be at the midpoint of the reference line. However, there’s no issue with shorter reference lines.

 

Here's my lisp

 

0 Likes
Message 11 of 17

MEAN28
Participant
Participant

Thanks, @Kent1Cooper I'll try that.

0 Likes
Message 12 of 17

MEAN28
Participant
Participant

So that was my mistake 😑.

 

@Kent1Cooper, it works like a charm thank you so much!

 

I'll study more to become as knowledgeable as you 😊.

 

0 Likes
Message 13 of 17

MEAN28
Participant
Participant

Thank you @Kent1Cooper @komondormrex @Moshe-A @ВeekeeCZ  for your time😊.

0 Likes
Message 14 of 17

MEAN28
Participant
Participant

Yes, and now I'm intrigued to see what the outcome will be.

0 Likes
Message 15 of 17

Kent1Cooper
Consultant
Consultant
Accepted solution

@Kent1Cooper wrote:

If you are willing to be required to pick on a Polyline [or Line or whatever you want the new Line to get its direction from] near a particular end [in your case, near the end that touches the yellow outline], I can imagine a pretty easy way to do this.  Is that an acceptable limitation?


Assuming that's acceptable, and that you do want the blue Lines at the stated length even if the reference Polyline bends before it reaches that length, here's what I had in mind [lightly tested]:

 

(defun c:adj (/ esel pt-start pt-angle)
  (initget (if *adjdist* 6 7)); no zero, no negative, no Enter on first use
  (setq *adjdist* ; global variable for default
    (cond
      ( (getdist
          (strcat
            "\nUNSA KATAAS GAR?"
            (if *adjdist* (strcat " <" (rtos *adjdist*) ">") "")
              ; offer prior value as default if present [current mode/precision settings]
            ": "
          ); strcat
        ); getdist
      ); User-input condition
      (*adjdist*); default on Enter when allowed
    ); cond
  ); setq
  (while
    (setq esel (entsel "\nSelect reference near touching end or <exit>: "))
    (setq
      pt-start (osnap (cadr esel) "_end")
      pt-angle (osnap (cadr esel) "_mid")
    ); setq
    (command "LINE"
      "_non" pt-start
      "_non" (polar pt-start (angle pt-start pt-angle) *adjdist*)
      ""
    ); command
  ); while
  (prin1)
)
(prompt "\nType 'adj' to run the program.")

 

It remembers your length and offers it as default on subsequent use.  You pick on the reference Polyline in an appropriate place, once, rather than at two specific points.  [In your sample drawing, you will need to designate which of the two overlapping ones you want, but it won't matter which one you choose.]  You don't need to use ESCape to end it [though you can] -- Enter or space will do, and <exit>ing is the default that you get from either of those.

But you need to pick on a reference Polyline [or Line, or MLine segment, or anything straight] at a location where ENDpoint Object Snap will go to where it meets what you want the Lines drawn from [your yellow outline], and where MIDpoint Object Snap will go to the midpoint of that reference, not [for example] to somewhere on the yellow outline.

It could use (getpoint) instead of (entsel), so that you wouldn't need to designate which one of overlapping ones you want it to Osnap to, but it could have trouble if you miss by far enough -- as written, it ensures you got something before it proceeds.  And it could be made to verify that you picked on something straight, and control the Layer, and have the usual enhancements added [Osnap control instead of explicitly calling for "_non", *error* handling, Undo begin/end wrapping].  But first see whether it does what you want otherwise.

Kent Cooper, AIA
0 Likes
Message 16 of 17

MEAN28
Participant
Participant

😮😬

 

That was really my reaction. This is so much faster than my Lisp!😄.

0 Likes
Message 17 of 17

MEAN28
Participant
Participant

THANK YOU SO MUCH @Kent1Cooper again😂.

0 Likes