convert 2D polylines to 3D polylines with elevation

convert 2D polylines to 3D polylines with elevation

zasanil
Advocate Advocate
8,701 Views
11 Replies
Message 1 of 12

convert 2D polylines to 3D polylines with elevation

zasanil
Advocate
Advocate

Hello,

I have a drawing with many 2D polylines that show a flat view of a point to point connection between 2 different elevation points. I would like to model the 2D polyline as a 3D polyline that shows the elevation changes. An example is attached. Could anyone help with a lisp please that would allow me to generate these faster? Right now in a top down view I am drawing each 3D polyline by tracing over the 2D polyline with apparent intersection turned on. I'm sure this could be automated.

Thanks!

Dan Nicholson C.I.D.
PCB Design Engineer
0 Likes
Accepted solutions (1)
8,702 Views
11 Replies
Replies (11)
Message 2 of 12

Kent1Cooper
Consultant
Consultant

How about this?  [Not the marked Solution, but Post 3 from phanaem]

Kent Cooper, AIA
0 Likes
Message 3 of 12

zasanil
Advocate
Advocate

I tried the routine that you listed, but it doesn't seem to generate the correct output. It just changes the 2dpolyline to 3dpolyline, but without adding the verticies needed no changing it's height.

Dan Nicholson C.I.D.
PCB Design Engineer
0 Likes
Message 4 of 12

marko_ribar
Advisor
Advisor

Here, try this :

 

