geometry.red 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. % geometry Version 1.1 | 6.9.98
  2. % Author | H.-G. Graebe | Univ. Leipzig
  3. % graebe@informatik.uni-leipzig.de
  4. COMMENT
  5. The package GEOMETRY is a small package for mechanized (plane)
  6. geometry manipulations with non degeneracy tracing.
  7. It provides the casual user with a couple of procedures that allow
  8. him/her to mechanize his/her own geometry proofs. It grew up from a
  9. course of lectures for students of computer science on this topic held
  10. by the author at the Univ. of Leipzig in fall 1996 and was updated
  11. after a similar lecture in spring 1998.
  12. Author : H.-G. Graebe
  13. Univ. Leipzig
  14. Institut fuer Informatik
  15. Augustusplatz 10 - 11
  16. D - 04109 Leipzig
  17. Germany
  18. email : graebe@informatik.uni-leipzig.de
  19. Version : 1.1, finished at Sept 6, 1998.
  20. Please send all Comments, bugs, hints, wishes, criticisms etc. to the
  21. above email address.
  22. Reduce version required : The program was tested under v. 3.6. but
  23. should run also under older versions. For the test file the pacakge
  24. CALI should be available.
  25. Relevant publications : See the bibliography in the manual.
  26. Key words : Mechanized geometry theorem proving.
  27. end comment;
  28. module geometry;
  29. comment
  30. Data structures:
  31. Point A :== {a1,a2} <=> A=(a1,a2)
  32. Line a :== {a1,a2,a3} <=> a1*x+a2*y+a3
  33. (including degenerate lines with a1=a2=0)
  34. end comment;
  35. put ('geometry,'name," Geometry ")$
  36. put ('geometry,'version," 1.1 ")$
  37. put ('geometry,'date," Sept 6, 1998 ")$
  38. algebraic(write(" Geometry ", get('geometry,'version),
  39. " Last update ",get('geometry,'date)));
  40. % ============= vector geometry ===============
  41. comment
  42. For affine (plane) geometry one can try to express the coordinates of
  43. all points in the configuration through barycentric coordinates wrt.
  44. three fixed non collinear "base points". Comparison of coefficients
  45. yields equations for the nondetermined ratios that may be solved.
  46. end comment;
  47. algebraic procedure getcoord(u,base);
  48. % extract coordinates wrt. base point list base.
  49. begin u:={u};
  50. for each x in base do u:=for each y in u join coeff(y,x);
  51. return u;
  52. end;
  53. % ============= Handling non degeneracy conditions ===============
  54. algebraic procedure clear_ndg; !*ndg!*:={};
  55. algebraic procedure print_ndg; !*ndg!*;
  56. algebraic procedure add_ndg(d);
  57. if not member(d,!*ndg!*) then !*ndg!*:=d . !*ndg!*;
  58. clear_ndg();
  59. % ================= elementary geometric constructions ===============
  60. % Generators:
  61. algebraic procedure Point(a,b); {a,b};
  62. algebraic procedure Line(a,b,c); {a,b,c};
  63. algebraic procedure pp_line(a,b);
  64. % The line through A and B.
  65. Line(part(b,2)-part(a,2),part(a,1)-part(b,1),
  66. part(a,2)*part(b,1)-part(a,1)*part(b,2));
  67. algebraic procedure intersection_point(a,b);
  68. % The intersection point of the lines a,b.
  69. begin scalar d,d1,d2;
  70. d:=part(a,1)*part(b,2)-part(b,1)*part(a,2);
  71. d1:=part(a,3)*part(b,2)-part(b,3)*part(a,2);
  72. d2:=part(a,1)*part(b,3)-part(b,1)*part(a,3);
  73. if d=0 then rederr"Lines are parallel";
  74. add_ndg(num d);
  75. return Point(-d1/d,-d2/d);
  76. end;
  77. algebraic procedure lot(p,a);
  78. % The perpendicular from P onto the line a.
  79. begin scalar u,v; u:=first a; v:=second a;
  80. return Line(v,-u,u*second p-v*first p);
  81. end;
  82. algebraic procedure par(p,a);
  83. % The parallel to line a through P.
  84. Line(part(a,1),part(a,2),
  85. -(part(a,1)*part(p,1)+part(a,2) *part(p,2)));
  86. algebraic procedure pedalpoint(p,a);
  87. % The pedal point of the perpendicular from P onto the line a.
  88. intersection_point(lot(P,a),a);
  89. algebraic procedure midpoint(a,b);
  90. % The midpoint of AB
  91. Point((part(a,1)+part(b,1))/2, (part(a,2)+part(b,2))/2);
  92. algebraic procedure varpoint(a,b,l);
  93. % The point D=l*A+(1-l)*B.
  94. Point(l*part(a,1)+(1-l)*part(b,1),l*part(a,2)+(1-l)*part(b,2));
  95. algebraic procedure choose_pl(a,u);
  96. % Choose a point on the line a using parameter u.
  97. begin scalar p,d;
  98. if part(a,2)=0 then
  99. << p:=Point(-part(a,3)/part(a,1),u); d:=part(a,1); >>
  100. else
  101. << p:=Point(u,-(part(a,3)+part(a,1)*u)/part(a,2));
  102. d:=part(a,2);
  103. >>;
  104. add_ndg(num d);
  105. return p;
  106. end;
  107. algebraic procedure sqrdist(a,b);
  108. % The square of the distance between the points A and B.
  109. (part(b,1)-part(a,1))^2+(part(b,2)-part(a,2))^2;
  110. % ================= elementary geometric properties ===============
  111. algebraic procedure collinear(a,b,c);
  112. % A,B,C are on a common line.
  113. det mat((part(a,1),part(a,2),1),
  114. (part(b,1),part(b,2),1),
  115. (part(c,1),part(c,2),1));
  116. algebraic procedure concurrent(a,b,c);
  117. % Lines a,b,c have a common point.
  118. det mat((part(a,1),part(a,2),part(a,3)),
  119. (part(b,1),part(b,2),part(b,3)),
  120. (part(c,1),part(c,2),part(c,3)));
  121. algebraic procedure parallel(a,b);
  122. % 0 <=> the lines a,b are parallel.
  123. part(a,1)*part(b,2)-part(b,1)*part(a,2);
  124. algebraic procedure orthogonal(a,b);
  125. % 0 <=> the lines a,b are orthogonal.
  126. part(a,1)*part(b,1)+part(a,2)*part(b,2);
  127. algebraic procedure point_on_line(p,a);
  128. % Substitute point P into the line a.
  129. part(p,1)*part(a,1)+part(p,2)*part(a,2)+part(a,3);
  130. % ================= the transversals in a triangle ===============
  131. algebraic procedure mp(b,c);
  132. % Midpoint perpendicular of BC.
  133. lot(midpoint(b,c),pp_line(b,c));
  134. algebraic procedure altitude(a,b,c);
  135. % Altitude from A onto BC.
  136. lot(a,pp_line(b,c));
  137. algebraic procedure median(a,b,c);
  138. % Median line from A to BC.
  139. pp_line(a,midpoint(b,c));
  140. % #########################################
  141. % # #
  142. % # Non linear geometric objects #
  143. % # #
  144. % #########################################
  145. % ===================== angles
  146. algebraic procedure l2_angle(a,b);
  147. % tan of the angle between the lines a and b.
  148. begin scalar d; d:=(part(a,1)*part(b,1)+part(a,2)*part(b,2));
  149. add_ndg(num(d));
  150. return (part(a,2)*part(b,1)-part(b,2)*part(a,1))/d;
  151. end;
  152. algebraic procedure p3_angle(A,B,C);
  153. % tan of the angle between the lines BA and BC
  154. l2_angle(pp_line(B,A),pp_line(B,C));
  155. algebraic procedure angle_sum(a,b);
  156. % a=tan(\alpha), b=tan(\beta). Returns tan(\alpha+\beta)
  157. begin scalar d; d:=(1-a*b); add_ndg(num d);
  158. return (a+b)/d;
  159. end;
  160. algebraic procedure point_on_bisector(P,A,B,C);
  161. % P is a point on the bisector of the angle ABC.
  162. % Returns num(u)*den(v)-num(v)*den(u) with
  163. % u:=angle(pp_line(A,B),pp_line(P,B))
  164. % v:=angle(pp_line(P,B),pp_line(C,B))
  165. begin scalar a1,a2,b1,b2,c1,c2,p1,p2;
  166. a1:=part(A,1); a2:=part(A,2);
  167. b1:=part(b,1); b2:=part(b,2);
  168. c1:=part(c,1); c2:=part(c,2);
  169. p1:=part(p,1); p2:=part(p,2);
  170. return ( - a1*b2 + a1*p2 + a2*b1 - a2*p1 - b1*p2 + b2*p1)*(b1**2 -
  171. b1*c1 - b1*p1 + b2**2 - b2*c2 - b2*p2 + c1*p1 + c2*p2) - (a1*b1 -
  172. a1*p1 + a2*b2 - a2*p2 - b1**2 + b1*p1 - b2**2 + b2*p2)*(b1*c2 -
  173. b1*p2 - b2*c1 + b2*p1 + c1*p2 - c2*p1)
  174. end;
  175. % ========== symmetric lines and points
  176. algebraic procedure sympoint(P,l);
  177. % The point symmetric to P wrt. the line l.
  178. varpoint(P,pedalpoint(P,l),-1);
  179. algebraic procedure symline(a,l);
  180. % The line symmetric to a wrt. the line l.
  181. begin scalar a1,a2,a3,l1,l2,l3,u;
  182. a1:=part(a,1); a2:=part(a,2); a3:=part(a,3);
  183. l1:=part(l,1); l2:=part(l,2); l3:=part(l,3);
  184. u:=l1^2 - l2^2;
  185. return Line(- a1*u - 2*a2*l1*l2, - 2*a1*l1*l2 + a2*u,
  186. - 2*(a1*l1 + a2*l2)*l3 + a3*(l1^2 + l2^2));
  187. end;
  188. % ===================== circles
  189. comment
  190. Circle1 represents a circle as the pair {M,sqr} consisting of
  191. the center M and the square of its radius.
  192. end comment;
  193. algebraic procedure Circle1(M,sqr); {M,sqr};
  194. algebraic procedure p3_circle1(A,B,C);
  195. % The circle through three given points
  196. begin scalar M;
  197. M:=intersection_point(mp(A,B),mp(B,C));
  198. return Circle1(M,sqrdist(M,A));
  199. end;
  200. algebraic procedure point_on_circle1(P,c);
  201. % Test a point P to be on c:Circle1.
  202. sqrdist(P,part(c,1))-part(c,2);
  203. algebraic procedure choose_pc(M,r,u);
  204. % Choose a point on the circle with center M and radius (not squared
  205. % radius !) r using a rational parametrization of the circle.
  206. begin scalar d;
  207. d:=(u^2+1); add_ndg(num d);
  208. return Point(r*(u^2-1)/d+part(M,1), 2*r*u/d+part(M,2));
  209. end;
  210. comment
  211. Another approach represents a circle through its equation
  212. c1*(x^2+y^2)+c2*x+c3*y+c4
  213. This is better adapted for analytic geometry. The coordinates are
  214. homogeneous as those for lines, hence we may adjust either c1=1 or
  215. allow for division-free computations without such a scaling. Another
  216. advantage of the latter is, that for c1=0 we get lines as circles with
  217. infinite radius.
  218. A circle is henceforth a quadruple c={c1,c2,c3,c4}.
  219. end comment;
  220. algebraic procedure Circle(c1,c2,c3,c4); {c1,c2,c3,c4};
  221. algebraic procedure c1_circle(M,sqr);
  222. % Circle from center M and squared radius sqr.
  223. Circle(1, -2*part(M,1), -2*part(M,2),
  224. part(M,1)^2 + part(M,2)^2 - sqr);
  225. algebraic procedure circle_center c;
  226. % The center of the circle c.
  227. begin add_ndg(num part(c,1));
  228. return Point(-part(c,2)/2/part(c,1) ,-part(c,3)/(2*part(c,1)));
  229. end;
  230. algebraic procedure circle_sqradius c;
  231. % The squared radius of the circle c.
  232. begin add_ndg(num part(c,1));
  233. return
  234. ((part(c,2)^2+part(c,3)^2) - 4*part(c,4)*part(c,1)) /
  235. (2*part(c,1))^2;
  236. end;
  237. algebraic procedure p3_circle(A,B,C);
  238. % The circle through three given points
  239. begin scalar a1,a2,a3,b1,b2,b3,c1,c2,c3;
  240. a1:=part(A,1); a2:=part(A,2); a3:=a1^2+a2^2;
  241. b1:=part(b,1); b2:=part(b,2); b3:=b1^2+b2^2;
  242. c1:=part(c,1); c2:=part(c,2); c3:=c1^2+c2^2;
  243. return Circle(a1*(b2-c2) + (a2-b2)*c1 + b1*(c2-a2),
  244. a3*(c2-b2) + (a2-c2)*b3 + (b2-a2)*c3,
  245. a3*(b1-c1) + (c1-a1)*b3 + (a1-b1)*c3,
  246. a3*(b2*c1-b1*c2) + (a1*c2-a2*c1)*b3 + (a2*b1-a1*b2)*c3)
  247. end;
  248. algebraic procedure point_on_circle(P,c);
  249. begin scalar p1,p2; p1:=part(P,1); p2:=part(P,2);
  250. return part(c,1)*(p1^2+p2^2)+part(c,2)*p1+part(c,3)*p2+part(c,4);
  251. end;
  252. algebraic procedure p4_circle(A,B,C,D);
  253. point_on_circle(D,p3_circle(A,B,C));
  254. % Intersecting with circles
  255. algebraic procedure other_cl_point(P,c,l);
  256. % circle c and line l intersect at P. The procedure returns their
  257. % second intersection point.
  258. if point_on_line(P,l) neq 0 then rederr "Point not on the line"
  259. else if point_on_circle(P,c) neq 0 then
  260. rederr "Point not on the circle"
  261. else begin scalar c1,c2,c3,l1,l2,d,d1,p1,p2;
  262. c1:=part(c,1); c2:=part(c,2); c3:=part(c,3);
  263. l1:=part(l,1); l2:=part(l,2); p1:=part(P,1); p2:=part(P,2);
  264. d:=c1*(l1^2 + l2^2); add_ndg(num d); d1:=c1*(l1^2-l2^2);
  265. return {(d1*p1+((2*c1*p2 + c3)*l1-c2*l2)*l2)/d,
  266. (- d1*p2+((2*c1*p1 + c2)*l2-c3*l1)*l1)/d};
  267. end;
  268. algebraic procedure other_cc_point(P,c1,c2);
  269. % Circles c1 and c2 intersect at P. The procedure returns their
  270. % second intersection point, computing by elimination the line through
  271. % the common intersection points.
  272. begin scalar l;
  273. l:=for i:=2:4 collect
  274. (part(c1,1)*part(c2,i)-part(c1,i)*part(c2,1));
  275. return other_cl_point(P,c1,l);
  276. end;
  277. algebraic procedure cl_tangent(c,l);
  278. % Line l is tangent to the circle c.
  279. begin scalar c1,c2,c3,c4,l1,l2,l3;
  280. c1:=part(c,1); c2:=part(c,2); c3:=part(c,3); c4:=part(c,4);
  281. l1:=part(l,1); l2:=part(l,2); l3:=part(l,3);
  282. return - 4*c1^2*l3^2 + 4*c1*c2*l1*l3 + 4*c1*c3*l2*l3 -
  283. 4*c1*c4*l1^2 - 4*c1*c4*l2^2 + c2^2*l2^2 - 2*c2*c3*l1*l2 +
  284. c3^2*l1^2
  285. end;
  286. algebraic procedure cc_tangent(c,d);
  287. % Two circles c,d are tangent.
  288. begin scalar c1,c2,c3,c4,d1,d2,d3,d4;
  289. c1:=part(c,1); c2:=part(c,2); c3:=part(c,3); c4:=part(c,4);
  290. d1:=part(d,1); d2:=part(d,2); d3:=part(d,3); d4:=part(d,4);
  291. return
  292. 4*c1^2*d4^2 - 4*c1*c2*d2*d4 - 4*c1*c3*d3*d4 - 8*c1*c4*d1*d4 +
  293. 4*c1*c4*d2^2 + 4*c1*c4*d3^2 + 4*c2^2*d1*d4 - c2^2*d3^2 + 2*c2*c3*d2*d3
  294. - 4*c2*c4*d1*d2 + 4*c3^2*d1*d4 - c3^2*d2^2 - 4*c3*c4*d1*d3 +
  295. 4*c4^2*d1^2
  296. end;
  297. % ============= some additional tools ===============
  298. symbolic operator list2mat;
  299. symbolic procedure list2mat u;
  300. 'mat. for each x in cdr reval u collect cdr x;
  301. algebraic procedure extractmat(polys,vars);
  302. % extract the coefficient matrix from the linear system polys.
  303. begin
  304. if length polys neq length vars then
  305. rederr"Number of variables doesn't match";
  306. for each p in polys do for each x in vars do
  307. if deg(p,x)>1 then rederr"Equations not of linear type";
  308. return list2mat
  309. for each x in vars collect
  310. for each p in polys collect coeffn(p,x,1);
  311. end;
  312. algebraic procedure red_hom_coords u;
  313. % Divide out the content of homogeneous coordinates.
  314. begin scalar l,g;
  315. l:=den first u; g:=num first u;
  316. for each x in rest u do <<l:=lcm(l,den x); g:=gcd(g,num x) >>;
  317. add_ndg(g);
  318. return for each x in u collect (x*l/g);
  319. end;
  320. endmodule; % geometry
  321. end;