• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#objective-cqtwindows誰得cocoapythonphprubygameguibathyscaphec翻訳omegat計画中(planning stage)frameworktwittertestdomvb.netdirectxbtronarduinopreviewerゲームエンジン

Mercury Geometry and Math Library


Commit MetaInfo

Revision7ff29fb8f53f14a882d75b05af9a84155d2a317b (tree)
Zeit2022-04-24 05:04:00
AutorEmily Dioxideson <emily@eter...>
CommiterEmily Dioxideson

Log Message

Use vectors to implement geometry2d

Ändern Zusammenfassung

Diff

--- a/mmath.geometry2d.m
+++ b/mmath.geometry2d.m
@@ -20,30 +20,116 @@
2020
2121 %------------------------------------------------------------------------------%
2222
23-:- type segment --->
24- segment(seg_x1::float, seg_y1::float, seg_x2::float, seg_y2::float).
23+:- type segment ---> segment(seg_p1::vector2, seg_p2::vector2).
24+
25+:- func segment(float, float, float, float) = segment.
26+:- mode segment(in, in, in, in) = (out) is det.
27+:- mode segment(di, di, di, di) = (uo) is det.
28+:- mode segment(mdi, mdi, mdi, mdi) = (muo) is det.
29+:- mode segment(out, out, out, out) = (in) is det.
30+:- mode segment(uo, uo, uo, uo) = (di) is det.
31+:- mode segment(muo, muo, muo, muo) = (mdi) is det.
32+:- mode segment(in, in, in, in) = (in) is semidet. % implied.
33+
34+:- func seg_x1(segment) = float.
35+:- func seg_y1(segment) = float.
36+:- func seg_x2(segment) = float.
37+:- func seg_y2(segment) = float.
38+
39+:- func 'seg_x1 :='(float, segment) = segment.
40+:- func 'seg_y1 :='(float, segment) = segment.
41+:- func 'seg_x2 :='(float, segment) = segment.
42+:- func 'seg_y2 :='(float, segment) = segment.
2543
2644 %------------------------------------------------------------------------------%
2745
28-:- type rectangle --->
29- rectangle(rect_x::float, rect_y::float, rect_w::float, rect_h::float).
46+:- type rectangle ---> rectangle(
47+ rect_pt::vector2,
48+ rect_w::float,
49+ rect_h::float).
50+
51+:- func rectangle(float, float, float, float) = rectangle.
52+:- mode rectangle(in, in, in, in) = (out) is det.
53+:- mode rectangle(di, di, di, di) = (uo) is det.
54+:- mode rectangle(mdi, mdi, mdi, mdi) = (muo) is det.
55+:- mode rectangle(out, out, out, out) = (in) is det.
56+:- mode rectangle(uo, uo, uo, uo) = (di) is det.
57+:- mode rectangle(muo, muo, muo, muo) = (mdi) is det.
58+:- mode rectangle(in, in, in, in) = (in) is semidet. % implied.
59+
60+:- func rect_x(rectangle) = float.
61+:- func rect_y(rectangle) = float.
62+
63+:- func 'rect_x :='(float, rectangle) = rectangle.
64+:- func 'rect_y :='(float, rectangle) = rectangle.
3065
3166 %------------------------------------------------------------------------------%
3267
33-:- type circle --->
34- circle(circle_x::float, circle_y::float, radius::float).
68+:- type circle ---> circle(circle_center::vector2, radius::float).
69+
70+:- func circle(float, float, float) = circle.
71+:- mode circle(in, in, in) = (out) is det.
72+:- mode circle(di, di, di) = (uo) is det.
73+:- mode circle(mdi, mdi, mdi) = (muo) is det.
74+:- mode circle(out, out, out) = (in) is det.
75+:- mode circle(uo, uo, uo) = (di) is det.
76+:- mode circle(muo, muo, muo) = (mdi) is det.
77+:- mode circle(in, in, in) = (in) is semidet. % implied.
78+
79+:- func circle_x(circle) = float.
80+:- func circle_y(circle) = float.
81+
82+:- func 'circle_x :='(float, circle) = circle.
83+:- func 'circle_y :='(float, circle) = circle.
3584
3685 %------------------------------------------------------------------------------%
3786
38-:- type point --->
39- point(x::float, y::float).
87+:- type point == vector2.
88+
89+:- func point(float, float) = point.
90+:- mode point(in, in) = (out) is det.
91+:- mode point(di, di) = (uo) is det.
92+:- mode point(mdi, mdi) = (muo) is det.
93+:- mode point(out, out) = (in) is det.
94+:- mode point(uo, uo) = (di) is det.
95+:- mode point(muo, muo) = (mdi) is det.
96+:- mode point(in, in) = (in) is semidet. % implied.
97+
98+:- func x(point) = float.
99+:- func y(point) = float.
100+
101+:- func 'x :='(float, point) = point.
102+:- func 'y :='(float, point) = point.
40103
41104 %------------------------------------------------------------------------------%
42105
43-:- type triangle --->
44- triangle(tri_x1::float, tri_y1::float,
45- tri_x2::float, tri_y2::float,
46- tri_x3::float, tri_y3::float).
106+:- type triangle ---> triangle(
107+ tri_p1::vector2,
108+ tri_p2::vector2,
109+ tri_p3::vector2).
110+
111+:- func triangle(float, float, float, float, float, float) = triangle.
112+:- mode triangle(in, in, in, in, in, in) = (out) is det.
113+:- mode triangle(di, di, di, di, di, di) = (uo) is det.
114+:- mode triangle(mdi, mdi, mdi, mdi, mdi, mdi) = (muo) is det.
115+:- mode triangle(out, out, out, out, out, out) = (in) is det.
116+:- mode triangle(uo, uo, uo, uo, uo, uo) = (di) is det.
117+:- mode triangle(muo, muo, muo, muo, muo, muo) = (mdi) is det.
118+:- mode triangle(in, in, in, in, in, in) = (in) is semidet. % implied.
119+
120+:- func tri_x1(triangle) = float.
121+:- func tri_y1(triangle) = float.
122+:- func tri_x2(triangle) = float.
123+:- func tri_y2(triangle) = float.
124+:- func tri_x3(triangle) = float.
125+:- func tri_y3(triangle) = float.
126+
127+:- func 'tri_x1 :='(float, triangle) = triangle.
128+:- func 'tri_y1 :='(float, triangle) = triangle.
129+:- func 'tri_x2 :='(float, triangle) = triangle.
130+:- func 'tri_y2 :='(float, triangle) = triangle.
131+:- func 'tri_x3 :='(float, triangle) = triangle.
132+:- func 'tri_y3 :='(float, triangle) = triangle.
47133
48134 %------------------------------------------------------------------------------%
49135
@@ -123,22 +209,6 @@
123209
124210 %------------------------------------------------------------------------------%
125211
126-:- pred segment_endpoints(segment, point, point).
127-:- mode segment_endpoints(in, out, out) is det.
128-:- mode segment_endpoints(di, uo, uo) is det.
129-:- mode segment_endpoints(out, in, in) is det.
130-:- mode segment_endpoints(uo, di, di) is det.
131-
132-%------------------------------------------------------------------------------%
133-
134-:- pred triangle_endpoints(triangle, point, point, point).
135-:- mode triangle_endpoints(in, out, out, out) is det.
136-:- mode triangle_endpoints(di, uo, uo, uo) is det.
137-:- mode triangle_endpoints(out, in, in, in) is det.
138-:- mode triangle_endpoints(uo, di, di, di) is det.
139-
140-%------------------------------------------------------------------------------%
141-
142212 :- pred triangle_segments(triangle, segment, segment, segment).
143213 :- mode triangle_segments(in, out, out, out) is det.
144214
@@ -232,6 +302,76 @@
232302
233303 %------------------------------------------------------------------------------%
234304
305+:- pragma inline(segment/4).
306+segment(X1, Y1, X2, Y2) = segment(vector(X1, Y1), vector(X2, Y2)).
307+
308+seg_x1(segment(vector(X, _), _)) = X.
309+seg_y1(segment(vector(_, Y), _)) = Y.
310+seg_x2(segment(_, vector(X, _))) = X.
311+seg_y2(segment(_, vector(_, Y))) = Y.
312+
313+'seg_x1 :='(X, segment(vector(_, Y), P2)) = segment(vector(X, Y), P2).
314+'seg_y1 :='(Y, segment(vector(X, _), P2)) = segment(vector(X, Y), P2).
315+'seg_x2 :='(X, segment(P1, vector(_, Y))) = segment(P1, vector(X, Y)).
316+'seg_y2 :='(Y, segment(P1, vector(X, _))) = segment(P1, vector(X, Y)).
317+
318+%------------------------------------------------------------------------------%
319+
320+:- pragma inline(rectangle/4).
321+rectangle(X, Y, W, H) = rectangle(vector(X, Y), W, H).
322+
323+rect_x(rectangle(vector(X, _), _, _)) = X.
324+rect_y(rectangle(vector(_, Y), _, _)) = Y.
325+
326+'rect_x :='(X, rectangle(vector(_, Y), W, H)) = rectangle(vector(X, Y), W, H).
327+'rect_y :='(Y, rectangle(vector(X, _), W, H)) = rectangle(vector(X, Y), W, H).
328+
329+%------------------------------------------------------------------------------%
330+
331+:- pragma inline(circle/3).
332+circle(X, Y, R) = circle(vector(X, Y), R).
333+
334+circle_x(circle(vector(X, _), _)) = X.
335+circle_y(circle(vector(_, Y), _)) = Y.
336+
337+'circle_x :='(X, circle(vector(_, Y), R)) = circle(vector(X, Y), R).
338+'circle_y :='(Y, circle(vector(X, _), R)) = circle(vector(X, Y), R).
339+
340+%------------------------------------------------------------------------------%
341+
342+:- pragma inline(point/2).
343+point(X, Y) = vector(X, Y).
344+
345+x(vector(X, _)) = X.
346+y(vector(_, Y)) = Y.
347+
348+'x :='(X, vector(_, Y)) = vector(X, Y).
349+'y :='(Y, vector(X, _)) = vector(X, Y).
350+
351+%------------------------------------------------------------------------------%
352+
353+:- pragma inline(triangle/6).
354+triangle(X1, Y1, X2, Y2, X3, Y3) = triangle(
355+ vector(X1, Y1),
356+ vector(X2, Y2),
357+ vector(X3, Y3)).
358+
359+tri_x1(triangle(vector(X, _), _, _)) = X.
360+tri_y1(triangle(vector(_, Y), _, _)) = Y.
361+tri_x2(triangle(_, vector(X, _), _)) = X.
362+tri_y2(triangle(_, vector(_, Y), _)) = Y.
363+tri_x3(triangle(_, _, vector(X, _))) = X.
364+tri_y3(triangle(_, _, vector(_, Y))) = Y.
365+
366+'tri_x1 :='(X, triangle(vector(_, Y), P2, P3)) = triangle(vector(X, Y), P2, P3).
367+'tri_y1 :='(Y, triangle(vector(X, _), P2, P3)) = triangle(vector(X, Y), P2, P3).
368+'tri_x2 :='(X, triangle(P1, vector(_, Y), P3)) = triangle(P1, vector(X, Y), P3).
369+'tri_y2 :='(Y, triangle(P1, vector(X, _), P3)) = triangle(P1, vector(X, Y), P3).
370+'tri_x3 :='(X, triangle(P1, P2, vector(_, Y))) = triangle(P1, P2, vector(X, Y)).
371+'tri_y3 :='(Y, triangle(P1, P2, vector(X, _))) = triangle(P1, P2, vector(X, Y)).
372+
373+%------------------------------------------------------------------------------%
374+
235375 % is_in_range(X, M, N)
236376 % Unifies if X is between M and N
237377 :- pred is_in_range(float, float, float).
@@ -331,22 +471,10 @@ rectangle_contains(rectangle(X1, Y1, W1, H1), rectangle(X2, Y2, W2, H2)) :-
331471
332472 %------------------------------------------------------------------------------%
333473
334-segment_endpoints(segment(X1, Y1, X2, Y2), point(X1, Y1), point(X2, Y2)).
335-
336-%------------------------------------------------------------------------------%
337-
338-triangle_endpoints(triangle(X1, Y1, X2, Y2, X3, Y3),
339- point(X1, Y1),
340- point(X2, Y2),
341- point(X3, Y3)).
342-
343-%------------------------------------------------------------------------------%
344-
345-triangle_segments(Triangle, S1, S2, S3) :-
346- triangle_endpoints(Triangle, P1, P2, P3),
347- segment_endpoints(S1, P1, P2),
348- segment_endpoints(S2, P2, P3),
349- segment_endpoints(S3, P3, P1).
474+triangle_segments(triangle(P1, P2, P3), S1, S2, S3) :-
475+ S1 = segment(P1, P2),
476+ S2 = segment(P2, P3),
477+ S3 = segment(P3, P1).
350478
351479 %------------------------------------------------------------------------------%
352480
@@ -481,35 +609,29 @@ collide_segments(S1, S2, Point) :-
481609
482610 %------------------------------------------------------------------------------%
483611
484-collide_segment_circle(Segment, Circle, P) :-
485- segment_endpoints(Segment, Point1, Point2),
612+collide_segment_circle(segment(P1, P2), Circle, P) :-
486613
487614 % If neither of the end points are within the circle, then check if the circle's
488615 % center is within the radius of the segment
489616 ( if
490- point_inside(Circle, Point1)
617+ point_inside(Circle, P1)
491618 then
492- P = Point1
619+ P = P1
493620 else if
494- point_inside(Circle, Point2)
621+ point_inside(Circle, P2)
495622 then
496- P = Point2
623+ P = P2
497624 else
498625 % If we take the dot product of the center of the circle and one of the
499626 % endpoints on the segment, this will tell us what the nearest point on
500627 % the segment is to the circle.
501628 % We can then test this location on the line for being within the radius
502629 % of the center of the circle.
503- Point1 = point(X1, Y1),
504- Vector1 = vector(X1, Y1),
505- Point2 = point(X2, Y2),
506- Vector2 = vector(X2, Y2),
507-
508- Circle = geometry2d.circle(XC, YC, _),
630+ Circle = geometry2d.circle(Center, _),
509631
510632 % Adjust the center and the segment to start at Point1
511- SegmentVector = Vector2 - Vector1,
512- CenterVector = vector(XC, YC) - Vector1,
633+ SegmentVector = P2 - P1,
634+ CenterVector = Center - P1,
513635
514636 % Get the length of the segment, which is our scaling value
515637 Length = vector.magnitude(SegmentVector),
@@ -519,26 +641,26 @@ collide_segment_circle(Segment, Circle, P) :-
519641
520642 T >= 0.0, T =< 1.0,
521643
522- SegmentVector * T = vector(NearestX, NearestY),
523- P = geometry2d.point(NearestX + X1, NearestY + Y1),
644+ SegmentVector * T = Nearest,
645+ P = Nearest + P1,
524646 point_inside(Circle, P)
525647 ).
526648
527649 %------------------------------------------------------------------------------%
528650
529651 collide_segment_rectangle(Segment, Rect, P) :-
530- segment_endpoints(Segment, Point1, Point2),
652+ Segment = segment(P1, P2),
531653
532654 % If neither of the end points are within the rectangle, then try to
533655 % intersect the segments.
534656 ( if
535- point_inside(Rect, Point1)
657+ point_inside(Rect, P1)
536658 then
537- P = Point1
659+ P = P1
538660 else if
539- point_inside(Rect, Point2)
661+ point_inside(Rect, P2)
540662 then
541- P = Point2
663+ P = P2
542664 else
543665 rectangles_intersect(Rect, bounding_box(Segment)),
544666 Rect = rectangle(X, Y, W, H),
@@ -547,23 +669,19 @@ collide_segment_rectangle(Segment, Rect, P) :-
547669 C3 = point(X + W, Y + H),
548670 C4 = point(X, Y + H),
549671 ( if
550- segment_endpoints(RectSegment, C1, C2),
551- collide_segments(RectSegment, Segment, SemiP)
672+ collide_segments(segment(C1, C2), Segment, SemiP)
552673 then
553674 P = SemiP
554675 else if
555- segment_endpoints(RectSegment, C2, C3),
556- collide_segments(RectSegment, Segment, SemiP)
676+ collide_segments(segment(C2, C3), Segment, SemiP)
557677 then
558678 P = SemiP
559679 else if
560- segment_endpoints(RectSegment, C3, C4),
561- collide_segments(RectSegment, Segment, SemiP)
680+ collide_segments(segment(C3, C4), Segment, SemiP)
562681 then
563682 P = SemiP
564683 else
565- segment_endpoints(RectSegment, C4, C1),
566- collide_segments(RectSegment, Segment, P)
684+ collide_segments(segment(C4, C1), Segment, P)
567685 )
568686 ).
569687
@@ -601,8 +719,8 @@ point_to_vector(geometry2d.point(X, Y)) = vector(X, Y).
601719 H = max(Y1, Y2) - Y),
602720 (point_inside(_, _) :- false),
603721 (translate(Translate, S1, S2) :-
604- segment_endpoints(S1, S1P1, S1P2),
605- segment_endpoints(S2, S2P1, S2P2),
722+ S1 = segment(S1P1, S1P2),
723+ S2 = segment(S2P1, S2P2),
606724 translate(Translate, S1P1, S2P1),
607725 translate(Translate, S1P2, S2P2)),
608726 (convex(segment(X1, Y1, X2, Y2), 0.0, [point(X1, Y1)|[point(X2, Y2)|[]]])),
@@ -704,21 +822,13 @@ point_to_vector(geometry2d.point(X, Y)) = vector(X, Y).
704822 Side2 = Side3
705823 )
706824 ),
707- (translate(Point, TriangleIn, TriangleOut) :-
708- triangle_endpoints(TriangleIn, P1in, P2in, P3in),
709- triangle_endpoints(TriangleOut, P1out, P2out, P3out),
710- translate(Point, P1in, P1out),
711- translate(Point, P2in, P2out),
712- translate(Point, P3in, P3out)
713- ),
714- (convex(Triangle, 0.0, [P1, P2, P3]) :-
715- triangle_endpoints(Triangle, P1, P2, P3)
825+ (translate(P, triangle(!.P1, !.P2, !.P3), triangle(!:P1, !:P2, !:P3)) :-
826+ translate(P, !P1),
827+ translate(P, !P2),
828+ translate(P, !P3)
716829 ),
717- (scale(X, Y, TriangleIn) = (TriangleOut) :-
718- triangle_endpoints(TriangleIn, P1, P2, P3),
719- triangle_endpoints(TriangleOut,
720- scale(X, Y, P1),
721- scale(X, Y, P2),
722- scale(X, Y, P3))
723- )
830+ convex(triangle(P1, P2, P3), 0.0, [P1|[P2|[P3|[]]]]),
831+ (scale(X, Y, triangle(P1, P2, P3)) = triangle(P * P1, P * P2, P * P3) :-
832+ P = vector(X, Y))
833+
724834 ].