Author Topic: Outline of a variable width lwpolyline  (Read 3768 times)

0 Members and 1 Guest are viewing this topic.

hmspe

  • Bull Frog
  • Posts: 362
Outline of a variable width lwpolyline
« on: September 05, 2010, 11:43:51 AM »
I have several blocks that use variable width lwpolys for arrowheads.  I need to create outlines of the arrowheads.  Looking to see if anyone has a routine that will draw an outline of a variable width polyline before I "reinvent the wheel".  Thanks in advance.
"Science is the belief in the ignorance of experts." - Richard Feynman

LE3

  • Guest
Re: Outline of a variable width lwpolyline
« Reply #1 on: September 05, 2010, 01:10:36 PM »
This one:
FILLMODE=0
and call Regen

hmspe

  • Bull Frog
  • Posts: 362
Re: Outline of a variable width lwpolyline
« Reply #2 on: September 05, 2010, 08:36:06 PM »
This one:
FILLMODE=0
and call Regen
Thanks, but I'm not sure that approach will work for what I'm trying to do.  I only have one entity to convert when I run the function, but I could have many in the drawing.  That means resetting fillmode and running regen a second time.  The intention for the function is to create an offset outline of a block.  The outline will be used to trim lines that cross the block.  Two regens will probably make the function too slow to be useful.

"Science is the belief in the ignorance of experts." - Richard Feynman

LE3

  • Guest
Re: Outline of a variable width lwpolyline
« Reply #3 on: September 06, 2010, 10:35:00 AM »
Now I am confused... post an image of the end result.
:)

Thanks, but I'm not sure that approach will work for what I'm trying to do.  I only have one entity to convert when I run the function, but I could have many in the drawing.  That means resetting fillmode and running regen a second time.  The intention for the function is to create an offset outline of a block.  The outline will be used to trim lines that cross the block.  Two regens will probably make the function too slow to be useful.

David Bethel

  • Swamp Rat
  • Posts: 656
Re: Outline of a variable width lwpolyline
« Reply #4 on: September 06, 2010, 01:51:01 PM »
If the original doesn't include any arc segments, I'd reconstruct entity using traces. It makes autocad do all of the math.  I'm lazy at heart on labor day.  -David
R12 Dos - A2K

hmspe

  • Bull Frog
  • Posts: 362
Re: Outline of a variable width lwpolyline
« Reply #5 on: September 07, 2010, 01:54:17 AM »
Thanks for the suggestions.  I've been playing around with various ideas and have the code below so far.  Still very much a work in progress.  Very little commenting, and variables are not declared yet.  I started with code from Alan Thompson for outlines of non-tapered polylines, although there's not a lot left from the original.  This code works fairly well for non-closed polylines, including tapered segments and arc segments.  Code needs to be added to join the segments and to handle start/end for closed polylines.

As to what started this, please see the attached concept drawing (saved down to 2004).  I do electrical, and I sometimes need to trim lines that cross blocks.  In the drawing the left symbol is a typical home run block.  The arrowhead is a variable width polyline, so to create an offset boundary to trim lines on I first need to explode the block to have access to the arrowhead,  then create an outline of the arrowhead (second symbol).  After that, offset all segments and draw circles at all line endpoints (third symbol).  Finally, run External Contour of Objects or something similar to create the offset outline (fourth symbol).  All the temporary linework gets drawn on a dedicated layer to make cleanup easy.  The code here is just for getting the outline of any component that is a polyline with width > 0.

Always open to suggestions....

