Solved! Go to Solution.
Solved by Lee_Mac. Go to Solution.
Solved by Lee_Mac. Go to Solution.
Solved by alanjt_. Go to Solution.
Solved by Lee_Mac. Go to Solution.
Since the arcs in a Revision Cloud will always include a 110 degree angle, you can use the following to obtain a SelectionSet of only Revision Clouds:
;; Select RevClouds - Lee Mac 2011 (defun LM:SelectRevClouds ( / bulge fuzz ) (setq bulge (/ (sin (/ (* 11. pi) 72.)) (cos (/ (* 11. pi) 72.))) fuzz 0.0001 ) (ssget "_X" (list '(0 . "LWPOLYLINE") '(-4 . "<OR") '(-4 . "<AND") '(-4 . "<NOT") '(-4 . "<OR") '(-4 . ">=") (cons 42 (+ bulge fuzz)) '(-4 . "<=") (cons 42 (- bulge fuzz)) '(-4 . "OR>") '(-4 . "NOT>") '(-4 . "AND>") '(-4 . "<AND") '(-4 . "<NOT") '(-4 . "<OR") '(-4 . ">=") (cons 42 (+ (- bulge) fuzz)) '(-4 . "<=") (cons 42 (- (- bulge) fuzz)) '(-4 . "OR>") '(-4 . "NOT>") '(-4 . "AND>") '(-4 . "OR>") ) ) )
With regards to determining the Arc Length, this may vary for each vertex pair - for this task, look into my Bulge Conversion functions.
If you do a dump on the object, you can get the length at the Length (RO) placeholder. I am assuming you mean the perimeter length. If you want the individual length, then I would follow Lee's suggestion.
Or a predicate function for use with a single selection:
(defun LM:RevCloud-p ( ent / bulg elst fuzz ) (setq elst (entget ent) bulg (/ (sin (/ (* 11. pi) 72.)) (cos (/ (* 11. pi) 72.))) fuzz 1e-8 ) (apply 'and (cons (eq "LWPOLYLINE" (cdr (assoc 0 elst))) (mapcar (function (lambda ( pair ) (if (= 42 (car pair)) (equal bulg (abs (cdr pair)) fuzz) t ) ) ) elst ) ) ) )
(defun c:test ( / ent ) (while (progn (setvar 'ERRNO 0) (setq ent (car (entsel "\nSelect RevCloud: "))) (cond ( (= 7 (getvar 'ERRNO)) (princ "\nMissed, try again.") ) ( (eq 'ENAME (type ent)) (if (null (LM:RevCloud-p ent)) (princ "\nObject is not a RevCloud.") ) ) ) ) ) (princ) )
@Lee_Mac wrote:Since the arcs in a Revision Cloud will always include a 110 degree angle, you can use the following to obtain a SelectionSet of only Revision Clouds:
....
...with the "grain of salt" that they would have to be Revision Clouds that had not been altered after they were put in.
The last arc segment of a Revcloud is often different enough from the others that I will adjust a few vertex locations to even them out a little. Or there's a stretch of arc segments going through a tight area, and I grab some grips and flatten them a little. Or I break a piece out of one for some reason, and not always at vertices. There are lots of things that can happen to Revclouds that would cause a check on the arc included angles to not recognize one.
I haven't tried your code for one other thing that I suspect it will miss on, even if all the segments are arcs at the right included angle. In a Revcloud that is not closed, the 42-code entry bulge factor associated with the last vertex is 0, not the 0.520567 that all the rest have. [And which you could use plain, in lieu of the trig calculation, considering the size of fuzz factor you have there.]
@thavasi1982 wrote:
Dear all, Is there any way to retrive the arc length from Revision cloud ....
As Lee mentioned, they're not always the same, but if getting the length of the first arc is good enough, you can do this to get the straight-line [chord] length between vertices [which is what I think AutoCAD uses]:
(distance
(vlax-curve-getStartPoint thePolyline)
(vlax-curve-getPointAtParam thePolyline 1)
)
or this, if you want the length along the curve of the arc:
(vlax-curve-getDistAtParam thePolyline 1)
You could also get the distances of several [parameters 0 to 1, 1 to 2, 2 to 3, etc.] and average them.
For the actual length, you could use:
(if (setq e (car (entsel))) (vlax-curve-getDistAtParam e (vlax-curve-getEndParam e)) )
For the chord distance of each LWPolyline segment, you could use:
(defun _LWPolylineSegmentChordLengths (pline / data lst) (foreach x (setq data (entget pline)) (if (eq (car x) 10) (setq lst (cons (cdr x) lst)) ) ) (mapcar 'distance (reverse lst) (if (eq (logand 1 (cdr (assoc 70 data))) 1) (append (cdr (reverse lst)) (list (last lst))) (cdr (reverse lst)) ) ) )
And if you wanted to get a total distance, just add the values together:
(apply '+ (_LWPolylineSegmentChordLengths (car (entsel))))
Kent1Cooper wrote:...with the "grain of salt" that they would have to be Revision Clouds that had not been altered after they were put in.
For sure - if the Revision Clouds have been modified it would be nigh impossible to determine what constitutes a Revision Cloud over any other LWPolyline.
@Lee_Mac wrote:....For sure - if the Revision Clouds have been modified it would be nigh impossible to determine what constitutes a Revision Cloud over any other LWPolyline.
You could go partway by checking that there are no (42 . 0.0) entries if the LWPolyline is closed, or other than the last one if it isn't closed [i.e. all segments are arcs], and with all (cdr (assoc 42)) entries having the same sign [i.e. all bulges in the same direction], and if you always put them on the same Layer, check for that. But there could still be LWPolylines that meet those criteria but weren't drawn as Revision Clouds.
Here's another Vanilla AutoLISP function to return the length of each LWPolyline segment:
(defun _PolySegmentLengths ( entity / _lwvertices ) (defun _lwvertices ( e ) (if (setq e (member (assoc 10 e) e)) (cons (cons (cdr (assoc 10 e)) (cdr (assoc 42 e)) ) (_lwvertices (cdr e)) ) ) ) ( (lambda ( data ) (mapcar (function (lambda ( a b ) (if (zerop (cdr a)) (distance (car a) (car b)) (* (/ (distance (car a) (car b)) (* 2.0 (sin (* 2.0 (atan (cdr a)))))) (* (atan (cdr a)) 4.0) ) ) ) ) data (if (= 1 (logand 1 (cdr (assoc 70 (entget entity))))) (append (cdr data) (list (car data))) (cdr data) ) ) ) (_lwvertices (entget entity)) ) )
Call it with the Entity Name of the LWPolyline:
(defun c:test ( / e ) (while (progn (princ "\nSelect LWPolyline...") (null (setq e (ssget "_+.:E:S" '((0 . "LWPOLYLINE"))))) ) ) (_PolySegmentLengths (ssname e 0)) )
@Lee_Mac wrote:Here's another Vanilla AutoLISP function to return the length of each LWPolyline segment:
....
(if (zerop (cdr a))
(distance (car a) (car b))
(* (/ (distance (car a) (car b)) (* 2.0 (sin (* 2.0 (atan (cdr a))))))(* (atan (cdr a)) 4.0)
)
....
The same can be done without needing to look at whether bulge factors are 0, or do trigonometric calculations for a multiplier of the straight-line distance between vertices [or even pay the least attention to bulge factors]. AutoLISP can find lengths along curves for you:
(vl-load-com)
(defun PSL ; = Polyline Segment Lengths
(ent / pardist edata inc); could add seglengths to localized list
(defun pardist (par)
(vlax-curve-getDistAtParam ent par)
); defun
(setq
edata (entget ent)
inc (1- (cdr (assoc 90 edata))); one less than # of vertices
); setq
(if (= (logand (cdr (assoc 70 edata)) 1) 1); closed
(setq seglengths ; then - start with end segment length
(list
(-
(vlax-curve-getDistAtParam ent (vlax-curve-getEndParam ent)); overall length
(pardist inc); length to last vertex
); -
); list
); setq
(setq seglengths nil); else - wipe out if previous use [omit this line if localized variable]
); if
(repeat inc
(setq seglengths
(cons (- (pardist inc) (pardist (setq inc (1- inc)))) seglengths)
); setq
); repeat
); defun
Use it similarly:
(psl AnEntityName)
Whether you localize the seglengths variable or not would depend on whether you want to keep the list of lengths around for further use, or can just use it as returned by the function.
(defun AT:GetLWPolylineSegmentDistances (e / p l) ;; Return each LWPolyline segment distance ;; e - valid LWPolyline ;; Alan J. Thompson, 11.07.11 (repeat (setq p (fix (vlax-curve-getEndParam e))) (setq l (cons (- (vlax-curve-getDistAtParam e p) (vlax-curve-getDistAtParam e (setq p (1- p))) ) l ) ) ) )
Yeah.... I was thinking somehow that the number of vertices was going to be the most the number of parameters could be, forgetting that for a closed one, it has that last parameter number beyond the last vertex's parameter number. [I should have thought of that, since I've done things that work with places along that last closing segment using parameter numbers higher than that of the last vertex.] That eliminates the need to treat it differently if it's closed than if it's open. Very concise.
@Kent1Cooper wrote:
@Lee_Mac wrote:Here's another Vanilla AutoLISP function to return the length of each LWPolyline segment:
....
(if (zerop (cdr a))
(distance (car a) (car b))
(* (/ (distance (car a) (car b)) (* 2.0 (sin (* 2.0 (atan (cdr a))))))(* (atan (cdr a)) 4.0)
)
....
The same can be done without needing to look at whether bulge factors are 0, or do trigonometric calculations for a multiplier of the straight-line distance between vertices [or even pay the least attention to bulge factors].
I think you missed the point of my code Kent, I wrote the function to solely use Vanilla AutoLISP functions, as stated in my previous post.
@Lee_Mac wrote:....
I think you missed the point of my code Kent, I wrote the function to solely use Vanilla AutoLISP functions, as stated in my previous post.
I'm aware of situations in which you can't use (command) functions [e.g. in reactors], or where you need to use something like scripts or macros instead of AutoLISP [e.g. for users of AutoCAD Lite]. But are there situations where it's necessary to use vanilla AutoLISP rather than more flavorful varieties?
@Kent1Cooper wrote:
@Lee_Mac wrote:....
I think you missed the point of my code Kent, I wrote the function to solely use Vanilla AutoLISP functions, as stated in my previous post.
I'm aware of situations in which you can't use (command) functions [e.g. in reactors], or where you need to use something like scripts or macros instead of AutoLISP [e.g. for users of AutoCAD Lite]. But are there situations where it's necessary to use vanilla AutoLISP rather than more flavorful varieties?
AutoLISP for Mac could be one such situation; but for me, its more the enjoyment of the challenge of creating a function solely restricted to Vanilla; the 'curve' functions make these kind of tasks a walk in the park, so it's nice to exercise the grey matter once in a while.