REQUEST FOR A LISP ARC TO LINE

REQUEST FOR A LISP ARC TO LINE

smallƑish
Advocate Advocate
2,174 Views
23 Replies
Message 1 of 24

REQUEST FOR A LISP ARC TO LINE

smallƑish
Advocate
Advocate

Replacing multiple arcs to pline, If both end of the arcs are on an orthogonal straight line, replace the arc with a straight line, If not on an ortho stright line find out the intersection point with reference to the arc mid-point direction, and make 3 point pline.

sample drawing. attached.

 

smallish_0-1703440367060.png

 

0 Likes
Accepted solutions (4)
2,175 Views
23 Replies
Replies (23)
Message 2 of 24

Kent1Cooper
Consultant
Consultant

That would not be difficult to code, but questions arise:

 

Your "after" runs L-shaped Polylines between Block insertion points that are close to Arc endpoints, but the Arc endpoints do not always lie at Block insertion points, nor coincide with the other Arc that ends in the vicinity:

Kent1Cooper_0-1703505377041.png

So something that converts an Arc to an L-shaped Polyline will not have the same result as your "after."  Which do you want -- Arcs or Blocks?

 

There is at least one Block that lies kind of near the path of one of the Arcs, but does not have any Arc endpoint(s) near it:

Kent1Cooper_1-1703505545164.png

And yet the "after" has two L's meeting at that Block.  Something that converts Arcs will not see or use that Block at all.  Should it go from selection of Blocks rather than Arcs?

And there are two L's possible connecting any two points that have differences in both X and Y coordinates [whether Arc endpoints or Block insertion points]:

Kent1Cooper_2-1703505856025.png

Can you define any criteria by which a routine could decide whether to do the red one or the blue one?  See also >this<.

 

And there's interesting related discussion, including code approaches to calculating the corners of the possible L's related to two known locations, >here<.

 

Kent Cooper, AIA
0 Likes
Message 3 of 24

smallƑish
Advocate
Advocate

First of all, thank you so much for a very detailed review of it as always your style.  Here my task is modifying existing drawings who prepared by someone else for better presentation and neat printing. As you instructed there are a lot of errors in it.  I have to correct it manually as we don't have any options. A screenshot is attached for better understanding. Regarding your 3rd screen shot the blue and red options, here doesn't matter both options are equal for the scenario.

 

 

smallish_0-1703510671604.png

 

 

0 Likes
Message 4 of 24

hak_vz
Advisor
Advisor

@smallƑish

Try this, not fully tested

