Polyline pick and user input

Polyline pick and user input

alique.langlois
Enthusiast Enthusiast
2,149 Views
18 Replies
Message 1 of 19

Polyline pick and user input

alique.langlois
Enthusiast
Enthusiast

I have a larger program that needs the user to pick path of a polyline between to block points and so far this is what I was able to hack together for what I wanted. The problem I am still having a hard time with the basics of the logic (I believe its the logic). Could someone point me in the right direction of where I might be going wrong? 

 

;---------------------------------------------------------------------------------
;                           Polyling place function                                 
;---------------------------------------------------------------------------------
; Polyline place  -  ALFEZ
; Create new layer if it dosen't exist.
; Polyline starts at blk1 point.
; Prompts user to pick points
; If point is not good user can undo (up to blk1 point) 
; when user hits enter polyline completes at blk2
;---------------------------------------------------------------------------------
(defun :pickpoly (blk1 blk2 / done out ens ben)
							; blk1 - block one data 
							; blk2 - block two data 
							;  - 
							;  - 
							;  - 

; make new layer if it doesnt exist
		(vl-cmdf "_.LAYER" "_Thaw" "HIDDEN" "_Make" "HIDDEN" "")
		(setvar 'attdia 0)
		(setvar 'attreq 0)
; start polyline with red colour 
		(setvar 'cecolor "1")
		(setvar 'cmdecho 0)
		(vl-cmdf "_PLINE" "_non" (if (= (car blk1) "COMBINER") (setq pnt (last blk1)) (setq pnt (caddr blk1))))
	(progn  ; pick route for polyline (user input to the destination block)
		(setq pnt (getpoint "\nNext point: " pnt))
		(command "_non" pnt)
    (while (progn
			(initget "Undo")
			(setq pnt
				(getpoint "\nNext point [Undo] <exit>: ")
		   );setq
	     );progn
      (cond ((= pnt "Undo")
				(command "erase" "last" ""))
			((command "_non" pnt))
	    );cond
      );while
			(T
			(command "_non" (caddr blk2) "")
			);T
	T) ; progn
	(setq pen (entlast))     ; get pline entity name
	(vl-cmdf "_.CHPROP" pen "" "_Color" 3 "")
	(setvar 'attdia 0)
	(setvar 'attreq 0)
out
); defun

Feel free to point me to other posts or resorcese that will help me.

0 Likes
Accepted solutions (3)
2,150 Views
18 Replies
Replies (18)
Message 2 of 19

SeeMSixty7
Advisor
Advisor

Looking at your code and the fact that you want the user to be able to draw a polyline. I would recommend putting  the user int he polyline command and checking the status of cmd active. The benefit is the user is then using a the normal pline command and can undo use osnaps, zoom, and everything. Once the complete the command, then your code picks back up and processes.

 

Something like this:

 

(command "pline")
(while (eq 1 (getvar "cmdactive"))
   (prompt "\nPick point: ")
   (command pause)
)

 

Good luck,

0 Likes
Message 3 of 19

alique.langlois
Enthusiast
Enthusiast

So in summery your proposing something along the lines of this?

 

;---------------------------------------------------------------------------------
;                           Polyling place function                                 
;---------------------------------------------------------------------------------
; Polyline place  -  ALFEZ
; Create new layer if it dosen't exist.
; Polyline starts at blk1 point.
; Prompts user to pick points
; If point is not good user can undo (up to blk1 point) 
; when user hits enter polyline completes at blk2
;---------------------------------------------------------------------------------
(defun :pickpoly (blk1 blk2 / done out ens ben)
							; blk1 - block one data 
							; blk2 - block two data 
							;  - 
							;  - 
							;  - 


		(vl-cmdf "_.LAYER" "_Thaw" "HIDDEN" "_Make" "HIDDEN" "")
		(setvar 'attdia 0)
		(setvar 'attreq 0)
; start polyline with red colour (hopefully, the user will have it start near or on the block perimeter) 
		(setvar 'cecolor "1")
		(setvar 'cmdecho 0)
		(command "pline" "_non" (if (= (car blk1) "COMBINER") (setq pnt (last blk1)) (setq pnt (caddr blk1))))
(while (eq 1 (getvar "cmdactive"))
(prompt "\nPick point: ")
(command pause)
) (T (command "_non" (caddr blk2) "") );T (setq pen (entlast)) ; get pline entity name (vl-cmdf "_.CHPROP" pen "" "_Color" 3 "") (setvar 'attdia 0) (setvar 'attreq 0) out ); defun

That is I understand correctly. Note I just trough this together so I doubt it works.

 

0 Likes
Message 4 of 19

SeeMSixty7
Advisor
Advisor
Accepted solution

Once the user ends the pline command, it is no longer active. You are trying to then end the pline at the endpoint of the second block. That will not work. You would want to do the following after the command is ended.

capture the last ent to a variable, capture the last point to a variable (getvar "LASTPOINT").

Then verify if the last point is the point at the 2nd block, if so do nothing and finish your function.

if it isn't then draw a pline from the last point variable you captured before and start from there, then the second point with be the point on the 2nd block. End your pline command at that point. run PEDIT and join the pervious captured entlast with the current entlast. Done.

(defun :pickpoly (blk1 blk2 / done out ens ben)
							; blk1 - block one data 
							; blk2 - block two data 
							;  - 
							;  - 
							;  - 


		(vl-cmdf "_.LAYER" "_Thaw" "HIDDEN" "_Make" "HIDDEN" "")
		(setvar 'attdia 0)
		(setvar 'attreq 0)
; start polyline with red colour (hopefully, the user will have it start near or on the block perimeter) 
		(setvar 'cecolor "1")
		(setvar 'cmdecho 0)
		(command "pline" "_non" (if (= (car blk1) "COMBINER") (setq pnt (last blk1)) (setq pnt (caddr blk1))))
		(while (eq 1 (getvar "cmdactive"))
           (prompt "\nPick point: ")
           (command pause)
        )
        (setq lastpt (getvar "lastpoint")
              lastent (entlast)
        )
        (if (/= lastpt (caddr blk2))
           (progn
               (command "pline" "_non" lastpt "_non" (caddr blk2));technically you could just hit enter for the start point if desired.
               (command "pedit" "l" "j" lastent "" "")
           )
        )
	(setq pen (entlast))     ; get pline entity name
	(vl-cmdf "_.CHPROP" pen "" "_Color" 3 "")
	(setvar 'attdia 0)
	(setvar 'attreq 0)
); defun

 

0 Likes
Message 5 of 19

alique.langlois
Enthusiast
Enthusiast

@SeeMSixty7  That is what I had read when I was trying to figure this out. Could one make my own variable to close the while loop?

0 Likes
Message 6 of 19

SeeMSixty7
Advisor
Advisor

You can, but then you are back to where you started and prompting the user for input to pass to the polyline command. Is there something else you are trying to accomplish, limit the user to a certain number of picks or???

0 Likes
Message 7 of 19

alique.langlois
Enthusiast
Enthusiast

@SeeMSixty7  I will try to give you a better idea of what I am trying to do. 

 

The larger program that will be using this sub. I going to use the polyline length property to return a length for a cable run between two points. The two-point is already defined but the route between is not defined and requires to user to put it in. The problem I had before is when osnap is active( and it will need to be in some cases) it will snap to endpoint or midpoint that is not intended. Hence the undo.  There is no limitation at this time. The future plan is to eventually program, into the subroutine the ability to select an already drawn polyline, to follow other cable runs back to the source with all change of directions being rounded and an offset done by a calculation that will be done with the length and user-inputted data set. Please, note that it is not for a long time but one is allowed to dream.  😉

 

I also have to do this over 1000 times a day so if I can reduce the number of keystrokes to the command call up and (enter / spacebar) the better.

 

This is also an ever-evolving project.

With that said. I am guessing going back to what I was doing before might be a better option? If so is there an example you could point me to. I am looking to learn and less so being given the answer.

0 Likes
Message 8 of 19

SeeMSixty7
Advisor
Advisor

Upload a sample drawing. I'll see if i can suggest some alternative thoughts or code enhancements.

0 Likes
Message 9 of 19

alique.langlois
Enthusiast
Enthusiast

Here is the sample drawing. The input list I was using for the routine was the (blockname entityname getpoint insertionpoint) 

0 Likes
Message 10 of 19

ВeekeeCZ
Consultant
Consultant

Isn't that exactly what my routine does? Just curious, what's wrong with that?

0 Likes
Message 11 of 19

alique.langlois
Enthusiast
Enthusiast

Hello @ВeekeeCZ.

The program I am talking about is the routine you had made for me. I am just expanding the features with subroutines. I am very grateful for your help on that and learned a ton from the code.

 

The only thing that it doesn't do is if the user inputs a wrong point there is no way to undoing it.  Sadly I have to stupid proof it a little some of the points that could go wrong. I am sharing this with other drafters I work with and they are not as flexible or open to new things. So I have to pad the walls as one could say. 

 

I am also doing this as more to push myself to learn. Hence why I am asking for the pointers and less just a final code. Note that would be a jerk thing to do since no one is getting paid for their work.

0 Likes
Message 12 of 19

ВeekeeCZ
Consultant
Consultant
Accepted solution

Well, add the UNDO is pretty easy.

Just locate the while loop and replace that with this

(while (progn
	 (initget "Undo")
	 (setq pnt (getpoint "\nNext point [Undo]: " (getvar 'lastpoint))))
  (if (= pnt "Undo")
    (command "_Undo")
    (command "_non" pnt)))

@SeeMSixty7  sorry for hijacking the thread... 

 

Message 13 of 19

SeeMSixty7
Advisor
Advisor

@ВeekeeCZ  No worries, LOL. It is all about learning. The more input the merrier in my opinion.

0 Likes
Message 14 of 19

alique.langlois
Enthusiast
Enthusiast

To be sure I am doing this right.

Switch out this:

(while (setq pnt (getpoint "\nNext point: " pnt))
	     (command "_non" pnt))
	   (command "_non" (last bl2) "")
	   T)

For this:

(while (progn
	 (initget "Undo")
	 (setq pnt (getpoint "\nNext point [Undo]: " (getvar 'lastpoint)))) ; could you explain what te getvar 'lastpoint is doing?
  (if (= pnt "Undo")
    (command "_Undo")
    (command "_non" pnt)))

 So far so good. But won't that remove the final point from being the destination of the polyline?

0 Likes
Message 15 of 19

alique.langlois
Enthusiast
Enthusiast

I agree! thank you for the education on the cmdactive variable. I hope to use it in the future.

0 Likes
Message 16 of 19

SeeMSixty7
Advisor
Advisor

You are welcome. You will discover there are a number of great people on here that will help you learn. @ВeekeeCZ has been doing that very thing for so many.

 

on your question about the (getvar "Lastpoint") in his code. It is creating a rubber band point to look consistent with the PLINE command. That way the user knows where they are picking a point from. So the user is not just picking points and possibly unsure of what point they have already picked.

 

Good luck!

0 Likes
Message 17 of 19

alique.langlois
Enthusiast
Enthusiast

Hello @ВeekeeCZ! So I am still debugging. I tried a few thing so to get the last point to be the second block. Is this even possible?

These are the two options and all seem to bug with a "Unknown command "NON". Press F1 for help."

I know it could be I am returning to many enters somehow.

option 1:

(setq ens (if (= (car blk1) "COMBINER") (setq pnt (last blk1)) (setq pnt (caddr blk1))))
		(vl-cmdf "_PLINE" "_non" ens)
	(progn  ; pick route for polyline (user input to the destination block)
			(while (progn
					(initget "Undo Exit")
					(setq pnt (getpoint "\nNext point [Undo/Exit] <Exit>: "  (getvar 'lastpoint)))
						(if (/= pnt (or "Exit" 0))
							(if (= pnt "Undo")
								(command "_Undo")
								(command "_non" pnt)
							) ;if
							(command "_non" (last blk2) ""))
					);progn
			) ;while
	T) ; progn

 

Option 2:

(setq ens (if (= (car blk1) "COMBINER") (setq pnt (last blk1)) (setq pnt (caddr blk1))))
		(vl-cmdf "_PLINE" "_non" ens)
	(progn  ; pick route for polyline (user input to the destination block)
			(while (progn
					(initget "Undo")
					(setq pnt (getpoint "\nNext point [Undo] <Exit>: "  (getvar 'lastpoint)))
							(if (= pnt "Undo")
								(command "_Undo")
								(command "_non" pnt)
							) ;if
					);progn
			) ;while
			(command "_non" (last blk2) "")
	T) ; progn

I had a third option using cond statements, I was not able to break out of the while loop.

 

I have attacked the full subroutine as well. 

;---------------------------------------------------------------------------------
;                           Polyling place function                                 
;---------------------------------------------------------------------------------
; Polyline place  -  ALFEZ
; Create new layer if it dosen't exist.
; Polyline starts at blk1 point.
; Prompts user to pick points
; If point is not good user can undo (up to blk1 point) 
; when user hits enter polyline completes at blk2
;---------------------------------------------------------------------------------
(defun :pickpoly (blk1 blk2 / *error* done out ens ben)
							; blk1 - block one data 
							; blk2 - block two data 
							;  - 
							;  - 
							;  - 

(setq *error* xx:Error)
		(vl-cmdf "_.LAYER" "_Thaw" "HIDDEN" "_Make" "HIDDEN" "")
		(setvar 'attdia 0)
		(setvar 'attreq 0)
; start polyline with red colour (hopefully, the user will have it start near or on the block perimeter) 
		(setvar 'cecolor "1")
		(setvar 'cmdecho 0)
		(setq ens (if (= (car blk1) "COMBINER") (setq pnt (last blk1)) (setq pnt (caddr blk1))))
		(vl-cmdf "_PLINE" "_non" ens)
	(progn  ; pick route for polyline (user input to the destination block)
			(while (progn
					(initget "Undo Exit")
					(setq pnt (getpoint "\nNext point [Undo/Exit] <Exit>: "  (getvar 'lastpoint)))
						(if (/= pnt (or "Exit" 0))
							(if (= pnt "Undo")
								(command "_Undo")
								(command "_non" pnt)
							) ;if
							(command "_non" (last blk2) ""))
					);progn
			) ;while
			;(command "_non" (last blk2) "")
	T) ; progn
	(setq pen (entlast))     ; get pline entity name
	(vl-cmdf "_.CHPROP" pen "" "_Color" 3 "")
	(setvar 'attdia 0)
	(setvar 'attreq 0)
out
); defun
;---------------------------------------------------------------------------------
0 Likes
Message 18 of 19

SeeMSixty7
Advisor
Advisor
Accepted solution

Your problem lies in where you are closing your progn statement.

;---------------------------------------------------------------------------------
;                           Polyling place function                                 
;---------------------------------------------------------------------------------
; Polyline place  -  ALFEZ
; Create new layer if it dosen't exist.
; Polyline starts at blk1 point.
; Prompts user to pick points
; If point is not good user can undo (up to blk1 point) 
; when user hits enter polyline completes at blk2
;---------------------------------------------------------------------------------
(defun :pickpoly (blk1 blk2 / *error* done out ens ben)
							; blk1 - block one data 
							; blk2 - block two data 
							;  - 
							;  - 
							;  - 

(setq *error* xx:Error)
		(vl-cmdf "_.LAYER" "_Thaw" "HIDDEN" "_Make" "HIDDEN" "")
		(setvar 'attdia 0)
		(setvar 'attreq 0)
; start polyline with red colour (hopefully, the user will have it start near or on the block perimeter) 
		(setvar 'cecolor "1")
		(setvar 'cmdecho 0)
		(setq ens (if (= (car blk1) "COMBINER") (setq pnt (last blk1)) (setq pnt (caddr blk1))))
		(vl-cmdf "_PLINE" "_non" ens)
;;;Updated code
		(progn
			(while
				(progn ; your while condition is what keeps you in the while loop
					(initget "Undo")
					(setq pnt (getpoint "\nNext point [Undo]: "  (getvar 'lastpoint)))
					;Deleted Exit option as when they simply hit enter the command moves on and exits the while statement
				) ;This progn statement ends with a value as long as user picks a point or provides input, once user hist enter it returns nil and exits loop
				(if (= pnt "Undo")
					(command "_Undo")
					(command "_non" pnt)
				) ;if
			);while
			(command "_non" (last blk2) "")
		)
;;;Updated Code End
		
	(setq pen (entlast))     ; get pline entity name
	(vl-cmdf "_.CHPROP" pen "" "_Color" 3 "")
	(setvar 'attdia 0)
	(setvar 'attreq 0)
out
); defun
;---------------------------------------------------------------------------------
0 Likes
Message 19 of 19

alique.langlois
Enthusiast
Enthusiast

Clearly this is an Art and not just a skill! Thank you both @SeeMSixty7  and @ВeekeeCZ  for your continuing help.  Now on to the next command. Time to learn more about SSET.

Cheers guys!