# mmath

• R/O
• HTTP
• SSH
• HTTPS

## コミット

#### よく使われているワード(クリックで追加)

Mercury Geometry and Math Library

### コミットメタ情報

リビジョン 7ff29fb8f53f14a882d75b05af9a84155d2a317b (tree) 2022-04-24 05:04:00 Emily Dioxideson Emily Dioxideson

### ログメッセージ

Use vectors to implement geometry2d

### 差分

--- a/mmath.geometry2d.m
+++ b/mmath.geometry2d.m
 @@ -20,30 +20,116 @@ 20 20 21 21 %------------------------------------------------------------------------------% 22 22 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. 25 43 26 44 %------------------------------------------------------------------------------% 27 45 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. 30 65 31 66 %------------------------------------------------------------------------------% 32 67 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. 35 84 36 85 %------------------------------------------------------------------------------% 37 86 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. 40 103 41 104 %------------------------------------------------------------------------------% 42 105 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. 47 133 48 134 %------------------------------------------------------------------------------% 49 135
 @@ -123,22 +209,6 @@ 123 209 124 210 %------------------------------------------------------------------------------% 125 211 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 - 142 212 :- pred triangle_segments(triangle, segment, segment, segment). 143 213 :- mode triangle_segments(in, out, out, out) is det. 144 214
 @@ -232,6 +302,76 @@ 232 302 233 303 %------------------------------------------------------------------------------% 234 304 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 + 235 375 % is_in_range(X, M, N) 236 376 % Unifies if X is between M and N 237 377 :- pred is_in_range(float, float, float).
 @@ -331,22 +471,10 @@ rectangle_contains(rectangle(X1, Y1, W1, H1), rectangle(X2, Y2, W2, H2)) :- 331 471 332 472 %------------------------------------------------------------------------------% 333 473 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). 350 478 351 479 %------------------------------------------------------------------------------% 352 480
 @@ -481,35 +609,29 @@ collide_segments(S1, S2, Point) :- 481 609 482 610 %------------------------------------------------------------------------------% 483 611 484 -collide_segment_circle(Segment, Circle, P) :- 485 - segment_endpoints(Segment, Point1, Point2), 612 +collide_segment_circle(segment(P1, P2), Circle, P) :- 486 613 487 614 % If neither of the end points are within the circle, then check if the circle's 488 615 % center is within the radius of the segment 489 616 ( if 490 - point_inside(Circle, Point1) 617 + point_inside(Circle, P1) 491 618 then 492 - P = Point1 619 + P = P1 493 620 else if 494 - point_inside(Circle, Point2) 621 + point_inside(Circle, P2) 495 622 then 496 - P = Point2 623 + P = P2 497 624 else 498 625 % If we take the dot product of the center of the circle and one of the 499 626 % endpoints on the segment, this will tell us what the nearest point on 500 627 % the segment is to the circle. 501 628 % We can then test this location on the line for being within the radius 502 629 % 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, _), 509 631 510 632 % 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, 513 635 514 636 % Get the length of the segment, which is our scaling value 515 637 Length = vector.magnitude(SegmentVector),
 @@ -519,26 +641,26 @@ collide_segment_circle(Segment, Circle, P) :- 519 641 520 642 T >= 0.0, T =< 1.0, 521 643 522 - SegmentVector * T = vector(NearestX, NearestY), 523 - P = geometry2d.point(NearestX + X1, NearestY + Y1), 644 + SegmentVector * T = Nearest, 645 + P = Nearest + P1, 524 646 point_inside(Circle, P) 525 647 ). 526 648 527 649 %------------------------------------------------------------------------------% 528 650 529 651 collide_segment_rectangle(Segment, Rect, P) :- 530 - segment_endpoints(Segment, Point1, Point2), 652 + Segment = segment(P1, P2), 531 653 532 654 % If neither of the end points are within the rectangle, then try to 533 655 % intersect the segments. 534 656 ( if 535 - point_inside(Rect, Point1) 657 + point_inside(Rect, P1) 536 658 then 537 - P = Point1 659 + P = P1 538 660 else if 539 - point_inside(Rect, Point2) 661 + point_inside(Rect, P2) 540 662 then 541 - P = Point2 663 + P = P2 542 664 else 543 665 rectangles_intersect(Rect, bounding_box(Segment)), 544 666 Rect = rectangle(X, Y, W, H),
 @@ -547,23 +669,19 @@ collide_segment_rectangle(Segment, Rect, P) :- 547 669 C3 = point(X + W, Y + H), 548 670 C4 = point(X, Y + H), 549 671 ( if 550 - segment_endpoints(RectSegment, C1, C2), 551 - collide_segments(RectSegment, Segment, SemiP) 672 + collide_segments(segment(C1, C2), Segment, SemiP) 552 673 then 553 674 P = SemiP 554 675 else if 555 - segment_endpoints(RectSegment, C2, C3), 556 - collide_segments(RectSegment, Segment, SemiP) 676 + collide_segments(segment(C2, C3), Segment, SemiP) 557 677 then 558 678 P = SemiP 559 679 else if 560 - segment_endpoints(RectSegment, C3, C4), 561 - collide_segments(RectSegment, Segment, SemiP) 680 + collide_segments(segment(C3, C4), Segment, SemiP) 562 681 then 563 682 P = SemiP 564 683 else 565 - segment_endpoints(RectSegment, C4, C1), 566 - collide_segments(RectSegment, Segment, P) 684 + collide_segments(segment(C4, C1), Segment, P) 567 685 ) 568 686 ). 569 687
 @@ -601,8 +719,8 @@ point_to_vector(geometry2d.point(X, Y)) = vector(X, Y). 601 719 H = max(Y1, Y2) - Y), 602 720 (point_inside(_, _) :- false), 603 721 (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), 606 724 translate(Translate, S1P1, S2P1), 607 725 translate(Translate, S1P2, S2P2)), 608 726 (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). 704 822 Side2 = Side3 705 823 ) 706 824 ), 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) 716 829 ), 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 + 724 834 ].