Automatic Align

Automatic Align

omarsvn
Enthusiast Enthusiast
2,733 Views
27 Replies
Message 1 of 28

Automatic Align

omarsvn
Enthusiast
Enthusiast

I worked in a simple code that let me align two polygons just choosing one of its lines, it worked but is not a 100% what I would like, I going to attach images as reference and the code I made.  I'd like to improve is20241011_145649_1.gifScreenshot (120).png the polygons should be aligned to the closest point of its vertices when I choose the line. They should not be aligned one inside the another, I don't know if it is possible to align the text included inside the polygon since most of the time the polygons contain text. finally I would like autoCAD requests me a distance as a kerf since sometimes a space is needed between polygons

 

(defun c:ALI ()
 
(setq picked_data (entsel "\nSelect object to align: ")
  picked_pline (car picked_data)
  picked_point (vlax-curve-getclosestpointto picked_pline (cadr picked_data))
  picked_param (fix (vlax-curve-getparamatpoint picked_pline picked_point)) 
  p1 (vlax-curve-getpointatparam picked_pline picked_param)
  p2 (vlax-curve-getpointatparam picked_pline (1+ picked_param))
)
  (setq picked_data2 (entsel "\nSelect the reference object: ")
  picked_pline2 (car picked_data2)
  picked_point2 (vlax-curve-getclosestpointto picked_pline2 (cadr picked_data2))
  picked_param2 (fix (vlax-curve-getparamatpoint picked_pline2 picked_point2)) 
  p3 (vlax-curve-getpointatparam picked_pline2 picked_param2)
  p4 (vlax-curve-getpointatparam picked_pline2 (1+ picked_param2))
)
  (command "align" pause "" p1 p3 p2 p4 "" "")
 
 
)
2,734 Views
27 Replies
Replies (27)
Message 2 of 28

Kent1Cooper
Consultant
Consultant

The important thing you didn't include in your image is what you started with.  "This is what I get" from what original configuration?  And along with that, where you picked on whatever you start with to get the result you got.

Kent Cooper, AIA
0 Likes
Message 3 of 28

omarsvn
Enthusiast
Enthusiast

The code I post let me do the image " This is what I get" If you see the polygons are aligned from de lines I picked, I pick a line from one of them and after a line from the other one, the question is the polygon goes inside of the other, let me post a gif how I would like the code works20241014_080002_1.gif

0 Likes
Message 4 of 28

Sea-Haven
Mentor
Mentor

The obvious is check if the polygon is CW or CCW this makes the direction fixed, second suggestion is you can select a segment of a polygon/pline you can compare the pick point to the ends of the segment so know which end to add.

 

For me would be draw polygon, then add rectangs including labels. Much easier than grabbing an existing rectang, I use a dcl for input of say offset and edge sizes. This is part 2 of another post here, Solved: create recctagles automatic - Autodesk Community - AutoCAD

0 Likes
Message 5 of 28

omarsvn
Enthusiast
Enthusiast
I was able to improve the code  provided by @beekeeCZ in another post and make what I want, AutoCAD request me for an offset that is the space between the "Source object" and "Destination Object" but it ask me every time for the offset, It is possible to store the offset distance and change it only when I require, most of the time I use 0.135 between polygons, so I want to store that distance and change it only when I need a different distance, somethig like when I store the radius, autoCAD store that distance so every time I call the fillet command I dont need to instert the radius distance
 
(defun c:Aligned (/ es en p1 p2 p3 p4 p5 p6)
 
  (if (and (setq o (getreal "Offset"))
(setq es (entsel "\nSource object: "))
   (setq p1 (osnap (cadr es) "_end"))
   (setq p3 (osnap (cadr es) "_nea"))
   (setq en (entsel "\nDestination object: "))
   (setq p2 (osnap (cadr en) "_end"))
   (setq p4 (osnap (cadr en) "_nea"))
   (setq ang (angle p2 p4))
   (setq p5 (polar p2 (+ ang (angtof "90")) o))
   (setq p6 (polar p4 (+ ang (angtof "90")) o))
   )
    (command "_.align" es "" "_non" p1 "_non" p5 "_non" p3 "_non" p6 "" "_No"))
  (princ)
  )
