line_segment.sml 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. structure LineSegment = struct
  2. type point = (int * int);
  3. datatype LineSegment = LineSegment of point * point;
  4. datatype ThreePointOrientation = Clockwise | CounterClockwise | Colinear;
  5. (* This only works for horizontal and vertical and diagonal line segments. *)
  6. fun contains_point seg point =
  7. let
  8. val (px,py) = point;
  9. val LineSegment ((ax, ay), (bx, by)) = seg;
  10. (* delta of start and end of segment *)
  11. val delta_x_ab = ax - bx;
  12. val delta_y_ab = ay - by;
  13. (* delta to point *)
  14. val delta_x_ap = ax - px;
  15. val delta_y_ap = ay - py;
  16. in
  17. ((point = (ax, ay)) orelse (point = (bx, by))) orelse
  18. (MathExtra.sign(delta_x_ab) = MathExtra.sign(delta_x_ap) andalso
  19. MathExtra.sign(delta_y_ab) = MathExtra.sign(delta_y_ap) andalso
  20. (((abs delta_x_ap) = (abs delta_y_ap)) orelse
  21. (delta_x_ap = 0) orelse
  22. (delta_y_ap = 0)))
  23. end;
  24. fun three_point_orientation (a: point) (b: point) (p: point) =
  25. (*
  26. Definition of orientation of 3 ordered points in a 2D plane:
  27. Co-linear order and orientation:
  28. C
  29. B
  30. A
  31. Clockwise order and orientation:
  32. B
  33. A
  34. C
  35. Counter-clockwise order and orientation:
  36. C
  37. A
  38. B
  39. Orientation can be found by substracting the 2 slopes of AB and BC from
  40. each other. This results in 3 cases:
  41. If the result is 0, then they 2 line segments AB and BC must have the
  42. same slope and that implies, that they are on the same line, which is
  43. called "colinear" or "colinearity".
  44. If the result is < 0, then the 2 line segments AB and BC have inequal
  45. slope and that BC has the higher slope. A higher slope means, that the
  46. turn from AB to BC is counter-clockwise, as seen in the following
  47. example:
  48. C
  49. B
  50. A
  51. If the result is > 0, then the 2 line segments AB and BC also have
  52. inequal slope, and AB has a higher slope than BC. This means, that the
  53. turn from AB to BC is clockwise, as seen in the following example:
  54. A
  55. B
  56. C
  57. The slope can be calculated as follows:
  58. A = (x1,y1)
  59. B = (x2,y2)
  60. C = (x3,y3)
  61. y2 - y1
  62. slope_AB = (y2-y1) / (x2-x1) = ---------
  63. x2 - x1
  64. y3 - y2
  65. slope_BC = (y3-y2) / (x3-x2) = ---------
  66. x3 - x2
  67. Substraction of fractions:
  68. a c ad - cb
  69. --- - --- = ---------
  70. b d bd
  71. TODO: How / why does the denominator disappear?
  72. *)
  73. let
  74. val (ax, ay) = a; (* p *)
  75. val (bx, by) = b; (* q *)
  76. val (px, py) = p; (* r *)
  77. in
  78. let
  79. (* But why?! -- Explain this formula. *)
  80. val result = (by - ay) * (px - bx) - (bx - ax) * (py - by);
  81. in
  82. if result = 0
  83. then Colinear
  84. else
  85. if result > 0
  86. then Clockwise
  87. else CounterClockwise
  88. end
  89. end;
  90. (* fun colinear seg1 seg2 = *)
  91. (* (* Implement check for colinearity. *) *)
  92. (* nil; *)
  93. (* fun intersection_point seg1 seg2 = *)
  94. (* let *)
  95. (* val LineSegment ((a1x, a1y), (b1x, b1y)) = seg1; *)
  96. (* val LineSegment ((a2x, a2y), (b2x, b2y)) = seg2; *)
  97. (* in *)
  98. (* (* SOME or NONE ... *) *)
  99. (* (* Implement algorithm to determin intersection point, if one exists. *) *)
  100. (* end; *)
  101. end;