align selected elemets to a line

align selected elemets to a line

eyal.ch
Collaborator Collaborator
3,494 Views
14 Replies
Message 1 of 15

align selected elemets to a line

eyal.ch
Collaborator
Collaborator

Hi everyone,

 

Could you help me with a lisp that:

 

After calling it , I will select some entities like circles,lines etc. and after that it allow to select one line from the selected entities (it also can be a line from a rectangle), and select another line to align all the selected entities to it.

like the image shown:

7070.jpg

( and not making it a block)

 

Thanks.

Eyal

0 Likes
Accepted solutions (1)
3,495 Views
14 Replies
Replies (14)
Message 2 of 15

Kent1Cooper
Consultant
Consultant

The ALIGN command will do that, easily enough -- you would just need to pick two locations along the particular edges, but it spares the need for any code.  Presumably you would need to pick two locations on each anyway, to pick each edge and to determine where on the original objects' edge should go to where on the target edge.

Kent Cooper, AIA
0 Likes
Message 3 of 15

eyal.ch
Collaborator
Collaborator

Hi @Kent1Cooper ,

I know that the align command let the user pick 2 points on the subject and 2 more points on the target.

but what I need is by selecting only one line it will align all the selected objects to the other line selected.

I want to save the 2 clicks.

it is for quick working.

 

I want by only 3 commands: 1.  selecting the objects , 2. pick one line from the selection , 3. pick another line as target.

and it will align the objects.

 

Thanks.

Message 4 of 15

cadffm
Consultant
Consultant

Yes, but you have to tell the program where the points L1.1 L2.1 and L1.2 L2.2 is!

 

I am pretty sure you don't want every time that the program use Startpoint-Line1 to Startpoint-Line2

and Endpoint-Line1 to Endpoint-Line2

😉

 

One solution can be:

The User click the Line(segment) near to the endpoint what should be Point1, the program detect the nearest endpoint for Point1 of Line1 and Line2,

the other side as Point2 of Line1 and Line2.

 

 

Sebastian

0 Likes
Message 5 of 15

eyal.ch
Collaborator
Collaborator

Hi,

 

It suppose to be like this code :

;;--------------------=={ Object Align }==--------------------;;
;;                                                            ;;
;;  This program will enable the user to dynamically align a  ;;
;;  selection of objects to a selected curve, with intuitive  ;;
;;  placement controls.                                       ;;
;;                                                            ;;
;;  Upon starting the program with the command syntax 'OA',   ;;
;;  the user is prompted to make a selection of objects to    ;;
;;  be aligned. Following a valid selection, the user is      ;;
;;  prompted to specify a base point to use during alignment; ;;
;;  at this prompt, the program will use the center of the    ;;
;;  bounding box of the selection of objects by default.      ;;
;;                                                            ;;
;;  The user is then prompted to select a curve object        ;;
;;  (this may be a Line, Polyline, Arc, Circle, Ellipse,      ;;
;;  XLine, Spline etc.) to which the objects are to be        ;;
;;  aligned. The selected curve may be a primary object, or   ;;
;;  nested with a Block or XRef to any level. After           ;;
;;  selection, the program offers several controls to aid     ;;
;;  with object placement displayed at the command line:      ;;
;;                                                            ;;
;;  [+/-] for [O]ffset | [</>] for [R]otation | <[E]xit>:     ;;
;;                                                            ;;
;;  The offset of the objects from the curve may be           ;;
;;  controlled incrementally by a tenth of the object height  ;;
;;  using the '+' / '-' keys, or a specific offset may be     ;;
;;  entered upon pressing the 'O' or 'o' key.                 ;;
;;                                                            ;;
;;  The set of objects may be rotated anti-clockwise or       ;;
;;  clockwise by 45 degrees relative to the curve by pressing ;;
;;  the '<' or '>' keys respectively; alternatively, the user ;;
;;  may enter a specific rotation by pressing the 'R' or 'r'  ;;
;;  key.                                                      ;;
;;                                                            ;;
;;  Finally, the user may place the objects and exit the      ;;
;;  program by either clicking the left or right mouse        ;;
;;  buttons, pressing Enter or Space, or by pressing the 'E'  ;;
;;  or 'e' keys.                                              ;;
;;                                                            ;;
;;  The program should perform successfully in all UCS &      ;;
;;  Views, and in all versions of AutoCAD that have Visual    ;;
;;  LISP functions available (AutoCAD 2000 onwards).          ;;
;;                                                            ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2012 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Version 1.3    -    14-12-2012                            ;;
;;------------------------------------------------------------;;

