@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