Hi masters!
I am working in a new LISP, to change the dimensions of a drawing for an aligned dimension. Dimensions you can see in the drawing are made of simple lines.
So, first of all i tried to identify the point nº3 of the triangles. After that i will make a dimensions between those 2.
I am stuck in this point and dont know how to get it. I imagine i need to identify the coordinates of those point. If anyone knows any other way to make it easier i will apreciate it.
How i will run the lisp? I will select only the items i need to change, and will run the lisp. I will do the same action again and again until all the dimensions are changed.
There is no need to create the dimstyle and layer, because both will be already created in the drawing.
Thanks in advance!
Solved! Go to Solution.
Solved by Kent1Cooper. Go to Solution.
@Anonymous
Would you ?
do the same action again and again until all the dimensions are changed.
by picking each 2 triangle at the time??
Yes, i will repeat the same action again and again until all are done. Making it automatic will be hard (as sometimes the dimensions are inclined, and with my knowledge i dont know if that will be possible)
Anyways i just need to identify the 3rd point of those triangles, which are a polilyne
It will be better to use GETPOINT, as such triangles have 6 vertex
;;;((16.1137 10.0344 0.0)
;;; (16.0824 10.0344 0.0)
;;; (16.1137 10.1182 0.0)
;;; (16.1449 10.0344 0.0)
;;; (16.1137 10.0344 0.0)
;;; (16.1137 10.0344 0.0))
so you can use
;IDENTIFY THE POINTS
(setq p1 (getpoint "\nPick the point " ))
(setq p2 (getpoint p1 "\nThe other point."))
;;; (setq pt1 (list (car p1) (cadr p1))
;;; (setq pt2 (list (car p2) (cadr p2))
)
I want to make it automatic. With getpoint you must select the points in the window.
Searching i found this function:
(setq e (nth 0 d))
Where 0 is the poisition of the list, and d is the list. Despite of this still dont know how to identify onlye the triangle
2 triangles 3 points each, do a furtherest distance apart will give the 2 outermost points angle does not matter.
@Anonymous ,
What's the point in getting the triangle head vertex with (getpoint) when you can achieve the same result by directly running DIMALIGNED?
When you can accomplish a task with standard command no lisp is needed - right?!
Moshe
@Sea-Haven , despite the triangle have 6 vertices, the OP also want to erase both triangles and the POLYLINES between them after doing the ALIGNED DIM
This is a part of a more complex lisp i am working on. I need to select and remove those lines. Thats why i want to make it automatic.
This is the lisp i have updates. I am still stuck in the part where i get the points of the polilyne.
(defun c:co (/ ss s1 s2 p1 p2 pt1 pt2)
(setq ss (ssget ()))
(setq s1 (acet-ss-ssget-filter ss '((8 . "*_linea"))) ; I will delete this items later
s2 (acet-ss-ssget-filter ss '((8 . "*_dist"))) ; I will delete this items later
s3 (acet-ss-ssget-filter ss '((8 . "*_linea")(0 . "LWPOLYLINE,POLYLINE")(-4 . "&")(70 . 1))) ;Select only the triangles. Polilynes which are closed
)
;IDENTIFY THE POINTS
(setq p1 ()
p2 ()
)
(setq pt1 (nth 2 p1)
pt2 (nth 2 p2)
)
;DRAW DIMENSION
(setvar "clayer" "_EST-ARM-REP")
(setvar "dimstyle" "05-DCE-50-ARM")
(command "_dimaligned" pt1 pt2 "")
;ERASE SELECTION 1 AND 2
(command "_erase" s1 s2 "")
(princ)
)
@Anonymous ,
What's the story of this drawing, from where it came? is it an option to ask the sender to fix this?
Moshe
@Anonymous wrote:
....
So, first of all i tried to identify the point nº3 of the triangles. ....
For that, it's a matter of (vlax-curve) Parameters, which start at 0 for the first vertex, just as (nth) uses 0 for the first item in a list and (ssname) uses 0 for the first object in the selection.
If pl is the entity name of the Polyline [gotten from something like, in your Message 10 code, (ssname s3 somenumber)], this will give you the 3rd vertex at the point of the arrow:
(vlax-curve-getPointAtParam pl 2)
But that depends on the arrow always being a 5-vertex construction like that, with the point at the 3rd vertex.
Make sure you have running Osnap off, or build in "none" Osnap calls when you use those points in a dimensioning command. And include the line
(vl-load-com)
in the command definition if that isn't done for you elsewhere.
@Anonymous
you post about the same topic before : at 04-01-2020 04:16 PM
and never give a like or comment
Thanks for your help @Kent1Cooper, but it didnt work at all.
The triangles i wanna select are always a 2D polilyne and always have 5 vertices.
First of all i converted the selection (which are 2 triangles) into a Vla-object, then i tried to get the points as you described. What did i do wrong? Osnap is off.
"error: wrong argument type: lentityp <Selection set: 3732"
(defun c:co (/ ss s1 s2 s3 s4 p1 p2 pt1 pt2)
(vl-load-com)
(setq ss (ssget ()))
(setq s1 (acet-ss-ssget-filter ss '((8 . "*_linea")))
s2 (acet-ss-ssget-filter ss '((8 . "*_dist")))
s3 (acet-ss-ssget-filter ss '((8 . "*_linea")(0 . "LWPOLYLINE,POLYLINE")(-4 . "&")(70 . 1)))
s4 (vlax-ename->vla-object s3)
)
;IDENTIFY THE POINTS
(setq p1 (car s4)
p2 (cdr s4)
)
(setq pt1 (vlax-curve-getPointAtParam p1 2)
pt2 (vlax-curve-getPointAtParam p2 2)
)
;DRAW DIMENSION
(setvar "clayer" "_EST-ARM-REP")
(command "_dimaligned" pt1 pt2 "")
;ERASE SELECTION 1 AND 2
(command "_erase" s1 s2 "")
(princ)
)
Thanks for your help!
@Anonymous wrote:
Thanks for your help @Kent1Cooper, but it didnt work at all.
The triangles i wanna select are always a 2D polilyne and always have 5 vertices.
First of all i converted the selection (which are 2 triangles) into a Vla-object, then i tried to get the points as you described. What did i do wrong? Osnap is off.
.... s3 (acet-ss-ssget-filter ss '((8 . "*_linea")(0 . "LWPOLYLINE,POLYLINE")(-4 . "&")(70 . 1))) s4 (vlax-ename->vla-object s3) ) ;IDENTIFY THE POINTS (setq p1 (car s4) p2 (cadr s4) ) (setq pt1 (vlax-curve-getPointAtParam p1 2) pt2 (vlax-curve-getPointAtParam p2 2) ) ....
....
If s3 is a selection set, you can't make a VLA object out of that -- it needs to be an entity name. So your s4 setting is incorrect. I think you could omit s4 altogether, and say:
(setq p1 (ssname s3 0) p2 (ssname s3 1))
and go from there.
The (vlax-curve-...) functions can take an entity name -- they don't require a VLA object.
@Kent1Cooper wrote:
....
.... s3 (acet-ss-ssget-filter ss '((8 . "*_linea")(0 . "LWPOLYLINE,POLYLINE")(-4 . "&")(70 . 1))) s4 (vlax-ename->vla-object s3) ) ;IDENTIFY THE POINTS (setq p1 (car s4) p2 (cadr s4) ) ....
....
If s3 is a selection set, you can't make a VLA object out of that -- it needs to be an entity name. So your s4 setting is incorrect. ....
In addition, if your idea was that s4 would be a selection set containing VLA objects [which it can't be -- selection sets contain entity names], then using (car s4) and (cadr s4) to get the two arrowheads out of it is also incorrect. Those functions are for getting the 1st and 2nd things from a list, not from a selection set.
Thank you so much @Kent1Cooper for your help!! that worked!
I also found another mistake in the list: to put a dimension i needed 3 point, so i get the 3rd point in the middle of the pt1 and pt2
I will leave the lisp here just i case anyone needs it in the future:
(defun c:co (/ ss s1 s2 s3 p1 p2 pt1 pt2 pt3 x y)
(vl-load-com)
(setq ss (ssget ()))
(setq s1 (acet-ss-ssget-filter ss '((8 . "*_linea")))
s2 (acet-ss-ssget-filter ss '((8 . "*_dist")))
s3 (acet-ss-ssget-filter ss '((8 . "*_linea")(0 . "LWPOLYLINE,POLYLINE")(-4 . "&")(70 . 1)))
)
;IDENTIFY THE POINTS
(setq p1 (ssname s3 0)
p2 (ssname s3 1)
)
(setq pt1 (vlax-curve-getPointAtParam p1 2)
pt2 (vlax-curve-getPointAtParam p2 2)
)
;GET MIDDLE POINT (PT3)
(setq x (/ (+ (car pt1) (car pt2)) 2)
y (/ (+ (cadr pt1) (cadr pt2)) 2)
z (/ (+ (caddr pt1) (caddr pt2)) 2)
pt3 (list x y z)
)
;DRAW DIMENSION
(setvar "clayer" "_EST-ARM-REP")
(command "_dimaligned" pt1 pt2 pt3)
;ERASE SELECTION 1 AND 2
(command "_erase" s1 s2 "")
(princ)
)
I think that the point of a polyline is to be able to join lines and arcs together into one continuous entity that can even be closed and offset as a whole. They are great for contours and property boundaries. 😁
John F. Uhden
@Anonymous hi,
Even though you closed this, here is the ultimate solution you can get 😀
command called CUSDIM (custom dimension) and it validates the triangles for it's vertices\edges and been an isosceles triangle, eliminating redundant vertices and if something been wrong, you will be alerted.
with CUSDIM you won't be worried about the head vertex been the 3rd point. it will be found no matter how the polyline was drawn 😀
the program start by declaring 2 constants:
(setq LINEAR_FUZZ 1e-3)
(setq ANGULAR_FUZZ 1e-5)
the (equal) function is used a lot to verifies points and angles been equals in limit. if the accuracy level is not enough for you, increase (or decrease) these constants. LINEAR_FUZZ is for points and ANGULAR_FUZZ is for angles.
another constant you would like to set is the dimension line offset distance (how far the dimension line is placed from the triangles):
(setq DL_OSET_DIST (* (getvar "dimtxt") (getvar "dimscale") 4))
as you can see it is 4 times DIMTXT under the current dimstyle. if it is too close\far change it as needed. the program does not handles the dimension style (which is very important) or layer, these are left for you.
if the triangles lays for horizontal\vertical dimension they will be drawn with DIMLINEAR otherwise it will be DIMALIGNED.
enjoy
Moshe
;;; cusdim.lsp
;;; Custom Dimension command
;;; by Moshe.A
;;; APR 28, 2020
(vl-load-com) ; load activex support
(defun c:cusdim (/ get_vertices elim_zero_seg elim_cont_seg get_head_vertex pos_dimlin ; local funcrions
LINEAR_FUZZ ANGULAR_FUZZ DL_OSET_DIST ss lst0 lst1 p0 p1 ;| local variables |;)
(defun get_vertices (ename / l lst)
(setq l (fix (vlax-curve-getEndParam ename)))
(repeat l
(setq lst (cons (vlax-curve-getPointAtParam ename (setq l (1- l))) lst))
); repeat
lst
); get_vertices
; eliminate zero distance segments
(defun elim_zero_seg (lst / points)
(while (not
(vl-every
'(lambda (t0 t1)
(if (not (equal (distance t0 t1) 0.0 LINEAR_FUZZ))
(setq points (cons t0 points))
); if
)
lst
(cdr (append lst (list (car lst))))
); vl-every
); not
(setq lst points points nil)
); while
points
); elim_zero_seg
; eliminate continuing segments
(defun elim_cont_seg (lst / points)
(while (not
(vl-every
'(lambda (t0 t1 t2)
(if (not (equal (angle t0 t1) (angle t1 t2) ANGULAR_FUZZ))
(setq points (cons t1 points))
); if
); lambda
lst
(cdr (append lst (list (car lst))))
(cddr (append lst (list (car lst)) (list (cadr lst))))
); vl-every
); not
(setq lst points points nil)
); while
(if (= (vl-list-length lst) 3)
points
(progn
(vlr-beep-reaction)
(alert "error: invalid triangle selected.")
); progn
); if
); elim_cont_seg
(defun get_head_vertex (lst / angleAtVertices angle_sum ; local functions
dataL)
(defun angleAtVertices (/ qang) ; local function
(defun qang (a0 a1 / a2)
(if (> a0 a1)
(setq a2 (- a0 a1))
(setq a2 (- a1 a0))
)
(if (> a2 pi)
(- (* pi 2) a2)
a2
)
); qang
(mapcar
'(lambda (t0 t1 t2)
(cons (qang (angle t1 t0) (angle t1 t2)) (list t1))
)
lst
(cdr (append lst (list (car lst))))
(cddr (append lst (list (car lst)) (list (cadr lst))))
); mapcar
); angleAtVertices
(defun angle_sum ()
(apply
'+
(mapcar
'(lambda (d)
(car d)
)
dataL
); mapcar
); apply
); angle_sum
; here start (get_head_vertex)
(setq dataL (angleAtVertices))
(cond
((not (equal (angle_sum) pi ANGULAR_FUZZ))
(vlr-beep-reaction)
(alert "error: invalid triangle selected.")
); case
((equal (car (nth 0 dataL)) (car (nth 1 dataL)) ANGULAR_FUZZ)
(cadr (nth 2 dataL))
)
((equal (car (nth 0 dataL)) (car (nth 2 dataL)) ANGULAR_FUZZ)
(cadr (nth 1 dataL))
)
((equal (car (nth 1 dataL)) (car (nth 2 dataL)) ANGULAR_FUZZ)
(cadr (nth 0 dataL))
)
( t ; not isosceles triangle
(vlr-beep-reaction)
(alert "error: invalid triangle selected.")
)
); cond
); get_head_vertex
; position dimension line
(defun pos_dimlin (t0 t1 / ax cx ang0 ang1)
(setq ang0 (angle t0 t1))
(setq ax (/ (distance t0 t1) 2))
(setq cx (sqrt (+ (expt ax 2) (expt DL_OSET_DIST 2))))
(setq ang1 (atan (/ DL_OSET_DIST ax)))
(if (and
(> ang0 (* pi 0.5))
(< ang0 (* pi 1.5))
)
(polar t0 (+ ang0 ang1) cx)
(polar t0 (- ang0 ang1) cx)
); if
); pos_dimlin
; here start (c:cusdim)
(setvar "cmdecho" 0)
; declare some constants
(setq LINEAR_FUZZ 1e-3)
(setq ANGULAR_FUZZ 1e-5)
; dimension line offset distance
(setq DL_OSET_DIST (* (getvar "dimtxt") (getvar "dimscale") 4))
(if (and
(setq ss (ssget '((0 . "*polyline") (70 . 1)))) ; filter closed AcDb2dPolyline and\or AcDbPolyline
(= (sslength ss) 2) ; only 2 objects allowed
)
(if (and
(setq lst0 (elim_zero_seg (get_vertices (ssname ss 0))))
(setq lst1 (elim_cont_seg lst0))
(setq p0 (get_head_vertex lst1))
(setq lst0 (elim_zero_seg (get_vertices (ssname ss 1))))
(setq lst1 (elim_cont_seg lst0))
(setq p1 (get_head_vertex lst1))
)
(cond
((or
(equal (car p0) (car p1) LINEAR_FUZZ)
(equal (cadr p0) (cadr p1) LINEAR_FUZZ)
)
(command "._dimlinear" "_None" p0 "_None" p1 "_None" (pos_dimlin p0 p1))
); case
( t
(command "._dimaligned" "_None" p0 "_None" p1 "_None" pos_dimlin p0 p1))
)
); cond
); if
); if
(setvar "cmdecho" 1)
(princ)
); c:cusdim
@Anonymous wrote:
... to put a dimension i needed 3 point, so i get the 3rd point in the middle of the pt1 and pt2
….
.... ;GET MIDDLE POINT (PT3) (setq x (/ (+ (car pt1) (car pt2)) 2) y (/ (+ (cadr pt1) (cadr pt2)) 2) z (/ (+ (caddr pt1) (caddr pt2)) 2) pt3 (list x y z) ) ....
For that part, here's a more concise way to do it, without separate variables for each coordinate:
(setq pt3 (mapcar '/ (mapcar '+ pt1 pt2) '(2 2 2)))
The inner [second] (mapcar) function adds the coordinates in each direction of the two points together all in one operation, and the outer [first] one divides the values of those sums by 2 each.
Can't find what you're looking for? Ask the community or share your knowledge.