LISP routine to "convert" a cornered 3D polyline to spline by connecting all vertices

LISP routine to "convert" a cornered 3D polyline to spline by connecting all vertices

Wojty1
Advocate Advocate
442 Views
16 Replies
Message 1 of 17

LISP routine to "convert" a cornered 3D polyline to spline by connecting all vertices

Wojty1
Advocate
Advocate

Hi everyone,

I need a LISP routine to draw a spline along all vertices of a 3D polyline.

 

Let's say I have something like this (an edgy 3DP): /\/\/\/\/\/\/\/\/\

and I'd like it to be that (a smooth spline): ~.,.~´'`~~.,.~´'`~~.,.~´'`~~.,.~´'`~~.,.~´'`~

 

Hope it's clear 😂

 

Does anyone have this kind of routine already coded?
Otherwise I'm thinking of something like "for each vertex, starting at index 1, draw a spline by connecting the other vertices one by one".

 

I'm familiar with the very basics of LISP, but not that good to write this kind of code yet.

 

Any help appreciated.

Windows 10 Pro 64-bit | Civil 3D 2024 / Revit 2024 (64-bit EN)
Intel Core i7-7700K / 2x 24" / 64 GB RAM / GeForce RTX 3060 OC V2

Windows 11 Pro 64-bit | All Autodesk Products 2023 - 2025
Intel Core i7-13850HX / 3x 24" / 128 GB RAM / nVidia RTX Ada 3500
0 Likes
Accepted solutions (1)
443 Views
16 Replies
Replies (16)
Message 2 of 17

Kent1Cooper
Consultant
Consultant

Does the PEDIT command's Spline curve option do what you want?

Kent Cooper, AIA
0 Likes
Message 3 of 17

Wojty1
Advocate
Advocate

@Kent1Cooper unfortunately not. It creates a curve by omitting the original vertices, but I need a spline with all it's control points being placed exactly on the 3DPoly's vertices (no more, no less).

 

The below screenshots show the difference:

RED: Spline by (manually) connecting the 3DP's vertices

BLUE: 3DP with PEDIT

Wojty1_0-1754996740033.png

 

Windows 10 Pro 64-bit | Civil 3D 2024 / Revit 2024 (64-bit EN)
Intel Core i7-7700K / 2x 24" / 64 GB RAM / GeForce RTX 3060 OC V2

Windows 11 Pro 64-bit | All Autodesk Products 2023 - 2025
Intel Core i7-13850HX / 3x 24" / 128 GB RAM / nVidia RTX Ada 3500
0 Likes
Message 4 of 17

autoid374ceb4990
Collaborator
Collaborator

Try this:

https://autocadtips1.com/2011/07/17/autolisp-polyline-to-spline/

This link contains  LISP code PL2SP.LSP.

The polyline has to be modified first  - use pedit "FIT" then run PL2SP.LSP.  Below is the result.

The black line is the original POLYLINE and the red line is the SPLINE

I don't think this will work with a 3DPLINE.

autoid374ceb4990_0-1755013842182.png

 

0 Likes
Message 5 of 17

Kent1Cooper
Consultant
Consultant

Are these 3D Polylnes actually 3D, i.e. do they have variant Z coordinates?  If they're actually flat/planar, and can be done as either 2D "heavy" or "lightweight" Polylines, maybe the PEDIT command's Fit option will work for you.  [At least it honors the vertex locations, though depending on the shape of things, it can have peculiar results.]  Unfortunately, it's another thing that isn't an option with 3D Polyline objects, even if they're planar.

Kent Cooper, AIA
0 Likes
Message 6 of 17

Sea-Haven
Mentor
Mentor

If you want a fixed pattern like these, which are made by drawing a pline with arcs in it as a repeating pattern. Just need to work out the sequence of lines and arcs in a pline. In the code matching image is a height size, these were done for house insulation. So could do a say 30deg line angle but would have a fixed arc.

 

SeaHaven_0-1755045685736.png

 

 

0 Likes
Message 7 of 17

Wojty1
Advocate
Advocate

@autoid374ceb4990

@Kent1Cooper

@Sea-Haven

 

These Polylines are actually 3D curbs {or any other topographic object) generated (drawn on a point cloud) by Leica Cyclone 3DR export. Each 3D Polyline is only correct at its vertices, since each vertex was picked from the point cloud. Since 3DR can only export 3D Polylines, all curves have to be drawn manually again by connecting the vertices of a Polyline with suitable linear objects (Spline, 3D Poly, Line) depending on the real world shape. 

So this process is time consuming and I needed an "easy" fix where I can choose a 3DP and let AUTOLISP do the "drawing". 