(defun c:ACL( / *error* ss adoc x1 y1 x2 y2)
	(defun *error* ( msg )
		(if (not (member msg '("Function cancelled" "quit / exit abort")))
			(princ)
		)
		(if (and adoc) (vla-endundomark adoc))
		(princ)
	)
	(princ "\nSelect arcs to convert to line >")
	(setq ss (ssget '((0 . "ARC"))) i -1)
	(setq adoc (vla-get-activedocument (vlax-get-acad-object))) 
	(vla-endundomark adoc)
	(vla-startundomark adoc)
	(while (< (setq i (1+ i)) (sslength ss))
		(setq eo (vlax-ename->vla-object (ssname ss i)))
		(mapcar 'set '(x1 y1) (vlax-get eo 'startpoint))
		(mapcar 'set '(x2 y2) (vlax-get eo 'endpoint))
		(cond
			((or (< (abs(- x1 x2)) 1e-8)(< (abs(- y1 y2)) 1e-8))
				(entmake
					(list
						(cons 0 "LINE")
						(cons 100 "AcDbEntity")
						(cons 100 "AcDbLine")
						(cons 10 (trans(list x1 y1) 1 0))
						(cons 11 (trans(list x2 y2) 1 0))
					)
				)
			)
			
			(T		
				(entmake
					(list
						(cons 0 "LINE")
						(cons 100 "AcDbEntity")
						(cons 100 "AcDbLine")
						(cons 10 (trans(list x1 y1) 1 0))
						(cons 11 (trans(list x1 y2) 1 0))
					)
				)
				(entmake
					(list
						(cons 0 "LINE")
						(cons 100 "AcDbEntity")
						(cons 100 "AcDbLine")
						(cons 10 (trans(list x1 y2) 1 0))
						(cons 11 (trans(list x2 y2) 1 0))
					)
				)
			)
		)
	)
	(vla-endundomark adoc)
	(princ)
)

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 5 of 24

smallƑish
Advocate
Advocate

@hak_vz  @It does the task. But the arcs are not deleting after making PLINE.

0 Likes
Message 6 of 24

hak_vz
Advisor
Advisor
Accepted solution

@smallƑish wrote:

@hak_vz  @It does the task. But the arcs are not deleting after making PLINE.


(defun c:ACL( / *error* ss adoc x1 y1 x2 y2)
	(defun *error* ( msg )
		(if (not (member msg '("Function cancelled" "quit / exit abort")))
			(princ)
		)
		(if (and adoc) (vla-endundomark adoc))
		(princ)
	)
	(princ "\nSelect arcs to convert to line >")
	(setq ss (ssget '((0 . "ARC"))) i -1)
	(setq adoc (vla-get-activedocument (vlax-get-acad-object))) 
	(vla-endundomark adoc)
	(vla-startundomark adoc)
	(while (< (setq i (1+ i)) (sslength ss))
		(setq eo (vlax-ename->vla-object (ssname ss i)))
		(mapcar 'set '(x1 y1) (vlax-get eo 'startpoint))
		(mapcar 'set '(x2 y2) (vlax-get eo 'endpoint))
		(cond
			((or (< (abs(- x1 x2)) 1e-8)(< (abs(- y1 y2)) 1e-8))
				(entmake
					(list
						(cons 0 "LINE")
						(cons 100 "AcDbEntity")
						(cons 100 "AcDbLine")
						(cons 10 (trans(list x1 y1) 1 0))
						(cons 11 (trans(list x2 y2) 1 0))
					)
				)
			)
			
			(T		
				(entmake
					(list
						(cons 0 "LINE")
						(cons 100 "AcDbEntity")
						(cons 100 "AcDbLine")
						(cons 10 (trans(list x1 y1) 1 0))
						(cons 11 (trans(list x1 y2) 1 0))
					)
				)
				(entmake
					(list
						(cons 0 "LINE")
						(cons 100 "AcDbEntity")
						(cons 100 "AcDbLine")
						(cons 10 (trans(list x1 y2) 1 0))
						(cons 11 (trans(list x2 y2) 1 0))
					)
				)
			)
		)
		(vla-delete eo)
	)
	
	(vla-endundomark adoc)
	(princ)
)

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 7 of 24

komondormrex
Mentor
Mentor
Accepted solution

for starter. needs each pline to be tuned in direction.

;*******************************************************************************************************************************************

(defun get_approximation_list (arc / approximation_steps approximation_distance approximation_point_list point_index)
	(setq approximation_steps (fix (/ (vla-get-arclength arc) (* 0.25 (vla-get-radius arc))))
		  approximation_distance (/ (vla-get-arclength arc) approximation_steps)
		  approximation_point_list (list (vlax-get arc 'startpoint))
		  point_index 0
	)
	(repeat approximation_steps
	  	(setq approximation_point_list (append approximation_point_list 
											  (list (vlax-curve-getpointatdist 
											  			arc 
											  			(* approximation_distance (setq point_index (1+ point_index)))
													)
											  )
									   )
		)
	)
	approximation_point_list
)

;*******************************************************************************************************************************************

(defun c:sf_arc_pline (/ arc_sset block_sset vertex_list)
	(if (setq arc_sset (ssget '((0 . "arc"))))
		(foreach arc (mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr (ssnamex arc_sset))))
			(setq block_sset (ssget "_f" (get_approximation_list arc) (list '(0 . "insert") (cons 2 "-ep-down light"))))
			(if block_sset
				(progn
					(setq vertex_list (mapcar '(lambda (vertex) (mapcar '+ '(0 0) vertex)) 
											   (mapcar '(lambda (insert) (cdr (assoc 10 (entget insert))))
														(vl-remove-if 'listp (mapcar 'cadr (ssnamex block_sset)))
											   )
									  )
					)
					(foreach segment (setq segment_list (mapcar 'list vertex_list (cdr vertex_list)))
						(command "_pline" "_non" (car segment) 
										  "_non" (list (car (car segment)) (cadr (cadr segment))) 
										  "_non" (cadr segment) ""
						)
					)
				)
			)
		)
	)
)

;*******************************************************************************************************************************************

 

Message 8 of 24

smallƑish
Advocate
Advocate

@hak_vz Thank you, That works for me. You saved me a ton of time. Respect and appreciate your dedication to help. 

Message 9 of 24

smallƑish
Advocate
Advocate

@komondormrex   for the thunderous code!

The automatic alignment of each block's basepoint in your code was a game-changer. It significantly simplified the process of correcting the drawing.

 

Eagerly await the next version as you mentioned it is a starter.

If possible please consider, all selected blocks basepoint  instead of only the Block name "-ep-down light"

Thank you 

0 Likes
Message 10 of 24

Kent1Cooper
Consultant
Consultant
Accepted solution

Here's my take on it [lightly tested]:

 

(defun C:DOIT (/ peac ss n arc startpt endpt ctr cornerA cornerB)
  (setq peac (getvar 'peditaccept))
  (setvar 'peditaccept 1)
  (if (setq ss (ssget "_:L" '((0 . "ARC"))))
    (repeat (setq n (sslength ss)); then
      (setq
        arc (ssname ss (setq n (1- n)))
        startpt (getpropertyvalue arc "startpoint")
        endpt (getpropertyvalue arc "endpoint")
        ctr (getpropertyvalue arc "center")
        cornerA (list (car startpt) (cadr endpt))
        cornerB (list (car endpt) (cadr startpt))
      ); setq
      (command "_.pedit" arc "_edit" "_straighten" "_next" "_go")
      (if (or (equal (car startpt) (car endpt) 1e-4) (equal (cadr startpt) (cadr endpt) 1e-4))
        (command "_eXit" ""); then -- single line segment only
        (command ; else -- L
          "_insert" "_non"
          (if
            (and
              (> (distance ctr cornerA) (distance ctr cornerB))
              (< (getpropertyvalue arc "totalangle") pi)
            ); and
            cornerA cornerB
          ); if
          "_eXit" ""
        ); command
      ); if
    ); repeat
    (prompt "\nNo Arc(s) on unlocked Layer(s) selected."); else
  ); if
  (setvar 'peditaccept peac)
  (prin1)
); defun

 

It does it by PEDITing the Arcs into Polylines, and changing them to line segments and adding a vertex if appropriate, so that they retain all their properties [Layer, color, linetype, linetype scale, lineweight] without the routine needing to account for any of that.

If the Arc's endpoints align in either the X or Y direction, it does only the single line segment, otherwise making the L.  The direction of the "bulge" of the L is in the direction of the Arc's bulge, so that, for example, the white original at left here will result in the green L's, not the red ones [overlapping segments] or the yellow ones [crossing Polylines].

Kent1Cooper_0-1703686919225.png

It could use the addition of *error* handling and Undo begin/end wrapping, but first see whether it does what you want otherwise.  It could also easily have the forcing of the endpoints to a nearby Block insertion point [if there is one -- might there ever not be?] included within the PEDIT operation.

Kent Cooper, AIA
Message 11 of 24

smallƑish
Advocate
Advocate

Your approach to problem-solving was truly impressive, filled with valuable insights and fresh information. It effectively serves the purpose of updating my drawing needs. 

0 Likes
Message 12 of 24

smallƑish
Advocate
Advocate

I wish to request an addition to the process, to make it more neat to read the drawings. 

possible to add a chamfer tip on the edges, concerning user-given length.

 

 

smallish_0-1703690037613.png

Yellow is the Existing arc, Cian is Pline what your code does, and Red Pline is my additional code request 

 

smallish_1-1703690155103.png

If the user can enter the value, it could be much easier for different drawing scales. 

 

 

 

 

smallish_2-1703690365170.png

so final the result could be like this

0 Likes
Message 13 of 24

Kent1Cooper
Consultant
Consultant

So not what's described in Message 1 any more....

 

That's certainly possible [though considerably more complex].  But there can be strange results, for example, when the difference in X or Y is small relative to the landing length, it would get results like this:

Kent1Cooper_0-1703692037945.png

Could you define any criteria for handling that differently, and in what way?  Maybe something like:

Kent1Cooper_1-1703692255984.png

 

 

Kent Cooper, AIA
0 Likes
Message 14 of 24

smallƑish
Advocate
Advocate

smallish_0-1704023073106.png

like this 

 

Updated reply.

0 Likes
Message 15 of 24

smallƑish
Advocate
Advocate

In most cases, the champer length would be less than that. if any rare or mistake cases; 

 

If the polar distance is less than the landing champer length. either consider it as a straight line rule, or reduce the chamfer length from the user entered

0 Likes
Message 16 of 24

Kent1Cooper
Consultant
Consultant

The imagery in Message 14 suggests you should consider whether, even in more straightforward situations, what you really want should be the yellow here, instead of the red as in Message 12:

Kent1Cooper_0-1703698143754.png

The red result would be easier, because the intermediate vertices are all offset in the same direction from the vertices of the plain L shape, whereas in the yellow result, each of them is offset in a different direction.

Kent Cooper, AIA
Message 17 of 24

Kent1Cooper
Consultant
Consultant

@smallƑish wrote:

In most cases, the champer length would be less than that. if any rare or mistake cases; ....


In your original, this situation is more common, not rare at all -- the ones I turned magenta and red are all in that kind of relationship between their ends:

Kent1Cooper_0-1703698609440.png

The red one is different in that I think it's really supposed to be two Arcs [because of your green intended result], but even if it were two that would be yellow, the magenta ones are still in the majority.

Kent Cooper, AIA
Message 18 of 24

smallƑish
Advocate
Advocate

Yes, I agree with you.  Red is the perfect option.

0 Likes
Message 19 of 24

smallƑish
Advocate
Advocate

Yes, I realize the fact. Hence do we have any options to consider, that wherever the arc ends are less than the landing length distance from a polar line, can we apply the straight line rule? 

0 Likes
Message 20 of 24

smallƑish
Advocate
Advocate
IS that ok to share your testing code?
0 Likes