Message 6 of 28

ВeekeeCZ
Consultant
Consultant
Accepted solution

Probably the simplest way is to use another command that sets this variable - it must be a global variable. 

 

(defun c:Aligned (/ es en p1 p2 p3 p4 p5 p6 ang)

  (if (not *aligned-offset*)
    (setq *aligned-offset* 0.135))
  
  (if (and (setq es (entsel "\nSource object: "))
	   (setq p1 (osnap (cadr es) "_end"))
	   (setq p3 (osnap (cadr es) "_nea"))
	   (setq en (entsel "\nDestination object: "))
	   (setq p2 (osnap (cadr en) "_end"))
	   (setq p4 (osnap (cadr en) "_nea"))
	   (setq ang (angle p2 p4))
	   (setq p5 (polar p2 (+ ang (angtof "90")) *aligned-offset*))
	   (setq p6 (polar p4 (+ ang (angtof "90")) *aligned-offset*))
	   )
    (command "_.align" es "" "_non" p1 "_non" p5 "_non" p3 "_non" p6 "" "_No"))
  (princ)
  )


(defun c:AlignedOffsetSetting ()
  (setq *aligned-offset* (getdist "\nSpecify offset: "))
  (princ)
  )

 

Message 7 of 28

marko_ribar
Advisor
Advisor

Here is just a little sophisticated version of @ВeekeeCZ code...

 

