LISP Debug, Repetitive copy & rotate

LISP Debug, Repetitive copy & rotate

michael_delouker
Contributor Contributor
806 Views
11 Replies
Message 1 of 12

LISP Debug, Repetitive copy & rotate

michael_delouker
Contributor
Contributor

Hey guys, looking for some assistance on this lisp I have. The idea is to select an object, copy the selection from a base point to be placed. When placed, rotation will be enabled by mouse. This should ideally be repetitive, with only the initial setup, to be broken by escape key. 

I have attached the file for reference. 

 

Any help would be greatly appreciated! Fairly new to the LISP customization.

 

If possible, the visual implementation from the generic move command (moving selection with cursor) would be ideal to have.

0 Likes
807 Views
11 Replies
Replies (11)
Message 2 of 12

Moshe-A
Mentor
Mentor

@michael_delouker hi,

 

before we move to fixing this lisp can you tell us if MOCORO command from express tools does what you want?

 

Moshe

 

0 Likes
Message 3 of 12

michael_delouker
Contributor
Contributor

@Moshe-A hello!

Not precisely, I find MOCORO to be a slight bit different from what I want.

Although I do enjoy the base point, and ability to repeatedly paste, I would like to paste then adjust rotation using mouse before moving to next instance, with this process being repeated.

0 Likes
Message 4 of 12

Kent1Cooper
Consultant
Consultant

You don't get to specify a prompt in (ssget) -- it always supplies its own, which is "Select objects: " always in the plural.  If you want to specify the prompt, even if only the same but in the singular, and if you always want to select only one object, use (entsel) instead, and apply (car) to the result to get the entity name of what you selected.  Also, with (entsel) after you pick it, you're done, and don't need to tell it you're done as with (ssget).

 

Which raises the question:  Do you, in fact, always want only one object?  Such a thing could be done with multiple objects [and MOCORO can, too], though there's a little trick to it [Copy the selection in place and then Move the Previous selection, rather than Copying the selection directly to a new location, so that each time, the Previous selection is available without User input].

 

Either way, what you have going is not far off, but needs to account for completing the Rotate command, and it should include re-setting the 'basePoint' variable to use the 'targetPoint' variable value from the previous copy each time.  It can be refined easily, if MOCORO doesn't suit your purpose well enough.

Kent Cooper, AIA
0 Likes
Message 5 of 12

Kent1Cooper
Consultant
Consultant

The commands will supply some of basically the same prompts for you, so you don't need to spell them out, and in fact don't need to put the target point into a variable at all.  If you let that happen within the Copy command under its own prompt, instead of asking for it ahead of time, then you get to see what you're Copying drag with the cursor.  Something like this [the only-one-object approach, and very lightly tested]?

