LISP To Convert Curves Into Multi-faceted Line Segments

LISP To Convert Curves Into Multi-faceted Line Segments

leekennewell
Contributor Contributor
2,052 Views
7 Replies
Message 1 of 8

LISP To Convert Curves Into Multi-faceted Line Segments

leekennewell
Contributor
Contributor

I need a LISP that converts curves into multi-faceted straight lines.  Please also instruct how to install (if applicable) & use it.

This will (hopfully) allow me to quickly create a wipeout polyline for complex geometry that have many non-line segments.  Note - I understand wipeout allows you to draw a polyline but this is time consuming and not affective with curves.

0 Likes
2,053 Views
7 Replies
Replies (7)
Message 2 of 8

TheCADnoob
Mentor
Mentor

Have you looked into the Wipeout option in SUPERHATCH?

https://help.autodesk.com/view/ACD/2023/ENU/?guid=GUID-89FB15FE-28B9-4A51-BACA-A393469EE1A6

 

CADnoob

EESignature

Message 3 of 8

gbattinPH5TG
Advocate
Advocate

This is from Giles Chanteau:

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/wipeout-with-arcs/m-p/12285968/highl...

 

;;; OB2WO (gile) -Gilles Chanteau- 10/03/07
;;; Creates a "Wipeout" from an object (circle, ellipse, or polyline with arcs)
;;; Works whatever the current ucs and object OCS
;;; http://forums.autodesk.com/t5/Visual-LISP-AutoLISP-and-General/wipeout-with-arcs/m-p/786490#M12148

(defun c:ob2wo (/ ent lst nor)
  (vl-load-com)
  (if (and (setq ent (car (entsel)))
	   (member (cdr (assoc 0 (entget ent)))
		   '("CIRCLE" "ELLIPSE" "LWPOLYLINE")
	   )
	   (setq lst (ent2ptlst ent))
	   (setq nor (cdr (assoc 210 (entget ent))))
      )
    (progn
      (vla-StartundoMark
	(vla-get-ActiveDocument (vlax-get-acad-object))
      )
      (makeWipeout lst nor)
      (initget "Yes No")
      (if
	(= (getkword "\nDelete source object? [Yes/No] <No>: ")
	   "Yes"
	)
	 (entdel ent)
      )
      (vla-EndundoMark
	(vla-get-ActiveDocument (vlax-get-acad-object))
      )
    )
  )
)


;;; ENT2PTLST
;;; Returns the vertices list of the polygon figuring the curve object
;;; Coordinates defined in OCS