(defun c:flw23pel ;fencelwpoly23dpolyelevations
  ( / *error* ucsf osm ss1 ss2 i lw pl sss ssl sspl e )

  (vl-load-com)

  (defun *error* ( msg )
    (if ucsf
      (command "_.UCS" "_P")
    )
    (command "_.ZOOM" "_P")
    (if osm
      (setvar 'osmode osm)
    )
    (if msg
      (prompt msg)
    )
    (princ)
  )

  (if (= 0 (getvar 'worlducs))
    (progn
      (command "_.UCS" "_W")
      (command "_.PLAN" "")
      (setq ucsf t)
    )
    (command "_.PLAN" "")
  )
  (setq osm (getvar 'osmode))
  (setvar 'osmode 0)
  (prompt "\nSelect OPEN \"STRAIGHT\" LWPOLYLINES that lie in plane parallel to WCS - PROJECTION LWPOLYLINES (NOT ELEVATION)...")
  (setq ss1 (ssget (list '(0 . "LWPOLYLINE") '(-4 . "<or") '(70 . 0) '(70 . 128) '(-4 . "or>") '(42 . 0.0) '(210 0.0 0.0 1.0))))
  (while (or
           (not ss1)
           (vl-every '(lambda ( x ) (not (equal (caddar (acet-geom-ss-extents-accurate (ssadd x))) (caddr (cadr (acet-geom-ss-extents-accurate (ssadd x)))) 1e-6))) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss1))))
           (not (vl-every '(lambda ( x ) (vl-every '(lambda ( y ) (if (= (car y) 42) (= (cdr y) 0.0) t)) (entget x))) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss1)))))
         )
    (prompt "\nEmpty sel.set or some OPEN \"STRAIGHT\" LWPOLYLINES not in plane parallel to WCS or some LWPOLYLINES have arced segments... Please reselect again...")
    (setq ss1 (ssget (list '(0 . "LWPOLYLINE") '(-4 . "<or") '(70 . 0) '(70 . 128) '(-4 . "or>") '(42 . 0.0) '(210 0.0 0.0 1.0))))
  )
  (prompt "\nSelect OPEN LWPOLYLINES that lie in plane parallel to WCS - ELEVATION LWPOLYLINES (NOT PROJECTION)...")
  (setq ss2 (ssget (list '(0 . "LWPOLYLINE") '(-4 . "<or") '(70 . 0) '(70 . 128) '(-4 . "or>") '(210 0.0 0.0 1.0))))
  (while (or
           (not ss2)
           (vl-every '(lambda ( x ) (not (equal (caddar (acet-geom-ss-extents-accurate (ssadd x))) (caddr (cadr (acet-geom-ss-extents-accurate (ssadd x)))) 1e-6))) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss2))))
         )
    (prompt "\nEmpty sel.set or some OPEN STRAIGHT LWPOLYLINES not in plane parallel to WCS... Please reselect again...")
    (setq ss2 (ssget (list '(0 . "LWPOLYLINE") '(-4 . "<or") '(70 . 0) '(70 . 128) '(-4 . "or>") '(210 0.0 0.0 1.0))))
  )
  (repeat (setq i (sslength ss1))
    (setq lw (ssname ss1 (setq i (1- i))))
    (setq pl (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= (car x) 10)) (entget lw))))
    (setq sss (ssget "_F" pl))
    (setq ssl (ssnamex sss))
    (setq ssl (vl-remove-if '(lambda ( x ) (eq (cadr x) lw)) ssl))
    (setq sspl (mapcar 'cadr (apply 'append (mapcar '(lambda ( x ) (vl-remove-if-not 'listp x)) ssl))))
    (setq sspl (vl-sort sspl '(lambda ( a b ) (< (vlax-curve-getparamatpoint lw (list (car a) (cadr a) (cdr (assoc 38 (entget lw))))) (vlax-curve-getparamatpoint lw (list (car b) (cadr b) (cdr (assoc 38 (entget lw)))))))))
    (command "_.3DPOLY")
    (foreach p sspl
      (if (vl-some '(lambda ( x ) (if (vlax-curve-getparamatpoint x (list (car p) (cadr p) (cdr (assoc 38 (entget x))))) (setq e x))) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss2))))
        (command "_non" (list (car p) (cadr p) (cdr (assoc 38 (entget e)))))
      )
    )
    (command "")
  )
  (*error* nil)
)

M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 5 of 12

Kent1Cooper
Consultant
Consultant

@zasanil wrote:

I tried the routine that you listed, but it doesn't seem to generate the correct output. ....


[I had mis-read your intent, exacerbated by assuming some things about what you meant from the Subject line, and not opening your sample drawing before....]

 

Your mention of Apparent Intersections got me thinking about another way of going about this, in process of which I found some interesting things that I had to account for.  For instance, Osnapping to the Apparent Intersection always results in the location on the object that's "in front" in the drawing order [not based on something like elevation].  And I thought it shouldn't be necessary to limit yourself to Polylines -- it ought to work with Lines, and maybe even other things.

 

This works [in limited testing] in your sample drawing, even if some Polylines [red and/or green] are Exploded into Lines, and with the introduction of other object types for what you have as either the red or the green elements.  It lacks an error handler and some other little tid-bits, so far, and it could also be made to prevent selection of Xlines or Mlines if there's any risk of those, return to the original view, etc.  But it asks you only to select the red parts in your sample drawing -- you don't need to select the green ones.

 

(defun C:TEST (/ ss n ent len inc dist ptlist)
  (command "_.ucs" "_world" "_.plan" "")
  (setq osm (getvar 'osmode))
  (setvar 'osmode 0)
  (alert "Select the non-3D crossing objects\n(not the different-level objects).")
  (if (setq ss (ssget '((0 . "*LINE,ARC,CIRCLE,ELLIPSE"))))
    (progn ; then
      (command "_.draworder" ss "" "_back"); because Osnap AppInt goes to "front" object
      (repeat (setq n (sslength ss))
        (setq
          ent (ssname ss (setq n (1- n)))
          len (vlax-curve-getDistAtParam ent (vlax-curve-getEndParam ent))
          inc (/ len 20);;; edit for reasonable number to ensure hitting all app. ints.
          dist (- inc)
          ptlist nil ; [to clear previous one if any]
        ); setq
        (repeat 21 ;;; edit if 'inc' divisor edited above [one more than divisor]
          (setq pt
            (osnap
              (cond ; [sometimes calculated dist overshoots end, returns nil]
                ((vlax-curve-getPointAtDist ent (setq dist (+ dist inc))))
                ((vlax-curve-getEndPoint ent))
              ); cond
              "_app"
            ); osnap
          ); setq
          (if (not (member pt ptlist)) (setq ptlist (cons pt ptlist))); found different point
        ); repeat
        (command "_3dpoly")
        (apply 'command ptlist); trace along found apparent intersections
        (command "")
      ); repeat
    ); progn
  ); if
  (setvar 'osmode osm)
  (princ)
); defun 

  

Kent Cooper, AIA
Message 6 of 12

zasanil
Advocate
Advocate

Hi Marko,

I seem to be getting an error when I tried your routine.

 

Command: FLW23PEL
_.PLAN
Enter an option [Current ucs/Ucs/World] <Current>: Regenerating model.
Command:
Select OPEN "STRAIGHT" LWPOLYLINES that lie in plane parallel to WCS - PROJECTION LWPOLYLINES (NOT ELEVATION)...
Select objects: Specify opposite corner: 7 found
Select objects:
_.copy
Select objects: ; error: Exception occurred: 0xC0000005 (Access Violation)
; warning: unwind skipped on exception
; error: Exception occurred: 0xC0000005 (Access Violation)
Select objects: Specify opposite corner: 5 found
Select objects:
Specify base point or [Displacement/Multiple] <Displacement>: m
Specify base point or [Displacement] <Displacement>:
Specify second point or [Array] <use first point as displacement>:
Specify second point or [Array/Exit/Undo] <Exit>:
Specify second point or [Array/Exit/Undo] <Exit>: *Cancel*

 

Thanks for trying though!

Dan Nicholson C.I.D.
PCB Design Engineer
0 Likes
Message 7 of 12

zasanil
Advocate
Advocate

Hi Kent,

I tried your code and it seems to partially work. It only created a few segments of the 3dpolyline as shown in the picture.

 

partial.jpg

Dan Nicholson C.I.D.
PCB Design Engineer
0 Likes
Message 8 of 12

marko_ribar
Advisor
Advisor

@zasanil wrote:

Hi Marko,

I seem to be getting an error when I tried your routine.

 

Command: FLW23PEL
_.PLAN
Enter an option [Current ucs/Ucs/World] <Current>: Regenerating model.
Command:
Select OPEN "STRAIGHT" LWPOLYLINES that lie in plane parallel to WCS - PROJECTION LWPOLYLINES (NOT ELEVATION)...
Select objects: Specify opposite corner: 7 found
Select objects:
_.copy
Select objects: ; error: Exception occurred: 0xC0000005 (Access Violation)
; warning: unwind skipped on exception
; error: Exception occurred: 0xC0000005 (Access Violation)
Select objects: Specify opposite corner: 5 found
Select objects:
Specify base point or [Displacement/Multiple] <Displacement>: m
Specify base point or [Displacement] <Displacement>:
Specify second point or [Array] <use first point as displacement>:
Specify second point or [Array/Exit/Undo] <Exit>:
Specify second point or [Array/Exit/Undo] <Exit>: *Cancel*

 

Thanks for trying though!


Just FYI, I've tested my code before I posted it on your posted DWG and it worked fine on my PC...

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 9 of 12

zasanil
Advocate
Advocate

Could the error be because of a different version of autocad? I'm using 2017. Not sure if that helps.

Dan Nicholson C.I.D.
PCB Design Engineer
0 Likes
Message 10 of 12

marko_ribar
Advisor
Advisor

@zasanil wrote:

Could the error be because of a different version of autocad? I'm using 2017. Not sure if that helps.


I don't know - I still don't have A2017 installed... Although I have A2016, I am prety sure I did test it on system with A2014... If that infp helps anyhow... I am not saying that it's A2017 as there may be some other issues - sysvars, OS, or something to me unknown different than your setting of ACAD, OS... Only thing I have to say ab your error message is that command COPY is issued and there is no anywhere in rotuine calls for that... Other than that my acaddoc.lsp has (setvar 'cmdecho 0) line... Maybe set CMDECHO to 0 before running, who knows...

 

M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 11 of 12

marko_ribar
Advisor
Advisor
Accepted solution

zasnil, sorry for the delay... My PC was busy scaning files, so I've tested my code on A2016 and yes if failed... So I figured out that it's because Adesk have something done with (acet-geom-ss-extents-accurate) function, but I think that that is applied perhaps to all (acet-xxx) functions of Express Tools, I don't know... So I've found workaround for this, but what will be for other cases I don't know... Why they did change something you'll have to ask Adesk... So this passed my tests on A2016 :

 

(defun c:flw23pel ;fencelwpoly23dpolyelevations
  ( / *error* bbucs ucsf osm ss1 ss2 i lw pl sss ssl sspl e )

  (vl-load-com)

  (defun *error* ( msg )
    (if ucsf
      (command-s "_.UCS" "_P")
    )
    (command-s "_.ZOOM" "_P")
    (if osm
      (setvar 'osmode osm)
    )
    (if msg
      (prompt msg)
    )
    (princ)
  )

  (defun bbucs ( ss / UCS2WCSMatrix WCS2UCSMatrix n ent minpt maxpt minptlst maxptlst minptbbx minptbby minptbbz minptbb maxptbbx maxptbby maxptbbz maxptbb )

    (vl-load-com)

    ;; Doug C. Broad, Jr.
    ;; can be used with vla-transformby to
    ;; transform objects from the UCS to the WCS
    (defun UCS2WCSMatrix ()
      (vlax-tmatrix
        (append
          (mapcar
           '(lambda (vector origin)
            (append (trans vector 1 0 t) (list origin))
          )
          (list '(1 0 0) '(0 1 0) '(0 0 1))
          (trans '(0 0 0) 0 1)
          )
          (list '(0 0 0 1))
        )
      )
    )
    ;; transform objects from the WCS to the UCS
    (defun WCS2UCSMatrix ()
      (vlax-tmatrix
        (append
          (mapcar
           '(lambda (vector origin)
            (append (trans vector 0 1 t) (list origin))
          )
          (list '(1 0 0) '(0 1 0) '(0 0 1))
          (trans '(0 0 0) 1 0)
          )
          (list '(0 0 0 1))
        )
      )
    )

    (if ss
      (progn
        (repeat (setq n (sslength ss))
          (setq ent (ssname ss (setq n (1- n))))
          (vla-TransformBy (vlax-ename->vla-object ent) (UCS2WCSMatrix))
          (vla-getboundingbox (vlax-ename->vla-object ent) 'minpoint 'maxpoint)
          (vla-TransformBy (vlax-ename->vla-object ent) (WCS2UCSMatrix))
          (setq minpt (vlax-safearray->list minpoint))
          (setq maxpt (vlax-safearray->list maxpoint))
          (setq minptlst (cons minpt minptlst))
          (setq maxptlst (cons maxpt maxptlst))
        )
        (setq minptbbx (caar (vl-sort minptlst '(lambda (a b) (< (car a) (car b))))))
        (setq minptbby (cadar (vl-sort minptlst '(lambda (a b) (< (cadr a) (cadr b))))))
        (setq minptbbz (caddar (vl-sort minptlst '(lambda (a b) (< (caddr a) (caddr b))))))
        (setq maxptbbx (caar (vl-sort maxptlst '(lambda (a b) (> (car a) (car b))))))
        (setq maxptbby (cadar (vl-sort maxptlst '(lambda (a b) (> (cadr a) (cadr b))))))
        (setq maxptbbz (caddar (vl-sort maxptlst '(lambda (a b) (> (caddr a) (caddr b))))))
        (setq minptbb (list minptbbx minptbby minptbbz))
        (setq maxptbb (list maxptbbx maxptbby maxptbbz))
      )
    )
    (list minptbb maxptbb)
  )

  (if (= 0 (getvar 'worlducs))
    (progn
      (command "_.UCS" "_W")
      (command "_.PLAN" "")
      (setq ucsf t)
    )
    (command "_.PLAN" "")
  )
  (setq osm (getvar 'osmode))
  (setvar 'osmode 0)
  (prompt "\nSelect OPEN \"STRAIGHT\" LWPOLYLINES that lie in plane parallel to WCS - PROJECTION LWPOLYLINES (NOT ELEVATION)...")
  (setq ss1 (ssget (list '(0 . "LWPOLYLINE") '(-4 . "<or") '(70 . 0) '(70 . 128) '(-4 . "or>") '(42 . 0.0) '(210 0.0 0.0 1.0))))
  (while (or
           (not ss1)
           (vl-every '(lambda ( x ) (not (equal (caddar (bbucs (ssadd x))) (caddr (cadr (bbucs (ssadd x)))) 1e-6))) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss1))))
           (not (vl-every '(lambda ( x ) (vl-every '(lambda ( y ) (if (= (car y) 42) (= (cdr y) 0.0) t)) (entget x))) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss1)))))
         )
    (prompt "\nEmpty sel.set or some OPEN \"STRAIGHT\" LWPOLYLINES not in plane parallel to WCS or some LWPOLYLINES have arced segments... Please reselect again...")
    (setq ss1 (ssget (list '(0 . "LWPOLYLINE") '(-4 . "<or") '(70 . 0) '(70 . 128) '(-4 . "or>") '(42 . 0.0) '(210 0.0 0.0 1.0))))
  )
  (prompt "\nSelect OPEN LWPOLYLINES that lie in plane parallel to WCS - ELEVATION LWPOLYLINES (NOT PROJECTION)...")
  (setq ss2 (ssget (list '(0 . "LWPOLYLINE") '(-4 . "<or") '(70 . 0) '(70 . 128) '(-4 . "or>") '(210 0.0 0.0 1.0))))
  (while (or
           (not ss2)
           (vl-every '(lambda ( x ) (not (equal (caddar (bbucs (ssadd x))) (caddr (cadr (bbucs (ssadd x)))) 1e-6))) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss2))))
         )
    (prompt "\nEmpty sel.set or some OPEN STRAIGHT LWPOLYLINES not in plane parallel to WCS... Please reselect again...")
    (setq ss2 (ssget (list '(0 . "LWPOLYLINE") '(-4 . "<or") '(70 . 0) '(70 . 128) '(-4 . "or>") '(210 0.0 0.0 1.0))))
  )
  (repeat (setq i (sslength ss1))
    (setq lw (ssname ss1 (setq i (1- i))))
    (setq pl (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= (car x) 10)) (entget lw))))
    (setq sss (ssget "_F" pl))
    (setq ssl (ssnamex sss))
    (setq ssl (vl-remove-if '(lambda ( x ) (eq (cadr x) lw)) ssl))
    (setq sspl (mapcar 'cadr (apply 'append (mapcar '(lambda ( x ) (vl-remove-if-not 'listp x)) ssl))))
    (setq sspl (vl-sort sspl '(lambda ( a b ) (< (vlax-curve-getparamatpoint lw (list (car a) (cadr a) (cdr (assoc 38 (entget lw))))) (vlax-curve-getparamatpoint lw (list (car b) (cadr b) (cdr (assoc 38 (entget lw)))))))))
    (command "_.3DPOLY")
    (foreach p sspl
      (if (vl-some '(lambda ( x ) (if (vlax-curve-getparamatpoint x (list (car p) (cadr p) (cdr (assoc 38 (entget x))))) (setq e x))) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss2))))
        (command "_non" (list (car p) (cadr p) (cdr (assoc 38 (entget e)))))
      )
    )
    (command "")
  )
  (*error* nil)
)

As you see - I've replacet (acet-geom-ss-extents-accurate) with (bbucs) sub function, and I suppose that when similar error occured on A2016, this fix would work and for A2017... Test it and maybe it'll work and for you...

 

Regards, and sorry for delay, M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 12 of 12

zasanil
Advocate
Advocate

That works well Marko!

Thank you very much.

Dan Nicholson C.I.D.
PCB Design Engineer
0 Likes