Hope you'll get a better understanding of why I'm looking for this specific task. 

 

If anybody knows such a routine, I'd be very happy.

Best regards 

 

Windows 10 Pro 64-bit | Civil 3D 2024 / Revit 2024 (64-bit EN)
Intel Core i7-7700K / 2x 24" / 64 GB RAM / GeForce RTX 3060 OC V2

Windows 11 Pro 64-bit | All Autodesk Products 2023 - 2025
Intel Core i7-13850HX / 3x 24" / 128 GB RAM / nVidia RTX Ada 3500
0 Likes
Message 8 of 17

autoid374ceb4990
Collaborator
Collaborator

If you have a 3DPLINE representing a topographic feature, why do you need it "smoothed"?

Can you post a drawing that has several examples of 3DPLINES that you have manually smoothed?

0 Likes
Message 9 of 17

Wojty1
Advocate
Advocate

Thanks for your efforts, but maybe I wasn't explaining my problem very well.

I'll try it again. Here's a screenshot showing the scenario:

 

Wojty1_0-1755088130515.png

 

What I have is a 3D Polyline which isn't accurate and needs to be replaced by a Spline connecting the 3DPoly's vertices.

Hope that makes sense now.

Windows 10 Pro 64-bit | Civil 3D 2024 / Revit 2024 (64-bit EN)
Intel Core i7-7700K / 2x 24" / 64 GB RAM / GeForce RTX 3060 OC V2

Windows 11 Pro 64-bit | All Autodesk Products 2023 - 2025
Intel Core i7-13850HX / 3x 24" / 128 GB RAM / nVidia RTX Ada 3500
0 Likes
Message 10 of 17

hosneyalaa
Advisor
Advisor

IF YOU  Used  Civil 3D 2024

TRY  FEATURE LINE   

0 Likes
Message 11 of 17

ВeekeeCZ
Consultant
Consultant

This automates a simple SPLINE redrawing.

 

(vl-load-com)