(defun c:oa

    (
        /
        *error*
        _copynested
        _curveobject-p
        _fixdxfdata
        _locked-p
        _selectif

        bb1 bb2 blk bnm bpt
        def dis
        enl ent
        fac
        gr1 gr2
        inc
        llp lst
        mat msg
        nrm
        obj
        pi2 pt1 pt2
        sel
        tmp
        urp uxa
    )

    (defun *error* ( msg )
        (if (and
                (= 'list  (type mat))
                (= 'ename (type ent))
            )
            (entdel ent)
        )
        (if (and (= 'vla-object (type blk)) (not (vlax-erased-p blk)))
            (vl-catch-all-apply 'vla-delete (list blk))
        )
        (if (and (= 'vla-object (type def)) (not (vlax-erased-p def)))
            (vl-catch-all-apply 'vla-delete (list def))
        )
        (foreach obj lst
            (if (not (vlax-erased-p obj))
                (vl-catch-all-apply 'vla-delete (list obj))
            )
        )
        (LM:endundo (LM:acdoc))
        (if (and msg (not (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")))
            (princ (strcat "\nError: " msg))
        )
        (princ)
    )
    
    (defun _curveobject-p ( ent )
        (null
            (vl-catch-all-error-p
                (vl-catch-all-apply 'vlax-curve-getendparam (list ent))
            )
        )
    )

    (defun _fixdxfdata ( elst )
        (vl-remove-if '(lambda ( pair ) (member (car pair) '(5 6 8 102 330))) elst)
    )

    (defun _copynested ( ent mat / enx )
        (if
            (setq ent
                (cond
                    (   (= "VERTEX" (cdr (assoc 0 (setq enx (entget ent)))))
                        (entmakex (_fixdxfdata (entget (setq ent (cdr (assoc 330 enx))))))
                        (setq ent (entnext ent)
                              enx (entget  ent)
                        )
                        (while (/= "SEQEND" (cdr (assoc 0 enx)))
                            (entmakex (_fixdxfdata enx))
                            (setq ent (entnext ent)
                                  enx (entget  ent)
                            )
                        )
                        (cdr (assoc 330 (entget (entmakex (_fixdxfdata enx)))))
                    )
                    (   (entmakex (_fixdxfdata enx))   )
                )
            )
            (if mat (vla-transformby (vlax-ename->vla-object ent) (vlax-tmatrix mat)))
        )
        ent
    )

    (defun _selectif ( msg pred )
        (
            (lambda ( pred / sel )
                (while
                    (progn (setvar 'errno 0) (setq sel (nentselp msg))
                        (cond
                            (   (= 7 (getvar 'errno))
                                (princ "\nMissed, try again.")
                            )
                            (   (= 'ename (type (car sel)))
                                (if (null (pred (car sel)))
                                    (princ "\nInvalid Object Selected.")
                                )
                            )
                        )
                    )
                )
                sel
            )
            (eval pred)
        )
    )
    
    (defun _locked-p ( layer )
        (= 4 (logand 4 (cdr (assoc 70 (tblsearch "LAYER" layer)))))
    )

    (if (null oa|rot)
        (setq oa|rot 0.0)
    )
    (if (null oa|off)
        (setq oa|off 0.0)
    )
    (cond
        (   (or
                (_locked-p (getvar 'clayer))
                (_locked-p "0")
            )
            (princ "\nCurrent Layer or Layer \"0\" locked.")
        )
        (   (null (setq sel (LM:ssget "\nSelect Objects to Align: " '("_:L" ((0 . "~VIEWPORT"))))))
            (princ "\n*Cancel*")
        )
        (   (progn
                (setq mat
                    (vlax-tmatrix
                        (append
                            (mapcar
                               '(lambda ( a b ) (append (trans a 1 0 t) (list b)))
                               '(
                                    (1.0 0.0 0.0)
                                    (0.0 1.0 0.0)
                                    (0.0 0.0 1.0)
                                )
                                (trans '(0.0 0.0 0.0) 0 1)
                            )
                           '((0.0 0.0 0.0 1.0))
                        )
                    )
                )
                (LM:startundo (LM:acdoc))
                (repeat (setq inc (sslength sel))
                    (setq obj (vla-copy (vlax-ename->vla-object (ssname sel (setq inc (1- inc)))))
                          lst (cons obj lst)
                    )
                    (vla-transformby obj mat)
                    (if (and (vlax-method-applicable-p obj 'getboundingbox)
                            (not
                                (vl-catch-all-error-p
                                    (vl-catch-all-apply 'vla-getboundingbox (list obj 'llp 'urp))
                                )
                            )
                        )
                        (setq bb1 (cons (vlax-safearray->list llp) bb1)
                              bb2 (cons (vlax-safearray->list urp) bb2)
                        )
                    )
                    (vla-put-visible obj :vlax-false)
                )
                (setq bb1 (apply 'mapcar (cons 'min bb1))
                      bb2 (apply 'mapcar (cons 'max bb2))
                )
                (cond
                    (   (setq bpt (getpoint "\nSpecify Base Point <Center>: "))
                        (setq bpt (trans bpt 1 0))
                    )
                    (   (setq bpt (mapcar (function (lambda ( a b ) (/ (+ a b) 2.0))) bb1 bb2)))
                )
                (null
                    (setq enl
                        (_selectif "\nSelect Curve: "
                            (function
                                (lambda ( x )
                                    (or (= "VERTEX" (cdr (assoc 0 (entget x)))) (_curveobject-p x))
                                )
                            )
                        )
                    )
                )
            )
            (*error* nil)
        )
        (   (not
                (or
                    (and
                        (setq mat (caddr enl))
                        (setq ent (_copynested (car enl) mat))
                    )
                    (and
                        (= "VERTEX" (cdr (assoc 0 (entget (car enl)))))
                        (setq ent (cdr (assoc 330 (entget (car enl)))))
                    )
                    (setq ent (car enl))
                )
            )
            (*error* nil)
            (princ "\nUnable to Recreate Nested Entity.")
        )
        (   t         
            (setq pt1 (cadr (grread t 9))
                  fac (/ (- (cadr bb2) (cadr bb1)) 2.0)
                  nrm (trans '(0.0 0.0 1.0) 1 0 t)
                  uxa (angle '(0.0 0.0 0.0) (trans (getvar 'ucsxdir) 0 nrm t))
                  pi2 (/ pi -2.0)
            )
            (setq inc 0)
            (while (tblsearch "BLOCK" (setq bnm (strcat "$tmp" (itoa (setq inc (1+ inc)))))))
            (foreach obj lst (vla-put-visible obj :vlax-true))
            (vla-copyobjects (LM:acdoc)
                (vlax-make-variant
                    (vlax-safearray-fill
                        (vlax-make-safearray vlax-vbobject (cons 0 (1- (length lst))))
                        lst
                    )
                )
                (setq def (vla-add (vla-get-blocks (LM:acdoc)) (vlax-3D-point bpt) bnm))
            )
            (foreach obj lst (vla-delete obj))
            (setq lst nil)
         
            (setq blk
                (vla-insertblock
                    (vlax-get-property (LM:acdoc) (if (= 1 (getvar 'cvport)) 'paperspace 'modelspace))
                    (vlax-3D-point (trans pt1 1 0))
                    bnm
                    1.0 1.0 1.0 0.0
                )
            )
            (vla-put-layer blk "0")
            (vla-put-normal blk (vlax-3D-point nrm))
            (setq msg (princ "\n[+/-] for [O]ffset | [</>] for [R]otation | <[E]xit>: "))

            (while
                (progn
                    (setq gr1 (grread t 15 0)
                          gr2 (cadr gr1)
                          gr1 (car  gr1)
                    )
                    (cond
                        (   (member gr1 '(3 5))
                            (setq pt2 (trans gr2 1 0)
                                  pt1 (vlax-curve-getclosestpointto ent pt2)
                            )
                            (if (not (equal pt1 pt2 1e-8))
                                (progn
                                    (setq dis (/ (* fac oa|off) (distance pt1 pt2)))
                                    (vla-put-insertionpoint blk (vlax-3D-point (mapcar '(lambda ( a b ) (+ a (* (- b a) dis))) pt1 pt2)))
                                    (vla-put-rotation blk (+ (angle (trans pt1 0 1) gr2) uxa oa|rot pi2))
                                )
                            )
                            (= 5 gr1)
                        )
                        (   (= 2 gr1)
                            (cond
                                (   (member gr2 '(043 061))
                                    (setq oa|off (+ oa|off 0.1))
                                )
                                (   (member gr2 '(045 095))
                                    (setq oa|off (- oa|off 0.1))
                                )
                                (   (member gr2 '(044 060))
                                    (setq oa|rot (+ oa|rot (/ pi 4.0)))
                                )
                                (   (member gr2 '(046 062))
                                    (setq oa|rot (- oa|rot (/ pi 4.0)))
                                )
                                (   (member gr2 '(013 032 069 101))
                                    nil
                                )
                                (   (member gr2 '(082 114))
                                    (if (setq tmp (getangle (strcat "\nSpecify Rotation <" (angtos oa|rot) ">: ")))
                                        (setq oa|rot tmp)
                                    )
                                    (princ msg)
                                )
                                (   (member gr2 '(079 111))
                                    (if (setq tmp (getdist (strcat "\nSpecify Offset <" (rtos (* fac oa|off)) ">: ")))
                                        (setq oa|off (/ tmp fac))
                                    )
                                    (princ msg)
                                )
                                (   t   )
                            )
                        )
                        (   (member gr1 '(011 025))
                            nil
                        )
                        (   t   )
                    )
                )
            )
            (if mat (entdel ent))
            (vla-explode blk)
            (vla-delete  blk)
            (vla-delete  def)
            (LM:endundo (LM:acdoc))
        )
    )
    (princ)
)

;; ssget  -  Lee Mac
;; A wrapper for the ssget function to permit the use of a custom selection prompt
;;
;; Arguments:
;; msg    - selection prompt
;; params - list of ssget arguments

(defun LM:ssget ( msg params / sel )
    (princ msg)
    (setvar 'nomutt 1)
    (setq sel (vl-catch-all-apply 'ssget params))
    (setvar 'nomutt 0)
    (if (not (vl-catch-all-error-p sel)) sel)
)

;; Start Undo  -  Lee Mac
;; Opens an Undo Group.

(defun LM:startundo ( doc )
    (LM:endundo doc)
    (vla-startundomark doc)
)

;; End Undo  -  Lee Mac
;; Closes an Undo Group.

(defun LM:endundo ( doc )
    (while (= 8 (logand 8 (getvar 'undoctl)))
        (vla-endundomark doc)
    )
)

;; Active Document  -  Lee Mac
;; Returns the VLA Active Document Object

(defun LM:acdoc nil
    (eval (list 'defun 'LM:acdoc 'nil (vla-get-activedocument (vlax-get-acad-object))))
    (LM:acdoc)
)
    
;;------------------------------------------------------------;;

(vl-load-com)
(princ
    (strcat
        "\n:: ObjectAlign.lsp | Version 1.3 | © Lee Mac "
        (menucmd "m=$(edtime,$(getvar,DATE),YYYY)")
        " www.lee-mac.com ::"
        "\n:: Type \"OA\" to Invoke ::"
    )
)
(princ)

;;------------------------------------------------------------;;
;;                         End of File                        ;;
;;------------------------------------------------------------;;

but with adaptation, I want to select not only one object and align it , but to select some objects and by selecting a line from it , and select a target line it align the bunch of line accordingly. 

 

this code work fine with selecting a rectangle line but not if I select a line.

 

Can anyone make this adaptation?

THanks,

0 Likes
Message 6 of 15

ВeekeeCZ
Consultant
Consultant
Accepted solution

First of all, you look like you misunderstood the purpose of the Forums. We are here to help you to write your own tools, not to write it for you. For free. The complex program like you posted. BTW it has its author!! Are you allowed to post it here, are you allowed to modify it? Have you bothered to read THIS? 

 

Anyway, here is a very simple example of how you can easily achieve almost what you want. As you can see, I have used like 5-6 different functions. nothing complicated. So stop scrounging and learn.

 

(defun c:Align+ (/ ss en p1 p2 p3 p4)

  (if (and (setq ss (ssget "_:L"))
	   (setq en (entsel "\nSource object: "))
	   (setq p1 (osnap (cadr en) "_end"))
	   (setq p3 (osnap (cadr en) "_nea"))
	   (setq en (entsel "\nDestination object: "))
	   (setq p2 (osnap (cadr en) "_nea"))
	   (setq p4 (osnap (cadr en) "_end"))
	   (setq p4 (polar (trans p2 1 0) (angle (trans p4 1 0) (trans p2 1 0)) (distance p2 p4)))
	   )
    (command "_.align" ss "" "_non" p1 "_non" p2 "_non" p3 "_non" p4 "" "_No"))
  (princ)
  )
 
Message 7 of 15

eyal.ch
Collaborator
Collaborator

PERFECT @ВeekeeCZ ,

 

Thank you, EXACTLY what I need.

 

 

0 Likes
Message 8 of 15

mkroll9in5in
Enthusiast
Enthusiast
You can add this to a macro and create a button where on the tail end of selecting and aligning, move; previous;; so you can fallow up by selecting a hard snapped destination point. ^C^C_Align+;\\\\\_m;p;;
I'm sure it can be interrogated into the lisp, I'm not that good YET. macros I'm fair at.
0 Likes
Message 9 of 15

WeTanks
Mentor
Mentor

please teach me,

I can also do it with (1),
What is the difference between (1) and (2)?

WeTanks_0-1684635414018.pngWeTanks_1-1684635453417.png

 

 

We.Tanks

EESignature

A couple of Fusion improvement ideas that could your vote/support:
図面一括印刷

0 Likes
Message 10 of 15

mkroll9in5in
Enthusiast
Enthusiast
To tell you the truth, I don't think it is really any better than using the traditional align command, but it does function just a little different. The \\\\\ is give you the option to make your necessary 5 click selection_ M is for Move; P is for previously selected;; allowing you to follow up with a source and destination. It might not be any faster, its just different.
Message 11 of 15

omarsvn
Enthusiast
Enthusiast

it is possible that "select object" and "source object" being the same? just clicking "select object" and "destination object" and the alignment take place? 20241014_080002_1.gif

0 Likes
Message 12 of 15

ВeekeeCZ
Consultant
Consultant

Sure. Seem like this should do the trick.

 

(defun c:Align+ (/ es en p1 p2 p3 p4)

  (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"))
	   )
    (command "_.align" es "" "_non" p1 "_non" p2 "_non" p3 "_non" p4 "" "_No"))
  (princ)
  )

 

0 Likes
Message 13 of 15

omarsvn
Enthusiast
Enthusiast

works fantastic! do you things is possible autoCAD request me for a space between them? for example a blade with 0.135 thickness is going to cut them and a kerf spaces is required between them

0 Likes
Message 14 of 15

Sea-Haven
Mentor
Mentor
0 Likes
Message 15 of 15

omarsvn
Enthusiast
Enthusiast
I was able to improve the code you provide 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 and change the distance 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
 
(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)
  )
0 Likes