RECTANGL.MOD 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. IMPLEMENTATION MODULE Rectangles;
  2. (*
  3. * REPERTOIRE
  4. * Release 1.6
  5. * By Charles Bradford and Cole Brecheen
  6. * (c) Copyright 1985-1992 PMI
  7. * Green Bay, Wisconsin
  8. * All rights reserved
  9. * (414) 468-6040
  10. *
  11. * $Header: D:/logfiles/mods/rectangl.mov 1.5 10 Mar 1991 15:35:22 coleb $
  12. *
  13. *
  14. * Adapted from an earlier version written and contributed
  15. * by Martin Johnston of GTJ Consultants, New York, NY.
  16. *
  17. *)
  18. IMPORT Numbers;
  19. VAR
  20. Initialized : BOOLEAN;
  21. PROCEDURE Init();
  22. BEGIN
  23. IF Initialized THEN
  24. RETURN;
  25. ELSE
  26. Initialized := TRUE;
  27. END;
  28. Numbers.Init();
  29. END Init;
  30. PROCEDURE PointInside( VAR p : APoint; VAR r : ARectangle) :
  31. BOOLEAN;
  32. BEGIN
  33. RETURN (p.col >= r.col1) AND (p.col < r.col2) AND (p.row >= r.row1) AND
  34. (p.row < r.row2);
  35. END PointInside;
  36. PROCEDURE Distance(p1, p2 : APoint) : CARDINAL;
  37. VAR
  38. colDiff, rowDiff : CARDINAL;
  39. PROCEDURE IntToCardRange(n : INTEGER) : CARDINAL;
  40. BEGIN
  41. IF n >= 0 THEN
  42. RETURN CARDINAL(n)+32767+1;
  43. ELSE
  44. RETURN CARDINAL(n+32767+1);
  45. END;
  46. END IntToCardRange;
  47. PROCEDURE dist(a, b : INTEGER) : CARDINAL;
  48. BEGIN
  49. IF a > b THEN
  50. RETURN IntToCardRange(a) - IntToCardRange(b);
  51. ELSE
  52. RETURN IntToCardRange(b) - IntToCardRange(a);
  53. END;
  54. END dist;
  55. BEGIN
  56. colDiff := dist(p1.col, p2.col);
  57. rowDiff := dist(p1.row, p2.row);
  58. RETURN Numbers.CardSqrt( (colDiff * colDiff) + (rowDiff * rowDiff) );
  59. END Distance;
  60. PROCEDURE RectsIntersect(VAR r1, r2, intersection : ARectangle) : BOOLEAN;
  61. BEGIN
  62. IF r1.row1 > r2.row1 THEN
  63. intersection.row1 := r1.row1;
  64. ELSE
  65. intersection.row1 := r2.row1;
  66. END;
  67. IF r1.row2 < r2.row2 THEN
  68. intersection.row2 := r1.row2;
  69. ELSE
  70. intersection.row2 := r2.row2;
  71. END;
  72. IF r1.col1 > r2.col1 THEN
  73. intersection.col1 := r1.col1;
  74. ELSE
  75. intersection.col1 := r2.col1;
  76. END;
  77. IF r1.col2 < r2.col2 THEN
  78. intersection.col2 := r1.col2;
  79. ELSE
  80. intersection.col2 := r2.col2;
  81. END;
  82. RETURN (intersection.row1 <= intersection.row2) AND
  83. (intersection.col1 <= intersection.col2);
  84. END RectsIntersect;
  85. PROCEDURE FindRowOnCol(VAR col1, row1, col2, row2, col : INTEGER) : INTEGER;
  86. VAR
  87. dcol, rise, run : INTEGER;
  88. PROCEDURE HalfPoint(xl, yl, xr, yr : INTEGER) : INTEGER;
  89. VAR
  90. syl, sxr, syr : INTEGER;
  91. BEGIN
  92. REPEAT
  93. syl := yl;
  94. sxr := xr;
  95. syr := yr;
  96. xr := (xl+xr) DIV 2;
  97. yr := (yl+yr) DIV 2;
  98. IF xr < col THEN
  99. xl := xr;
  100. yl := yr;
  101. xr := sxr;
  102. yr := syr;
  103. END;
  104. UNTIL ((syl=yl) AND (syr=yr));
  105. RETURN yr;
  106. END HalfPoint;
  107. BEGIN
  108. IF row1 = row2 THEN
  109. RETURN row1;
  110. ELSE
  111. rise := row2-row1;
  112. run := col2-col1;
  113. dcol := Numbers.LowestCommonDenom(rise, run);
  114. IF dcol # rise THEN
  115. rise := rise DIV dcol;
  116. run := run DIV dcol;
  117. END;
  118. dcol := col-col1;
  119. IF (ABS(32767 DIV rise) < ABS(dcol)) OR ((32767 DIV ABS(dcol)) <
  120. ABS(rise)) THEN
  121. RETURN HalfPoint(col1, row1, col2, row2);
  122. ELSE
  123. RETURN ((rise*dcol) DIV run)+row1;
  124. END;
  125. END;
  126. END FindRowOnCol;
  127. PROCEDURE LineInside(TheLine : ALine; r : ARectangle; VAR
  128. intersection : ALine) : BOOLEAN;
  129. PROCEDURE order(VAR col1, col2, row1, row2 : INTEGER);
  130. VAR
  131. col : INTEGER;
  132. BEGIN
  133. IF col1 > col2 THEN
  134. col := col1;
  135. col1 := col2;
  136. col2 := col;
  137. col := row1;
  138. row1 := row2;
  139. row2 := col;
  140. END;
  141. END order;
  142. BEGIN
  143. WITH TheLine DO
  144. order(p1.col, p2.col, p1.row, p2.row);
  145. IF (p1.col < r.col1) AND (p2.col > r.col1) THEN
  146. p1.row := FindRowOnCol(p1.col, p1.row, p2.col, p2.row, r.col1);
  147. p1.col := r.col1;
  148. END;
  149. IF (p1.col < r.col2) AND (p2.col > r.col2) THEN
  150. p2.row := FindRowOnCol(p1.col, p1.row, p2.col, p2.row, r.col2);
  151. p2.col := r.col2;
  152. END;
  153. order(p1.row, p2.row, p1.col, p2.col);
  154. IF (p1.row < r.row1) AND (p2.row > r.row1) THEN
  155. p1.col := FindRowOnCol(p1.row, p1.col, p2.row, p2.col, r.row1);
  156. p1.row := r.row1;
  157. END;
  158. IF (p1.row < r.row2) AND (p2.row > r.row2) THEN
  159. p2.col := FindRowOnCol(p1.row, p1.col, p2.row, p2.col, r.row2);
  160. p2.row := r.row2;
  161. END;
  162. IF PointInside(p1, r) AND PointInside(p2, r) THEN
  163. intersection := TheLine;
  164. RETURN TRUE;
  165. ELSE
  166. RETURN FALSE;
  167. END;
  168. END;
  169. END LineInside;
  170. PROCEDURE DefineRectangle(VAR r : ARectangle; col1, row1, col2, row2 :
  171. INTEGER);
  172. BEGIN
  173. r.col1 := col1;
  174. r.row1 := row1;
  175. r.col2 := col2;
  176. r.row2 := row2;
  177. END DefineRectangle;
  178. PROCEDURE DefineByPoints(VAR r : ARectangle; TopLeft, BottomRight
  179. : APoint);
  180. BEGIN
  181. r.TopLeft := TopLeft;
  182. r.BottomRight := BottomRight;
  183. END DefineByPoints;
  184. PROCEDURE RectIsInside( VAR r1, r2 : ARectangle) : BOOLEAN;
  185. BEGIN
  186. RETURN (r1.col1 >= r2.col1) AND (r1.col2 <= r2.col2) AND
  187. (r1.row1 >= r2.row1) AND (r1.row2 <= r2.row2);
  188. END RectIsInside;
  189. PROCEDURE ShrinkRect( VAR r : ARectangle );
  190. BEGIN
  191. IF r.col2 > (r.col1 + 1) THEN
  192. INC( r.col1 );
  193. DEC( r.col2 );
  194. END;
  195. IF r.row2 > (r.row1 + 1) THEN
  196. INC( r.row1 );
  197. DEC( r.row2 );
  198. END;
  199. END ShrinkRect;
  200. PROCEDURE ExpandRect( VAR r : ARectangle );
  201. BEGIN
  202. IF r.col1 > 1 THEN
  203. DEC( r.col1 );
  204. END;
  205. IF r.row1 > 1 THEN
  206. DEC( r.row1 );
  207. END;
  208. INC( r.col2 );
  209. INC( r.row2 );
  210. END ExpandRect;
  211. BEGIN
  212. Initialized := FALSE;
  213. Init();
  214. END Rectangles.