(defun c:aligned-curves ( / ftoa es en p1 p2 p3 p4 p5 p6 an pp ch ) ;;; *gap* - global variable ;;;

  (or (not (vl-catch-all-error-p (vl-catch-all-apply (function vlax-get-acad-object) nil))) (vl-load-com))

  (defun ftoa ( n / m a s b )
    (if (numberp n)
      (progn
        (setq m (fix ((if (< n 0) - +) n 1e-8)))
        (setq a (abs (- n m)))
        (setq m (itoa m))
        (setq s "")
        (while (and (not (equal a 0.0 1e-6)) (setq b (fix (* a 10.0))))
          (setq s (strcat s (itoa b)))
          (setq a (- (* a 10.0) b))
        )
        (if (= (type n) (quote int))
          m
          (if (= s "")
            m
            (if (and (= m "0") (< n 0))
              (strcat "-" m "." s)
              (strcat m "." s)
            )
          )
        )
      )
    )
  )

  (initget 4)
  (setq *gap*
    (cond
      ( (getdist (strcat "\nPick or specify gap between pieces <" (ftoa (setq *gap* (if (not *gap*) 0.0 *gap*))) "> : ")) )
      ( t *gap* )
    )
  )
  (if
    (and
      (setq es (entsel "\nPick source polygonal polyline you want to align..."))
      (setq p3 (vlax-curve-getclosestpointto (car es) (cadr es)))
      (setq p1 (if (< (- (vlax-curve-getparamatpoint (car es) p3) (fix (vlax-curve-getparamatpoint (car es) p3))) (- (1+ (fix (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getpointatparam (car es) (fix (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getpointatparam (car es) (1+ (fix (vlax-curve-getparamatpoint (car es) p3))))))
      (setq en (entsel "\nPick destination polygonal polyline to which you want to align..."))
      (setq p4 (vlax-curve-getclosestpointto (car en) (cadr en)))
      (setq p2 (if (< (- (vlax-curve-getparamatpoint (car en) p4) (fix (vlax-curve-getparamatpoint (car en) p4))) (- (1+ (fix (vlax-curve-getparamatpoint (car en) p4))) (vlax-curve-getparamatpoint (car en) p4))) (vlax-curve-getpointatparam (car en) (fix (vlax-curve-getparamatpoint (car en) p4))) (vlax-curve-getpointatparam (car en) (1+ (fix (vlax-curve-getparamatpoint (car en) p4))))))
      (setq an (angle p2 p4))
      (setq p5 (polar p2 (- an (* 0.5 pi)) *gap*))
      (setq p6 (polar p4 (- an (* 0.5 pi)) *gap*))
      (not (initget 1))
      (setq pp (getpoint "\nPick or specify point inside destination polygonal polyline : "))
    )
    (if
      (and
        (< (distance pp p5) (distance pp p2))
        (< (distance pp p6) (distance pp p4))
      )
      (progn
        (setq p5 (polar p2 (+ an (* 0.5 pi)) *gap*))
        (setq p6 (polar p4 (+ an (* 0.5 pi)) *gap*))
        (vl-cmdf "_.align" (car es) "" "_non" p1 "_non" p5 "_non" p3 "_non" p6 "" "_No")
        (initget "Yes No")
        (setq ch (getkword "\nIs alighment correct - without interferences [Yes/No]  : "))
        (if (not ch)
          (setq ch "No")
        )
        (if (= ch "No")
          (progn
            (vl-cmdf "_.undo" 1)
            (setq p1 (if (> (- (vlax-curve-getparamatpoint (car es) p3) (fix (vlax-curve-getparamatpoint (car es) p3))) (- (1+ (fix (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getpointatparam (car es) (fix (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getpointatparam (car es) (1+ (fix (vlax-curve-getparamatpoint (car es) p3))))))
            (vl-cmdf "_.align" (car es) "" "_non" p1 "_non" p5 "_non" p3 "_non" p6 "" "_No")
          )
        )
      )
      (progn
        (vl-cmdf "_.align" (car es) "" "_non" p1 "_non" p5 "_non" p3 "_non" p6 "" "_No")
        (initget "Yes No")
        (setq ch (getkword "\nIs alighment correct - without interferences [Yes/No]  : "))
        (if (not ch)
          (setq ch "No")
        )
        (if (= ch "No")
          (progn
            (vl-cmdf "_.undo" 1)
            (setq p1 (if (> (- (vlax-curve-getparamatpoint (car es) p3) (fix (vlax-curve-getparamatpoint (car es) p3))) (- (1+ (fix (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getpointatparam (car es) (fix (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getpointatparam (car es) (1+ (fix (vlax-curve-getparamatpoint (car es) p3))))))
            (vl-cmdf "_.align" (car es) "" "_non" p1 "_non" p5 "_non" p3 "_non" p6 "" "_No")
          )
        )
      )
    )
  )
  (princ)
)

Regards, M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 8 of 28

Kent1Cooper
Consultant
Consultant
Accepted solution

@omarsvn wrote:
.... most of the time I use 0.135 between polygons, so I want to store that distance and change it only when I need a different distance, somethig like when I store the radius, autoCAD store that distance so every time I call the fillet command I dont need to instert the radius distance
....

That way of handling the default [as FILLET does] means you don't need to answer a prompt for the distance [if there's a value set in it], but it just proceeds with the current value unless you specifically call for an option to set a value.  [The other way, as OFFSET does it, is to ask you for a value every time, and offer you a default which you can accept with Enter/space, but you are still required to take the step of accepting it if you don't want to set a different value.]

 

Here's a way to do that FILLET-like approach [lightly tested]:

 

(defun C:Aligned (/ es en p1 p2 p3 p4 ang p5 p6)
  (while (or (not es) (not (listp es))); didn't select something
    (if *AO* (prompt (strcat "\nCurrent Aligned Offset distance: " (rtos *AO*) ".")))
    (initget 4 "Offset"); no negative, allow "Offset" as option
    (setq es (entsel "\nSource object or <Offset>: "))
    (if (or (not *AO*) (= es "Offset")); no value yet, or chose option
      (setq *AO* ; = Aligned-command Offset distance [global for default]
        (cond
          ( (getdist
              (strcat
                "\nOffset distance <"
                (if *AO* (rtos *AO*) "0.135")
                  ; offer prior value as default if present, 0.135 default on first use
                ">: "
              ); strcat
            ); getdist
          ); User-input condition
          (*AO*); current default [when present] on Enter
          (0.135); initial default on Enter at first use
        ); cond
      ); setq
    ); if
  ); while
  (setq
    p1 (osnap (cadr es) "_end")
    p3 (osnap (cadr es) "_nea")
    en (entsel "\nDestination object: ")
    p2 (osnap (cadr en) "_end")
    p4 (osnap (cadr en) "_nea")
    ang (angle p2 p4)
    p5 (polar p2 (+ ang (/ pi 2)) *AO*)
    p6 (polar p4 (+ ang (/ pi 2)) *AO*)
  ); setq
  (command "_.align" es "" "_non" p1 "_non" p5 "_non" p3 "_non" p6 "" "_No")
  (princ)
)

 

On first use, it asks for a source object or to call for the Offset option and set a value, and if you don't call for the option then, it asks for an Offset distance after selecting the source object, offering your typical value as an initial default that you can accept, or type in or pick on-screen what you want.  On subsequent uses, it first reports the current Offset distance [also as FILLET reports its mode and radius], and asks for a source object or to call for the Offset option and set a value [or, if you then decide to, still keep the current one].  If you don't want to set a new value, all you do is select the source object and destination object.  It always asks for the source object first, so the prompt for that can contain Offset as an option that you can call for or bypass.

 

It's otherwise your code, though I streamlined the (setq)ing of a lot of variables into one function.

 

Depending on surroundings, your Osnapping to set p1/p2 could find some other object's ENDpoint closer than the one you intend, if that other object is within Osnap APERTURE range.  If that's a problem, it can be overcome by changing the APERTURE System Variable setting [temporarily] to match the PICKBOX setting, so the Osnap "window" doesn't reach out to other things.  That would justify including *error* handling to ensure APERTURE gets reset, in which case setting OSMODE to 0 could also be included, to eliminate the "_non" Osnap calls, and Undo begin/end wrapping could be added.

 

Consider whether you want to allow an Offset distance of zero.  If not, (initget 6 ...).

Kent Cooper, AIA
Message 9 of 28

omarsvn
Enthusiast
Enthusiast

It works great! thank you

Message 10 of 28

omarsvn
Enthusiast
Enthusiast

It works the only thing I try to avoid input the offset every time, even if I have to enter to accept the value on the screen, I wanted to store it  in only in the case I need it,  changes it 

Message 11 of 28

omarsvn
Enthusiast
Enthusiast
Accepted solution

works great! thank you

Message 12 of 28

Sea-Haven
Mentor
Mentor

For me it would be pick a pline segment near an end then,

SeaHaven_0-1729034669235.png

Then just draw the rectang aligned to the pline and start point. The values would be saved every time so could do pick Ok, pick  Ok, pick change values Ok etc.

 

Just a suggestion.

0 Likes
Message 13 of 28

Kent1Cooper
Consultant
Consultant

@omarsvn wrote:

works great! thank you


You're welcome.  It occurs to me to wonder:  Since the way it works requires only that selected objects have ENDpoints and NEArest points, it will operate not only on Polylines as in your images, and just Lines, and Blocks with such things contained in them, and so on, but also on all kinds of possibly inappropriate things, such as Arcs, Polylines picked on arc segments, Splines, or partial Ellipses.  It will accept selection of things it will have trouble with because they don't have both those Osnappable locations, such as Circles [no ENDpoint] or Text [neither].

 

Would it be worth having it check whether you picked appropriate things, before proceeding?

Kent Cooper, AIA
0 Likes
Message 14 of 28

marko_ribar
Advisor
Advisor

I am still sticking with my version, just little adapted for various entity types like curves and blocks, just like Kent explained...

See if this suits you; there are several picks and one question that you (user) should answer (is alignment correct, or pieces interfere each other)... Still I left global variable usage inside routine and not within separate (defun) as I think that it's more appropriate to enter its value through routine and if satisfied with value just by hitting ENTER to procede further with execution...

 

(defun c:aligned-blks ( / ftoa es en p11 p12 p2 p3 p4 p5 p6 an pp ch ) ;;; *gap* - global variable ;;;

  (or (not (vl-catch-all-error-p (vl-catch-all-apply (function vlax-get-acad-object) nil))) (vl-load-com))

  (defun ftoa ( n / m a s b )
    (if (numberp n)
      (progn
        (setq m (fix ((if (< n 0) - +) n 1e-8)))
        (setq a (abs (- n m)))
        (setq m (itoa m))
        (setq s "")
        (while (and (not (equal a 0.0 1e-6)) (setq b (fix (* a 10.0))))
          (setq s (strcat s (itoa b)))
          (setq a (- (* a 10.0) b))
        )
        (if (= (type n) (quote int))
          m
          (if (= s "")
            m
            (if (and (= m "0") (< n 0))
              (strcat "-" m "." s)
              (strcat m "." s)
            )
          )
        )
      )
    )
  )

  (initget 4)
  (setq *gap*
    (cond
      ( (getdist (strcat "\nPick or specify gap between pieces <" (ftoa (setq *gap* (if (not *gap*) 0.0 *gap*))) "> : ")) )
      ( t *gap* )
    )
  )
  (if
    (and
      (setq es (entsel "\nPick source polygonal polyline-block you want to align..."))
      (setq p3 (osnap (cadr es) "_nea"))
      (setq p11 (osnap (cadr es) "_end"))
      (setq es (entsel "\nPick source polygonal polyline-block you want to align near other end of segment..."))
      (setq p12 (osnap (cadr es) "_end"))
      (setq en (entsel "\nPick destination polygonal polyline-block to which you want to align..."))
      (setq p4 (osnap (cadr en) "_nea"))
      (setq p2 (osnap (cadr en) "_end"))
      (setq an (angle p2 p4))
      (setq p5 (polar p2 (- an (* 0.5 pi)) *gap*))
      (setq p6 (polar p4 (- an (* 0.5 pi)) *gap*))
      (not (initget 1))
      (setq pp (getpoint "\nPick or specify point inside destination polygonal polyline : "))
    )
    (if
      (and
        (< (distance pp p5) (distance pp p2))
        (< (distance pp p6) (distance pp p4))
      )
      (progn
        (setq p5 (polar p2 (+ an (* 0.5 pi)) *gap*))
        (setq p6 (polar p4 (+ an (* 0.5 pi)) *gap*))
        (vl-cmdf "_.align" (car es) "" "_non" p11 "_non" p5 "_non" p3 "_non" p6 "" "_No")
        (initget "Yes No")
        (setq ch (getkword "\nIs alighment correct - without interferences [Yes/No]  : "))
        (if (not ch)
          (setq ch "No")
        )
        (if (= ch "No")
          (progn
            (vl-cmdf "_.undo" 1)
            (vl-cmdf "_.align" (car es) "" "_non" p12 "_non" p5 "_non" p3 "_non" p6 "" "_No")
          )
        )
      )
      (progn
        (vl-cmdf "_.align" (car es) "" "_non" p11 "_non" p5 "_non" p3 "_non" p6 "" "_No")
        (initget "Yes No")
        (setq ch (getkword "\nIs alighment correct - without interferences [Yes/No]  : "))
        (if (not ch)
          (setq ch "No")
        )
        (if (= ch "No")
          (progn
            (vl-cmdf "_.undo" 1)
            (vl-cmdf "_.align" (car es) "" "_non" p12 "_non" p5 "_non" p3 "_non" p6 "" "_No")
          )
        )
      )
    )
  )
  (princ)
)

Regards, M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 15 of 28

komondormrex
Mentor
Mentor

is it still open to suggestions? like this.

komondormrex_2-1729087401759.gif

 

Message 16 of 28

omarsvn
Enthusiast
Enthusiast

Yes sir, can you share the code?, I created a offset with my basic knowledge of autolisp but sometimes the polygons overlaping each other, it depends how the code recognize the points20241016_105003_1.gif

0 Likes
Message 17 of 28

komondormrex
Mentor
Mentor
Accepted solution

sure,

 

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

;	komondormrex, oct 2024
;	'align_with' custom command

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

(defun is_ccw (segment_list / angle_list)
	(defun diff_angle (angle_1 angle_2)
	  	(setq angle_1 (if (> angle_2 (+ pi angle_1)) (+ (* pi 2) angle_1) angle_1))
	  	(setq angle_2 (if (> angle_1 (+ pi angle_2)) (+ (* pi 2) angle_2) angle_2))
	  	(- angle_2 angle_1)
	)
	(setq angle_list (mapcar '(lambda (segment) (apply 'angle segment)) segment_list))
	(if (> (apply '+ (mapcar '(lambda (angle_1 angle_2) (diff_angle angle_1 angle_2)) angle_list (cdr angle_list))) 0) t nil)
)

(defun c:align_with (/ align_data ref_data align_picked_point align_picked_param- align_picked_point- align_picked_param+ align_picked_point+
					   ref_picked_point ref_picked_param- ref_picked_point- ref_picked_param+ ref_picked_point+
					   align_point_param align_point align_angle ref_point_param ref_point ref_angle align_rotate_angle align_offset
					   ref_segment_list offset_angle_correction 
				    )
	(vla-startundomark (vla-get-activedocument (vlax-get-acad-object)))
	(if (null align_offset_saved) (setq align_offset_saved 0.135))
	(while (and (setq align_offset align_offset_saved)
				(not (= 'list (type (setq align_data (vl-catch-all-apply 'entsel (list "\nSelect edge of pline to align (<Esc> to set offset): "))))))
		   )
			(if (or (vl-catch-all-error-p align_data)
					(null align_data)
				)
					(setq align_offset (if (null (setq align_offset (getreal (strcat "\nEnter offset from reference edge <" (rtos align_offset_saved) ">: "))))
						 				   	align_offset_saved
						 				   	(setq align_offset_saved align_offset)
						 			   	)
					)
			)
	)
	(setq ref_data (entsel "\nSelect edge of reference pline: ")
		  ref_segment_list (mapcar '(lambda (start end) (list (cdr start) (cdr end)))
							    	(setq vertices (vl-remove-if '(lambda (group) (/= 10 (car group))) (entget (car ref_data))))
							    	(append (cdr vertices) (list (car vertices)))
					   	   )
		  offset_angle_correction (if (is_ccw ref_segment_list) '- '+)
	  	  align_picked_point (vlax-curve-getclosestpointto (setq align_pline (car align_data)) (cadr align_data))
	  	  align_picked_param- (fix (vlax-curve-getparamatpoint align_pline align_picked_point))
	  	  align_picked_point- (vlax-curve-getpointatparam align_pline align_picked_param-)
	  	  align_picked_param+ (1+  align_picked_param-)
	  	  align_picked_point+ (vlax-curve-getpointatparam align_pline align_picked_param+)
		  align_vertices (mapcar 'cdr (vl-remove-if '(lambda (group) (/= 10 (car group))) (entget align_pline)))
	  	  ref_picked_point (vlax-curve-getclosestpointto (setq ref_pline (car ref_data)) (cadr ref_data))
	  	  ref_picked_param (vlax-curve-getparamatpoint ref_pline ref_picked_point)
	  	  ref_picked_param- (fix ref_picked_param)
	  	  ref_picked_point- (vlax-curve-getpointatparam ref_pline ref_picked_param-)
	  	  ref_picked_param+ (1+ ref_picked_param-)
	  	  ref_picked_point+ (vlax-curve-getpointatparam ref_pline ref_picked_param+)
		  ref_picked_angle (angle (trans '(0 0) 1 0) (vlax-curve-getfirstderiv ref_pline ref_picked_param))
	)
  	(if (< (distance align_picked_point align_picked_point+)
		   (distance align_picked_point align_picked_point-)
		)
  			(setq align_point align_picked_point+
				  align_angle (angle align_point align_picked_point-)
			)
  			(setq align_point align_picked_point-
				  align_angle (angle align_point align_picked_point+)
			)
  	)
  	(if (< (distance ref_picked_point ref_picked_point+)
		   (distance ref_picked_point ref_picked_point-)
		)
  			(setq ref_point ref_picked_point+
				  ref_angle (angle ref_point ref_picked_point-)
			)
  			(setq ref_point ref_picked_point-
				  ref_angle (angle ref_point ref_picked_point+)
			)
  	)
	(setq align_rotate_angle (- ref_angle align_angle))
	(foreach object (mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr (ssnamex (ssget "_cp" align_vertices)))))
		(vla-rotate object (vlax-3d-point align_point) align_rotate_angle)
		(vla-move object (vlax-3d-point align_point)
						 (vlax-3d-point (polar ref_point ((eval offset_angle_correction) ref_picked_angle (* 0.5 pi)) align_offset))
		)
	)
	(vla-endundomark (vla-get-activedocument (vlax-get-acad-object)))
	(princ)
)

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

 

updated

 

Message 18 of 28

omarsvn
Enthusiast
Enthusiast

It works fantastic! but I have a problem and is about how the text and lines are contained inside de polygon, there are text and lines that don't follow the polygon when it aligning, and my conclusion is because they are touching the edges, text, lines and block are really inside the polygon not touching any of its edges align according with the polygon. And is it possible works when the polygons are already blocks? I attach dwg to better illustration

Message 19 of 28

komondormrex
Mentor
Mentor

check update in message 17. _wp changed to _cp. but if there is zero offset between items unpredictable results could come.

Message 20 of 28

marko_ribar
Advisor
Advisor

@omarsvn 

Here is my final version... Should perform correctly with both curves and blocks with texts/attributes... It is like you showed - single click on source and single click on destination... If I were you, I'd mark this also as solution... Haven't checked your DWG though, but I suppose that it'll work correct - it worked with my DWG...

 

(defun c:aligned ( / *error* ftoa cmd pck es en p11 p12 p2 p3 p4 p5 p6 an pp ll ur ) ;;; *gap* - global variable ;;;

  (or (not (vl-catch-all-error-p (vl-catch-all-apply (function vlax-get-acad-object) nil))) (vl-load-com))

  (defun *error* ( m )
    (if (= 8 (logand 8 (getvar (quote undoctl))))
      (if command-s
        (command-s "_.undo" "_e")
        (vl-cmdf "_.undo" "_e")
      )
    )
    (if pck
      (setvar (quote pickfirst) pck)
    )
    (if cmd
      (setvar (quote cmdecho) cmd)
    )
    (if m
      (prompt m)
    )
    (princ)
  )

  (defun ftoa ( n / m a s b )
    (if (numberp n)
      (progn
        (setq m (fix ((if (< n 0) - +) n 1e-8)))
        (setq a (abs (- n m)))
        (setq m (itoa m))
        (setq s "")
        (while (and (not (equal a 0.0 1e-6)) (setq b (fix (* a 10.0))))
          (setq s (strcat s (itoa b)))
          (setq a (- (* a 10.0) b))
        )
        (if (= (type n) (quote int))
          m
          (if (= s "")
            m
            (if (and (= m "0") (< n 0))
              (strcat "-" m "." s)
              (strcat m "." s)
            )
          )
        )
      )
    )
  )

  (setq cmd (getvar (quote cmdecho)))
  (setvar (quote cmdecho) 0)
  (setq pck (getvar (quote pickfirst)))
  (setvar (quote pickfirst) 1)
  (if (= 8 (logand 8 (getvar (quote undoctl))))
    (vl-cmdf "_.undo" "_e")
  )
  (vl-cmdf "_.undo" "_be")
  (initget 4)
  (setq *gap*
    (cond
      ( (getdist (strcat "\nPick or specify gap between pieces <" (ftoa (setq *gap* (if (not *gap*) 0.0 *gap*))) "> : ")) )
      ( t *gap* )
    )
  )
  (if
    (and
      (setq es (entsel "\nPick source polygonal polyline-block you want to align..."))
      (setq p3 (osnap (cadr es) "_nea"))
      (setq p11 (osnap (cadr es) "_end"))
      (if (= (cdr (assoc 0 (entget (car es)))) "INSERT")
        (progn
          (vl-cmdf "_.-refedit" "_non" p3 "_O" "_All" "_No")
          (setq p12 (if (> (- (vlax-curve-getparamatpoint (car (nentselp p3)) p3) (fix (vlax-curve-getparamatpoint (car (nentselp p3)) p3))) (- (1+ (fix (vlax-curve-getparamatpoint (car (nentselp p3)) p3))) (vlax-curve-getparamatpoint (car (nentselp p3)) p3))) (vlax-curve-getpointatparam (car (nentselp p3)) (fix (vlax-curve-getparamatpoint (car (nentselp p3)) p3))) (vlax-curve-getpointatparam (car (nentselp p3)) (1+ (fix (vlax-curve-getparamatpoint (car (nentselp p3)) p3))))))
          (vl-cmdf "_.refclose" "_D")
        )
        (setq p12 (if (> (- (vlax-curve-getparamatpoint (car es) p3) (fix (vlax-curve-getparamatpoint (car es) p3))) (- (1+ (fix (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getpointatparam (car es) (fix (vlax-curve-getparamatpoint (car es) p3))) (vlax-curve-getpointatparam (car es) (1+ (fix (vlax-curve-getparamatpoint (car es) p3))))))
      )
      (setq en (entsel "\nPick destination polygonal polyline-block to which you want to align..."))
      (setq p4 (osnap (cadr en) "_nea"))
      (setq p2 (osnap (cadr en) "_end"))
      (setq an (angle p2 p4))
      (setq p5 (polar p2 (- an (* 0.5 pi)) *gap*))
      (setq p6 (polar p4 (- an (* 0.5 pi)) *gap*))
      (progn
        (vla-getboundingbox (vlax-ename->vla-object (car en)) (quote ll) (quote ur))
        (mapcar (function set) (list (quote ll) (quote ur)) (mapcar (function safearray-value) (list ll ur)))
        (setq pp (mapcar (function (lambda ( a b ) (/ (+ a b) 2.0))) ll ur))
      )
    )
    (if
      (and
        (< (distance pp p5) (distance pp p2))
        (< (distance pp p6) (distance pp p4))
      )
      (progn
        (setq p5 (polar p2 (+ an (* 0.5 pi)) *gap*))
        (setq p6 (polar p4 (+ an (* 0.5 pi)) *gap*))
        (vl-cmdf "_.align" (car es) "" "_non" p11 "_non" p5 "_non" p3 "_non" p6 "" "_No")
        (if (and (not (zerop *gap*)) (vlax-invoke (vlax-ename->vla-object (car es)) (quote intersectwith) (vlax-ename->vla-object (car en)) acextendnone))
          (progn
            (vl-cmdf "_.undo" 1)
            (vl-cmdf "_.align" (car es) "" "_non" p12 "_non" p5 "_non" p3 "_non" p6 "" "_No")
          )
        )
      )
      (progn
        (vl-cmdf "_.align" (car es) "" "_non" p11 "_non" p5 "_non" p3 "_non" p6 "" "_No")
        (if (and (not (zerop *gap*)) (vlax-invoke (vlax-ename->vla-object (car es)) (quote intersectwith) (vlax-ename->vla-object (car en)) acextendnone))
          (progn
            (vl-cmdf "_.undo" 1)
            (vl-cmdf "_.align" (car es) "" "_non" p12 "_non" p5 "_non" p3 "_non" p6 "" "_No")
          )
        )
      )
    )
  )
  (*error* nil)
)

HTH.

Regards, M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes