Author Topic: Segmented Arcs in a closed Polyline  (Read 2154 times)

0 Members and 1 Guest are viewing this topic.

RAYAKMAL

  • Guest
Segmented Arcs in a closed Polyline
« on: February 26, 2015, 12:10:59 AM »
My intention is to convert all arcs-segments in a polyline into continuous segmented lines.
Here's my code. It works, except it can't handle a closed polyline where the last segment has a bulge in it.
Any help or If someone has a better solution using Visual Lisp that I can use, is greatly appreciated. 

Regards,
Rakaryan

Code: [Select]
(defun c:VIS-PARCEL-SEGPOLY ( )

  (if (setq ent1 (entsel "\nSelect Polyline: "))
      (progn
         (setq ename (car ent1))
         (setq etype (dxf-code 0 ename))
         (setq okboss (member etype '( "POLYLINE" )))   

         (if okboss
             (progn
                (setq pblst (getpb-list ename)) ; List of vertex n bulge
                (setq lgth  (length pblst))
                (setq n 0)
                (setq vrtx_lst '())

                (setq pt1lst (nth n pblst))
                (setq ptawal (car  pt1lst))

                (while (< n (- lgth 1))
                          (setq pt1lst (nth n pblst)) ; pt1 coordinates & bulge
                          (setq pt2lst (nth (+ n 1) pblst)) ; pt2 coordinates & bulge
                          (setq pt1   (car  pt1lst))   ; pt1 Coordinates
                          (setq pt2   (car  pt2lst))   ; pt2 Coordinates

                          (setq bulg1 (cadr pt1lst))   ; pt1 Bulge                 

                          ;; Calculate Center and Radius of Arc.
                          (cond ( (= bulg1 0.0) ; No Bulge
                                  (setq vrtx_lst (append vrtx_lst (list pt1)))
                                )
                                ( (/= bulg1 0.0)
                                  ;; Find Radius n Center of Arc
                                  (setq vrtx_lst (append vrtx_lst (list pt1)))
                                  ;; Find parameters of ARC
                                  (setq radiucentr (bul2arc pt1 pt2 bulg1))
                                  (setq radiu      (car  radiucentr))
                                  (setq centr      (cadr radiucentr))
                                  (setq chord      (distance pt1 pt2))

                                  (setq lc         (abs (* radiu 4.0 (atan bulg1))))


                                  ;; Notes: (FIX 0.5) = 0

                                  ;;
                                  (if (= 0.0 (fix lc))
                                      (setq lc_intgr (/ lc 3))
                                      (setq lc_intgr (* (fix lc) 3))
                                  )

                                  (setq delta_ang (* 2 (asin (/ (* 0.5 chord) radiu))))
                                  (setq d_ang (/ delta_ang lc_intgr))
                                  (setq idx2 1)
                                  (setq cur_ang (* d_ang idx2))

                                  (while (< cur_ang delta_ang)
                                     (if (< bulg1 0.0)
                                        (setq newvrtx (polar centr (- (angle centr pt1) cur_ang) radiu))
                                        (setq newvrtx (polar centr (+ (angle centr pt1) cur_ang) radiu))
                                     )
                                     ;; Add new Vertex(es)
                                     (setq vrtx_lst (append vrtx_lst (list newvrtx)))
                                     (setq idx2 (+ idx2 1))
                                     (setq cur_ang (* d_ang idx2))
                                  ); end of while
                                )
                          ); end of cond
                          (setq n (+ n 1))
                       ); end of while

                       (setq vrtx_lst (append vrtx_lst (list pt2)))
                       (if (vlax-curve-isClosed ename) ;; Closed Polyline?
                          (setq vrtx_lst (append vrtx_lst (list ptawal)))
                       )
                       (command "pline")
                       (foreach n vrtx_lst (command n))                     
                       (command)
                       (command "erase" ename "")

             );progn
         );end if

      );progn
  );end if
  (princ)

)

;;
;; REINI URBAN & Sergei M. Komarov
;;
;; Function: BUL2ARC                                                          º
;; Purpose : Calculates and return Radius R and Centerpoint C of              º
;;           an ARC Segmen with startpoint P1, endpoint P2 and bulge Bul      º
;; Example :                                                                  º
;;
;;     bulge = +-tan(ang/4). *Very important!!!* If the arc segment of a
;;                            polyline is drawn counterclockwise, the bulge
;;                            is positive. If it's drawn clockwise - the bulge
;;                            is negative!
;;                            +Bulge = left turn
;;                            -Bulge = right turn
;;
;;     angle = 4*atan(abs(bulge))
;;     bulge = +-(2*altitude) / chord. (+ CCW, - CW as mentioned above)
;;
(defun BUL2ARC (P1 P2 BUL / a b c h r chord)
   (setq chord (distance p1 p2)
            h (* chord 0.5 (abs bul))
            r (/ (* 0.5 chord)(sin (* 2 (atan (abs bul)))))
            b (angle p1 p2)
            a (atan (/ (- r h)(* 0.5 chord)))
            a (if (> bul 0)(+ a b)(- b a))
            c (polar p1 a r)
   )
   (list r c)
)

;; ----------------------------------------------------------------------------

;;
;; Function: GETVERTS                                                         º
;; Purpose : Extracting Polyline Vertices                                     º
;;           Extract the start and end point of each line in a polyline       º
;; Example : getverts (ename)                                                 º
;;

(defun getverts ( en )
   (get 10 (cdr (edlgetent en)))
)
;; ----------------------------------------------------------------------------

;;Or let's say you want to get the bulges too,
;;and create list of points and bulges, PB-list, so
;;
;; Function: GETVERTS                                                         º
;; Purpose : Extracting Polyline Vertices and Bulges                          º
;; Example : getpb-list (ename)                                               º
;;

(defun getpb-list ( en )
   (get '(10 42) (cdr (edlgetent en)))
)
;; ----------------------------------------------------------------------------

;;Look for those "miraculous" GET and EDLGETENT functions

(defun edlgetent( e / d edl)
   (setq d (entget e) edl (list d))
   (if (= 1 (get 66 d)) ;; entities follow
       (while (/= "SEQEND" (get 0 (setq d (entget (setq e (entnext e))))))
          (setq edl (cons d edl))
       )
   )
   (reverse edl) ;; list of entget's Entity Data Lists ;; {without SEQEND in it}
)

;;Now, GET is real tricky. Basically speaking, it's just the
;;regular (cdr (assoc ...), BUT because of some recursion it preserves the list
;;structure of it's argument(s). You may even specify your keys in whatever list
;;structure you want, like (get '(2 10 (40 41 42) 50) list-of-entgets-of blocks),
;;for example.
;;General GET{ key(s) list(s) } function

(defun get (k l)
   (if (atom (caar l)) ;; l is ASSOC'able list
       (cond ;; use this list
             ((atom k) ;; k is a key
              (cdr(Assoc k l))
             )
             ((and (cdr k)(atom (cdr k))) ;; '(0 . 8) -> ("ENTITY" . "LAYER")
              (cons (get (car k) l) (cdr (assoc (cdr k) l)))
             )
             (T ;; k is a list of smthg - get inside
              (mapcar '(lambda(subk)(get subk l)) k)
             )
       )
       ;; else - get inside list
       (mapcar '(lambda(subl)(get k subl)) l)
    )
)
;; ----------------------------------------------------------------------------

;;
;; Function: ACOS ASIN ACSC ASEC ACOT etc etc..[TRIGONOMETRIC FUNCTIONS]      º
;; Example : (setq A (ASIN 0.5))                                              º
;; Return  : 0.523598 which is in Radians.                                    º
;;
(defun ACOS (X) ;Inverse cosine
  (- (/ pi 2.0) (atan (/ X (sqrt (- 1.0 (* X X))))))
)
(defun ASIN (X) ; Inverse sine
  (atan (/ X (sqrt (- 1.0 (* X X)))))
)
(defun ACSC (X) ; Inverse cosecant
  (+ (atan (/ 1.0 (sqrt (- (* X X) 1.0)))) (* (/ pi 2.0)
    (- (if (< X 0) (- 1.0) (+ 1.0)) 1.0)))
)
(defun ASEC (X) ; Inverse secant
  (+ (atan (sqrt (- (* X X) 1.0))) (* (/ pi 2.0)
    (- (if (< X 0) (- 1.0) (+ 1.0)) 1.0)))
)
(defun ACOT (X) ; Inverse cotangent
  (- (/ pi 2.0) (atan X))
)
(defun SEC (X) ; Secant
  (/ 1.0 (cos X))
)
(defun CSC (X) ; Cosecant
  (/ 1.0 (sin X))
)
(defun TAN (X) ; Tangent
  (/ (sin X) (cos X))
)
(defun COT (X) ; Cotangent
  (/ (cos X) (sin X))
)

;;o~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~o
;; FIND DXF GROUP
;;o~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~o

(defun dxf-code (code enm /) (cdr (assoc code (entget enm))))

ribarm

  • Gator
  • Posts: 3265
  • Marko Ribar, architect
Re: Segmented Arcs in a closed Polyline
« Reply #1 on: February 26, 2015, 07:10:48 AM »
Convert your 2d heavy polyline to LWPOLYLINE and apply : "lws-arcs-seg.lsp" or "lws-arcs-seg-d.lsp" from PLINETOOLS posted here :
http://www.cadtutor.net/forum/showthread.php?67924-Draw-polyline-along-with-2-or-more-adjacent-closed-polylines/page3&p=#25

HTH, M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Segmented Arcs in a closed Polyline
« Reply #2 on: February 26, 2015, 09:13:55 AM »
code for 2dPolyline and lwpolyline:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:test (/ o i)
  2.   (setq o (vlax-ename->vla-object (car (entsel "\nSelect Polyline: "))))
  3.   (repeat (fix (setq i (vlax-curve-getEndParam o))) (vla-setbulge o (setq i (1- i)) 0.0))
  4.   (princ)
  5. )

ronjonp

  • Needs a day job
  • Posts: 7527
Re: Segmented Arcs in a closed Polyline
« Reply #3 on: February 26, 2015, 09:18:18 AM »
Perhaps THIS as well.

You should also try getting into the habit of localizing your variables:

Code: [Select]
(defun c:vis-parcel-segpoly (/         bulg1    centr   chord    cur_ang  delta_ang
              d_ang    ename    ent1   etype    idx2     lc      lc_intgr
              lgth     n          newvrtx   okboss    pblst     pt1      pt1lst
              pt2      pt2lst   ptawal   radiu    radiucentr      vrtx_lst
             )
.....
« Last Edit: February 26, 2015, 09:31:27 AM by ronjonp »

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

RAYAKMAL

  • Guest
Re: Segmented Arcs in a closed Polyline
« Reply #4 on: February 26, 2015, 10:03:35 PM »
Perhaps THIS as well.

You should also try getting into the habit of localizing your variables:

Code: [Select]
(defun c:vis-parcel-segpoly (/         bulg1    centr   chord    cur_ang  delta_ang
              d_ang    ename    ent1   etype    idx2     lc      lc_intgr
              lgth     n          newvrtx   okboss    pblst     pt1      pt1lst
              pt2      pt2lst   ptawal   radiu    radiucentr      vrtx_lst
             )
.....

@Marko Ribar        Thanks, for the extensive library of codes.

@ElpanovEvgeniy  Thanks, I learned new things from your code

@Ronjonp              Thanks, I finally use your suggestion. I use 'TracePline" from JoeBurke's code
And your suggestion regarding localizing variables, you are correct.
I usually make some variables local, set error traps etc.
That's what I learn from Tony Tanzillo's article about "Clean and Robust programming" in Cadence Magazine years ago (circa 1995).
Since I only use notepad, sometimes I leave all the variables as it is during debugging.
Thanks again to you all.


Regards


Rakaryan