(defun c:CRM (/ selObj basePoint); = Copy & Rotate Multiple
  (if (setq selObj (car (entsel "\nSelect object: ")))
    (progn
      (setq basePoint (getpoint "\nBase point: "))
      (while T  ;; Infinite loop, will break on Esc
        (command "copy" selObj "" basePoint pause)
        ;; Get the last created object
        (setq selObj (entlast)); replace original selection
        (setq basePoint (getvar 'lastpoint)); replace earlier one
        ;; Rotate the object interactively
        (command-s "_.rotate" selObj "" basePoint "_reference")
      )
    )
  )
)

It could be made to do things like verify that you actually selected something before proceeding, and could have all the usual enhancements added.

Kent Cooper, AIA
0 Likes
Message 6 of 12

Moshe-A
Mentor
Mentor

@michael_delouker  hi,

 

Check this...to finish the command just press enter at Select object(s) (not ESC)

also note the command is wrapped for one Undo (like any other standard command)

 

if you want to pick the base point for the rotate, replace "@" with pause

(command-s "._rotate" "_si" ss1 "@" pause pause)

 

enjoy

Moshe

 

 

 

 

 

 

(defun c:CopyRotate (/ undoEchoCtrl ; local function
		       ss0 ss1 lastEnt)

 (defun undoEchoCtrl (step)
  (setvar "cmdecho" 0)

  (if (eq step 'BEGIN)
   (command "._undo" "_begin")
   (command "._undo" "_end")
  )

  (setvar "cmdecho" 1)
 )

 ; here start command
 (undoEchoCtrl 'BEGIN)
  
 (while (setq ss0 (ssget))
  (setq lastEnt (entlast))
  
  (command-s "._copy" "_si" ss0 pause pause)
   
  (setq ss1 (ssadd))
  (while (setq lastEnt (entnext lastEnt))
   (ssadd lastEnt ss1)
  )
   
  (command-s "._rotate" "_si" ss1 "@" pause pause)
 ); while

 (undoEchoCtrl 'END)
 (princ)
); c:CopyRotate

 

 

 

 

 

0 Likes
Message 7 of 12

michael_delouker
Contributor
Contributor

This is great! I really appreciate the explanation as well. Especially the copy command under its own prompt. I had never known!

 

The function is amazing as well! I really enjoy how it references the previously placed instance.

 

Would you have recommendations around assuming the specified reference angle as well as the second point prompts so the function could strictly rely on the mouse position? Im assuming we can set the initial as the previous references characteristics?

 

 

0 Likes
Message 8 of 12

Kent1Cooper
Consultant
Consultant

@michael_delouker wrote:

....

Would you have recommendations around assuming the specified reference angle as well as the second point prompts so the function could strictly rely on the mouse position? Im assuming we can set the initial as the previous references characteristics?


If you want to assume a zero reference angle each time, if that would serve for "so the function could strictly rely on the mouse position," you can just remove the "_referene" option entry from the end of the (command-s) function.  Since the routine just leaves you in the command, you would still be able to call for that option yourself when needed.

 

If you want the previous ending rotation to be used as the base reference direction each time, something would need to be saved, but it's hard to know what.  If the object is a Block or (M)Text, its rotation can be pulled.  But if it's just about anything else, I'm not sure how to record the rotation.  The location picked to set it for the latest round does not become "@" or (getvar 'lastpoint), but rather the rotation base point does, so there's no basis for reading the chosen rotation from command inputs.  If the object is a Line, its direction could be pulled, but that would not always be the rotation picked for the latest round, and even when it is, it might read the opposite direction from what you want.

 

It should be possible by asking for points for the rotation, saving them to variables, but it may not be possible for you to see the rotation drag in the process.  Would that be acceptable?

Kent Cooper, AIA
0 Likes
Message 9 of 12

komondormrex
Mentor
Mentor

hey there,

check this other one 

;*********************************************************************************************************************************************************

;	'move_copy_rotate' custom command
;	koondormrex, jul 2024

;*********************************************************************************************************************************************************

(defun c:move_copy_rotate (/ command_ended moving_started selection_sets move_rotate_sset_object error_occurred grread_data
		      	        	 1st_point initial_copy arbituary_angle
		      	     	  )
	(vla-startundomark (vla-get-activedocument (vlax-get-acad-object)))
	(if (null arbituary_angle_saved) (setq arbituary_angle_saved 0))
	(if (null (vl-catch-all-error-p
				(setq move_rotate_sset_object (vl-catch-all-apply 'vla-item (list (vla-get-selectionsets (vla-get-activeDocument (vlax-get-acad-object)))
																   				  "move_rotate_sset"
																			)
											  )
				)
			  )
		)
	  	(vla-delete move_rotate_sset_object)
	)
	(setq move_rotate_sset_object (vla-add (vla-get-selectionsets (vla-get-activedocument (vlax-get-acad-object))) "move_rotate_sset"))
	(vla-selectonscreen move_rotate_sset_object)
  	(grtext -1 (if copy_mode "Copy Mode" "Move Mode"))
	(while (not command_ended)
			(if moving_started
			  	(progn
					(if (and
					      	(null initial_copy)
							copy_mode
					    )
						(progn
						  	(vlax-map-collection move_rotate_sset_object
							  	'(lambda (object)
							     		(vla-copy object)
							     	)
							)
						  	(setq initial_copy t)
					  	)
				  	)
					(princ "\r<+> Mode, <Tab> 90° CCW, <Space> arbituary, Left Click, Right Click to set to point")
			  	)
			  	(if copy_mode
				  	(princ "\r<+> Mode, Left Click, Right Click to set copy from point")
	  				(princ "\r<+> Mode, Left Click, Right Click to set move from point")
			  	)
		  	)
			(setq error_occurred (if (vl-catch-all-error-p (setq grread_data (vl-catch-all-apply 'grread (list t 12 0)))) t nil))
		    		(cond
						(
							error_occurred
								(princ "\nCommand cancelled")	                      			;	command cancellation
								(vlax-map-collection move_rotate_sset_object
									'(lambda (object)
									    (vla-erase object)
									 )
								)
								(setq command_ended t)
						)
						(
							(= 3 (car grread_data))                                        		;	left click
								(if (not moving_started)
									(setq moving_started t
									      1st_point (cadr grread_data)
									)
								  	(if copy_mode
									  	(vlax-map-collection move_rotate_sset_object
										  	'(lambda (object)
										     		(vla-copy object)
										     	)
										)
										(setq command_ended t)
								  	)
								)
						)
						(
							(and
							 	(= 5 (car grread_data))		                                	;	cursor moving
								moving_started
							)
							(vlax-map-collection move_rotate_sset_object
							  '(lambda (object)
								    (vla-move object (vlax-3d-point 1st_point) (vlax-3d-point (cadr grread_data)))
							   )
							)
							(setq 1st_point (cadr grread_data))
						)
				  		(
							(or
								(= 25 (car grread_data))		                                ;	right click
								(= 11 (car grread_data))										;	beekeeper's note on 'shortcutmenu
							)
							 	(if moving_started
									(progn
									  	(setq 1st_point_before 1st_point
											  1st_point (getpoint 1st_point_before (if copy_mode "\rPick copy to point: " "\rPick move to point: "))
										)
									  	(vlax-map-collection move_rotate_sset_object
										  	'(lambda (object)
											    	(vla-move object (vlax-3d-point 1st_point_before) (vlax-3d-point 1st_point))
											 )
										)
									  	(if copy_mode
										  	(vlax-map-collection move_rotate_sset_object
									  			'(lambda (object)
									     				(vla-copy object)
									     			 )
											)
									  	)
										(if (not copy_mode) (setq command_ended t))
								 	)
									(setq 1st_point (getpoint (if copy_mode "\rPick copy from point: " "\rPick move from point: "))
									      moving_started t
									)
								  )
						)
						(
							(and
							     (equal '(2 32) grread_data)		                       			;	tab
							     moving_started
						        )
								(vlax-map-collection move_rotate_sset_object
								  	'(lambda (object)
								     		(vla-rotate object (vlax-3d-point 1st_point) (* +0.5 pi))
								     	)
								)
						)
				  		(
							(and
						 		(equal '(2 9) grread_data)		                        		;	space
								moving_started
							)
								(if (null (setq arbituary_angle (getangle 1st_point (strcat "\nSecond rotation point <" (angtos arbituary_angle_saved 0 2) ">: "))))
									(setq arbituary_angle arbituary_angle_saved)
									(setq arbituary_angle_saved arbituary_angle)
								)
								(vlax-map-collection move_rotate_sset_object
								  	'(lambda (object)
								     		(vla-rotate object (vlax-3d-point 1st_point) arbituary_angle)
								     )
								)
						)
						(
							(equal '(2 43) grread_data)		                       				;	either +
						 		(setq copy_mode (not copy_mode))
						 		(grtext -1 (if copy_mode "Copy Mode" "Move Mode"))
						)
						(
							t
						)
				)
	)
  	(grtext -1 "")
	(vla-endundomark (vla-get-activedocument (vlax-get-acad-object)))
	(princ)
  )

;*********************************************************************************************************************************************************
0 Likes
Message 10 of 12

michael_delouker
Contributor
Contributor

I believe the variety of the load with this function will just be with block objects, so if we could proceed with that that would be perfect!

0 Likes
Message 11 of 12

Kent1Cooper
Consultant
Consultant

@michael_delouker wrote:

I believe the variety of the load with this function will just be with block objects....


If you want such a thing for use with only a Block, should it automatically use the insertion point of the Block as the base point for the Copying as well as the Rotating, or would you still want to specify the base point because it might not always be the Block's insertion point?

Kent Cooper, AIA
0 Likes
Message 12 of 12

michael_delouker
Contributor
Contributor

Still specify the base point ideally during the initialization phase I believe is the ideal currently!

0 Likes