Please help! Parallel Line Lisp Failing

Please help! Parallel Line Lisp Failing

Anonymous
Not applicable
1,896 Views
12 Replies
Message 1 of 13

Please help! Parallel Line Lisp Failing

Anonymous
Not applicable

Hi everyone. 

I attempted to right a lisp that would compare multiple lines to one reference line, and if the lines were parallel to turn them red and if not to turn them yellow. I need this to be as precise as possible. Here is my attempt, if anyone has any insight please let me know.

Thanks

 

toreyrueschhoff_0-1599673217733.png

 

0 Likes
Accepted solutions (2)
1,897 Views
12 Replies
Replies (12)
Message 2 of 13

pendean
Community Legend
Community Legend
Can you post the actual LSP file please?
0 Likes
Message 3 of 13

Anonymous
Not applicable

Yup!

Sorry about that, here you go.

 

 

0 Likes
Message 4 of 13

ВeekeeCZ
Consultant
Consultant
Accepted solution

Post the drawing with failing examples.

 

IMHO the code looks good and works. Only thing I have noticed that you are comparing real numbers without fuzz. That might be a cause of your issues. Use the equal for the comparison:

 

((equal refangle comangle 1e-3) (vlax-put-property vlaEntcom 'Color 1))

 

Edit: Also noticed that you use 180. You should use PI instead, since get-angle returns an angle in radians.

Message 5 of 13

Anonymous
Not applicable

Well I need it to be as precise as possible. I'm trying to detect up to .00000001 degree difference. And the other thing that fails is when I rotate the line I am comparing by 180 degrees. I will try to post pics shortly

0 Likes
Message 6 of 13

ВeekeeCZ
Consultant
Consultant

See my edit note in previous msg.

You need to work in rads, or convert rads to dgr. That's your issue. See HERE  what get-angle returns.

0 Likes
Message 7 of 13

Anonymous
Not applicable

Here is the photo you requested, I apologize I didn't have much time to clean it up

 

toreyrueschhoff_0-1599677695645.png

 

 

0 Likes
Message 8 of 13

Anonymous
Not applicable

Okay let me try that.

0 Likes
Message 9 of 13

Anonymous
Not applicable

Thank you that worked for the 180 degree flip, could you give me the syntax for fuzz? Do I just put the willing amount of difference after the two values I want to equal?

0 Likes
Message 10 of 13

ВeekeeCZ
Consultant
Consultant
Accepted solution

Yes. But see yourself HERE in help.

Message 11 of 13

Anonymous
Not applicable

Yes!! Thank you!

Message 12 of 13

hak_vz
Advisor
Advisor

 

(defun collinear (p1 p2 p3 p4 / a b e)
	; Author: Miljenko Hatlak (hak_vz)
	; 14.02.2020.
	; https://forums.autodesk.com/t5/user/viewprofilepage/user-id/5530556
	; Test if two 2d line segments overlap 
	; p1________p3______p4________p2
	; Usage (collinear (getpoint)(getpoint)(getpoint)(getpoint))
	; return: Boolean value
	
	;Align vectors to point to same direction
	(if (/= (angle p1 p2) (angle p3 p4))(setq e p3 p3 p4 p4 e))
	; Calculate distance of a point and its projection
	(setq 
		a (distance p3 (perpendicular_from_point_to_line p1 p2  p3))
		b (distance p4 (perpendicular_from_point_to_line p1 p2  p4))
	)
	(and
		;Collinearity test - if projection of a point to the line is "that same point"
		; points are colinear
		(and a (<= a 1e-7))
		(and b (<= b 1e-7))
		
		;Test for overlapping
		(or
			(= (+ (distance p1 p3) (distance p2 p3))(distance p1 p2))
			(= (+ (distance p1 p4) (distance p2 p4))(distance p1 p2))
			(> (distance p3 p4)(distance p2 p4))
		)
		;If edgepoints coincide asume they don't overlap
		(not (apply '= (mapcar '= p2 p3)))
		(not (apply '= (mapcar '= p1 p4)))
	)
)
(defun perpendicular_from_point_to_line (lin1 lin2 p / x1 y1 x2 y2 x3 y3 k m n ret)
;returns point on a line (line1 line2) as a perpendicular projection from point p
	(mapcar 'set '(x1 x2 x3) (mapcar 'car (list lin1 lin2 p)))
	(mapcar 'set '(y1 y2 y3) (mapcar 'cadr (list lin1 lin2 p)))
	(setq 
		m (-(*(- y2 y1) (- x3 x1))(*(- x2 x1) (- y3 y1)))
		n (+(* (- y2 y1)(- y2 y1))(*(- x2 x1)(- x2 x1)))
	)
	(cond 
		((/= n 0.0) 
			(setq 
				k (/ m n)
				ret (list(- x3 (* k(- y2 y1)))(+ y3 (* k(- x2 x1))))
			)
		)
	)
	ret
)

 

 

Here is my code I've used in one of my scripts. Collinearity is not your subject but it may be useful. Function perpendicular_from_point_to_line gives projection point of a point on a line A to line B.

If you find projection points for a start end end point of line A to line B and compare lengths of projection lines you don't have to relay on angle comparison. Arguments are lin1 '((line1_start) (line1_end)) lin2 '((line2_start) (line2_end)) and p is any point on a line1, let say start point.

 

Also when compare two numbers on a decimal places one of the options is to multiply both values with some large coefficient and compare  absolute value of its difference, ie. 0.00001515 0.00001521  multiply by 1e8 and you have to calculate if difference is larger than threshold  value. This apply for small numbers , so to get rid of number part left of decimal point multiply it with coefficient, divide with him and take 1 down i.e (k*m / k) - 1.

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.
0 Likes
Message 13 of 13

leeminardi
Mentor
Mentor

@Anonymous 

"...I'm trying to detect up to .00000001 degree difference..."

 

That's a very small angle which is beyond the precision you may be able to get with the get-angle function.  Also note that angle precision is a function of the distance between the ends of the line.

In the image below I copied the top white line 3 times and then trimmed the copies by different amounts. TESTPL3.lsp (without any fuzz) was used. Notice that the two shortest lines were not considered parallel but the least trimmed line was considered parallel. 

image.png

In the above example the white line is about 10 long.  The 4 lines were located near 0,0,0.

 

I made a copy of the 4 trimmed lines displaced by 100000 in x and re-executed TESTPL3.  Here is the result.

image.png

All 3 trimmed lines are identified as not be parallel!  Remember that all line vertices have a finite precision.  The precision is about 15 significant digits.   As you move further from 0,0,0 more of those 15 digits are used to the left of the decimal point leaving fewer to the right.  This limits the angle precision of lines at random angle.   Another way to think of this is to draw a line at an angle on grid paper with the restriction that a line at an angle must start and end at a grid intersection.  The shorter the line the less flexibility you have in defining its angle.

 

I was thinking of another approach to this would be to take a dot product of a vector from point 1 to 2 with a vector from 3 to 4 and then to divide by the product of the two vector's magnitude.  This would yield the cosine of the angle between the two lines.  If this number is close to 1 then they are almost parallel. One problem with this approach is that the cosine function is very flat at angles near 0 degrees.  To address this you could reverse the x and y components of one of the vector thus making it perpendicular and then take the dot product. In this case a value 0 for the cosine  (or near 0) would indicate that the vectors were perpendicular and the lines parallel. 

 

Bottom line?  It is important to include a fuzz factor but what you use for the fuzz and its value is critical.

lee.minardi
0 Likes