View Full Version : How to convert 3D Polylines to 2D Polylines
GreyHippo
2006-12-27, 09:01 PM
I converted an Arcview Shapefile to DXF and the resulting drawing has a bunch of 3D Polylines. I need to convert these to 2D Polylines. I was exploding and then joining them together but it is taking to much time. Is there a faster or easier way to do this? There are over 100,000 3D polylines I have to do this to.
rkmcswain
2006-12-27, 11:03 PM
I converted an Arcview Shapefile to DXF and the resulting drawing has a bunch of 3D Polylines. I need to convert these to 2D Polylines. I was exploding and then joining them together but it is taking to much time. Is there a faster or easier way to do this? There are over 100,000 3D polylines I have to do this to.
If you just want to flatten the 3D polylines to a certain elevation and you don't care if they are still technically 3D polylines, then just use the ET "flatten" command. It will leave the entities as 3D polylines, but each vertex will be set to 0.00
If you really want to convert the 3D polyline to a 2D polyline, then ToolPac (http://www.dotsoft.com/toolpac.htm) has a function to do this. The resulting entities are POLYLINE entities, but can easily be converted to LWPOLYLINE entities if desired by using the ._CONVERTPOLY command.
If you don't have ToolPac (http://www.dotsoft.com/toolpac.htm), then you can use WMFOUT and WMFIN. After you bring the entities back with WMFIN, you can use ._PEDIT to join them all back up in one swoop....
If you just want to flatten the 3D polylines to a certain elevation and you don't care if they are still technically 3D polylines, then just use the ET "flatten" command. It will leave the entities as 3D polylines, but each vertex will be set to 0.00
If you really want to convert the 3D polyline to a 2D polyline, then ToolPac (http://www.dotsoft.com/toolpac.htm) has a function to do this. The resulting entities are POLYLINE entities, but can easily be converted to LWPOLYLINE entities if desired by using the ._CONVERTPOLY command.
If you don't have ToolPac (http://www.dotsoft.com/toolpac.htm), then you can use WMFOUT and WMFIN. After you bring the entities back with WMFIN, you can use ._PEDIT to join them all back up in one swoop....
Why not just explode the polyline; flatten the "Previous" selection set; Pedit one of the entities; then use the Join option of the Pedit command to join the Previous selection set? Why use WMFOUT / WMFIN?
Try this but very quick and dirty
Tested 1 time only on A2005
Works too slowly, approx. 2000 polylines in 8 minutes
(defun C:X3P (/ *error* adoc obj_lst ss tmp_ss)
(alert "Works slowly, converted \n
2000 polylines in 8 minutes")
(or (vl-load-com))
(defun *error* (msg)
(princ msg)
(vla-endundomark
(vla-get-activedocument
(vlax-get-acad-object)))
(princ)
)
(defun delobject (obj)
(vl-catch-all-apply
(function (lambda()
(vla-delete obj)))))
(or adoc
(setq adoc (vla-get-activedocument
(vlax-get-acad-object))))
(vla-endundomark
adoc)
(vla-startundomark
adoc)
(setvar "peditaccept" 1)
(setvar "delobj" 1)
(setq ss (ssget "_X" (list (cons 0 "POLYLINE")
(cons 100 "AcDb3dPolyline"))))
(vlax-for a (vla-get-activeselectionset adoc)
(setq obj_lst (vlax-invoke a 'Explode))
(setq tmp_ss (ssadd))
(foreach itm obj_lst
(ssadd (vlax-vla-object->ename itm) tmp_ss))
(command "._pedit" "_m" tmp_ss "" "_j" 0.000 "")
(delobject a)
(setq tmp_ss nil)
)
(*error* nil)
(princ)
)
~'J'~
rkmcswain
2006-12-28, 12:52 AM
Why not just explode the polyline; flatten the "Previous" selection set; Pedit one of the entities; then use the Join option of the Pedit command to join the Previous selection set? Why use WMFOUT / WMFIN?
You are right. No need to export/import.
You can even save one more step. No need to ._PEDIT "one" of the entities first. You can just use ._PEDIT, window the entire selection, then use the _Join option.
In the case of other complex entities (MLINE, SPLINE, TEXT, etc.) that you may want to "explode" or "flatten", then the WMFIN/OUT trick will work.
Thanks for the catch!
GreyHippo
2006-12-28, 02:57 AM
The main problem is when I explode 20,000 3D polylines, Autocad converts them to over 200,000 smaller lines and then that creates a huge drawing file and takes forever to join them to polylines. I just don't want to watch and wait for it to finish, but that maybe my only option.
I guess I will a little over each lunch break.
Lions60
2006-12-28, 01:37 PM
Here is just a real simple code to change all your 3d polylines into 2d Polylines. If your prefer you can get rid of the alert. It is just there to let you know what the program is doing.
(defun 3dp ()
(alert "Converting 3dPolyLines to 2DPolyLines")
(setq ss (ssget "X" '((0 . "POLYLINE"))))
(command "explode" ss)
(setq ss (ssget "X" '((0 . "LINE"))))
(command "pedit" ss "y" "j"ss"""")
)
rkmcswain
2006-12-28, 02:35 PM
Here is just a real simple code to change all your 3d polylines into 2d Polylines. If your prefer you can get rid of the alert. It is just there to let you know what the program is doing.
Lions60, this will not work. See comments below.
(defun 3dp () ;Missing the "C:".
Yes, it will still run as (3dp), but many people won't know this.
(alert "Converting 3dPolyLines to 2DPolyLines")
(setq ss (ssget "X" '((0 . "POLYLINE")))) ;This selects all POLYLINE entities, not just 3D.
(command "explode" ss) ;This will not work. You would have to walk the selection set
and explode each one.
(setq ss (ssget "X" '((0 . "LINE"))))
(command "pedit" ss "y" "j"ss"""") ;This will fail also, because the
resulting LINE entities are still 3D.
You also fail to account for the setting of PEDITACCEPT.
Lastly, you would need the "_M" (multiple option) in there.
)
A better lisp solution would be to walk each 3D Polyline entity, scoop up the coordinates, erase it, then remake a 2D polyline in its place at the desired elevation.
Lions60
2006-12-28, 06:05 PM
Ok, this redraws all 3d polylines as 2d polylines, but this does not join the polylines together.
(defun c:3DP>2DP (/ OLDVAR1 COUNT LINENO NO SS1 SS2 ENT EDATA PT1 PT2)
(command ".undo" "Mark")
(setq old_plinetype (getvar "PLINETYPE"))
(setvar "PLINETYPE" 0)
(setq OLDVAR1 (getvar "CMDECHO")) (setvar "CMDECHO" 0)
(if
(setq SS2 (ssget "X" ' ((100 . "AcDb3dPolyline"))))
(progn
(setq no (sslength ss2))
(setq count 0)
(repeat no
(progn
(setq ent (ssname ss2 count))
(setq edata (entget ent))
(command "explode" ent)
(setq count (1+ count))
)
)
)
)
(if
(setq SS1 (ssget "X" ' ((0 . "Line"))))
(progn ; added
(setq LINENO (sslength SS1))
(setq COUNT 0)
(setq PLINFO (ssadd))
(repeat LINENO
(progn
(setq ENT (ssname SS1 COUNT))
(setq EDATA (entget ENT))
(setq PT1 ( cdr (assoc 10 EDATA)))
(setq PT2 ( cdr (assoc 11 EDATA)))
(command "Pline" PT1 PT2 "")
(ssadd (entlast) PLINFO)
(prompt (strcat "Processing line no. " (itoa COUNT) "\r"))
(setq COUNT (1+ COUNT))
)
)
) ; added end (progn
) ; added end (if
(COMMAND "ERASE" SS1 "")
(setvar "CMDECHO" OLDVAR1)
(prompt (strcat "\n" "Erasing original lines..." "\n"))
(setvar "PLINETYPE" old_plinetype)
(princ) ; end program
); end 3dp.lsp
CAB2k
2006-12-28, 06:14 PM
Another lisp by TT.
http://tinyurl.com/y3639e
GreyHippo
2006-12-29, 06:08 PM
I first tried Lion's but it seamed like autocad locked up on me, then I tried Cab's suggestion and it worked perfectly.
Thanks, you saved me a bunch of time!!!
peter
2006-12-30, 03:10 PM
Here is a 3dto2d function using activeX
After flattening the 3dpoly's you could try using the express tools "overkill" to join them together.
You can also use a pjoin.lsp routine to join them.
(defun C:3DTo2D (/ intCount
lstCoordiantes
objDocument
obj2dPolyline
obj3dPolyline
ssSelections
strProperty
)
(if (setq ssSelections (ssget (list (cons 0 "polyline"))))
(vlax-for obj3dPolyline (vla-get-activeselectionset
(setq objDocument (vla-get-activedocument
(vlax-get-acad-object))))
(if (= (vla-get-objectname obj3dPolyline) "AcDb3dPolyline")
(progn
(setq intCount 0
lstCoordinates (mapcar
'(lambda (sngCoordinate)
(if (= (/ (setq intCount (1+ intCount)) 3.0)
(/ intCount 3)
)
nil
sngCoordinate
)
)
(vlax-get obj3dPolyline "coordinates")
)
lstCoordinates (vl-remove nil lstCoordinates)
obj2dPolyline (vla-addlightweightpolyline
(vla-get-block
(vla-get-activelayout objDocument))
(listtosafearray 5 lstCoordinates))
)
(foreach strProperty (list "truecolor" "layer" "linetype" "closed")
(vlax-put obj2dPolyline strProperty (vlax-get obj3dPolyline strProperty))
)
(vla-delete obj3dPolyline)
)
)
)
)
(princ)
)
; This function creates a safearray from a list and the safearray type symbol
; for example: (listtosafearray vlax-vbinteger (list 0) )
(defun ListToSafeArray (symSafeArrayType lstItems / safArray)
(setq safArray (vlax-make-safearray symSafeArrayType (cons 0 (1- (length lstItems)))))
(vlax-safearray-fill safArray lstItems)
)
;vlax-vbInteger (2) Integer
;vlax-vbLong (3) Long integer
;vlax-vbSingle (4) Single-precision floating-point number
;vlax-vbDouble (5) Double-precision floating-point number
;vlax-vbString (8) String
;vlax-vbObject (9) Object
;vlax-vbBoolean (11) Boolean
;vlax-vbVariant (12) Variant
(princ "C:3dTo2d")
(prin1)
GreyHippo
2006-12-31, 09:22 PM
I will try your routine once I get back in the office on Tuesday to see which way is faster. Happy New Year.
watsonlisp
2007-01-02, 04:16 AM
I suggest using the Flatten lisp program, then the pljoin lisp program.
watsonlisp
2007-01-02, 04:19 AM
Here's one I wrote a long time ago.
(DEFUN C:GPJ (/ PT1 PT2 SSET SSETN PLN LP ENT LA PLN2 TFC CV ENTL EVS SV EVT VE1 VE2 SI1 SI2 SII1 SII2 SI SII PF FB FE FLTR)
(PROMPT "*GROUP POLYLINE JOIN*")
(SETQ SSET (SSGET '((0 . "LWPOLYLINE"))))
(SETQ SSETN (SSLENGTH SSET))
(SETQ PLN SSETN)
(PRINT SSETN)
(PROMPT " POLYLINES SELECTED")
(SETQ SSETN (- SSETN 1))
(SETQ LOOP 1)
(WHILE LOOP
(SETQ ENT (SSNAME SSET SSETN))
(SETQ LA (ASSOC 8 (ENTGET ENT)))
(SETQ ENTL (ENTGET ENT))
(SETQ VE1 (CDR (ASSOC 10 ENTL)))
(SETQ EVS VE1)
(SETQ SV 1)
(WHILE SV
(SETQ ENTL (CDR ENTL))
(SETQ EVT (ASSOC 10 ENTL))
(IF (/= EVT NIL)
(SETQ VE2 (CDR EVT))
(SETQ SV NIL)
)
) ;END WHILE SV
(SETQ SI1 (MAPCAR '+ '(0.1 0.1 0.0) VE1))
(SETQ SI2 (MAPCAR '+ '(-0.1 -0.1 0.0) VE1))
(SETQ SII1 (MAPCAR '+ '(0.1 0.1 0.0) VE2))
(SETQ SII2 (MAPCAR '+ '(-0.1 -0.1 0.0) VE2))
(SETQ PF '(0 . "LWPOLYLINE"))
(SETQ FB '(-4 . "<AND"))
(SETQ FE '(-4 . "AND>"))
(SETQ FLTR (LIST FB PF LA FE))
(SETQ SI (SSGET "C" SI1 SI2 FLTR))
(SETQ SII (SSGET "C" SII1 SII2 FLTR))
(IF (= SI NIL)
(SETQ SI ENT)
)
(IF (= SII NIL)
(SETQ SII ENT)
)
(SETQ CV (CDR (ASSOC 70 (ENTGET ENT))))
(IF (> CV 0)
(SETQ TFC 1)
(SETQ TFC 0)
)
(IF (= TFC 0)
(COMMAND "PEDIT" ENT "J" SI SII "" "X")
)
(SETQ LP 1)
(WHILE LP
(SETQ SSETN (- SSETN 1))
(PROMPT "\nJOIN ATEMPT # ")
(PRINC SSETN)
(IF (/= (SSNAME SSET SSETN) NIL)
(SETQ NT (ENTGET (SSNAME SSET SSETN)))
(SETQ NT 1)
)
(IF (= NT NIL)
(SETQ LP 1)
(SETQ LP NIL)
)
(IF (< SSETN 0)
(SETQ LOOP NIL)
)
) ;END WHILE LP
) ;END WHILE LOOP
(SETQ SSET NIL)
(SETQ SSET NIL)
(PRINC)
) ;END JPL[ Moderator Action = ON ] What are [ CODE ] tags... (http://forums.augi.com/misc.php?do=bbcode#code) [ Moderator Action = OFF ]
GreyHippo
2007-01-04, 05:25 PM
I tried the programs by Peter and CAB and both work very well but Peter's is about twice as fast, I guess its because of Active X commands.
Thanks to all who helped, you saved me a ton of time!
CAB2k
2007-01-04, 05:32 PM
Oh, that's not my lisp. I just posted the link.
Glad you got what you needed.
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.