(defun c:3dtospline ( / :listgroupby s i e cxy p c) (defun :listgroupby (lst num / rtn) (repeat (/ (length lst) num) (setq rtn (cons (list (car lst) (cadr lst) (caddr lst)) rtn) lst (cdddr lst))) (reverse rtn)) (if (setq s (ssget '((0 . "POLYLINE")))) (repeat (setq i (sslength s)) (and (setq e (ssname s (setq i (1- i)))) (setq c (vlax-get (vlax-ename->vla-object e) 'coordinates)) (setq c (:listgroupby c 3)) (setq cxy (mapcar '(lambda (x) (reverse (cdr (reverse x)))) c)) ) (progn (initcommandversion) (command "_.spline") (foreach p cxy (command "_non" (trans p 0 1))) (command "")))) (princ) )

 

Message 12 of 17

hmsilva
Mentor
Mentor
Accepted solution

Another

(defun c:demo ( / 3d-pt e l)
    (vl-load-com)
    
    ;; Evgeniy Elpanov 
    (defun 3d-pt (lst)
	(if lst
	    (cons (list (car lst) (cadr lst) (caddr lst)) (3d-pt (cdddr lst)))
	)
    )
    
    (if	(and
	    (setq e (car (entsel "\nSelect a 3D-Polyline: ")))
	    (= "POLYLINE" (cdr (assoc 0 (entget e))))
	)
	(progn
	    (setq l (vlax-safearray->list (vlax-variant-value (vla-get-Coordinates (vlax-ename->vla-object e)))))
	    (setq l (3d-pt l))
	    
	    ;; Stefan BMR
	    (entmake
		(append
		    (list
			'(0 . "SPLINE")
			'(100 . "AcDbEntity")
			'(100 . "AcDbSpline")
			'(70 . 40)
			'(71 . 3)
			(cons 74 (length l))
			'(44 . 1.0e-005)
		    )
		    (mapcar '(lambda (x) (cons 11 x)) l)
		)
	    )
	    
	    ;uncomment to erase 3d polyline;(entdel e)
	)
	(prompt "\nNot a 3D-Polyline... ")
    )
    (princ)
    )

 

Hope this helps,
Henrique

 

EESignature

Message 13 of 17

Wojty1
Advocate
Advocate

@ВeekeeCZ Unfortunately your LISP only works on 2D Polylines

@hmsilva It works great! Could you add the option to draw the Spline on the same layer as the 3D Polyline? I've tried but can't get it right:

 

(defun c:3dp2spline_v012 ( / 3d-pt e l y)
    (vl-load-com)
    
    ;; Evgeniy Elpanov 
    (defun 3d-pt (lst)
	(if lst
	    (cons (list (car lst) (cadr lst) (caddr lst)) (3d-pt (cdddr lst)))
	)
    )
    
    (if	(and
	    (setq e (car (entsel "\nSelect a 3D-Polyline: ")))
	    (= "POLYLINE" (cdr (assoc 0 (entget e))))
	)
	(progn
	    (setq l (vlax-safearray->list (vlax-variant-value (vla-get-Coordinates (vlax-ename->vla-object e)))))
	    (setq l (3d-pt l))

	    ;; Wojty1
		(setq y (cdr (assoc 8 (entget e))))
		(print y)
		
	    ;; Stefan BMR
	    (entmake
		(append
		    (list
			'(0 . "SPLINE")
			
			;; Wojty1
			'(8 . y)
			
			'(100 . "AcDbEntity")
			'(100 . "AcDbSpline")
			'(70 . 40)
			'(71 . 3)
			(cons 74 (length l))
			'(44 . 1.0e-005)
		    )
		    (mapcar '(lambda (x) (cons 11 x)) l)
		)
	    )

		;uncomment to erase 3d polyline;(entdel e)
		
	)
	(prompt "\nNot a 3D-Polyline... ")
    )
    (princ)
    )

 

I can't figure out where and how to put my code. 

Windows 10 Pro 64-bit | Civil 3D 2024 / Revit 2024 (64-bit EN)
Intel Core i7-7700K / 2x 24" / 64 GB RAM / GeForce RTX 3060 OC V2

Windows 11 Pro 64-bit | All Autodesk Products 2023 - 2025
Intel Core i7-13850HX / 3x 24" / 128 GB RAM / nVidia RTX Ada 3500
0 Likes
Message 14 of 17

hmsilva
Mentor
Mentor

@Wojty1 

Change

'(8 . y)

to

(cons 8  y)

 

Hope this helps,
Henrique

EESignature

0 Likes
Message 15 of 17

ВeekeeCZ
Consultant
Consultant

Well, I did that on purpose... but you can simply remove that... in this line use just c instead of cxy.

 

(foreach p cxy (command "_non" (trans p 0 1)))

 

0 Likes
Message 16 of 17

Wojty1
Advocate
Advocate

@hmsilva Many thanks, that did the trick!

 

I added one line so the created Spline will have the same layer as the 3DP and red color:

(cons 62 1)

 

;(defun c:3dp2spline ( / 3d-pt e l y)
(defun c:3D2S ( / 3d-pt e l y)
    (vl-load-com)
    
    ;; Evgeniy Elpanov 
    (defun 3d-pt (lst)
	(if lst
	    (cons (list (car lst) (cadr lst) (caddr lst)) (3d-pt (cdddr lst)))
	)
    )
    
    (if	(and
	    (setq e (car (entsel "\nSelect a 3D-Polyline: ")))
	    (= "POLYLINE" (cdr (assoc 0 (entget e))))
	)
	(progn
	    (setq l (vlax-safearray->list (vlax-variant-value (vla-get-Coordinates (vlax-ename->vla-object e)))))
	    (setq l (3d-pt l))
	    ;; Wojty1
		(setq y (cdr (assoc 8 (entget e))))
	    ;; Stefan BMR
	    (entmake
		(append
		    (list
			'(0 . "SPLINE")
			;; Wojty1
			(cons 8 y)
			(cons 62 1)
			'(100 . "AcDbEntity")
			'(100 . "AcDbSpline")
			'(70 . 40)
			'(71 . 3)
			(cons 74 (length l))
			'(44 . 1.0e-005)
		    )
		    (mapcar '(lambda (x) (cons 11 x)) l)
		)
	    )

		;uncomment to erase 3d polyline;(entdel e)
		
	)
	(prompt "\nNot a 3D-Polyline... ")
    )
    (princ)
    )

 

Now the code is perfect for my needs!

Thanks to you all

 

@ВeekeeCZ Not sure about that (didn't test yet), but may it be that your code is slightly slower since it uses Commands instead of Entity Lists?

 

Windows 10 Pro 64-bit | Civil 3D 2024 / Revit 2024 (64-bit EN)
Intel Core i7-7700K / 2x 24" / 64 GB RAM / GeForce RTX 3060 OC V2

Windows 11 Pro 64-bit | All Autodesk Products 2023 - 2025
Intel Core i7-13850HX / 3x 24" / 128 GB RAM / nVidia RTX Ada 3500
Message 17 of 17

hmsilva
Mentor
Mentor

You're welcome,
Glad I could help

Henrique

EESignature

0 Likes