arith3.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <draw.h>
  12. #include <geometry.h>
  13. /*
  14. * Routines whose names end in 3 work on points in Affine 3-space.
  15. * They ignore w in all arguments and produce w=1 in all results.
  16. * Routines whose names end in 4 work on points in Projective 3-space.
  17. */
  18. Point3 add3(Point3 a, Point3 b){
  19. a.x+=b.x;
  20. a.y+=b.y;
  21. a.z+=b.z;
  22. a.w=1.;
  23. return a;
  24. }
  25. Point3 sub3(Point3 a, Point3 b){
  26. a.x-=b.x;
  27. a.y-=b.y;
  28. a.z-=b.z;
  29. a.w=1.;
  30. return a;
  31. }
  32. Point3 neg3(Point3 a){
  33. a.x=-a.x;
  34. a.y=-a.y;
  35. a.z=-a.z;
  36. a.w=1.;
  37. return a;
  38. }
  39. Point3 div3(Point3 a, double b){
  40. a.x/=b;
  41. a.y/=b;
  42. a.z/=b;
  43. a.w=1.;
  44. return a;
  45. }
  46. Point3 mul3(Point3 a, double b){
  47. a.x*=b;
  48. a.y*=b;
  49. a.z*=b;
  50. a.w=1.;
  51. return a;
  52. }
  53. int eqpt3(Point3 p, Point3 q){
  54. return p.x==q.x && p.y==q.y && p.z==q.z;
  55. }
  56. /*
  57. * Are these points closer than eps, in a relative sense
  58. */
  59. int closept3(Point3 p, Point3 q, double eps){
  60. return 2.*dist3(p, q)<eps*(len3(p)+len3(q));
  61. }
  62. double dot3(Point3 p, Point3 q){
  63. return p.x*q.x+p.y*q.y+p.z*q.z;
  64. }
  65. Point3 cross3(Point3 p, Point3 q){
  66. Point3 r;
  67. r.x=p.y*q.z-p.z*q.y;
  68. r.y=p.z*q.x-p.x*q.z;
  69. r.z=p.x*q.y-p.y*q.x;
  70. r.w=1.;
  71. return r;
  72. }
  73. double len3(Point3 p){
  74. return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
  75. }
  76. double dist3(Point3 p, Point3 q){
  77. p.x-=q.x;
  78. p.y-=q.y;
  79. p.z-=q.z;
  80. return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
  81. }
  82. Point3 unit3(Point3 p){
  83. double len=sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
  84. p.x/=len;
  85. p.y/=len;
  86. p.z/=len;
  87. p.w=1.;
  88. return p;
  89. }
  90. Point3 midpt3(Point3 p, Point3 q){
  91. p.x=.5*(p.x+q.x);
  92. p.y=.5*(p.y+q.y);
  93. p.z=.5*(p.z+q.z);
  94. p.w=1.;
  95. return p;
  96. }
  97. Point3 lerp3(Point3 p, Point3 q, double alpha){
  98. p.x+=(q.x-p.x)*alpha;
  99. p.y+=(q.y-p.y)*alpha;
  100. p.z+=(q.z-p.z)*alpha;
  101. p.w=1.;
  102. return p;
  103. }
  104. /*
  105. * Reflect point p in the line joining p0 and p1
  106. */
  107. Point3 reflect3(Point3 p, Point3 p0, Point3 p1){
  108. Point3 a, b;
  109. a=sub3(p, p0);
  110. b=sub3(p1, p0);
  111. return add3(a, mul3(b, 2*dot3(a, b)/dot3(b, b)));
  112. }
  113. /*
  114. * Return the nearest point on segment [p0,p1] to point testp
  115. */
  116. Point3 nearseg3(Point3 p0, Point3 p1, Point3 testp){
  117. double num, den;
  118. Point3 q, r;
  119. q=sub3(p1, p0);
  120. r=sub3(testp, p0);
  121. num=dot3(q, r);;
  122. if(num<=0) return p0;
  123. den=dot3(q, q);
  124. if(num>=den) return p1;
  125. return add3(p0, mul3(q, num/den));
  126. }
  127. /*
  128. * distance from point p to segment [p0,p1]
  129. */
  130. #define SMALL 1e-8 /* what should this value be? */
  131. double pldist3(Point3 p, Point3 p0, Point3 p1){
  132. Point3 d, e;
  133. double dd, de, dsq;
  134. d=sub3(p1, p0);
  135. e=sub3(p, p0);
  136. dd=dot3(d, d);
  137. de=dot3(d, e);
  138. if(dd<SMALL*SMALL) return len3(e);
  139. dsq=dot3(e, e)-de*de/dd;
  140. if(dsq<SMALL*SMALL) return 0;
  141. return sqrt(dsq);
  142. }
  143. /*
  144. * vdiv3(a, b) is the magnitude of the projection of a onto b
  145. * measured in units of the length of b.
  146. * vrem3(a, b) is the component of a perpendicular to b.
  147. */
  148. double vdiv3(Point3 a, Point3 b){
  149. return (a.x*b.x+a.y*b.y+a.z*b.z)/(b.x*b.x+b.y*b.y+b.z*b.z);
  150. }
  151. Point3 vrem3(Point3 a, Point3 b){
  152. double quo=(a.x*b.x+a.y*b.y+a.z*b.z)/(b.x*b.x+b.y*b.y+b.z*b.z);
  153. a.x-=b.x*quo;
  154. a.y-=b.y*quo;
  155. a.z-=b.z*quo;
  156. a.w=1.;
  157. return a;
  158. }
  159. /*
  160. * Compute face (plane) with given normal, containing a given point
  161. */
  162. Point3 pn2f3(Point3 p, Point3 n){
  163. n.w=-dot3(p, n);
  164. return n;
  165. }
  166. /*
  167. * Compute face containing three points
  168. */
  169. Point3 ppp2f3(Point3 p0, Point3 p1, Point3 p2){
  170. Point3 p01, p02;
  171. p01=sub3(p1, p0);
  172. p02=sub3(p2, p0);
  173. return pn2f3(p0, cross3(p01, p02));
  174. }
  175. /*
  176. * Compute point common to three faces.
  177. * Cramer's rule, yuk.
  178. */
  179. Point3 fff2p3(Point3 f0, Point3 f1, Point3 f2){
  180. double det;
  181. Point3 p;
  182. det=dot3(f0, cross3(f1, f2));
  183. if(fabs(det)<SMALL){ /* parallel planes, bogus answer */
  184. p.x=0.;
  185. p.y=0.;
  186. p.z=0.;
  187. p.w=0.;
  188. return p;
  189. }
  190. p.x=(f0.w*(f2.y*f1.z-f1.y*f2.z)
  191. +f1.w*(f0.y*f2.z-f2.y*f0.z)+f2.w*(f1.y*f0.z-f0.y*f1.z))/det;
  192. p.y=(f0.w*(f2.z*f1.x-f1.z*f2.x)
  193. +f1.w*(f0.z*f2.x-f2.z*f0.x)+f2.w*(f1.z*f0.x-f0.z*f1.x))/det;
  194. p.z=(f0.w*(f2.x*f1.y-f1.x*f2.y)
  195. +f1.w*(f0.x*f2.y-f2.x*f0.y)+f2.w*(f1.x*f0.y-f0.x*f1.y))/det;
  196. p.w=1.;
  197. return p;
  198. }
  199. /*
  200. * pdiv4 does perspective division to convert a projective point to affine coordinates.
  201. */
  202. Point3 pdiv4(Point3 a){
  203. if(a.w==0) return a;
  204. a.x/=a.w;
  205. a.y/=a.w;
  206. a.z/=a.w;
  207. a.w=1.;
  208. return a;
  209. }
  210. Point3 add4(Point3 a, Point3 b){
  211. a.x+=b.x;
  212. a.y+=b.y;
  213. a.z+=b.z;
  214. a.w+=b.w;
  215. return a;
  216. }
  217. Point3 sub4(Point3 a, Point3 b){
  218. a.x-=b.x;
  219. a.y-=b.y;
  220. a.z-=b.z;
  221. a.w-=b.w;
  222. return a;
  223. }