geoprover.red 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. % GeoProver | Version 1.3a | Jan 20 2003
  2. % Author: H.-G. Graebe, Univ. Leipzig, Germany
  3. % http://www.informatik.uni-leipzig.de/~graebe
  4. module geoprover;
  5. comment
  6. GeoProver inline part. Version 1.3
  7. Data structures:
  8. Point A :== {a1,a2} <=> A=(a1,a2)
  9. Line a :== {a1,a2,a3} <=> a1*x+a2*y+a3 = 0
  10. Circle c :== {c0,c1,c2,c3} <=> c0*(x^2+y^2)+c1*x+c2*y+c3 = 0
  11. end comment;
  12. put ('geoprover,'name," GeoProver ")$
  13. put ('geoprover,'version," 1.3a ")$
  14. put ('geoprover,'date," December 30, 2002")$
  15. algebraic(write(" Geoprover ", get('geoprover,'version),
  16. " Last update ",get('geoprover,'date)));
  17. % ============= Handling non degeneracy conditions ===============
  18. algebraic procedure clear_ndg; !*ndg!*:={};
  19. algebraic procedure print_ndg; !*ndg!*;
  20. algebraic procedure add_ndg(d);
  21. if not member(d,!*ndg!*) then !*ndg!*:=d . !*ndg!*;
  22. clear_ndg(); % Initialization
  23. % ================= elementary geometric constructions ===============
  24. % Generators:
  25. algebraic procedure is_equal(a,b); a-b;
  26. %algebraic procedure Normal(a); a;
  27. algebraic procedure Point(a,b); {a,b};
  28. algebraic procedure Line(a,b,c); reduce_coords({a,b,c});
  29. algebraic procedure par_point(a,b,c);
  30. Point(part(a,1)-part(b,1)+part(c,1),
  31. part(a,2)-part(b,2)+part(c,2));
  32. algebraic procedure pp_line(a,b);
  33. % The line through A and B.
  34. Line(part(b,2)-part(a,2),part(a,1)-part(b,1),
  35. part(a,2)*part(b,1)-part(a,1)*part(b,2));
  36. algebraic procedure intersection_point(a,b);
  37. % The intersection point of the lines a,b.
  38. begin scalar d,d1,d2;
  39. d:=part(a,1)*part(b,2)-part(b,1)*part(a,2);
  40. d1:=part(a,3)*part(b,2)-part(b,3)*part(a,2);
  41. d2:=part(a,1)*part(b,3)-part(b,1)*part(a,3);
  42. if d=0 then rederr"Lines are parallel";
  43. add_ndg(num d);
  44. return Point(-d1/d,-d2/d);
  45. end;
  46. algebraic procedure ortho_line(p,a);
  47. % The line through P orthogonal to the line a.
  48. begin scalar u,v; u:=first a; v:=second a;
  49. return Line(v,-u,u*second p-v*first p);
  50. end;
  51. algebraic procedure par_line(p,a);
  52. % The parallel to line a through P.
  53. Line(part(a,1),part(a,2),
  54. -(part(a,1)*part(p,1)+part(a,2) *part(p,2)));
  55. algebraic procedure varpoint(b,a,l);
  56. % The point D=l*A+(1-l)*B.
  57. Point(l*part(a,1)+(1-l)*part(b,1),l*part(a,2)+(1-l)*part(b,2));
  58. algebraic procedure line_slider(a,u);
  59. % Slider on the line a using parameter u.
  60. begin scalar p,d;
  61. if part(a,2)=0 then
  62. << p:=Point(-part(a,3)/part(a,1),u); d:=part(a,1); >>
  63. else
  64. << p:=Point(u,-(part(a,3)+part(a,1)*u)/part(a,2));
  65. d:=part(a,2);
  66. >>;
  67. add_ndg(num d);
  68. return p;
  69. end;
  70. algebraic procedure circle_slider(M,A,u);
  71. % Slider on the circle with center M and circumfere point A using
  72. % parameter u.
  73. begin scalar a1,a2,m1,m2,d;
  74. a1:=part(A,1); a2:=part(A,2); d:= u^2 + 1;
  75. m1:=part(M,1); m2:=part(M,2);
  76. add_ndg(num d);
  77. return Point((a1*(u^2-1) + 2*m1 + 2*(m2-a2)*u)/d,
  78. (a2 + 2*(m1-a1)*u + (2*m2-a2)*u^2)/d);
  79. end;
  80. algebraic procedure sqrdist(a,b);
  81. % The square of the distance between the points A and B.
  82. (part(b,1)-part(a,1))^2+(part(b,2)-part(a,2))^2;
  83. % ================= elementary geometric properties ===============
  84. algebraic procedure is_collinear(a,b,c);
  85. % A,B,C are on a common line.
  86. det mat((part(a,1),part(a,2),1),
  87. (part(b,1),part(b,2),1),
  88. (part(c,1),part(c,2),1));
  89. algebraic procedure is_concurrent(a,b,c);
  90. % Lines a,b,c have a common point.
  91. det mat((part(a,1),part(a,2),part(a,3)),
  92. (part(b,1),part(b,2),part(b,3)),
  93. (part(c,1),part(c,2),part(c,3)));
  94. algebraic procedure is_parallel(a,b);
  95. % 0 <=> the lines a,b are parallel.
  96. part(a,1)*part(b,2)-part(b,1)*part(a,2);
  97. algebraic procedure is_orthogonal(a,b);
  98. % 0 <=> the lines a,b are orthogonal.
  99. part(a,1)*part(b,1)+part(a,2)*part(b,2);
  100. algebraic procedure on_line(p,a);
  101. % Substitute point P into the line a.
  102. part(p,1)*part(a,1)+part(p,2)*part(a,2)+part(a,3);
  103. algebraic procedure eq_dist(a,b,c,d); sqrdist(a,b)-sqrdist(c,d);
  104. % #########################################
  105. % # #
  106. % # Non linear geometric objects #
  107. % # #
  108. % #########################################
  109. % ===================== angles
  110. algebraic procedure l2_angle(a,b);
  111. % tan of the angle between the lines a and b.
  112. begin scalar d; d:=(part(a,1)*part(b,1)+part(a,2)*part(b,2));
  113. add_ndg(num(d));
  114. return (part(a,2)*part(b,1)-part(b,2)*part(a,1))/d;
  115. end;
  116. algebraic procedure angle_sum(a,b);
  117. % a=tan(\alpha), b=tan(\beta). Returns tan(\alpha+\beta)
  118. begin scalar d; d:=(1-a*b); add_ndg(num d);
  119. return (a+b)/d;
  120. end;
  121. algebraic procedure eq_angle(a,b,c,d,e,f);
  122. p3_angle(a,b,c)-p3_angle(d,e,f);
  123. algebraic procedure on_bisector(P,A,B,C);
  124. % P is a point on the bisector of the angle ABC.
  125. % Returns num(u)*den(v)-num(v)*den(u) with
  126. % u:=angle(pp_line(A,B),pp_line(P,B))
  127. % v:=angle(pp_line(P,B),pp_line(C,B))
  128. begin scalar a1,a2,b1,b2,c1,c2,p1,p2;
  129. a1:=part(A,1); a2:=part(A,2);
  130. b1:=part(b,1); b2:=part(b,2);
  131. c1:=part(c,1); c2:=part(c,2);
  132. p1:=part(p,1); p2:=part(p,2);
  133. return ( - a1*b2 + a1*p2 + a2*b1 - a2*p1 - b1*p2 + b2*p1)*(b1^2 -
  134. b1*c1 - b1*p1 + b2^2 - b2*c2 - b2*p2 + c1*p1 + c2*p2) - (a1*b1 -
  135. a1*p1 + a2*b2 - a2*p2 - b1^2 + b1*p1 - b2^2 + b2*p2)*(b1*c2 -
  136. b1*p2 - b2*c1 + b2*p1 + c1*p2 - c2*p1)
  137. end;
  138. algebraic procedure rotate(C, A, angle);
  139. begin scalar ac1,ac2;
  140. ac1:=part(A,1)-part(C,1); ac2:=part(A,2)-part(C,2);
  141. return Point(part(C,1)+ac1*cos(angle*pi)-ac2*sin(angle*pi),
  142. part(C,2)+ac1*sin(angle*pi)+ac2*cos(angle*pi));
  143. end;
  144. % ========== symmetric lines and points
  145. algebraic procedure sym_line(a,l);
  146. % The line symmetric to a wrt. the line l.
  147. begin scalar a1,a2,a3,l1,l2,l3,u;
  148. a1:=part(a,1); a2:=part(a,2); a3:=part(a,3);
  149. l1:=part(l,1); l2:=part(l,2); l3:=part(l,3);
  150. u:=l1^2 - l2^2;
  151. return Line(- a1*u - 2*a2*l1*l2, - 2*a1*l1*l2 + a2*u,
  152. - 2*(a1*l1 + a2*l2)*l3 + a3*(l1^2 + l2^2));
  153. end;
  154. % ===================== circles
  155. algebraic procedure Circle(c1,c2,c3,c4); reduce_coords({c1,c2,c3,c4});
  156. algebraic procedure pc_circle(M,A);
  157. % Circle with center M and Point A on circumference.
  158. Circle(1, -2*part(M,1), -2*part(M,2),
  159. part(A,1)*(2*part(M,1)-part(A,1)) +
  160. part(A,2)*(2*part(M,2)-part(A,2)));
  161. algebraic procedure circle_center c;
  162. % The center of the circle c.
  163. begin add_ndg(num part(c,1));
  164. return Point(-part(c,2)/2/part(c,1) ,-part(c,3)/(2*part(c,1)));
  165. end;
  166. algebraic procedure circle_sqradius c;
  167. % The squared radius of the circle c.
  168. begin add_ndg(num part(c,1));
  169. return
  170. ((part(c,2)^2+part(c,3)^2) - 4*part(c,4)*part(c,1)) /
  171. (2*part(c,1))^2;
  172. end;
  173. algebraic procedure p3_circle(A,B,C);
  174. % The circle through three given points
  175. begin scalar a1,a2,a3,b1,b2,b3,c1,c2,c3;
  176. a1:=part(A,1); a2:=part(A,2); a3:=a1^2+a2^2;
  177. b1:=part(b,1); b2:=part(b,2); b3:=b1^2+b2^2;
  178. c1:=part(c,1); c2:=part(c,2); c3:=c1^2+c2^2;
  179. return Circle(a1*(b2-c2) + (a2-b2)*c1 + b1*(c2-a2),
  180. a3*(c2-b2) + (a2-c2)*b3 + (b2-a2)*c3,
  181. a3*(b1-c1) + (c1-a1)*b3 + (a1-b1)*c3,
  182. a3*(b2*c1-b1*c2) + (a1*c2-a2*c1)*b3 + (a2*b1-a1*b2)*c3)
  183. end;
  184. algebraic procedure on_circle(P,c);
  185. begin scalar p1,p2; p1:=part(P,1); p2:=part(P,2);
  186. return part(c,1)*(p1^2+p2^2)+part(c,2)*p1+part(c,3)*p2+part(c,4);
  187. end;
  188. % Intersecting with circles
  189. algebraic procedure other_cl_point(P,c,l);
  190. % circle c and line l intersect at P. The procedure returns their
  191. % second intersection point.
  192. if on_line(P,l) neq 0 then rederr "Point not on the line"
  193. else if on_circle(P,c) neq 0 then
  194. rederr "Point not on the circle"
  195. else begin scalar c1,c2,c3,l1,l2,d,d1,p1,p2;
  196. c1:=part(c,1); c2:=part(c,2); c3:=part(c,3);
  197. l1:=part(l,1); l2:=part(l,2); p1:=part(P,1); p2:=part(P,2);
  198. d:=c1*(l1^2 + l2^2); add_ndg(num d); d1:=c1*(l1^2-l2^2);
  199. return {(d1*p1+((2*c1*p2 + c3)*l1-c2*l2)*l2)/d,
  200. (- d1*p2+((2*c1*p1 + c2)*l2-c3*l1)*l1)/d};
  201. end;
  202. algebraic procedure radical_axis(c1,c2);
  203. % Radical axis of the circles c1 and c2, i.e. the line through the
  204. % intersection points of the two circles if they intersect.
  205. for i:=2:4 collect
  206. (part(c1,1)*part(c2,i)-part(c1,i)*part(c2,1));
  207. algebraic procedure other_cc_point(P,c1,c2);
  208. % Circles c1 and c2 intersect at P. The procedure returns their
  209. % second intersection point.
  210. other_cl_point(P,c1,radical_axis(c1,c2));
  211. algebraic procedure is_cl_tangent(c,l);
  212. % Line l is tangent to the circle c.
  213. begin scalar c1,c2,c3,c4,l1,l2,l3;
  214. c1:=part(c,1); c2:=part(c,2); c3:=part(c,3); c4:=part(c,4);
  215. l1:=part(l,1); l2:=part(l,2); l3:=part(l,3);
  216. return - 4*c1^2*l3^2 + 4*c1*c2*l1*l3 + 4*c1*c3*l2*l3 -
  217. 4*c1*c4*l1^2 - 4*c1*c4*l2^2 + c2^2*l2^2 - 2*c2*c3*l1*l2 +
  218. c3^2*l1^2
  219. end;
  220. algebraic procedure is_cc_tangent(c,d);
  221. % Two circles c,d are tangent.
  222. begin scalar c1,c2,c3,c4,d1,d2,d3,d4;
  223. c1:=part(c,1); c2:=part(c,2); c3:=part(c,3); c4:=part(c,4);
  224. d1:=part(d,1); d2:=part(d,2); d3:=part(d,3); d4:=part(d,4);
  225. return
  226. 4*c1^2*d4^2 - 4*c1*c2*d2*d4 - 4*c1*c3*d3*d4 - 8*c1*c4*d1*d4 +
  227. 4*c1*c4*d2^2 + 4*c1*c4*d3^2 + 4*c2^2*d1*d4 - c2^2*d3^2 + 2*c2*c3*d2*d3
  228. - 4*c2*c4*d1*d2 + 4*c3^2*d1*d4 - c3^2*d2^2 - 4*c3*c4*d1*d3 +
  229. 4*c4^2*d1^2
  230. end;
  231. % ============= some additional tools ===============
  232. symbolic operator list2mat;
  233. symbolic procedure list2mat u;
  234. 'mat. for each x in cdr reval u collect cdr x;
  235. algebraic procedure extractmat(polys,vars);
  236. % extract the coefficient matrix from the linear system polys.
  237. begin
  238. if length polys neq length vars then
  239. rederr"Number of variables doesn't match";
  240. for each p in polys do for each x in vars do
  241. if deg(p,x)>1 then rederr"Equations not of linear type";
  242. return list2mat
  243. for each x in vars collect
  244. for each p in polys collect coeffn(p,x,1);
  245. end;
  246. algebraic procedure reduce_coords u;
  247. % Divide out the content of homogeneous coordinates.
  248. begin scalar l,g;
  249. l:=den first u; g:=num first u;
  250. for each x in rest u do <<l:=lcm(l,den x); g:=gcd(g,num x) >>;
  251. add_ndg(g);
  252. return for each x in u collect (x*l/g);
  253. end;
  254. % ================ new
  255. algebraic procedure circle_inverse(M,R,P);
  256. % compute the inverse of P wrt. the circle pc_circle(M,R)
  257. begin scalar m1,m2,r1,r2,p1,p2,d;
  258. m1:=part(M,1); m2:=part(M,2);
  259. r1:=part(R,1); r2:=part(R,2);
  260. p1:=part(P,1); p2:=part(P,2);
  261. d:=(m1-p1)^2+(m2-p2)^2;
  262. add_ndg(d);
  263. return ((m1-p1)^2+(m2-p2)^2+(m1-r1)^2+(m2-r2)^2)/d;
  264. end;
  265. % GeoProver code generated from database
  266. algebraic procedure altitude(A__,B__,C__);
  267. ortho_line(A__,pp_line(B__,C__));
  268. algebraic procedure centroid(A__,B__,C__);
  269. intersection_point(median(A__,B__,C__),median(B__,C__,A__));
  270. algebraic procedure circumcenter(A__,B__,C__);
  271. intersection_point(p_bisector(A__,B__), p_bisector(B__,C__));
  272. algebraic procedure csym_point(P__,Q__);
  273. varpoint(Q__,P__,-1);
  274. algebraic procedure fixedpoint(A__,B__,u_);
  275. varpoint(A__,B__,u_);
  276. algebraic procedure is_concyclic(A__,B__,C__,D__);
  277. on_circle(D__,p3_circle(A__,B__,C__));
  278. algebraic procedure median(A__,B__,C__);
  279. pp_line(A__,midpoint(B__,C__));
  280. algebraic procedure midpoint(A__,B__);
  281. fixedpoint(A__,B__,1/2);
  282. algebraic procedure orthocenter(A__,B__,C__);
  283. intersection_point(altitude(A__,B__,C__),altitude(B__,C__,A__));
  284. algebraic procedure other_incenter(M__,A__,B__);
  285. intersection_point(ortho_line(A__,pp_line(M__,A__)),
  286. ortho_line(B__,pp_line(M__,B__)));
  287. algebraic procedure p3_angle(A__,B__,C__);
  288. l2_angle(pp_line(B__,A__),pp_line(B__,C__));
  289. algebraic procedure p9_center(A__,B__,C__);
  290. circle_center(p9_circle(A__,B__,C__));
  291. algebraic procedure p9_circle(A__,B__,C__);
  292. p3_circle(midpoint(A__,B__),midpoint(A__,C__),midpoint(B__,C__));
  293. algebraic procedure p_bisector(B__,C__);
  294. ortho_line(midpoint(B__,C__),pp_line(B__,C__));
  295. algebraic procedure pappus_line(A__,B__,C__,D__,E__,F__);
  296. pp_line(intersection_point(pp_line(A__,E__),pp_line(B__,D__)),
  297. intersection_point(pp_line(A__,F__),pp_line(C__,D__)));
  298. algebraic procedure pedalpoint(P__,a_);
  299. intersection_point(ortho_line(P__,a_),a_);
  300. algebraic procedure sqrdist_pl(A__,l_);
  301. sqrdist(A__,pedalpoint(A__,l_));
  302. algebraic procedure sym_point(P__,l_);
  303. fixedpoint(P__,pedalpoint(P__,l_),2);
  304. algebraic procedure triangle_area(A__,B__,C__);
  305. 1/2*is_collinear(A__,B__,C__);
  306. endmodule; % GeoProver
  307. end;