(setq inc (sslength sel)
enx (entget (ssname sel (1- inc)))
spf (polar '(0.0 0.0) (+ (cdr (assoc 50 enx)) (/ pi 2.0)) (* (cdr (assoc 40 enx)) spf))
vec (trans spf (trans '(0.0 0.0 1.0) 1 0 t) 0)
)
;;--------------------=={ Align Text }==----------------------;;
;; ;;
;; This program enables the user to reposition a selection ;;
;; of text objects equispaced by a factor of the text height ;;
;; and aligned in a direction perpendicular to the rotation ;;
;; angle of the text. ;;
;; ;;
;; The program assumes all text objects in the selection ;;
;; have the same rotation and will align each text object ;;
;; using its Text Alignment Point. ;;
;; ;;
;; The program will perform successfully with text ;;
;; constructed in any UCS plane. ;;
;;------------------------------------------------------------;;
;; Author: Lee Mac, Copyright © 2013 - www.lee-mac.com (http://www.lee-mac.com) ;;
;;------------------------------------------------------------;;
;; Version 1.3 - 23-04-2013 ;;
;;------------------------------------------------------------;;
(defun c:at ( / *error* bpt enx inc ins lst sel spf vec )
(setq spf 1.5) ;; Line Spacing Factor
(defun *error* ( msg )
(LM:endundo (LM:acdoc))
(if (not (wcmatch (strcase msg t) "*break,*cancel*,*exit*"))
(princ (strcat "\nError: " msg))
)
(princ)
)
(if (setq sel (ssget "_:L" '((0 . "TEXT"))))
(progn
(setq inc (sslength sel)
enx (entget (ssname sel (1- inc)))
spf (polar '(0.0 0.0) (+ (cdr (assoc 50 enx)) (/ pi 2.0)) (* (cdr (assoc 40 enx)) spf))
vec (trans spf (trans '(0.0 0.0 1.0) 1 0 t) 0)
)
(repeat inc
(setq lst (cons (entget (ssname sel (setq inc (1- inc)))) lst)
ins (cons (caddr (trans (aligntext:gettextinsertion (car lst)) (cdr (assoc -1 (car lst))) vec)) ins)
)
)
(setq lst (mapcar '(lambda ( n ) (nth n lst)) (vl-sort-i ins '>))
bpt (aligntext:gettextinsertion (car lst))
)
(LM:startundo (LM:acdoc))
(foreach itm (cdr lst)
(aligntext:puttextinsertion (setq bpt (mapcar '- bpt spf)) itm)
)
(LM:endundo (LM:acdoc))
)
)
(princ)
)
(defun aligntext:getdxfkey ( enx )
(if
(and
(zerop (cdr (assoc 72 enx)))
(zerop (cdr (assoc 73 enx)))
)
10 11
)
)
(defun aligntext:gettextinsertion ( enx )
(cdr (assoc (aligntext:getdxfkey enx) enx))
)
(defun aligntext:puttextinsertion ( ins enx )
( (lambda ( key )
(if (entmod (subst (cons key ins) (assoc key enx) enx))
(entupd (cdr (assoc -1 enx)))
)
)
(aligntext:getdxfkey enx)
)
)
;; 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)
;;------------------------------------------------------------;;
;; End of File ;;
;;------------------------------------------------------------;;
At the top of the code, the variable spf is initially defined as the line spacing factor - a numerical value to be multiplied by the text height to give the distance between each successive aligned text objects.
The program first prompts the user for a selection of text objects to align (assigned to the variable sel), and then retrieves the DXF data (enx) for the last entity in this selection (the use of the last text entity is arbitrary).
The variable spf is then redefined as a vector with direction perpendicular to the angle of the last text entity in the selection, and magnitude equal to the line spacing factor multiplied by the text height of the last text entity. Note that this vector is defined in the active UCS plane.
The variable vec is then the WCS representation of the newly defined line spacing vector (spf); this is obtained by transforming the spf vector from the coordinate system defined by the normal vector to the UCS plane [this normal vector is obtained using the expression: (trans '(0.0 0.0 1.0) 1 0 t)] to WCS (trans argument 0).
The variable vec will be used to defined a coordinate system wherein the normal vector is perpendicular to the angle of the text (i.e. the WCS representation of the spf vector).
The program then iterates over the main selection (variable sel), and constructs two lists: a list of the DXF data for all text entities in the selection (variable lst), and a list of the z-coordinate values of the text insertion points after translation to the coordinate system defined by the vector vec - this will be used as a sorting index (variable ins).
The list of text entity DXF data (lst) is then sorted based on the sort order of the ins list which has been sorted by decreasing z-value. The program then obtains the OCS coordinates of the first text entity in this sorted list to be used as the base point for the alignment.
Finally, the program iterates over the remaining items in the sorted list of DXF data, modifying the text insertion point of each text object to a point given by the previous text insertion point spaced by the spf vector - note that this assumes that the active UCS plane is parallel to the OCS plane of the selected text.
(trans spf (trans '(0.0 0.0 1.0) 1 0 t) 0)
as i understand, (trans) is tracking the vector generated between the Wcs and Ucs, and then offsetting the resulting point respectively. in this way the point is always located at the same place. correct?
( 0.810921 0.405103 -0.422254 ) ( 1.2 ) ( 0.810921 0.405103 -0.422254 )·( 1.2 5.3 4.7 ) (( 0.810921 x 1.2) + ( 0.405103 x 5.3) + (-0.422254 x 4.7))
(-0.172367 0.854962 0.489213 ) x ( 5.3 ) = (-0.172367 0.854962 0.489213 )·( 1.2 5.3 4.7 ) = ((-0.172367 x 1.2) + ( 0.854962 x 5.3) + ( 0.489213 x 4.7))
( 0.559193 -0.323931 0.763133 ) ( 4.7 ) ( 0.559193 -0.323931 0.763133 )·( 1.2 5.3 4.7 ) (( 0.559193 x 1.2) + (-0.323931 x 5.3) + ( 0.763133 x 4.7))
(Where · represents the vector dot product (http://en.wikipedia.org/wiki/Dot_product))about the nested trans,Code: [Select](trans spf (trans '(0.0 0.0 1.0) 1 0 t) 0)
(trans vector '(0.0 0.0 1.0) from UCS to WCS return 0.0 0.0 -1.0
The variable spf is then redefined as a vector with direction perpendicular to the angle of the last text entity in the selection, and magnitude equal to the line spacing factor multiplied by the text height of the last text entity. Note that this vector is defined in the active UCS plane.
The variable vec is then the WCS representation of the newly defined line spacing vector (spf); this is obtained by transforming the spf vector from the coordinate system defined by the normal vector to the UCS plane [this normal vector is obtained using the expression: (trans '(0.0 0.0 1.0) 1 0 t)] to WCS (trans argument 0).
The variable vec will be used to defined a coordinate system wherein the normal vector is perpendicular to the angle of the text (i.e. the WCS representation of the spf vector).
The program then iterates over the main selection (variable sel), and constructs two lists: a list of the DXF data for all text entities in the selection (variable lst), and a list of the z-coordinate values of the text insertion points after translation to the coordinate system defined by the vector vec - this will be used as a sorting index (variable ins).
(trans spf (trans '(0.0 0.0 1.0) 1 0 t) 0)
The list of text entity DXF data (lst) is then sorted based on the sort order of the ins list which has been sorted by decreasing z-value. The program then obtains the OCS coordinates of the first text entity in this sorted list to be used as the base point for the alignment.
Read about the 'Arbitrary Axis Algorithm' in the DXF documentation first. I think that will answer a lot of your questions.
The arbitrary axis algorithm is used by AutoCAD internally to implement the arbitrary but consistent generation of object coordinate systems for all entities that use object coordinates.
Given a unit-length vector to be used as the Z axis of a coordinate system, the arbitrary axis algorithm generates a corresponding X axis for the coordinate system. The Y axis follows by application of the right-hand rule.
The method is to examine the given Z axis (also called the normal vector). If it is close to the positive or negative world Z axis, cross the world Y axis with the given Z axis to arrive at the arbitrary X axis. If it is not close, cross the world Z axis with the given Z axis to arrive at the arbitrary X axis. The boundary at which the decision is made was chosen to be both inexpensive to calculate and completely portable across machines. This is achieved by having a sort of “square” polar cap, the bounds of which are 1/64, which is precisely specifiable in six decimal-fraction digits and in six binary-fraction bits.
The variable vec will be used to defined a coordinate system wherein the normal vector is perpendicular to the angle of the text (i.e. the WCS representation of the spf vector).
Variable vec, is the anchor of spf in the WCS, it has the same location and the same angle.
Than the z axis of the entity insertion point is translated from OCS to the coordinate system defined by vec, that’s because z axis is ruling x and y properties?
this code translating UCS to its cooriponding WCS,
spf is the vector, it being translated from translating from ______ vector to WCS
1._______ is something that i cant figure out, please help!
2.why the program needs WCS equivlent?
1. why the program gets only the Z coordinates rather the whole OCS?
2.why Z is being sorted?
QuoteThe arbitrary axis algorithm is used by AutoCAD internally to implement the arbitrary but consistent generation of object coordinate systems for all entities that use object coordinates.
what they mean arbitery? randomly? and it can be connsistent?
QuoteGiven a unit-length vector to be used as the Z axis of a coordinate system, the arbitrary axis algorithm generates a corresponding X axis for the coordinate system. The Y axis follows by application of the right-hand rule.
as i understand, the algorithem get as an input the Z axie, and generate corresponding x and y, is that right?
QuoteThe method is to examine the given Z axis (also called the normal vector). If it is close to the positive or negative world Z axis, cross the world Y axis with the given Z axis to arrive at the arbitrary X axis. If it is not close, cross the world Z axis with the given Z axis to arrive at the arbitrary X axis. The boundary at which the decision is made was chosen to be both inexpensive to calculate and completely portable across machines. This is achieved by having a sort of “square” polar cap, the bounds of which are 1/64, which is precisely specifiable in six decimal-fraction digits and in six binary-fraction bits.
this is too far...what is 64/1?
The expression: (trans '(0.0 0.0 1.0) 1 0 t) constitutes the 'from' argument for the trans function. This expression returns the normal vector of the UCS plane - the trans function will then use the Arbitrary Axis Algorithm to construct a coordinate system from this normal vector to use for the transformation.
Hey...
This may help...
This is the 'Arbitrary Axis Algorithm' in use to place a BlockReference aligned on three Points in 3D-Space...
http://www.theswamp.org/index.php?topic=37429.msg522021#msg522021
greets Reltro
Thanks you for your outstanding desire to help others and taking the time to explain, appriciate that.
QuoteThe expression: (trans '(0.0 0.0 1.0) 1 0 t) constitutes the 'from' argument for the trans function. This expression returns the normal vector of the UCS plane - the trans function will then use the Arbitrary Axis Algorithm to construct a coordinate system from this normal vector to use for the transformation.
why not just (trans spf 1 0) aka translate spf from ucs to Wcs?
At the top of the code, the variable spf is initially defined as the line spacing factor - a numerical value to be multiplied by the text height to give the distance between each successive aligned text objects.
The program first prompts the user for a selection of text objects to align (assigned to the variable sel), and then retrieves the DXF data (enx) for the last entity in this selection (the use of the last text entity is arbitrary).
The variable spf is then redefined as a vector with direction perpendicular to the angle of the last text entity in the selection, and magnitude equal to the line spacing factor multiplied by the text height of the last text entity. Note that this vector is defined in the active UCS plane.
The variable vec is then the WCS representation of the newly defined line spacing vector (spf); this is obtained by transforming the spf vector from the coordinate system defined by the normal vector to the UCS plane [this normal vector is obtained using the expression: (trans '(0.0 0.0 1.0) 1 0 t)] to WCS (trans argument 0).
The variable vec will be used to defined a coordinate system wherein the normal vector is perpendicular to the angle of the text (i.e. the WCS representation of the spf vector).
The program then iterates over the main selection (variable sel), and constructs two lists: a list of the DXF data for all text entities in the selection (variable lst), and a list of the z-coordinate values of the text insertion points after translation to the coordinate system defined by the vector vec - this will be used as a sorting index (variable ins).
The list of text entity DXF data (lst) is then sorted based on the sort order of the ins list which has been sorted by decreasing z-value. The program then obtains the OCS coordinates of the first text entity in this sorted list to be used as the base point for the alignment.
Finally, the program iterates over the remaining items in the sorted list of DXF data, modifying the text insertion point of each text object to a point given by the previous text insertion point spaced by the spf vector - note that this assumes that the active UCS plane is parallel to the OCS plane of the selected text.
Hi Lee
did you sort it because the selection order? if so, how did you get the idea that Z is to be sorted?
as i understand you sort lst list, couldn't you just redefine lst with the new sorted list?Code: [Select](setq lst (mapcar '(lambda ( n ) (nth n lst)) (vl-sort-i ins '>))
couldn't you justCode: [Select](setq lst (vl-sort-i ins '>))
or am i missing something?
Shay
did you sort it because the selection order? if so, how did you get the idea that Z is to be sorted?
as i understand you sort lst list, couldn't you just redefine lst with the new sorted list?Code: [Select](setq lst (mapcar '(lambda ( n ) (nth n lst)) (vl-sort-i ins '>))
couldn't you justCode: [Select](setq lst (vl-sort-i ins '>))
(foreach itm (cdr lst)
(aligntext:puttextinsertion (setq bpt (mapcar '- bpt spf)) itm)