(defun ent2ptlst (ent / obj dist n lst p_lst prec)
  (vl-load-com)
  (if (= (type ent) 'ENAME)
    (setq obj (vlax-ename->vla-object ent))
  )
  (cond
    ((member (cdr (assoc 0 (entget ent))) '("CIRCLE" "ELLIPSE"))
     (setq dist	(/ (vlax-curve-getDistAtParam
		     obj
		     (vlax-curve-getEndParam obj)
		   )
		   50
		)
	   n	0
     )
     (repeat 50
       (setq
	 lst
	  (cons
	    (trans
	      (vlax-curve-getPointAtDist obj (* dist (setq n (1+ n))))
	      0
	      (vlax-get obj 'Normal)
	    )
	    lst
	  )
       )
     )
    )
    (T
     (setq p_lst (vl-remove-if-not
		   '(lambda (x)
		      (or (= (car x) 10)
			  (= (car x) 42)
		      )
		    )
		   (entget ent)
		 )
     )
     (while p_lst
       (setq
	 lst
	  (cons
	    (append (cdr (assoc 10 p_lst))
		    (list (cdr (assoc 38 (entget ent))))
	    )
	    lst
	  )
       )
       (if (/= 0 (cdadr p_lst))
	 (progn
	   (setq prec (1+ (fix (* 25 (sqrt (abs (cdadr p_lst))))))
		 dist (/ (- (if	(cdaddr p_lst)
			      (vlax-curve-getDistAtPoint
				obj
				(trans (cdaddr p_lst) ent 0)
			      )
			      (vlax-curve-getDistAtParam
				obj
				(vlax-curve-getEndParam obj)
			      )
			    )
			    (vlax-curve-getDistAtPoint
			      obj
			      (trans (cdar p_lst) ent 0)
			    )
			 )
			 prec
		      )
		 n    0
	   )
	   (repeat (1- prec)
	     (setq
	       lst (cons
		     (trans
		       (vlax-curve-getPointAtDist
			 obj
			 (+ (vlax-curve-getDistAtPoint
			      obj
			      (trans (cdar p_lst) ent 0)
			    )
			    (* dist (setq n (1+ n)))
			 )
		       )
		       0
		       ent
		     )
		     lst
		   )
	     )
	   )
	 )
       )
       (setq p_lst (cddr p_lst))
     )
    )
  )
  lst
)


;;; MakeWipeout creates a "wipeout" from a points list and the normal vector of the object

(defun MakeWipeout (pt_lst nor / dxf10 max_dist cen dxf_14)
  (if (not (member "acismui.arx" (arx)))
    (arxload "acismui.arx")
  )
  (setq	dxf10 (list (apply 'min (mapcar 'car pt_lst))
		    (apply 'min (mapcar 'cadr pt_lst))
		    (caddar pt_lst)
	      )
  )
  (setq
    max_dist
     (float
       (apply 'max
	      (mapcar '- (apply 'mapcar (cons 'max pt_lst)) dxf10)
       )
     )
  )
  (setq cen (mapcar '+ dxf10 (list (/ max_dist 2) (/ max_dist 2) 0.0)))
  (setq
    dxf14 (mapcar
	    '(lambda (p)
	       (mapcar '/
		       (mapcar '- p cen)
		       (list max_dist (- max_dist) 1.0)
	       )
	     )
	    pt_lst
	  )
  )
  (setq dxf14 (reverse (cons (car dxf14) (reverse dxf14))))
  (entmake (append (list '(0 . "WIPEOUT")
			 '(100 . "AcDbEntity")
			 '(100 . "AcDbWipeout")
			 '(90 . 0)
			 (cons 10 (trans dxf10 nor 0))
			 (cons 11 (trans (list max_dist 0.0 0.0) nor 0))
			 (cons 12 (trans (list 0.0 max_dist 0.0) nor 0))
			 '(13 1.0 1.0 0.0)
			 '(70 . 7)
			 '(280 . 1)
			 '(71 . 2)
			 (cons 91 (length dxf14))
		   )
		   (mapcar '(lambda (p) (cons 14 p)) dxf14)
	   )
  )
)

 

0 Likes
Message 4 of 8

Valentin_CAD
Mentor
Mentor

@leekennewell ,

 

Use APPLOAD to load the Arc2seg.lsp.

 

Select the polyline with the arcs (this will make arcs to line segments).

If not closed, select Yes in the PROPERTIES, this will allow the WIPEOUT to work.

 

ValentinWSP_0-1698064169760.png

 

 

 

 

Before:

ValentinWSP_1-1698064169791.png

 

 

ValentinWSP_2-1698064169563.png

 

 

 

After:

ValentinWSP_3-1698064169670.png

 

ValentinWSP_4-1698064169694.png

 

 

 

ValentinWSP_5-1698064169756.png

 

 



Select the "Mark as Solution" if my post solves your issue or answers your question.

Seleccione "Marcar como solución" si mi publicación resuelve o responde a su pregunta.


Emilio Valentin

0 Likes
Message 5 of 8

Kent1Cooper
Consultant
Consultant

The attached PolylineArcsToLineSegments.lsp is a very much shorter way to convert arc segments in LWPolylines to multiple line segments.  So far it's limited to LWPolylines, because it's possible to filter selection of them to "see" only those that contain any arc segment(s), so you can select a whole area of stuff and it will ignore those without.  But with some expansion it could allow for "heavy" 2D Polylines, as well as [with a change in file and command names] Circles and Arcs.  It would then need to do some evaluating of each Polyline to determine whether it contains arc segments, instead of just proceeding with everything found in the selection.

 

It works on multiple Polylines, open or closed.  It doesn't contain Wipeout creation [not viable with open ones anyway], but its operation can easily be incorporated into something that does, with an added check that they're closed.

 

It takes advantage of the fact that SPLINEDIT's Polyline option converts a Spline into a Polyline with only line segments.  So the routine forces a Polyline to become a Spline, by BREAKing a small gap and drawing in a short straight Spline, then JOINing that to the rest for a Spline result.  Then it SPLINEDITs that into a Polyline.

 

It has the "drawback" that any line segments in the original will become subdivided with some short line segments at the ends, because of the way Splines handle straight parts in the vicinity of changes in direction.  But they're still collinear -- it makes no difference geometrically.

 

If needed for some high-precision requirement, you can play with the size of the gap it makes for its little Spline infix [currently 1/50 of the length of the first segment], and with the precision number 1 in the SPLINEDIT command [even at that lowest precision, it results in very short segments, it seems to me plenty short for Wipeout purposes].

Kent Cooper, AIA
0 Likes
Message 6 of 8

Kent1Cooper
Consultant
Consultant

@leekennewell wrote:

I need a LISP that converts curves into multi-faceted straight lines.  ....


All the suggestions so far are about Polyline arc segments and in some cases Circles and Arcs.  But since you use the word "curves" without restriction, which could also include Ellipses and Splines, I will suggest the attached WobblyPline.lsp routine, with its WPL command.  [It's around in this Forum already, but in older versions.]  Read the comments at the top of the file.

 

It makes any kind of finite AutoCAD (vlax-curve)-class object [Line, Arc, Circle, any kind of Polyline, Ellipse or Spline, open or closed] into a Polyline of line segments only, divided up into as many segments as you choose.  You tell it how much "wobble" you want, that is, how randomized the vertex locations should be relative to the path of the object you're wobblyizing.  When it asks for "Maximum displacement as percentage of average segment length:" give it zero, and the resulting Polyline vertices will all lie exactly on the source object's path, evenly spaced along it.

 

The main benefit it has is that you can use it to make a Wipeout-basis Polyline from even a Spline or Ellipse, as well as from the "usual suspects" already covered in this topic.  The drawback, if it is one, is that it must divide up the total length of the source object equally, which means that with a Polyline containing line segments, even those, however long, can be subdivided with intermediate vertices [depending on lengths relative to your specified number of segments].

 

Another benefit is that you don't need to have a Wipeout-boundary object already drawn to convert.  You can draw it inside the WPL command.  See the first options prompt.  If you do have something already drawn, use the EXisting option and select it.

 

You also get the choice of whether to keep or delete the source path object, so you can make a Wipeout from the Polyline it makes and still have the outline of it as its original object, when that's wanted.

Kent Cooper, AIA
Message 7 of 8

Ricardo092
Community Visitor
Community Visitor

Thanks for sharing your lisp file, it's the closest thing I've found so far to what I'm looking for.


How could I modify the file to indicate the maximum segment length or the maximum rotation angle instead of the number of segments into which I want to subdivide each arc?

 

This would be an indirect way of determining the number of segments into which each arc will be subdivided.

0 Likes
Message 8 of 8

Valentin_CAD
Mentor
Mentor

@Ricardo092 ,

 


@Ricardo092 wrote:


How could I modify the file to indicate the maximum segment length or the maximum rotation angle instead of the number of segments into which I want to subdivide each arc?


 

In your case, consider using the Arc2Lin utility (VLX-Lisp) to convert arc entities and circles to line objects (with the given accuracy). [Attached or download from HERE]

 

ValentinWSP_0-1730372375590.png

 



Select the "Mark as Solution" if my post solves your issue or answers your question.

Seleccione "Marcar como solución" si mi publicación resuelve o responde a su pregunta.


Emilio Valentin

0 Likes