222 lines
8.9 KiB
Common Lisp
222 lines
8.9 KiB
Common Lisp
;;; PLDIET.lsp [command name: PLD]
|
|
;;; To put lightweight PolyLines on a DIET (remove excess vertices); usually
|
|
;;; used for contours with too many too-closely-spaced vertices.
|
|
;;; Concept from PVD routine [posted on AutoCAD Customization Discussion
|
|
;;; Group by oompa_l, July 2009] by Brian Hailey, added to by CAB, and
|
|
;;; WEED and WEED2 routines by Skyler Mills at Cadalyst CAD Tips [older
|
|
;;; routines for "heavy" Polylines that won't work on newer lightweight ones];
|
|
;;; simplified in entity data list processing, and enhanced in other ways [error
|
|
;;; handling, default values, join collinear segments beyond max. distance,
|
|
;;; limit to current space/tab, account for change in direction across 0 degrees,
|
|
;;; option to keep or eliminate arc segments] by Kent Cooper, August 2009.
|
|
;;; Last edited 28 August 2013
|
|
;
|
|
(defun C:PLD
|
|
(/ *error* cmde disttemp cidtemp arctemp plinc plsel pl
|
|
pldata ucschanged front 10to42 vinc verts vert1 vert2 vert3)
|
|
;
|
|
(defun *error* (errmsg)
|
|
(if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
|
|
(princ (strcat "\nError: " errmsg))
|
|
); end if
|
|
(if ucschanged (command "_.ucs" "_prev"))
|
|
; ^ i.e. don't go back unless routine reached UCS change but didn't change back
|
|
(command "_.undo" "_end")
|
|
(setvar 'cmdecho cmde)
|
|
); end defun - *error*
|
|
;
|
|
(setq cmde (getvar 'cmdecho))
|
|
(setvar 'cmdecho 0)
|
|
(command "_.undo" "_begin")
|
|
(setq
|
|
disttemp
|
|
(getdist
|
|
(strcat
|
|
"\nMaximum distance between non-collinear vertices to straighten"
|
|
(if *distmax* (strcat " <" (rtos *distmax* 2 2) ">") ""); default only if not first use
|
|
": "
|
|
); end strcat
|
|
); end getdist & disttemp
|
|
*distmax*
|
|
(cond
|
|
(disttemp); user entered number or picked distance
|
|
(*distmax*); otherwise, user hit Enter - keep value
|
|
); end cond & *distmax*
|
|
cidtemp
|
|
(getangle
|
|
(strcat
|
|
"\nMaximum change in direction to straighten"
|
|
(strcat ; offer prior choice if not first use; otherwise 15 degrees
|
|
" <"
|
|
(if *cidmax* (angtos *cidmax*) (angtos (/ pi 12)))
|
|
">"
|
|
); end strcat
|
|
": "
|
|
); end strcat
|
|
); end getdist & cidtemp
|
|
*cidmax*
|
|
(cond
|
|
(cidtemp); user entered number or picked angle
|
|
(*cidmax*); Enter with prior value set - use that
|
|
((/ pi 12)); otherwise [Enter on first use] - 15 degrees
|
|
); end cond & *cidmax*
|
|
plinc 0 ; incrementer through selection set of Polylines
|
|
); end setq
|
|
(initget "Retain Straighten")
|
|
(setq
|
|
arctemp
|
|
(getkword
|
|
(strcat
|
|
"\nRetain or Straighten arc segments [R/S] <"
|
|
(if *arcstr* (substr *arcstr* 1 1) "S"); at first use, S default; otherwise, prior choice
|
|
">: "
|
|
); end strcat
|
|
); end getkword
|
|
*arcstr*
|
|
(cond
|
|
(arctemp); if User typed something, use it
|
|
(*arcstr*); if Enter and there's a prior choice, keep that
|
|
("Straighten"); otherwise [Enter on first use], Straighten
|
|
); end cond & *arcstr*
|
|
); end setq
|
|
;
|
|
(prompt "\nSelect LWPolylines to put on a diet, or press Enter to select all: ")
|
|
(cond
|
|
((setq plsel (ssget '((0 . "LWPOLYLINE"))))); user-selected Polylines
|
|
((setq plsel (ssget "X" (list '(0 . "LWPOLYLINE") (cons 410 (getvar 'ctab))))))
|
|
; all Polylines [in current space/tab only]
|
|
); end cond
|
|
;
|
|
(repeat (sslength plsel)
|
|
(setq pl (ssname plsel plinc))
|
|
(while
|
|
(equal (vlax-curve-getStartPoint pl) (vlax-curve-getPointAtParam pl 1) 1e-6)
|
|
; to correct for possibility that more than one vertices at beginning coincide,
|
|
; in which case Pline does not define a CS under UCS OBject, causing error
|
|
(command "_.pedit" pl "_edit" "_straighten" "" "" "_go" "_exit" "")
|
|
); while
|
|
(setq pldata (entget pl))
|
|
(if (/= (cdr (last pldata)) (trans '(0 0 1) 1 0)); extr. direction not parallel current CS
|
|
; for correct angle & distance calculations [projected onto current construction
|
|
; plane], since 10-code entries for LWPolylines are only 2D points:
|
|
(progn
|
|
(command "_.ucs" "_new" "_object" pl) ; set UCS to match object
|
|
(setq ucschanged T) ; marker for *error* to reset UCS if routine doesn't
|
|
); end progn
|
|
); end if
|
|
(setq
|
|
front ; list of "front end" [pre-vertices] entries, minus entity names & handle
|
|
(vl-remove-if
|
|
'(lambda (x)
|
|
(member (car x) '(-1 330 5 10 40 41 42 210))
|
|
); end lambda
|
|
pldata
|
|
); end removal & front
|
|
10to42 ; list of all code 10, 40, 41, 42 entries only
|
|
(vl-remove-if-not
|
|
'(lambda (x)
|
|
(member (car x) '(10 40 41 42))
|
|
); end lambda
|
|
pldata
|
|
); end removal & 10to42
|
|
vinc (/ (length 10to42) 4); incrementer for vertices within each Polyline
|
|
verts nil ; eliminate from previous Polyline [if any]
|
|
); end setq
|
|
(if (= *arcstr* "Straighten")
|
|
(progn
|
|
(setq bulges ; find any bulge factors
|
|
(vl-remove-if-not
|
|
'(lambda (x)
|
|
(and
|
|
(= (car x) 42)
|
|
(/= (cdr x) 0.0)
|
|
); end and
|
|
); end lambda
|
|
10to42
|
|
); end removal & bulges
|
|
); end setq
|
|
(foreach x bulges (setq 10to42 (subst '(42 . 0.0) x 10to42)))
|
|
; straighten all arc segments to line segments
|
|
); end progn
|
|
); end if
|
|
(repeat vinc
|
|
(setq
|
|
verts ; sub-group list: separate list of four entries for each vertex
|
|
(cons
|
|
(list
|
|
(nth (- (* vinc 4) 4) 10to42)
|
|
(nth (- (* vinc 4) 3) 10to42)
|
|
(nth (- (* vinc 4) 2) 10to42)
|
|
(nth (1- (* vinc 4)) 10to42)
|
|
); end list
|
|
verts
|
|
); end cons & verts
|
|
vinc (1- vinc) ; will be 0 at end
|
|
); end setq
|
|
); end repeat
|
|
(while (nth (+ vinc 2) verts); still at least 2 more vertices
|
|
(if
|
|
(or ; only possible if chose to Retain arc segments
|
|
(/= (cdr (assoc 42 (nth vinc verts))) 0.0); next segment is arc
|
|
(/= (cdr (assoc 42 (nth (1+ vinc) verts))) 0.0); following segment is arc
|
|
); end or
|
|
(setq vinc (1+ vinc)); then - don't straighten from here; move to next
|
|
(progn ; else - analyze from current vertex
|
|
(setq
|
|
vert1 (cdar (nth vinc verts)) ; point-list location of current vertex
|
|
vert2 (cdar (nth (1+ vinc) verts)); of next one
|
|
vert3 (cdar (nth (+ vinc 2) verts)); of one after that
|
|
ang1 (angle vert1 vert2)
|
|
ang2 (angle vert2 vert3)
|
|
); end setq
|
|
(if
|
|
(or
|
|
(equal ang1 ang2 0.0001); collinear, ignoring distance
|
|
(and
|
|
(<= (distance vert1 vert3) *distmax*)
|
|
; straightens if direct distance from current vertex to two vertices later is
|
|
; less than or equal to maximum; if preferred to compare distance along
|
|
; Polyline through intermediate vertex, replace above line with this:
|
|
; (<= (+ (distance vert1 vert2) (distance vert2 vert3)) *distmax*)
|
|
(<=
|
|
(if (> (abs (- ang1 ang2)) pi); if difference > 180 degrees
|
|
(+ (min ang1 ang2) (- (* pi 2) (max ang1 ang2)))
|
|
; then - compensate for change in direction crossing 0 degrees
|
|
(abs (- ang1 ang2)); else - size of difference
|
|
); end if
|
|
*cidmax*
|
|
); end <=
|
|
); end and
|
|
); end or
|
|
(setq verts (vl-remove (nth (1+ vinc) verts) verts))
|
|
; then - remove next vertext, stay at current vertex for next comparison
|
|
(setq vinc (1+ vinc)); else - leave next vertex, move to it as new base
|
|
); end if - distance & change in direction analysis
|
|
); end progn - line segments
|
|
); end if - arc segment check
|
|
); end while - working through vertices
|
|
(setq
|
|
front (subst (cons 90 (length verts)) (assoc 90 front) front)
|
|
; update quantity of vertices for front end
|
|
10to42 nil ; clear original set
|
|
); end setq
|
|
(foreach x verts (setq 10to42 (append 10to42 x)))
|
|
; un-group four-list vertex sub-lists back to one list of all 10, 40, 41, 42 entries
|
|
(setq pldata (append front 10to42 (list (last pldata))))
|
|
; put front end, vertex entries and extrusion direction back together
|
|
(entmake pldata)
|
|
(entdel pl); remove original
|
|
(setq plinc (1+ plinc)); go on to next Polyline
|
|
(if ucschanged
|
|
(progn
|
|
(command "_.ucs" "_prev")
|
|
(setq ucschanged nil) ; eliminate UCS reset in *error* since routine did it already
|
|
); end progn
|
|
); end if - UCS reset
|
|
); end repeat - stepping through set of Polylines
|
|
(command "_.undo" "_end")
|
|
(setvar 'cmdecho cmde)
|
|
(princ)
|
|
); end defun - PLD
|
|
(prompt "\nType PLD to put PolyLines on a Diet.")
|