Code: [Select]
(defun c:Test (/ selected_polyline Pt Pobj polyline_entity polyline_type data_list VertexPt PtListIndex StWd EndWd PolyList OldIndex StPos counter
                        tmpList ShouldClose)

  (defun ChangeOldStyle (Ent / Pent counter polyline_entity PolyInfoList StPos start_point ShouldClose)
    (setq Pent Ent)
    (setq counter 0)
    (while
      (and (setq Ent (entnext Ent))
            (setq polyline_entity (entget Ent))
            (= (cdr (assoc 0 polyline_entity)) "VERTEX")
      )
      (setq PolyInfoList
        (append PolyInfoList (list (assoc 10 polyline_entity))
                                   (list (assoc 40 polyline_entity))
                                   (list (assoc 41 polyline_entity))
                                   (list (assoc 42 polyline_entity))
                             )
        )
        (if (equal counter 0)
          (setq start_point (cdr (assoc 10 polyline_entity)))
        )
        (setq counter (1+ counter))
      )
      PolyInfoList
    )

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  (if (and (setq selected_polyline (entsel "\n Select polyline: "))
;           (setq Pt (getpoint "\n Select point on polyline: "))
           (setq polyline_entity (entget (car selected_polyline)))
           (wcmatch (setq polyline_type (cdr (assoc 0 polyline_entity))) "*POLYLINE")
;           (setq counter -4)
      )
    (progn
      (if (= polyline_type "POLYLINE")                                         ; convert to LWPOLYLINE if necessary
        (setq data_list (ChangeOldStyle (car selected_polyline)))
        (progn
          (foreach x polyline_entity
            (if (member (car x) '(10 42 40 41))                                ; get points, widths, and bulges
              (setq data_list (cons x data_list))
            )
          )
          (if (and (= (rem (cdr (assoc 70 polyline_entity)) 2) 1)              ; true if closed
                   (not (equal (nth 3 data_list) (last data_list)))            ; test for start point = end point
              )
            (setq data_list (cons (last data_list) data_list)                  ; add end point if necessary
                  data_list (cons (cons 40 0) data_list)
                  data_list (cons (cons 41 0) data_list)
                  data_list (cons (cons 42 0) data_list)
            )
          )
          (setq data_list (reverse data_list))
        )
      )
      (if data_list
        (progn
          (setq counter 0)
          (setq first nil)
          (setq data_length (- (length data_list) 6))
          (setq data_length2 (- (length data_list) 8))
          (while (<= counter data_length)                                      ; loop through data
            (setq start_point (cdr (nth counter data_list)))
            (setq end_point (cdr (nth (+ 4 counter) data_list)))
            (setq start_width (/ (cdr (nth (+ 1 counter) data_list)) 2.0))
            (setq end_width (/ (cdr (nth (+ 2 counter) data_list)) 2.0))
            (setq bulge (cdr (nth (+ 3 counter) data_list)))
            (if (> (abs bulge) 0.0)                                                    ; arc segments have budge > 0
              (progn
                (setq half_angle (* 2 (atan bulge)))
                (setq center_direction ((if (< bulge 0) - +) (- (angle start_point end_point) half_angle) (/ pi 2)))
                (setq radius (abs (/ (/ (distance start_point end_point) 2.0) (sin half_angle))))
                (setq center_point (polar start_point center_direction radius))
                (setq mid_width (/ (+ start_width end_width) 2.0))
                (setq start_angle (angle center_point start_point))
                (setq end_angle (angle center_point end_point))
                (setq pt1 (polar center_point start_angle (+ radius start_width)))
                (setq pt2 (polar center_point (+ start_angle half_angle) (+ radius (/ (+ start_width end_width) 2.0))))
                (setq pt3 (polar center_point end_angle (+ radius end_width)))
                (command ".pline" "non" pt1 "width" "0.0" "0.0" "a" "s" "non" pt2 "non" pt3 "")
                (setq pt4 (polar center_point start_angle (- radius start_width)))
                (setq pt5 (polar center_point (+ start_angle half_angle) (- radius (/ (+ start_width end_width) 2.0))))
                (setq pt6 (polar center_point end_angle (- radius end_width)))
                (command ".pline" "non" pt4 "width" "0.0" "0.0" "a" "s" "non" pt5 "non" pt6 "")
                (if (= first nil)
                  (progn
                    (command ".pline" "non" pt1 "width" "0.0" "0.0" "non" pt4 "")
                    (setq first 1)
                  ) 
                )
                (if (>= counter data_length2)
                  (progn
                    (command ".pline" "non" pt3 "width" "0.0" "0.0" "non" pt6 "")
                  )
                ) 
              )
              (progn
                (if (or (> start_width 0.0)
                        (> end_width 0.0)
                    )
                  (progn
                    (setq line_angle (angle start_point end_point))
                    (setq pt1 (polar start_point (+ line_angle (/ pi 2.0)) start_width))
                    (setq pt2 (polar end_point (+ line_angle (/ pi 2.0)) end_width))
                    (command ".pline" "non" pt1 "width" "0.0" "0.0" "non" pt2 "")
                    (setq pt4 (polar start_point (+ line_angle (* (/ pi 2.0) 3.0)) start_width))
                    (setq pt5 (polar end_point (+ line_angle (* (/ pi 2.0) 3.0)) end_width))
                    (command ".pline" "non" pt4 "width" "0.0" "0.0" "non" pt5 "")
                    (if (= first nil)
                      (progn
                        (command ".pline" "non" pt1s "width" "0.0" "0.0" "non" pt1e "")
                        (setq first 1)
                      ) 
                    )                 
                    (if (>= counter data_length2)
                      (progn
                        (command ".pline" "non" pt2 "width" "0.0" "0.0" "non" pt5 "")
                      ) 
                    ) 
                  ) 
                  (progn
                    (command ".pline" "non" start_point "width" "0.0" "0.0" "non" end_point "")
                    (setq first 1)
                  )
                )
              ) 
            )
            (setq counter (+ 4 counter))
          )
        )
      )
    )
  )
  (princ)
)
"Science is the belief in the ignorance of experts." - Richard Feynman

ronjonp

  • Needs a day job
  • Posts: 7529
Re: Outline of a variable width lwpolyline
« Reply #6 on: September 07, 2010, 11:01:41 AM »
How about creating a dynamic block with a visibility state and a background mask?

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

hmspe

  • Bull Frog
  • Posts: 362
Re: Outline of a variable width lwpolyline
« Reply #7 on: September 07, 2010, 06:04:31 PM »
How about creating a dynamic block with a visibility state and a background mask?
Thanks for the suggestion.  I would probably use a dynamic block if I was starting from scratch, and if the staff was not using Bricscad.  Most of the symbols this needs to work with were created long before dynamic blocks were available, and some like the home run symbol are actually each unique symbols because they get recreated to trim to whatever block they are inserted on.  It made sense at the time to do it that way.
"Science is the belief in the ignorance of experts." - Richard Feynman

chlh_jd

  • Guest