Finding lines that are not straight.

Finding lines that are not straight.

keshishian
Contributor Contributor
3,722 Views
26 Replies
Message 1 of 27

Finding lines that are not straight.

keshishian
Contributor
Contributor

Hello,

 

Attached is a lisp command that moves all "non straight" lines to a new layer. It is very accurate or (not accurate) and moves a lot of good lines to the new layer. Is there a way to:

1- Isolate lines that are between a few degrees of 90 and 270, compare their x coordinates, and if not 0 move to the new layer?

1- Isolate lines that are between a few degree of 0 and 180, compare their y coordinates, and if not 0 move to the new layer?

 

Any suggestion will be very much appreciated. Application used is AutoCAD 2024 LT

 

Thank You.

0 Likes
Accepted solutions (1)
3,723 Views
26 Replies
Replies (26)
Message 2 of 27

Kent1Cooper
Consultant
Consultant

[You don't really mean "straight" -- all LINEs are necessarily straight -- but rather "orthogonal."]

 

That would involve changing (=) functions [which require exact equality] to (equal) functions with a fuzz factor for determination of whethery they are within "a few degrees."  It shouldn't be difficult to make that adjustment, and distinguish the almost-vertical from the almost-horizontal, but you will need to define "a few degrees" more specifically.

Kent Cooper, AIA
0 Likes
Message 3 of 27

keshishian
Contributor
Contributor

Thank you for your reply, and and yes I meant orthogonal. The plus minus range will be 2 degrees or 0.0349066 radians. Is this the line you are referring to? (Sorry, I am not very good at lisp and had help writing this a long time ago.)

 

if (and (not (= ang 0.0)) (not (= ang a1)) (not (= ang pi)) (not (= ang a3)))

 

Thanks again.

0 Likes
Message 4 of 27

Kent1Cooper
Consultant
Consultant

Yes, that's the code line that is checking whether the angle of the Line is not any of the orthogonal directions.  It would need to be split into two cases if you want to distinguish almost-vertical from almost-horizontal, although it's not clear to me that you do, since you say "the new Layer" in both cases as if there's only one, and since the items are both numbered 1.

Kent Cooper, AIA
0 Likes
Message 5 of 27

keshishian
Contributor
Contributor

Thank You.

0 Likes
Message 6 of 27

Kent1Cooper
Consultant
Consultant
Accepted solution

Try the attached NotQuiteOrthoLines.lsp and its NQOL command.  [I used the wording "Not Quite" rather than simply "NOT," because a Line at (for example) 45° is clearly NOT Orthogonal, but the whole point of the Topic seems to be that you don't want a Line like that flagged.]  You can change the tolerance for how far off of orthogonal to test for, and for how precisely orthogonal a Line needs to be to leave it alone, at the <-- EDIT lines.

 

It assigns to all such Lines, whether not quite horizontal or not quite vertical, on the same Layer/color, because your original did, but it could be made to differentiate.

 

It doesn't check the angle of a Line against all four directional possibilities, but rather looks at the (rem)ainder of the angle when divided by 90°, resulting in a single how-far-off-orthogonal-is-it value.  It checks against two values rather than four, i.e. whether that is within 2° of either 0° or 90°, because for a Line that's 1° off, that remainder could be either 1° or 89°.

 

As in your original, it puts things on the Layer and assigns the red color as a property override.  Consider assigning that color to the Layer, and making the Lines put on it BYLAYER in color.  That way, when you've fixed something that's a little off, you can just change it to its intended Layer, and won't also need to strip the color override from it.

 

And other questions arise....  The same kind of check for Polyline line segments or Mline segments?  [It couldn't change the Layer/color of an individual segment, so some other flagging method would be needed.]  The same kind of check for rotation angles of Blocks and/or Text and/or Mtext?

Kent Cooper, AIA
0 Likes
Message 7 of 27

komondormrex
Mentor
Mentor

hey,

making a list of non-ortho lines within 2 degrees deviation

(if (setq lines_sset (ssget "_x" '((0 . "line"))))
			(setq lines_list_notstraight (vl-remove-if '(lambda (line) (or 
													 				   	   (equal (vla-get-angle line) 0 		  (/ pi 90))
																		   (equal (vla-get-angle line) (* 0.5 pi) (/ pi 90))
			      														   (equal (vla-get-angle line) pi         (/ pi 90))
																		   (equal (vla-get-angle line) (* 1.5 pi) (/ pi 90))
													 				   	   (equal (vla-get-angle line) (* 2.0 pi) (/ pi 90))
												 				   	   )
							   					    	)
								  						(mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr (ssnamex lines_sset))))
							     		 )
			)
	)

 

0 Likes
Message 8 of 27

keshishian
Contributor
Contributor

Thank you so much Kent, this is exactly what I wanted and sorry for late reply. I don't use polylines or mlines.

0 Likes
Message 9 of 27

keshishian
Contributor
Contributor

Hello komondormrex, thank you for your reply. How do I make this a function so I can load with  APPLOAD?

I tried this but to no avail.

 

(defun NSLINE
(if (setq lines_sset (ssget "_x" '((0 . "line"))))
(setq lines_list_notstraight (vl-remove-if '(lambda (line) (or
(equal (vla-get-angle line) 0 (/ pi 90))
(equal (vla-get-angle line) (* 0.5 pi) (/ pi 90))
(equal (vla-get-angle line) pi (/ pi 90))
(equal (vla-get-angle line) (* 1.5 pi) (/ pi 90))
(equal (vla-get-angle line) (* 2.0 pi) (/ pi 90))
)
)
(mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr (ssnamex lines_sset))))
)
)
)
)

