Animation or realtime pre-draw the result

Animation or realtime pre-draw the result

eakos1
Advocate Advocate
1,601 Views
17 Replies
Message 1 of 18

Animation or realtime pre-draw the result

eakos1
Advocate
Advocate

I've made an program which makes an "turn back" on two parallel lines. 

Is it possible somehow to make the program so like eg.: stretch command works, if the user moves the mouse, realtime shows how the result will looks like. 

It would be really good if before clicking for the final position we could see how the result will be. 

 

 

 

By the way, why get I after running the program this message?

eakos1_0-1702072104516.png

 

 

(defun C:turnback_simple (/ ortho	; save the original value
		    snapping		; save the original value
		    r			; radius
		    a			; first line
		    b			; second line
		    pl1			; first point
		    pl2			; second point
		    ps1			; firts point
		    ps2			; second point
		    p_inters		; theoretical intersection point of the selected lines
		    pl1_midle		; point for direction of theoretical middle line
		    pl2_midle		; point for direction of theoretical middle line
		    p_end_ARC		; selected point where the ARC should ended
		    ang1		; angle
		    ang2		; angle
		    ang_inside		; inside angle between the lines
		    center		; center point of ARC
		    object_ARC		; object name of the ARC
		    en1			; first entity LINE+point
		    en2			; second entity LINE+point
		    distance_parallel	; distance between the parallel lines
		    p			; help for exchanging the cordinates
)
  (vl-load-com)
  (setq	ortho	(getvar 'orthomode)
	snapang	(getvar 'snapang)
  )

  (setq r 3)
  (command "fillet" "r" r "")

  (setq a (entsel "\n Select the first line"))
  (setq b (entsel "\n Select the second line"))

  (setq pl1 (vlax-curve-getStartPoint (car a)))
  (setq ps1 (vlax-curve-getStartPoint (car b)))
  (setq pl2 (vlax-curve-getEndPoint (car a)))
  (setq ps2 (vlax-curve-getEndPoint (car b)))

  ;; ---- check whether there is an intersection - the lines are parallel ???
  ;;      if nil then the LINES are parallel
  (setq p_inters (inters pl1 pl2 ps1 ps2 nil))


  ;; ---- check whether the lines end - start points are on the same end,
  ;;      if not correct it
  (if (or (> (distance pl1 ps1) (distance pl1 ps2))
	  (> (distance pl2 ps2) (distance pl2 ps1))
      )
    (progn
      (setq
	p   ps2
	ps2 ps1
	ps1 p
      )
    )					; progn
  )					; if

  ;; ---- check whether the lines end - start points are close to the selected points,
  ;;      if not correct it

  (if (> (distance (cadr a) pl1) (distance (cadr a) pl2))
    (progn
      (setq
	p   pl2
	pl2 pl1
	pl1 p
      )
      (setq
	p   ps2
	ps2 ps1
	ps1 p
      )
    )					; progn
  )					; if

  
; Create the turn back curve if the lines are parallel  
  (if (not p_inters)

    (progn

      (setq ang1 (angle pl1 pl2))
      (setq a (list (car a) pl2))
      (setq ang2 (angle ps1 ps2))
      (setq b (list (car b) ps2))

      (setq distance_parallel
	     (distance
	       (inters pl1
		       pl2
		       ps1
		       (polar ps1 (+ ang2 (/ pi 2)) 10)
		       nil
	       )
	       ps1
	     )
      )

      ;; --- calculate the middle points	
      (setq pl1_midle
		      (polar ps2 (- ang2 (/ pi 2)) (/ distance_parallel 2))
	    pl2_midle
		      (polar ps1 (- ang2 (/ pi 2)) (/ distance_parallel 2))
      )


      ;; --- check whether the pl1_midle is betwwen the lines or is outside
      (if (> (distance pl1_midle (inters pl1 pl2 ps2 pl1_midle nil))
	     distance_parallel
	  )
	(progn
	  (setq	pl1_midle
			  (polar ps2 (+ ang2 (/ pi 2)) (/ distance_parallel 2))
		pl2_midle
			  (polar ps1 (+ ang2 (/ pi 2)) (/ distance_parallel 2))
	  )

	)				; progn
      )					; if

      (setvar 'orthomode 1)
      (setvar
	'snapang
	(angle pl1_midle pl2_midle)
      )
      (setq p_end_ARC
	     (getpoint pl1_midle "\nSpecify the end of the ARC: ")
      )
      (setvar 'orthomode ortho)
      (setvar 'snapang snapang)

      (setq center
	     (polar
	       p_end_ARC
	       (angle pl2_midle pl1_midle)
	       r
	     )
      )



      (entmake (list (cons 0 "Arc")
		     (cons 10 center)
		     (cons 40 r)
		     (cons 51 (- ang2 (/ pi 2)))
		     (cons 50 (+ ang1 (/ pi 2)))
	       )
      )					;entmake
      (setq object_ARC (entlast))

      (if (< (distance pl1 (polar center (- ang1 (/ pi 2)) r))
	     (distance pl1 (polar center (+ ang1 (/ pi 2)) r))
	  )
	(setq
	  en2 (list
		object_ARC
		(polar center (- ang1 (/ pi 2)) r)
	      )
	)
	(setq
	  en2 (list
		object_ARC
		(polar center (+ ang1 (/ pi 2)) r)
	      )
	)
      )					; if

      (command "fillet" en2 a "")

      (if (< (distance ps1 (polar center (+ ang2 (/ pi 2)) r))
	     (distance ps1 (polar center (- ang2 (/ pi 2)) r))
	  )
	(setq
	  en2 (list
		object_ARC
		(polar center (+ ang2 (/ pi 2)) r)
	      )
	)
	(setq
	  en2 (list
		object_ARC
		(polar center (- ang2 (/ pi 2)) r)
	      )
	)
      )					;if

      (command "fillet" en2 b "")

    );progn

  )					;if

  (princ)
)					;defun

 

 

 

 

 

 

 

0 Likes
1,602 Views
17 Replies
Replies (17)
Message 2 of 18

eakos1
Advocate
Advocate

 

Just for better understanding, this are the "turn back" curves. 

We have a lot of lines which are connected with fillet but sometimes we need make these turning back points. 

 

eakos1_0-1702073196805.png

 

 

0 Likes
Message 3 of 18

leeminardi
Mentor
Mentor

The following is a bit primitive and does not do exactly what you want but may be of some benefit.

It sets the ucs in line with the line leading into the turnback and then turns on ortho mode.  At that point you can use stretch to adjust an existing turnback as needed dynamically.  The code does not set the ucs back to what it was nor turnoff ortho.  

(defun c:test (/ l en)
  (setq	l  (entsel "\nSelect line leading to turn back.")
	en (car l)
  )
  (command "_ucs" "ob" en)
  (setvar "orthomode" 1)
  (command "_stretch")
  (princ)
)

 

 

lee.minardi
0 Likes
Message 4 of 18

Sea-Haven
Mentor
Mentor

2 suggestions a complex one is can do GRDRAW and drag the end so dwg updates, it is complex, doable at a price.

 

The other is to just pick the 4 points on the straights then choose a result like, equal see left in image , +/- 45 etc see right in image, so bulge is drawn to suit.

0 Likes
Message 5 of 18

Kent1Cooper
Consultant
Consultant

I see the radius of 3 is built in.  If that's always the same, is there also the sameness of the lines always being the same distance apart?  If so, a BLOCK would be comparatively easy to work with, and could be dragged visibly into position.

EDIT:  Having actually opened the drawing, I see that the distance between Lines is not the same in the separated sample from the larger field of Lines.  If there are only a few limited Line spacings, Blocks could still be a good approach.  If the spacing could be anything, a routine could build one for the particular spacing, and use that.

Kent Cooper, AIA
0 Likes
Message 6 of 18

Kent1Cooper
Consultant
Consultant

@eakos1 wrote:

.... why get I after running the program this message?

That is because in an AutoLisp (command) function, giving FILLET the two selections completes the command.  Remove the extraneous Enter "" from the ends of those FILLET commands.

Kent Cooper, AIA
Message 7 of 18

eakos1
Advocate
Advocate

The distance is not always the same, it is from 2 up to 8. 

And so also the radius should be variable - later I will add to the program. 

 

In my mind is the MOVE command. If I draw at first the ARC only, it can be moved in the right position and later let do the FILLET with the program. If it works with ortho mode, that only could be selected the point in a given line angel it could be a good solution. Is it works this way ?

0 Likes
Message 8 of 18

eakos1
Advocate
Advocate

I've jut made a test program.  But if I let run it, it not setup the orthomode and can I move the mouse everywhere. 

But if I let run the program until the (command "_.move" obj "" center) line, than the setup of orthomode is correct and works fine. 

 

What can be the problem?

 

(defun c:test_move (/ r e e_angle p_start center pl1 pl2 obj)
  (vl-load-com)
  (setq	ortho	(getvar 'orthomode)
	snapang	(getvar 'snapang)
  )

  (setq r 3)
  (setq e (car (entsel)))
  (setq
    e_angle (angle
	      (vlax-curve-getStartPoint (vlax-ename->vla-object e))
	      (vlax-curve-getEndPoint (vlax-ename->vla-object e))
	    )
  )
  (setq p_start (vlax-curve-getStartPoint (vlax-ename->vla-object e)))
  (setq center (vlax-curve-getStartPoint (vlax-ename->vla-object e)))
  (setq pl1 (polar p_start (+ e_angle (/ pi 2)) 3))
  (setq pl2 (polar p_start (- e_angle (/ pi 2)) 3))
  (entmake (list (cons 0 "Arc")
		 (cons 10 center)
		 (cons 40 r)
		 (cons 51 (- e_angle (/ pi 2)))
		 (cons 50 (+ e_angle (/ pi 2)))
	   )
  )
  (setq obj (entlast))
  (entmake (list (cons 0 "point") (cons 10 pl1) (cons 62 1)))
  (entmake (list (cons 0 "point") (cons 10 pl2) (cons 62 2)))

  (setvar 'orthomode 1)
  (setvar
    'snapang
    e_angle
  )
  (command "_.move" obj "" center)

  (setvar 'orthomode ortho)
  (setvar 'snapang snapang)


)					;defun

 

0 Likes
Message 9 of 18

Kent1Cooper
Consultant
Consultant

@eakos1 wrote:

... But if I let run it, it not setup the orthomode and can I move the mouse everywhere. 

....

What can be the problem?

....
  (command "_.move" obj "" center)

  (setvar 'orthomode ortho)
....

That (command) function is leaving you in the MOVE command awaiting the destination point, and then ORTHOMODE gets reset before you supply that.  You need to allow for the destination point:

 

(command "_.move" obj "" center pause)

 

Or, you can use the function that waits for completion of the command before going on:

 

(command-s "_.move" obj "" center)

 

By the way, some suggestions:  You can (setq) as many variables as you want within one (setq) function, as you do a little bit, but take it further.  And the (vlax-curve-...) functions do not require conversion of an entity to a VLA object -- they can take an entity name.  And you set two variables to the same thing spelled out at length in the same way for both, but you can do that for the first one and then just set the second one to the first one, or better yet, don't bother with the second one.  So you could do this:

 

  (setq
    ortho (getvar 'orthomode)
    snapang (getvar 'snapang)
    r 3
    e (car (entsel))
    e_angle (angle (vlax-curve-getStartPoint e) (vlax-curve-getEndPoint e))
    center (vlax-curve-getStartPoint e)
    pl1 (polar p_start (+ e_angle (/ pi 2)) 3)
    pl2 (polar p_start (- e_angle (/ pi 2)) 3)
  ); setq

 

Kent Cooper, AIA
Message 10 of 18

eakos1
Advocate
Advocate

Thank you very much. I've learned something new today. 🙂

Defining with setq all variable together is any advance except it looks more nice?

 

Why I do it separate is, if I stack with something, I want to try something new and I want to see the result, with separate lines I can let run every single line what I want. 

 

0 Likes
Message 11 of 18

ВeekeeCZ
Consultant
Consultant

What if you could just STRETCH it.

 

(defun c:Turnback ( / s p a a1 a2 b b1 b2 r c c0 c1 c2 ac bc)
  
  (if (and (setq s (ssget "_:L" '((0 . "LINE"))))
	   
	   (or (= 2 (sslength s))
	       (prompt "\nError: Crossing/window selection of 2 lines is required."))
	   
	   (setq p (mapcar '/ (apply 'mapcar (cons '+ (mapcar 'cadr (cdr (last (ssnamex s)))))) '(4 4 4))) ; sorry about this, center of window selection.
	   
	   (setq a (ssname s 0))
	   (setq a1 (cdr (assoc 10 (entget a))))
	   (setq a2 (cdr (assoc 11 (entget a))))
	   (if (< (distance p a1) (distance p a2)) t (mapcar 'set '(a2 a1) (list a1 a2)))
	   
	   (setq b (ssname s 1))
	   (setq b1 (cdr (assoc 10 (entget b))))
	   (setq b2 (cdr (assoc 11 (entget b))))
	   (if (< (distance p b1) (distance p b2)) t (mapcar 'set '(b2 b1) (list b1 b2)))
	   
	   (or (equal (angle a1 a2) (angle b1 b2) 1e-9)
	       (prompt "\nError: Selected lines are not parallel."))
	   
	   (setq r (1+ (fix (* 0.66 (distance a1 b1)))))
	   ;(setq r (cond ((getdist (strcat "\nSpecify radius <" (rtos r) ">: "))) (r)))
	   
	   (setq c0 (polar (mapcar '/ (mapcar '+ a1 b1) '(2 2)) (angle a2 a1) r))
	   (setq c (entmakex (list '(0 . "arc") (cons 10 c0) (cons 40 r) (cons 51 (- (angle b1 b2) (/ pi 2))) (cons 50 (+ (angle a1 a2) (/ pi 2))))))
	   (setq c1 (vlax-curve-getstartpoint c))
	   (setq c2 (vlax-curve-getendpoint c))
	   (if (< (distance c1 a1) (distance c1 b1)) t (mapcar 'set '(c2 c1) (list c1 c2)))
	   
	   (setvar 'filletrad r)
	   (vl-cmdf "_.fillet" (list c c1) (list a a1))
	   (setq ac (entlast))
	   (vl-cmdf "_.fillet" (list c c2) (list b b1))
	   (setq bc (entlast))
	   )
    
    (command-s "_.stretch"
      	       s
      	       (list c (vlax-curve-getstartpoint c))
      	       (list ac (vlax-curve-getstartpoint ac))
      	       (list bc (vlax-curve-getstartpoint bc))
               ""))
  
  (princ)
  )

 

0 Likes
Message 12 of 18

eakos1
Advocate
Advocate

Thank you the idea with stretch and for the program. 

But the program works not by me - see the video. (I've just added lines draw the points p a1 a2 b1 b2 to see what does the program)

1. On one end it not perform the fillet. I followed the program and by this line do nothing. 

eakos1_0-1702219309108.png

2.  These distances c1 a1 and c1 b1 is not enough to check. These can be equal or both can be the bigger. 

 

eakos1_1-1702219393567.png

 

0 Likes
Message 13 of 18

ВeekeeCZ
Consultant
Consultant

Understood. I made it just for an ideal scenario ... 

Use a cross-selection as you would if you use the STRETCH command.

 

eekeeCZ_1-1702222336164.png

 

It's just a concept preview. Only you know all the conditions needed to cover.

0 Likes
Message 14 of 18

komondormrex
Mentor
Mentor

check this out. not a shortie one but gives you a real time pre-draw with moving.

(defun c:u_turn (/ point_selected pline radius line_1 line_2 line_12_end_mid_level_point most_far_turn_border_point
		   to_far_direction half_distance line_temp center_point_1 circle_aux line_1_aux center_point_2
		   pline_point_1 pline_point_2 pline_point_3 pline_point_4 alpha_1 alpha_2
		   bulge_1 bulge_2 bulge_3 bulge_4 grread_data 
		)
  (setq radius 3.0
    	line_1 (car (entsel "\nLine_1: "))
	line_2 (car (entsel "\nLine_2: "))
	line_12_end_mid_level_point (mapcar '* '(0.5 0.5)
					 (mapcar '+ (vlax-get (vlax-ename->vla-object line_1) 'endpoint)
						    (vlax-get (vlax-ename->vla-object line_2) 'endpoint)
					 )
				    )
  	most_far_turn_border_point (getpoint "\nMost far turn border: ")
	most_far_turn_border_point (inters line_12_end_mid_level_point
					   (polar line_12_end_mid_level_point (vla-get-angle (vlax-ename->vla-object line_1)) 1)  
					   most_far_turn_border_point
					   (polar most_far_turn_border_point (+ (* 0.5 pi) (vla-get-angle (vlax-ename->vla-object line_1))) 1)
					   nil
			     	   )
	to_far_direction (if (> (distance most_far_turn_border_point (vlax-get (vlax-ename->vla-object line_1) 'startpoint))
			        (distance most_far_turn_border_point (vlax-get (vlax-ename->vla-object line_1) 'endpoint))
			     )
			       (vla-get-angle (vlax-ename->vla-object line_1))
			       (+ pi (vla-get-angle (vlax-ename->vla-object line_1)))
		    	 )
	half_distance (distance line_12_end_mid_level_point
				(inters (vlax-get (vlax-ename->vla-object line_1) 'startpoint)
					(vlax-get (vlax-ename->vla-object line_1) 'endpoint)
					line_12_end_mid_level_point
					(polar line_12_end_mid_level_point (+ (* 0.5 pi) to_far_direction) 1)
					nil
				)
		      )
  )
	(if (equal (angle line_12_end_mid_level_point
		    (inters (vlax-get (vlax-ename->vla-object line_2) 'startpoint)
			    (vlax-get (vlax-ename->vla-object line_2) 'endpoint)
			    line_12_end_mid_level_point
			    (polar line_12_end_mid_level_point (- to_far_direction (* 0.5 pi)) 1)
			    nil
		    )
	     )
	     (- to_far_direction (* 0.5 pi))
	)
		(setq line_temp line_1
		      line_1 line_2
		      line_2 line_temp
		)
	)
	(setq center_point_1 (polar most_far_turn_border_point (+ pi to_far_direction) radius)
	  	circle_aux (vla-addcircle (vla-get-block (vla-get-activelayout (vla-get-activedocument (vlax-get-acad-object))))
		     		          (vlax-3d-point center_point_1)
	    		    		  (+ radius radius)
			   )
		line_1_aux (vla-addline (vla-get-block (vla-get-activelayout (vla-get-activedocument (vlax-get-acad-object))))
			   		(vlax-3d-point (setq line_1_aux_point (polar center_point_1 (+ (* 0.5 pi) to_far_direction) (+ half_distance radius))))
			   		(vlax-3d-point (polar line_1_aux_point (+ pi to_far_direction) (* 2 (vla-get-length (vlax-ename->vla-object line_1)))))
		           )
	  	center_point_2 (vlax-invoke circle_aux 'intersectwith line_1_aux acextendnone)
	  	pline_point_1 (polar center_point_2 (- to_far_direction (* 0.5 pi)) radius)
		pline_point_2 (polar center_point_1 (angle center_point_1 center_point_2) radius)
		alpha_1 (atan (/ (sqrt (- (expt (distance center_point_1 center_point_2) 2) (expt (+ radius half_distance) 2))) (+ radius half_distance)))
		alpha_2 (* 2 (+ (* 0.5 pi) alpha_1))
		pline_point_3 (polar center_point_1 (- to_far_direction (* 0.5 alpha_2)) radius)
		pline_point_4 (polar center_point_2 (- to_far_direction (* 0.5 pi)) (+ radius (* 2 half_distance)))
		bulge_1 (/ (sin (* 0.25 alpha_1)) (cos (* 0.25 alpha_1)))
		bulge_2 (* -1 (/ (sin (* 0.25 alpha_2)) (cos (* 0.25 alpha_2))))
		bulge_3 bulge_1
		bulge_4 0
	)
	(vla-erase circle_aux)
	(vla-erase line_1_aux)
	(setq pline (vla-addlightweightpolyline (vla-get-block (vla-get-activelayout (vla-get-activedocument (vlax-get-acad-object))))
					          (vlax-safearray-fill (vlax-make-safearray vlax-vbdouble '(0 . 7))
							  (apply 'append (mapcar '(lambda (vertex) 
											(mapcar '+ '(0 0) vertex)
							   			  ) 
							   			  (list pline_point_1 pline_point_2 pline_point_3 pline_point_4)
								         )
						          )
					          )
		      )
	)
	(mapcar '(lambda (index bulge) (vla-setbulge pline index bulge)) '(0 1 2 3) (list bulge_1 bulge_2 bulge_3 bulge_4))
  	(while (not point_selected)
		(princ "\rMove cursor to move filleted pline, LMB to stop")
		(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
					(vla-erase pline)
			 		(setq point_selected t)
			 		
		 	)
			(
			 	(= 3 (car grread_data))
			 		(setq point_selected t)
		 	)
			(
			 	(= 5 (car grread_data))
			 		(vla-move pline (vlax-3d-point most_far_turn_border_point)
						  	(vlax-3d-point (setq most_far_turn_border_point
									      (inters (cadr grread_data)
						  				      (polar (cadr grread_data) (+ (* 0.5 pi) to_far_direction) 1)
										      line_12_end_mid_level_point
										      (polar line_12_end_mid_level_point to_far_direction 1)
										      nil
								   	      )
					    			       )
			   				)
				        )
			 )
			 (
			 	(or
				    (= 25 (car grread_data))
				    (= 11 (car grread_data))
			    	)
			 		(vla-move pline (vlax-3d-point most_far_turn_border_point)
						  	(vlax-3d-point (inters
									 (setq most_far_turn_border_point (getpoint (getpoint "\nFirst point: ") "\nSecond point: "))
				  				         (polar most_far_turn_border_point (+ (* 0.5 pi) to_far_direction) 1)
								         line_12_end_mid_level_point
								         (polar line_12_end_mid_level_point to_far_direction 1)
								         nil
						   	      		)
			   				)
				        )
			  		(setq point_selected t)
			 )
			 (
			  	t
			 )
		)
	)
)

 

Message 15 of 18

eakos1
Advocate
Advocate

Thanks for everyone who helped me. I get very good inputs, I learned a lot again. Now I can use the grread too. 

But my final decision was to use the MOVE command because it was the easiest way to improve my program. 

This is my current code. It works fine now and it can do not only symmetrical turnback but also left/right shifted designs. And also possible to define the radius at the beginning. 

 

0 Likes
Message 16 of 18

eakos1
Advocate
Advocate

I want to ask one question. If I'm in the program by the MOVE command and I push the ESC button than the program will exit from the MOVE command and will follow up to the end, but will leave in the drawing an ARC segment. 

I tried to add an *error* handling and inside a command to delete the created ARC but it seems that the MOVE command has its own error handling and so it not works. Is this the case or I do something wrong?

Or it is to difficult to interrupt the program by pushing the ESC button? 

 

 

   (defun *error* (msg)
;;;	(if ortho (setvar 'orthomode ortho)
;;;	) ;_ if
;;;	(if snapang (setvar 'snapang snapang)
;;;	) ;_ if
;;;	(if osmode (setvar 'osmode osmode)
;;;	) ;_ if
	(if object_ARC (vla-erase (vlax-ename->vla-object object_ARC))
	) ;_ if
	(if (not (member msg '("Function cancelled" "quit / exit abort" "No valid fillet with radius 3.0000")))
	  (princ (strcat "\nError: " msg))
	) ;_ if
	(princ)
      ) ;_ defun

 

0 Likes
Message 17 of 18

Sea-Haven
Mentor
Mentor

An idea set a UNDOMARK and add undo  to your error defun. 

 

(setq doc (vla-get-activedocument (vlax-get-acad-object)))

(vla-startundomark doc)
do your code
at end of code
(vla-endundomark doc)

 

Message 18 of 18

ВeekeeCZ
Consultant
Consultant

First, always localize the *error* function, always.

 

But the main issue is the command-s function that prevents the command (move) from falling straight into *error* and KEEPS ON evaluating the rest of the code. Do you really want to do that? I would rather use the classic command function instead. 

 

And yes, the -s version is necessary if used within the *error* function itself.