Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Arc Length

17 REPLIES 17
SOLVED
Reply
Message 1 of 18
thavasi1982
6063 Views, 17 Replies

Arc Length

Dear all, Is there any way to retrive the arc length from Revision cloud and how can we identify that object is a Revision Cloud. Thanks in Advance STM
17 REPLIES 17
Message 2 of 18
Lee_Mac
in reply to: thavasi1982

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.

Message 3 of 18
Anonymous
in reply to: thavasi1982

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.

Message 4 of 18
Lee_Mac
in reply to: thavasi1982

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) )

 

Message 5 of 18
Kent1Cooper
in reply to: Lee_Mac


@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.]

Kent Cooper, AIA
Message 6 of 18
Kent1Cooper
in reply to: thavasi1982


@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.

Kent Cooper, AIA
Message 7 of 18
alanjt_
in reply to: Kent1Cooper

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))))

 

Message 8 of 18
Lee_Mac
in reply to: Kent1Cooper


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.

Message 9 of 18
Kent1Cooper
in reply to: Lee_Mac


@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.

Kent Cooper, AIA
Message 10 of 18
Lee_Mac
in reply to: thavasi1982

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))
)

 

Message 11 of 18
thavasi1982
in reply to: thavasi1982

Dear all, Soory for the delay Thanks for your reply. I got solution. Many thanks to all. STM
Message 12 of 18
Kent1Cooper
in reply to: Lee_Mac


@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.

Kent Cooper, AIA
Message 13 of 18
alanjt_
in reply to: Kent1Cooper

(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
            )
    )
  )
)

 

Message 14 of 18
Kent1Cooper
in reply to: alanjt_

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.

Kent Cooper, AIA
Message 15 of 18
alanjt_
in reply to: Kent1Cooper

🙂

Message 16 of 18
Lee_Mac
in reply to: Kent1Cooper


@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.

Message 17 of 18
Kent1Cooper
in reply to: Lee_Mac


@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?

Kent Cooper, AIA
Message 18 of 18
Lee_Mac
in reply to: Kent1Cooper


@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.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost