93 lines
2.4 KiB
Plaintext
93 lines
2.4 KiB
Plaintext
|
|
||
|
/* A line is defined by its end points. */
|
||
|
/* This class shows examples of calling its own and other class */
|
||
|
/* predicates. */
|
||
|
|
||
|
:- object(line(_Point1, _Point2)).
|
||
|
|
||
|
|
||
|
:- info([
|
||
|
authors is 'Paulo Moura',
|
||
|
version is 1.0,
|
||
|
date is 2000/4/22,
|
||
|
comment is 'Parametric object for representing geometric lines.',
|
||
|
parnames is ['Point1', 'Point2'],
|
||
|
source is 'Example adopted from the POEM system by Ben Staveley-Taylor.']).
|
||
|
|
||
|
|
||
|
:- public(length/1).
|
||
|
:- mode(length(-number), one).
|
||
|
|
||
|
:- public(intersects/1).
|
||
|
:- mode(intersects(+nonvar), one).
|
||
|
|
||
|
:- public(signed_distance/2).
|
||
|
:- mode(signed_distance(+nonvar, -number), one).
|
||
|
|
||
|
:- public(distance/2).
|
||
|
:- mode(distance(+nonvar, -number), one).
|
||
|
|
||
|
|
||
|
length(Length) :-
|
||
|
/* sets Len to the length of the owner line */
|
||
|
parameter(1, P1),
|
||
|
parameter(2, P2),
|
||
|
P1::distance(P2, Length).
|
||
|
|
||
|
|
||
|
intersects(Line2) :-
|
||
|
/* succeeds if Line2 intersects the owner line. */
|
||
|
/* this isn't necessarily a good method, but shows how to */
|
||
|
/* call class procedures from within the class definition. */
|
||
|
parameter(1, P1),
|
||
|
parameter(2, P2),
|
||
|
Line1 = line(P1, P2),
|
||
|
Line2 = line(P3, P4),
|
||
|
Line2::signed_distance(P1, D1),
|
||
|
Line2::signed_distance(P2, D2),
|
||
|
opposite_signs(D1, D2),
|
||
|
Line1::signed_distance(P3, D3),
|
||
|
Line1::signed_distance(P4, D4),
|
||
|
opposite_signs(D3, D4).
|
||
|
|
||
|
|
||
|
signed_distance(Point, Dist) :-
|
||
|
/* finds the perpendicular distance from point to line. */
|
||
|
/* the sign of the answer depends on which side of the */
|
||
|
/* line the point is on. */
|
||
|
parameter(1, P1),
|
||
|
parameter(2, P2),
|
||
|
P1 = point(X1, Y1),
|
||
|
P2 = point(X2, Y2),
|
||
|
Point = point(X3, Y3),
|
||
|
A is X2-X1,
|
||
|
B is Y1-Y2,
|
||
|
C is X1*Y2-X2*Y1,
|
||
|
Dist is (A*Y3+B*X3+C)/sqrt(A*A+B*B).
|
||
|
|
||
|
|
||
|
distance(Point, Dist) :-
|
||
|
/* as 'signed_distance', but Dist always >= 0 */
|
||
|
parameter(1, P1),
|
||
|
parameter(2, P2),
|
||
|
line(P1, P2)::signed_distance(Point, Temp),
|
||
|
Dist is abs(Temp).
|
||
|
|
||
|
|
||
|
/* 'opposite_signs' succeeds if its arguments are of opposite signs. */
|
||
|
/* It has a feature in that 'opposite_signs(0,0)' succeeds: this is */
|
||
|
/* because 0 is treated as having optional sign. */
|
||
|
|
||
|
opposite_signs(A, B) :-
|
||
|
o_s_aux(A, B).
|
||
|
|
||
|
opposite_signs(A, B) :-
|
||
|
o_s_aux(B, A).
|
||
|
|
||
|
o_s_aux(A, B) :-
|
||
|
A >= 0,
|
||
|
B =< 0.
|
||
|
|
||
|
|
||
|
:- end_object.
|