0 Likes
Message 10 of 27

komondormrex
Mentor
Mentor

hey there,

make it that way

 

(defun nslines (/ lines_sset lines_list_notstraight)
	(if (setq lines_sset (ssget "_x" '((0 . "line"))))
		(setq lines_list_notstraight (vl-remove-if '(lambda (line) (or 
					 				   	   (equal (vla-get-angle line) 0 	  (/ pi 90))
										   (equal (vla-get-angle line) (* 0.5 pi) (/ pi 90))
									   	   (equal (vla-get-angle line) pi         (/ pi 90))
										   (equal (vla-get-angle line) (* 1.5 pi) (/ pi 90))
					 				   	   (equal (vla-get-angle line) (* 2.0 pi) (/ pi 90))
				 				   	   )
			   				    )
				  			    (mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr (ssnamex lines_sset))))
			     		 )
		)
	)
  	(mapcar '(lambda (line) (entmod (append (entget (vlax-vla-object->ename line)) (list (cons 8 "NOTSTRAIGHT")) (list (cons 62 1))))) lines_list_notstraight)
  	(princ)
)

 

0 Likes
Message 11 of 27

keshishian
Contributor
Contributor

Thank you very much.  I revised it to (defun c:nslines from (defun nslines

0 Likes
Message 12 of 27

keshishian
Contributor
Contributor
Hello Kent,
One quick question. I tried different precession values but could not make an angle of 0.0156 degree to be detected. That is an offset of of 1/32" at one end of a line. What is the smallest possible angle that this function can see? The precision of my drawing are always 1/64th. Thank you.

(equal offortho 0 1e-6); orthogonal <-- EDIT precision as desired
0 Likes
Message 13 of 27

Kent1Cooper
Consultant
Consultant

@keshishian wrote:
.... What is the smallest possible angle that this function can see? The precision of my drawing are always 1/64th. ....

(equal offortho 0 1e-6); orthogonal <-- EDIT precision as desired

For tighter precision in calculating what's close enough to orthogonal, increase the 6 [on two lines].  I'm not sure there's a minimum, except that AutoCAD can't deal with more than 16 significant figures, so there's no point in increasing it past somewhere around 16.

 

Of course, the angular difference caused by a coordinate difference of 1/64" between endpoints will vary depending on the length of the line.  Both these lines have the same Y-coordinate 1/64" error from end to end, but are at very different angles:

Kent1Cooper_0-1710884609728.png

 

Kent Cooper, AIA
0 Likes
Message 14 of 27

miroko
Enthusiast
Enthusiast

Hello,

 

This is very usefull function and I alsao like to thank since will be using it as well.

 

I tried to add some more actions to it like automatically select all the affected lines at the end so that user immediatelly see them all selected.

Could not figure out how to include such in the original lisp so added new command to end of lisp and created a script that runs the two commands one after another:

 

lisp:

 

(defun C:SelectNQOL ( / sel1)
(setq sel1 (ssget "_X" '((-4 . "<or")(8 . "NotQuiteOrtho")(-4 . "or>"))))
(sssetfirst nil sel1)
(princ)
)

 

 

script:

(load "NotQuiteOrthoLines.lsp")
NQOL
SelectNQOL

 

 

All is working fine but I guess this can be included somehow into the original lisp?

 

Then also new questions appeared.

Sometimes user would like to run the function only on a specific part of a drawing, not all (for various reasons).

How to edit the original lisp that is marked as solution in this thread so that user is asked to select objects to check.

For example if user first select the objects then start lisp then it would check only selected objects.

If user does not select anything before starting the lisp then lisp would ask if to run it on all dwg or asking to select objects.

 

Does someone have time to help implementing this?

 

regards

miroko

0 Likes
Message 15 of 27

Kent1Cooper
Consultant
Consultant

@miroko wrote:

.... to run the function only on a specific part of a drawing, not all (for various reasons).

How to edit the original lisp that is marked as solution in this thread so that user is asked to select objects to check.

....


For that, just remove the "_X".   It will then ask the User to select, and will "see" only Line objects among what they select.  It's a little more complicated to have it work on pre-selected objects, but that can be done -- maybe later.

Kent Cooper, AIA
Message 16 of 27

Kent1Cooper
Consultant
Consultant

@miroko wrote:

....

I tried to ... automatically select all the affected lines at the end so that user immediatelly see them all selected.

Could not figure out how to include such in the original lisp ....


For that, try adding the blue line [untested]:

....

    (princ (strcat "Not Quite Orthogonal Lines: " (itoa (sslength sss))))

    (sssetfirst nil sss)
  ); progn

....

Kent Cooper, AIA
Message 17 of 27

Kent1Cooper
Consultant
Consultant

The attached seems to do both those things -- accepts pre-selection, or if none containing Lines, asks for User selection*, and selects/grips/highlights results at the end -- in very limited testing.  [I put a 2 at the end of the file name to differentiate, but did not change the command name defined inside.]

 

*It has a quirk I may try to figure out later:  If there's no pre-selection, it allows normal multiple cumulative selection typical in editing commands and with (ssget).  But if there is a pre-selection, but it contains no Line(s), it asks the User to select, but somehow allows only one selection containing any Line(s) [one window, one pick], though it allows multiple tries until one contains any Line(s), and then it immediately proceeds with that.  Maybe the setting of ss with the (cond) function needs to be structured differently, but I'll have to work on that.

Kent Cooper, AIA
Message 18 of 27

miroko
Enthusiast
Enthusiast

I tried all three solutions and it works. Yes, there is this small "quirk" but it is not really anything worrying.

 

I see we can control the color of it by writing in code color number (1 is red, so we can put any other color).

(entmod (append edata (list '(8 . "NotQuiteOrtho") '(62 . 1))))

 

Thank you very much for help.

0 Likes
Message 19 of 27

Kent1Cooper
Consultant
Consultant

[For future reference, never use the "Reply to the Topic..." slot below the last Message.  When you do that, your Message always shows as being in Reply to the author of Message 1.  Instead, always use the REPLY or QUICK REPLY button at the bottom right in the Message you are actually Replying to.  That will show correctly to whom you are Replying.]

Kent Cooper, AIA
0 Likes
Message 20 of 27

miroko
Enthusiast
Enthusiast

Yes, you are right. I noticed this as well.

0 Likes