convert ellipse to polyline

convert ellipse to polyline

MikeKovacik4928
Advisor Advisor
10,555 Views
14 Replies
Message 1 of 15

convert ellipse to polyline

MikeKovacik4928
Advisor
Advisor

Can anyone send me a lisp that does the above.

I have searched and found a zillion of them, but maybe someone can recommend/post a specific one

I want to convert both a full ellipse and a partial ellipse into a polyline

so I can have an accurate shape I can use for a wipeout.

 

Mike Kovacik

Joburg, South Africa

0 Likes
Accepted solutions (2)
10,556 Views
14 Replies
Replies (14)
Message 2 of 15

dlanorh
Advisor
Advisor

I don't know if you can convert it, but you could construct it. For guidance look Here

 

I am not one of the robots you're looking for

0 Likes
Message 3 of 15

MikeKovacik4928
Advisor
Advisor

No I don't want to construct it, I want to convert it.

I believe it can be done using lisp.

I just want the routine so I can try it out

 

Mike

0 Likes
Message 4 of 15

_gile
Consultant
Consultant
Accepted solution

You can try the following routine.

It defines 2 commands:

EL2PL to convert the selected ellipses and elliptcal arcs into polylines

PELL to draw on the fly a polyline which is an approximation of ellipse or elliptical arc

The generated polylines are similar to the ones generated by AutoCAD when PELLIPSE system variable is equal to 1.

 

;; EllipseToPolyline
;; Returns a polyline (vla-object) which is an approximation of the ellipse (or elliptical arc)
;;
;; Argument : an ellipse (vla-object)

(defun EllipseToPolyline (el	/     cl    norm  cen	elv   pt0   pt1	  pt2	pt3   pt4   ac0
			  ac4	a04   a02   a24	  bsc0	bsc2  bsc3  bsc4  plst	blst  spt   spa
			  fspa	srat  ept   epa	  fepa	erat  n
			 )
  (vl-load-com)
  (setq	cl   (= (ang<2pi (vla-get-StartAngle el))
		(ang<2pi (vla-get-EndAngle el)))
	norm (vlax-get el 'Normal)
	cen  (trans (vlax-get el 'Center) 0 norm)
	elv  (caddr cen)
	cen  (3dTo2dPt cen)
	pt0  (mapcar '+ (trans (vlax-get el 'MajorAxis) 0 norm) cen)
	ac0  (angle cen pt0)
	pt4  (mapcar '+ cen (trans (vlax-get el 'MinorAxis) 0 norm))
	pt2  (3dTo2dPt (trans (vlax-curve-getPointAtparam el (/ pi 4.)) 0 norm))
	ac4  (angle cen pt4)
	a04  (angle pt0 pt4)
	a02  (angle pt0 pt2)
	a24  (angle pt2 pt4)
	bsc0 (/ (ang<2pi (- a02 ac4)) 2.)
	bsc2 (/ (ang<2pi (- a04 a02)) 2.)
	bsc3 (/ (ang<2pi (- a24 a04)) 2.)
	bsc4 (/ (ang<2pi (- (+ ac0 pi) a24)) 2.)
	pt1  (inters pt0
		     (polar pt0 (+ ac0 (/ pi 2.) bsc0) 1.)
		     pt2
		     (polar pt2 (+ a02 bsc2) 1.)
		     nil
	     )
	pt3  (inters pt2
		     (polar pt2 (+ a04 bsc3) 1.)
		     pt4
		     (polar pt4 (+ a24 bsc4) 1.)
		     nil
	     )
	plst (list pt4 pt3 pt2 pt1 pt0)
	blst (mapcar '(lambda (b) (tan (/ b 2.)))
		     (list bsc4 bsc3 bsc2 bsc0)
	     )
  )
  (foreach b blst
    (setq blst (cons b blst))
  )
  (foreach b blst
    (setq blst (cons b blst))
  )
  (foreach p (cdr plst)
    (setq ang  (angle cen p)
	  plst (cons
		 (polar cen (+ ang (* 2 (- ac4 ang))) (distance cen p))
		 plst
	       )
    )
  )
  (foreach p (cdr plst)
    (setq ang  (angle cen p)
	  plst (cons
		 (polar cen (+ ang (* 2 (- ac0 ang))) (distance cen p))
		 plst
	       )
    )
  )
  (setq	pl
	 (vlax-invoke
	   (vla-get-ModelSpace (vla-get-ActiveDocument (vlax-get-acad-object)))
	   'AddLightWeightPolyline
	   (apply 'append
		  (setq	plst
			 (reverse (if cl
				    (cdr plst)
				    plst
				  )
			 )
		  )
	   )
	 )
  )
  (vlax-put pl 'Normal norm)
  (vla-put-Elevation pl elv)
  (mapcar '(lambda (i v) (vla-SetBulge pl i v))
	  '(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16)
	  blst
  )
  (if cl
    (vla-put-Closed pl :vlax-true)
    (progn
      (setq spt	 (vlax-curve-getClosestPointTo pl (vlax-get el 'Startpoint))
	    spa	 (vlax-curve-getParamAtPoint pl spt)
	    fspa (fix spa)
	    ept	 (vlax-curve-getClosestPointTo pl (vlax-get el 'Endpoint))
	    epa	 (vlax-curve-getParamAtPoint pl ept)
	    fepa (fix epa)
	    n	 0
      )
      (cond
	((equal spt (trans pt0 norm 0) 1e-9)
	 (if (= epa fepa)
	   (setq plst (sublist plst 0 (1+ fepa))
		 blst (sublist blst 0 (1+ fepa))
	   )
	   (setq erat (/ (- (vlax-curve-getDistAtParam pl epa)
			    (vlax-curve-getDistAtParam pl fepa)
			 )
			 (- (vlax-curve-getDistAtParam pl (rem (1+ fepa) 17))
			    (vlax-curve-getDistAtParam pl fepa)
			 )
		      )
		 plst (append (sublist plst 0 (1+ fepa))
			      (list (3dTo2dPt (trans ept 0 norm)))
		      )
		 blst (append (sublist blst 0 (1+ fepa))
			      (list (k*bulge (nth fepa blst) erat))
		      )
	   )
	 )
	)
	((equal ept (trans pt0 norm 0) 1e-9)
	 (if (= spa fspa)
	   (setq plst (sublist plst fspa nil)
		 blst (sublist blst fspa nil)
	   )
	   (setq srat (/ (- (vlax-curve-getDistAtParam pl (rem (1+ fspa) 17))
			    (vlax-curve-getDistAtParam pl spa)
			 )
			 (- (vlax-curve-getDistAtParam pl (rem (1+ fspa) 17))
			    (vlax-curve-getDistAtParam pl fspa)
			 )
		      )
		 plst (cons (3dTo2dPt (trans spt 0 norm))
			    (sublist plst (1+ fspa) nil)
		      )
		 blst (cons (k*bulge (nth fspa blst) srat)
			    (sublist blst (1+ fspa) nil)
		      )
	   )
	 )
	)
	(T
	 (setq srat (/ (- (vlax-curve-getDistAtParam pl (rem (1+ fspa) 17))
			  (vlax-curve-getDistAtParam pl spa)
		       )
		       (- (vlax-curve-getDistAtParam pl (rem (1+ fspa) 17))
			  (vlax-curve-getDistAtParam pl fspa)
		       )
		    )
	       erat (/ (- (vlax-curve-getDistAtParam pl epa)
			  (vlax-curve-getDistAtParam pl fepa)
		       )
		       (- (vlax-curve-getDistAtParam pl (rem (1+ fepa) 17))
			  (vlax-curve-getDistAtParam pl fepa)
		       )
		    )
	 )
	 (if (< epa spa)
	   (setq plst (append
			(if (= spa fspa)
			  (sublist plst fspa nil)
			  (cons	(3dTo2dPt (trans spt 0 norm))
				(sublist plst (1+ fspa) nil)
			  )
			)
			(cdr (sublist plst 0 (1+ fepa)))
			(if (/= epa fepa)
			  (list (3dTo2dPt (trans ept 0 norm)))
			)
		      )
		 blst (append
			(if (= spa fspa)
			  (sublist blst fspa nil)
			  (cons
			    (k*bulge (nth fspa blst) srat)
			    (sublist blst (1+ fspa) nil)
			  )
			)
			(sublist blst 0 fepa)
			(if (= epa fepa)
			  (list (nth fepa blst))
			  (list (k*bulge (nth fepa blst) erat))
			)
		      )
	   )
	   (setq plst (append
			(if (= spa fspa)
			  (sublist plst fspa (1+ (- fepa fspa)))
			  (cons	(3dTo2dPt (trans spt 0 norm))
				(sublist plst (1+ fspa) (- fepa fspa))
			  )
			)
			(list (3dTo2dPt (trans ept 0 norm)))
		      )
		 blst (append
			(if (= spa fspa)
			  (sublist blst fspa (- fepa fspa))
			  (cons
			    (k*bulge (nth fspa blst) srat)
			    (sublist blst (1+ fspa) (- fepa fspa))
			  )
			)
			(if (= epa fepa)
			  (list (nth fepa blst))
			  (list (k*bulge (nth fepa blst) erat))
			)
		      )
	   )
	 )
	)
      )
      (vlax-put pl 'Coordinates (apply 'append plst))
      (foreach b blst
	(vla-SetBulge pl n b)
	(setq n (1+ n))
      )
    )
  )
  pl
)

;; Ang<2pi
;; Returns the angle expression betweem 0 and 2*pi
(defun ang<2pi (ang)
  (if (and (<= 0 ang) (< ang (* 2 pi)))
    ang
    (ang<2pi (rem (+ ang (* 2 pi)) (* 2 pi)))
  )
)

;; 3dTo2dPt
;; Returns the 2d point (x y) of a 3d point (x y z)
(defun 3dTo2dPt (pt) (list (car pt) (cadr pt)))

;; Tan
;; Returns the angle tangent
(defun tan (a) (/ (sin a) (cos a)))

;; SUBLIST 
;; Returns a sub list
;;
;; Arguments
;; lst : a list
;; start : start index (first item = 0)
;; leng : the sub list length (number of items) or nil
(defun sublist (lst start leng / n r)
  (if (or (not leng) (< (- (length lst) start) leng))
    (setq leng (- (length lst) start))
  )
  (setq n (+ start leng))
  (while (< start n)
    (setq r (cons (nth (setq n (1- n)) lst) r))
  )
)

;; K*BULGE
;; Returns the proportinal bulge to the référence bulge
;; Arguments :
;; b : the bulge
;; k : the proportion ratio (between angles or arcs length)
(defun k*bulge (b k / a)
  (setq a (atan b))
  (/ (sin (* k a)) (cos (* k a)))
)

;; EL2PL
;; Converts ellipses and elliptcal arcs into polylines

(defun c:el2pl (/ *error* fra acdoc ss)
  (vl-load-com)
  (defun *error* (msg)
    (if	(and (/= msg "Fonction annulée")
	     (/= msg "Function cancelled")
	)
      (princ (strcat (if (= "FRA" (getvar 'locale))
		       "\nErreur: "
		       "\Error: "
		     )
		     msg
	     )
      )
    )
    (vla-endUndoMark acdoc)
    (princ)
  )
  (setq acdoc (vla-get-ActiveDocument (vlax-get-acad-object)))
  (if (ssget '((0 . "ELLIPSE")))
    (progn
      (vla-StartUndoMark acdoc)
      (vlax-for	e (setq ss (vla-get-ActiveSelectionSet acdoc))
	(EllipseToPolyline e)
	(vla-delete e)
      )
      (vla-delete ss)
      (vla-EndUndoMark acdoc)
    )
  )
  (princ)
)

;; PELL
;; Draws an ellipse or an elliptical arc approximation (polyline) on the fly
(defun c:pell (/ *error* ec pe old ent)
  (vl-load-com)
  (defun *error* (msg)
    (if	(and msg
	     (/= msg "Fonction annulée")
	     (/= msg "Function cancelled")
	)
      (princ (strcat (if (= "FRA" (getvar 'locale))
		       "\nErreur: "
		       "\Error: "
		     )
		     msg
	     )
      )
    )
    (setvar 'cmdecho ec)
    (setvar 'pellipse pe)
    (princ)
  )
  (setq	ec  (getvar 'cmdecho)
	pe  (getvar 'pellipse)
	old (entlast)
  )
  (setvar 'cmdecho 1)
  (setvar 'pellipse 0)
  (command "_.ellipse")
  (while (/= 0 (getvar 'cmdactive))
    (command pause)
  )
  (if (not (eq old (setq ent (entlast))))
    (progn
      (EllipseToPolyline (vlax-ename->vla-object ent))
      (entdel ent)
    )
  )
  (*error* nil)
)


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 15

MikeKovacik4928
Advisor
Advisor

Gilles

 

Perfect!!

Thanks

 

Mike

0 Likes
Message 6 of 15

Kent1Cooper
Consultant
Consultant

Be aware that an Ellipse made with PELLIPSE = 1 has only 16 vertices, and is an approximation  of a true elliptical shape.  It may be plenty precise for your purposes, but if you need greater accuracy, you can do this:

 

Use ReverseDirection.lsp and its RD command, available >here<.  It can reverse the direction of various things that AutoCAD's REVERSE command cannot, and in the case of an Ellipse, it does it by making a Spline  running the other way [if you agree to that -- you will be asked whether to convert it].  It asks for a precision, and you can ask for any number of defining points you want.  It offers 24 as the initial default, which is already of higher precision than AutoCAD's ellipse-approximating Polyline, but you can ask for thousands if you like.  Then you can use SPLINEDIT to convert the resulting Spline to a Polyline if that's what you need, in which command you will also be asked for a precision.

Kent Cooper, AIA
Message 7 of 15

_gile
Consultant
Consultant

One advantage of the polyline approximation is that it only contains circular arcs.
Some CNC machines do not like ellipses, and generally hate splines.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 8 of 15

MikeKovacik4928
Advisor
Advisor

Kent

 

Thanks, I will bear that in mind and have a look at that lisp.

However for my purposes it is more than adequate.

It is not for manufacturing or profile cutting, it is only for a silhouette outline I am

using for a wipeout on a 2d assembly drawings using standard library parts'

I am making the old blocks more accurate and the drawings look more "professional"

by incorporating wipeouts into the blocks so that lines overlapping each other don't cross

but are hidden, making it more like an actual 2d projected drawing, rather than a hodge podge

of crossing lines. The only other way was to actually explode all the blocks and trim the hidden lines out,

but that was not an option. I have gradually been doing this exercise of updating all the library blocks

with wipeouts and attributes for the last 2 years.

Unfortunately, I am the only one using them, no-one else uses them, as. unfortunately,

 we don't have any form of standardisation, or any central location of blocks on a server. Everyone

uses their own blocks, own their own drives.

Crazy, I know, but beyond my control. I have suggested it to the drawing office management on a few occasions

and have now given up!!

 

Mike

 

Mike

 

0 Likes
Message 9 of 15

Kent1Cooper
Consultant
Consultant

@_gile wrote:

One advantage of the polyline approximation is that it only contains circular arcs.
Some CNC machines do not like ellipses, and generally hate splines.


 

That's why I suggested SPLINEDIT at the end, to convert it.  That also results in an all-arc-segment Polyline, which can be to any desired higher degree of accuracy in tracing a true elliptical shape [again -- if needed, which it may not be for most people's purposes].

Kent Cooper, AIA
0 Likes
Message 10 of 15

ronjonp
Mentor
Mentor

@MikeKovacik4928 wrote:

...

by incorporating wipeouts into the blocks so that lines overlapping each other don't cross

 

 

Mike

 

Mike

 


FWIW, if you're using CTB to plot, you can use a solid hatch with RGB color set to 255,255,255 and achieve the same results. I used wipeouts many moons ago and they gave me more headaches with plotting than they were worth.

 

If you have the need for a circular wipeout, LEE has some code HERE to do that.

0 Likes
Message 11 of 15

MikeKovacik4928
Advisor
Advisor

that is exactly what I am doing with the shapes that have curves in them.

As you know wipeouts work only with straight line segments

Therefore I am using a combination of wipeouts for line silhouettes

and 255,255,255 solid hatching for curved silhouettes.

 

Mike

0 Likes
Message 12 of 15

ronjonp
Mentor
Mentor

 


@MikeKovacik4928 wrote:

that is exactly what I am doing with the shapes that have curves in them.

As you know wipeouts work only with straight line segments

Therefore I am using a combination of wipeouts for line silhouettes

and 255,255,255 solid hatching for curved silhouettes.

 

Mike


Why mix and match? You could just hatch the ellipses as well.

Message 13 of 15

MikeKovacik4928
Advisor
Advisor

You have a point there

Seeing that I am mixing wipeouts and solid hatching, why not solid hatch the ellipses

instead of converting them to polylines for wipeouts.

 

Good idea! I think I will do just that

 

Mike

0 Likes
Message 14 of 15

Kent1Cooper
Consultant
Consultant
Accepted solution

@MikeKovacik4928 wrote:

.... wipeouts work only with straight line segments....


 

If you're still interested [maybe not, in light of the latest Messages], there is a way to convert an Ellipse directly into a straight-line-segments-only Polyline, using a no-wobble application of the WPL command in WobblyPline.lsp -- check >this< out [it's even about that specific task, though applicable much more widely].

Kent Cooper, AIA
Message 15 of 15

MikeKovacik4928
Advisor
Advisor

Thanks Kent

I Will download and investigate. Your option sounds good too. I will use both and compare the pros and cons of each and report back

Mike

 

0 Likes