1 /*
2  * Copyright 2012,2013 Google, Inc. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * Google Author(s): Behdad Esfahbod, Maysum Panju
17  */
18 
19 #ifndef GLYPHY_GEOMETRY_HH
20 #define GLYPHY_GEOMETRY_HH
21 
22 #include "glyphy-common.hh"
23 
24 namespace GLyphy {
25 namespace Geometry {
26 
27 template <typename Type> struct Pair;
28 struct Vector;
29 struct SignedVector;
30 struct Point;
31 struct Line;
32 struct Segment;
33 struct Arc;
34 struct Bezier;
35 
36 /* returns tan (2 * atan (d)) */
tan2atan(double d)37 inline double tan2atan (double d) { return 2 * d / (1 - d*d); }
38 
39 /* returns sin (2 * atan (d)) */
sin2atan(double d)40 inline double sin2atan (double d) { return 2 * d / (1 + d*d); }
41 
42 /* returns cos (2 * atan (d)) */
cos2atan(double d)43 inline double cos2atan (double d) { return (1 - d*d) / (1 + d*d); }
44 
45 template <typename Type>
46 struct Pair {
47   typedef Type ElementType;
48 
PairGLyphy::Geometry::Pair49   inline Pair (const Type &first_, const Type &second_) : first (first_), second (second_) {}
50 
51   Type first, second;
52 };
53 
54 struct Point : glyphy_point_t {
PointGLyphy::Geometry::Point55   inline Point (double x_, double y_) { x = x_; y = y_; }
56   inline explicit Point (const Vector &v);
PointGLyphy::Geometry::Point57   inline Point (const glyphy_point_t &p) { *(glyphy_point_t *)this = p; }
58 
59   inline bool operator == (const Point &p) const;
60   inline bool operator != (const Point &p) const;
61   inline Point& operator+= (const Vector &v);
62   inline Point& operator-= (const Vector &v);
63   inline const Point operator+ (const Vector &v) const;
64   inline const Point operator- (const Vector &v) const;
65   inline const Vector operator- (const Point &p) const;
66   inline const Point midpoint (const Point &p) const;
67   inline const Line bisector (const Point &p) const;
68   inline double distance_to_point (const Point &p) const; /* distance to point! */
69   inline double squared_distance_to_point (const Point &p) const; /* square of distance to point! */
70 
71   inline bool is_finite (void) const;
72   inline const Point lerp (const double &a, const Point &p) const;
73 };
74 
75 struct Vector {
VectorGLyphy::Geometry::Vector76   inline Vector (double dx_, double dy_) : dx (dx_), dy (dy_) {}
VectorGLyphy::Geometry::Vector77   inline explicit Vector (const Point &p) : dx (p.x), dy (p.y) {}
78 
79   inline bool operator == (const Vector &v) const;
80   inline bool operator != (const Vector &v) const;
81   inline const Vector operator+ (void) const;
82   inline const Vector operator- (void) const;
83   inline Vector& operator+= (const Vector &v);
84   inline Vector& operator-= (const Vector &v);
85   inline Vector& operator*= (const double &s);
86   inline Vector& operator/= (const double &s);
87   inline const Vector operator+ (const Vector &v) const;
88   inline const Vector operator- (const Vector &v) const;
89   inline const Vector operator* (const double &s) const;
90   inline const Vector operator/ (const double &s) const;
91   inline double operator* (const Vector &v) const; /* dot product */
92   inline const Point operator+ (const Point &p) const;
93 
94   inline bool is_nonzero (void) const;
95   inline double len (void) const;
96   inline double len2 (void) const;
97   inline const Vector normalized (void) const;
98   inline const Vector ortho (void) const;
99   inline const Vector normal (void) const; /* ortho().normalized() */
100   inline double angle (void) const;
101 
102   inline const Vector rebase (const Vector &bx, const Vector &by) const;
103   inline const Vector rebase (const Vector &bx) const;
104 
105   double dx, dy;
106 };
107 
108 struct SignedVector : Vector {
SignedVectorGLyphy::Geometry::SignedVector109   inline SignedVector (const Vector &v, bool negative_) : Vector (v), negative (negative_) {}
110 
111   inline bool operator == (const SignedVector &v) const;
112   inline bool operator != (const SignedVector &v) const;
113   inline const SignedVector operator- (void) const;
114 
115   bool negative;
116 };
117 
118 struct Line {
LineGLyphy::Geometry::Line119   inline Line (double a_, double b_, double c_) : n (a_, b_), c (c_) {}
LineGLyphy::Geometry::Line120   inline Line (Vector n_, double c_) : n (n_), c (c_) {}
LineGLyphy::Geometry::Line121   inline Line (const Point &p0, const Point &p1) :
122                n ((p1 - p0).ortho ()), c (n * Vector (p0)) {}
123 
124   inline const Point operator+ (const Line &l) const; /* line intersection! */
125   inline const SignedVector operator- (const Point &p) const; /* shortest vector from point to line */
126 
127 
128   inline const Line normalized (void) const;
129   inline const Vector normal (void) const;
130 
131   Vector n; /* line normal */
132   double c; /* n.dx*x + n.dy*y = c */
133 };
134 
135 struct Segment {
SegmentGLyphy::Geometry::Segment136   inline Segment (const Point &p0_, const Point &p1_) :
137 		  p0 (p0_), p1 (p1_) {}
138 
139   inline const SignedVector operator- (const Point &p) const; /* shortest vector from point to ***line*** */
140   inline double distance_to_point (const Point &p) const; /* shortest distance from point to segment */
141   inline double squared_distance_to_point (const Point &p) const; /* shortest distance squared from point to segment */
142   inline bool contains_in_span (const Point &p) const; /* is p in the stripe formed by sliding this segment? */
143   inline double max_distance_to_arc (const Arc &a) const;
144 
145 
146   Point p0;
147   Point p1;
148 };
149 
150 
151 
152 struct Arc {
ArcGLyphy::Geometry::Arc153   inline Arc (const Point &p0_, const Point &p1_, const Point &pm, bool complement) :
154 	      p0 (p0_), p1 (p1_),
155 	      d (p0_ == pm || p1_ == pm ? 0 :
156 		 tan (((p1_-pm).angle () - (p0_-pm).angle ()) / 2 - (complement ? 0 : M_PI_2))) {}
ArcGLyphy::Geometry::Arc157   inline Arc (const Point &p0_, const Point &p1_, const double &d_) :
158 	      p0 (p0_), p1 (p1_), d (d_) {}
ArcGLyphy::Geometry::Arc159   inline Arc (const Point &center, double radius, const double &a0, const double &a1, bool complement) :
160 	      p0 (center + Vector (cos(a0),sin(a0)) * radius),
161 	      p1 (center + Vector (cos(a1),sin(a1)) * radius),
162 	      d (tan ((a1 - a0) / 4 - (complement ? 0 : M_PI_2))) {}
ArcGLyphy::Geometry::Arc163   inline Arc (const glyphy_arc_t &a) : p0 (a.p0), p1 (a.p1), d (a.d) {}
operator glyphy_arc_tGLyphy::Geometry::Arc164   inline operator glyphy_arc_t (void) const { glyphy_arc_t a = {p0, p1, d}; return a; }
165 
166   inline bool operator == (const Arc &a) const;
167   inline bool operator != (const Arc &a) const;
168   inline const SignedVector operator- (const Point &p) const; /* shortest vector from point to arc */
169 
170   inline double radius (void) const;
171   inline const Point center (void) const;
172   inline const Pair<Vector> tangents (void) const;
173 
174   inline Bezier approximate_bezier (double *error) const;
175 
176   inline bool wedge_contains_point (const Point &p) const;
177   inline double distance_to_point (const Point &p) const;
178   inline double squared_distance_to_point (const Point &p) const;
179   inline double extended_dist (const Point &p) const;
180 
181   inline void extents (glyphy_extents_t &extents) const;
182 
183   Point p0, p1;
184   double d; /* Depth */
185 };
186 
187 struct Bezier {
BezierGLyphy::Geometry::Bezier188   inline Bezier (const Point &p0_, const Point &p1_,
189 		 const Point &p2_, const Point &p3_) :
190 		 p0 (p0_), p1 (p1_), p2 (p2_), p3 (p3_) {}
191 
192   inline const Point point (const double &t) const;
193   inline const Point midpoint (void) const;
194   inline const Vector tangent (const double &t) const;
195   inline const Vector d_tangent (const double &t) const;
196   inline double curvature (const double &t) const;
197   inline const Pair<Bezier> split (const double &t) const;
198   inline const Pair<Bezier> halve (void) const;
199   inline const Bezier segment (const double &t0, const double &t1) const;
200 
201   Point p0, p1, p2, p3;
202 };
203 
204 
205 /* Implementations */
206 
207 
208 /* Point */
209 
Point(const Vector & v)210 inline Point::Point (const Vector &v) {
211   x = v.dx;
212   y = v.dy;
213 }
operator ==(const Point & p) const214 inline bool Point::operator == (const Point &p) const {
215   return x == p.x && y == p.y;
216 }
operator !=(const Point & p) const217 inline bool Point::operator != (const Point &p) const {
218   return !(*this == p);
219 }
operator +=(const Vector & v)220 inline Point& Point::operator+= (const Vector &v) {
221   x += v.dx;
222   y += v.dy;
223   return *this;
224 }
operator -=(const Vector & v)225 inline Point& Point::operator-= (const Vector &v) {
226   x -= v.dx;
227   y -= v.dy;
228   return *this;
229 }
operator +(const Vector & v) const230 inline const Point Point::operator+ (const Vector &v) const {
231   return Point (*this) += v;
232 }
operator -(const Vector & v) const233 inline const Point Point::operator- (const Vector &v) const {
234   return Point (*this) -= v;
235 }
operator -(const Point & p) const236 inline const Vector Point::operator- (const Point &p) const {
237   return Vector (x - p.x, y - p.y);
238 }
239 
midpoint(const Point & p) const240 inline const Point Point::midpoint (const Point &p) const {
241   return *this + (p - *this) / 2;
242 }
bisector(const Point & p) const243 inline const Line Point::bisector (const Point &p) const {
244   Vector d = p - *this;
245   return Line (d.dx * 2, d.dy * 2, d * Vector (p) + d * Vector (*this));
246 }
247 
distance_to_point(const Point & p) const248 inline double Point::distance_to_point (const Point &p) const {
249   return ((*this) - p).len ();
250 }
251 
squared_distance_to_point(const Point & p) const252 inline double Point::squared_distance_to_point (const Point &p) const {
253   return ((*this) - p).len2 ();
254 }
255 
is_finite(void) const256 inline bool Point::is_finite (void) const {
257   return isfinite (x) && isfinite (y);
258 }
lerp(const double & a,const Point & p) const259 inline const Point Point::lerp (const double &a, const Point &p) const {
260   /* The following two cases are special-cased to get better floating
261    * point stability.  We require that points that are the same be
262    * bit-equal. */
263   if (a == 0)   return *this;
264   if (a == 1.0) return p;
265   return Point ((1-a) * x + a * p.x, (1-a) * y + a * p.y);
266 }
267 
268 
269 /* Vector */
270 
operator ==(const Vector & v) const271 inline bool Vector::operator == (const Vector &v) const {
272   return dx == v.dx && dy == v.dy;
273 }
operator !=(const Vector & v) const274 inline bool Vector::operator != (const Vector &v) const {
275   return !(*this == v);
276 }
operator +(void) const277 inline const Vector Vector::operator+ (void) const {
278   return *this;
279 }
operator -(void) const280 inline const Vector Vector::operator- (void) const {
281   return Vector (-dx, -dy);
282 }
operator +=(const Vector & v)283 inline Vector& Vector::operator+= (const Vector &v) {
284   dx += v.dx;
285   dy += v.dy;
286   return *this;
287 }
operator -=(const Vector & v)288 inline Vector& Vector::operator-= (const Vector &v) {
289   dx -= v.dx;
290   dy -= v.dy;
291   return *this;
292 }
operator *=(const double & s)293 inline Vector& Vector::operator*= (const double &s) {
294   dx *= s;
295   dy *= s;
296   return *this;
297 }
operator /=(const double & s)298 inline Vector& Vector::operator/= (const double &s) {
299   dx /= s;
300   dy /= s;
301   return *this;
302 }
operator +(const Vector & v) const303 inline const Vector Vector::operator+ (const Vector &v) const {
304   return Vector (*this) += v;
305 }
operator -(const Vector & v) const306 inline const Vector Vector::operator- (const Vector &v) const {
307   return Vector (*this) -= v;
308 }
operator *(const double & s) const309 inline const Vector Vector::operator* (const double &s) const {
310   return Vector (*this) *= s;
311 }
operator *(const double & s,const Vector & v)312 inline const Vector operator* (const double &s, const Vector &v) {
313   return v * s;
314 }
operator /(const double & s) const315 inline const Vector Vector::operator/ (const double &s) const {
316   return Vector (*this) /= s;
317 }
operator *(const Vector & v) const318 inline double Vector::operator* (const Vector &v) const { /* dot product */
319   return dx * v.dx + dy * v.dy;
320 }
operator +(const Point & p) const321 inline const Point Vector::operator+ (const Point &p) const {
322   return p + *this;
323 }
324 
is_nonzero(void) const325 inline bool Vector::is_nonzero (void) const {
326   return dx || dy;
327 }
len(void) const328 inline double Vector::len (void) const {
329   return hypot (dx, dy);
330 }
len2(void) const331 inline double Vector::len2 (void) const {
332   return dx * dx + dy * dy;
333 }
normalized(void) const334 inline const Vector Vector::normalized (void) const {
335   double d = len ();
336   return d ? *this / d : *this;
337 }
ortho(void) const338 inline const Vector Vector::ortho (void) const {
339   return Vector (-dy, dx);
340 }
normal(void) const341 inline const Vector Vector::normal (void) const {
342   return ortho ().normalized ();
343 }
angle(void) const344 inline double Vector::angle (void) const {
345   return atan2 (dy, dx);
346 }
347 
rebase(const Vector & bx,const Vector & by) const348 inline const Vector Vector::rebase (const Vector &bx,
349 				    const Vector &by) const {
350   return Vector (*this * bx, *this * by);
351 }
rebase(const Vector & bx) const352 inline const Vector Vector::rebase (const Vector &bx) const {
353   return rebase (bx, bx.ortho ());
354 }
355 
356 
357 /* SignedVector */
358 
operator ==(const SignedVector & v) const359 inline bool SignedVector::operator == (const SignedVector &v) const {
360   return (const Vector &)(*this) == (const Vector &)(v) && negative == v.negative;
361 }
operator !=(const SignedVector & v) const362 inline bool SignedVector::operator != (const SignedVector &v) const {
363   return !(*this == v);
364 }
operator -(void) const365 inline const SignedVector SignedVector::operator- (void) const {
366   return SignedVector (-(const Vector &)(*this), !negative);
367 }
368 
369 
370 /* Line */
371 
operator +(const Line & l) const372 inline const Point Line::operator+ (const Line &l) const {
373   double det = n.dx * l.n.dy - n.dy * l.n.dx;
374   if (!det)
375     return Point (GLYPHY_INFINITY, GLYPHY_INFINITY);
376   return Point ((c * l.n.dy - n.dy * l.c) / det,
377 		       (n.dx * l.c - c * l.n.dx) / det);
378 }
operator -(const Point & p) const379 inline const SignedVector Line::operator- (const Point &p) const {
380   double mag = -(n * Vector (p) - c) / n.len ();
381   return SignedVector (n.normalized () * mag, mag < 0); /******************************************************************************************* FIX. *************************************/
382 }
383 
operator -(const Point & p,const Line & l)384 inline const SignedVector operator- (const Point &p, const Line &l) {
385   return -(l - p);
386 }
387 
normalized(void) const388 inline const Line Line::normalized (void) const {
389   double d = n.len ();
390   return d ? Line (n / d, c / d) : *this;
391 }
normal(void) const392 inline const Vector Line::normal (void) const {
393   return n;
394 }
395 
396 /* Segment */
operator -(const Point & p) const397 inline const SignedVector Segment::operator- (const Point &p) const {
398   /* shortest vector from point to line */
399   return p - Line (p1, p0); /************************************************************************************************** Should the order (p1, p0) depend on d?? ***********************/
400 }
401 
402 /* Segment */
contains_in_span(const Point & p) const403 inline bool Segment::contains_in_span (const Point &p) const {
404   if (p0 == p1)
405     return false;
406 
407   /* shortest vector from point to line */
408   Line temp (p0, p1);
409   double mag = -(temp.n * Vector (p) - temp.c) / temp.n.len ();
410   Vector y (temp.n.normalized () * mag);
411   Point z = y + p;
412 
413   // Check if z is between p0 and p1.
414 
415   if (fabs (p1.y - p0.y) > fabs (p1.x - p0.x)) {
416     return ((z.y - p0.y > 0 && p1.y - p0.y > z.y - p0.y) ||
417             (z.y - p0.y < 0 && p1.y - p0.y < z.y - p0.y));
418   }
419   else {
420     return ((0 < z.x - p0.x && z.x - p0.x < p1.x - p0.x) ||
421             (0 > z.x - p0.x && z.x - p0.x > p1.x - p0.x));
422   }
423 }
424 
distance_to_point(const Point & p) const425 inline double Segment::distance_to_point (const Point &p) const {
426   if (p0 == p1)
427     return 0;
428 
429   // Check if z is between p0 and p1.
430   Line temp (p0, p1);
431   if (contains_in_span (p))
432     return -(temp.n * Vector (p) - temp.c) / temp.n.len ();
433 
434   double dist_p_p0 = p.distance_to_point (p0);
435   double dist_p_p1 = p.distance_to_point (p1);
436   return (dist_p_p0 < dist_p_p1 ? dist_p_p0 : dist_p_p1) * (-(temp.n * Vector (p) - temp.c) < 0 ? -1 : 1);
437 }
438 
439 
squared_distance_to_point(const Point & p) const440 inline double Segment::squared_distance_to_point (const Point &p) const {
441   if (p0 == p1)
442     return 0;
443 
444   // Check if z is between p0 and p1.
445   Line temp (p0, p1);
446   if (contains_in_span (p))
447     return (temp.n * Vector (p) - temp.c) * (temp.n * Vector (p) - temp.c) / (temp.n * temp.n);
448 
449   double dist_p_p0 = p.squared_distance_to_point (p0);
450   double dist_p_p1 = p.squared_distance_to_point (p1);
451   return (dist_p_p0 < dist_p_p1 ? dist_p_p0 : dist_p_p1);
452 }
453 
454 
max_distance_to_arc(const Arc & a) const455 inline double Segment::max_distance_to_arc (const Arc &a) const {
456   double max_distance = fabs(a.distance_to_point(p0)) ;
457   return  max_distance >  fabs(a.distance_to_point(p1)) ? max_distance : fabs(a.distance_to_point(p1)) ;
458 }
459 
460 
461 
462 /* Arc */
463 
operator ==(const Arc & a) const464 inline bool Arc::operator == (const Arc &a) const {
465   return p0 == a.p0 && p1 == a.p1 && d == a.d;
466 }
operator !=(const Arc & a) const467 inline bool Arc::operator != (const Arc &a) const {
468   return !(*this == a);
469 }
470 
471 
operator -(const Point & p) const472 inline const SignedVector Arc::operator- (const Point &p) const {
473 
474   if (fabs(d) < 1e-5) {
475     Segment arc_segment (p0, p1);
476     return arc_segment - p;
477   }
478   if (wedge_contains_point (p)){
479     Vector difference = (center () - p).normalized () * fabs (p.distance_to_point (center ()) - radius ());
480 
481     return SignedVector  (difference, ((p - center ()).len () < radius ()) ^ (d < 0));
482   }
483   double d0 = p.squared_distance_to_point (p0);
484   double d1 = p.squared_distance_to_point (p1);
485 
486   Arc other_arc (p0, p1, (1.0 + d) / (1.0 - d));  /********************************* NOT Robust. But works? *****************/
487   Vector normal = center () - (d0 < d1 ? p0 : p1) ;
488 
489   if (normal.len() == 0)
490     return SignedVector (Vector (0, 0), true);    /************************************ Check sign of this S.D. *************/
491 
492   return SignedVector (Line (normal.dx, normal.dy, normal * Vector ((d0 < d1 ? p0 : p1))) - p, !other_arc.wedge_contains_point(p));
493 }
494 
operator -(const Point & p,const Arc & a)495 inline const SignedVector operator- (const Point &p, const Arc &a) {
496   return -(a - p);
497 }
498 
499 
500 
radius(void) const501 inline double Arc::radius (void) const
502 {
503   return fabs ((p1 - p0).len () / (2 * sin2atan (d)));
504 }
505 
center(void) const506 inline const Point Arc::center (void) const
507 {
508   return (p0.midpoint (p1)) + (p1 - p0).ortho () / (2 * tan2atan (d));
509 }
510 
tangents(void) const511 inline const Pair<Vector> Arc::tangents (void) const
512 {
513   Vector dp = (p1 - p0) * .5;
514   Vector pp = dp.ortho () * -sin2atan (d);
515   dp = dp * cos2atan (d);
516   return Pair<Vector> (dp + pp, dp - pp);
517 }
518 
519 
520 
approximate_bezier(double * error) const521 inline Bezier Arc::approximate_bezier (double *error) const
522 {
523   Vector dp = p1 - p0;
524   Vector pp = dp.ortho ();
525 
526   if (error)
527     *error = dp.len () * pow (fabs (d), 5) / (54 * (1 + d*d));
528 
529   dp *= ((1 - d*d) / 3);
530   pp *= (2 * d / 3);
531 
532   Point p0s = p0 + dp - pp;
533   Point p1s = p1 - dp - pp;
534 
535   return Bezier (p0, p0s, p1s, p1);
536 }
537 
538 
wedge_contains_point(const Point & p) const539 inline bool Arc::wedge_contains_point (const Point &p) const
540 {
541   Pair<Vector> t = tangents ();
542   if (fabs (d) <= 1)
543     return (p - p0) * t.first  >= 0 && (p - p1) * t.second <= 0;
544   else
545     return (p - p0) * t.first  >= 0 || (p - p1) * t.second <= 0;
546 }
547 
548 
549 /* Distance may not always be positive, but will be to an endpoint whenever necessary. */
distance_to_point(const Point & p) const550 inline double Arc::distance_to_point (const Point &p) const {
551   if (fabs(d) < 1e-5) {
552     Segment arc_segment (p0, p1);
553     return arc_segment.distance_to_point (p);
554   }
555 
556   SignedVector difference = *this - p;
557 
558   if (wedge_contains_point (p) && fabs(d) > 1e-5)
559     return fabs (p.distance_to_point (center ()) - radius ()) * (difference.negative ? -1 : 1);
560   double d1 = p.squared_distance_to_point (p0);
561   double d2 = p.squared_distance_to_point (p1);
562   return (d1 < d2 ? sqrt(d1) : sqrt(d2)) * (difference.negative ? -1 : 1);
563 }
564 
565 /* Distance will be to an endpoint whenever necessary. */
squared_distance_to_point(const Point & p) const566 inline double Arc::squared_distance_to_point (const Point &p) const {
567   if (fabs(d) < 1e-5) {
568     Segment arc_segment (p0, p1);
569     return arc_segment.squared_distance_to_point (p);
570   }
571 
572   //SignedVector difference = *this - p;
573 
574   if (wedge_contains_point (p) && fabs(d) > 1e-5) {
575     double answer = p.distance_to_point (center ()) - radius ();
576     return answer * answer;
577   }
578   double d1 = p.squared_distance_to_point (p0);
579   double d2 = p.squared_distance_to_point (p1);
580   return (d1 < d2 ? d1 : d2);
581 }
582 
extended_dist(const Point & p) const583 inline double Arc::extended_dist (const Point &p) const {
584   Point m = p0.lerp (.5, p1);
585   Vector dp = p1 - p0;
586   Vector pp = dp.ortho ();
587   float d2 = tan2atan (d);
588   if ((p - m) * (p1 - m) < 0)
589     return (p - p0) * (pp + dp * d2).normalized ();
590   else
591     return (p - p1) * (pp - dp * d2).normalized ();
592 }
593 
extents(glyphy_extents_t & extents) const594 inline void Arc::extents (glyphy_extents_t &extents) const {
595   glyphy_extents_clear (&extents);
596   glyphy_extents_add (&extents, &p0);
597   glyphy_extents_add (&extents, &p1);
598   Point c = center ();
599   double r = radius ();
600   Point p[4] = {c + r * Vector (-1,  0),
601 		c + r * Vector (+1,  0),
602 		c + r * Vector ( 0, -1),
603 		c + r * Vector ( 0, +1)};
604   for (unsigned int i = 0; i < 4; i++)
605     if (wedge_contains_point (p[i]))
606       glyphy_extents_add (&extents, &p[i]);
607 }
608 
609 
610 /* Bezier */
611 
point(const double & t) const612 inline const Point Bezier::point (const double &t) const {
613   Point p01 = p0.lerp (t, p1);
614   Point p12 = p1.lerp (t, p2);
615   Point p23 = p2.lerp (t, p3);
616   Point p012 = p01.lerp (t, p12);
617   Point p123 = p12.lerp (t, p23);
618   Point p0123 = p012.lerp (t, p123);
619   return p0123;
620 }
621 
midpoint(void) const622 inline const Point Bezier::midpoint (void) const
623 {
624   Point p01 = p0.midpoint (p1);
625   Point p12 = p1.midpoint (p2);
626   Point p23 = p2.midpoint (p3);
627   Point p012 = p01.midpoint (p12);
628   Point p123 = p12.midpoint (p23);
629   Point p0123 = p012.midpoint (p123);
630   return p0123;
631 }
632 
tangent(const double & t) const633 inline const Vector Bezier::tangent (const double &t) const
634 {
635   double t_2_0 = t * t;
636   double t_0_2 = (1 - t) * (1 - t);
637 
638   double _1__4t_1_0_3t_2_0 = 1 - 4 * t + 3 * t_2_0;
639   double _2t_1_0_3t_2_0    =     2 * t - 3 * t_2_0;
640 
641   return Vector (-3 * p0.x * t_0_2
642 			+3 * p1.x * _1__4t_1_0_3t_2_0
643 			+3 * p2.x * _2t_1_0_3t_2_0
644 			+3 * p3.x * t_2_0,
645 			-3 * p0.y * t_0_2
646 			+3 * p1.y * _1__4t_1_0_3t_2_0
647 			+3 * p2.y * _2t_1_0_3t_2_0
648 			+3 * p3.y * t_2_0);
649 }
650 
d_tangent(const double & t) const651 inline const Vector Bezier::d_tangent (const double &t) const {
652   return Vector (6 * ((-p0.x + 3*p1.x - 3*p2.x + p3.x) * t + (p0.x - 2*p1.x + p2.x)),
653 			6 * ((-p0.y + 3*p1.y - 3*p2.y + p3.y) * t + (p0.y - 2*p1.y + p2.y)));
654 }
655 
curvature(const double & t) const656 inline double Bezier::curvature (const double &t) const {
657   Vector dpp = tangent (t).ortho ();
658   Vector ddp = d_tangent (t);
659   /* normal vector len squared */
660   double len = dpp.len ();
661   double curvature = (dpp * ddp) / (len * len * len);
662   return curvature;
663 }
664 
split(const double & t) const665 inline const Pair<Bezier > Bezier::split (const double &t) const {
666   Point p01 = p0.lerp (t, p1);
667   Point p12 = p1.lerp (t, p2);
668   Point p23 = p2.lerp (t, p3);
669   Point p012 = p01.lerp (t, p12);
670   Point p123 = p12.lerp (t, p23);
671   Point p0123 = p012.lerp (t, p123);
672   return Pair<Bezier> (Bezier (p0, p01, p012, p0123),
673 		       Bezier (p0123, p123, p23, p3));
674 }
675 
halve(void) const676 inline const Pair<Bezier > Bezier::halve (void) const
677 {
678   Point p01 = p0.midpoint (p1);
679   Point p12 = p1.midpoint (p2);
680   Point p23 = p2.midpoint (p3);
681   Point p012 = p01.midpoint (p12);
682   Point p123 = p12.midpoint (p23);
683   Point p0123 = p012.midpoint (p123);
684   return Pair<Bezier> (Bezier (p0, p01, p012, p0123),
685 		       Bezier (p0123, p123, p23, p3));
686 }
687 
segment(const double & t0,const double & t1) const688 inline const Bezier Bezier::segment (const double &t0, const double &t1) const
689 {
690   Point p01 = p0.lerp (t0, p1);
691   Point p12 = p1.lerp (t0, p2);
692   Point p23 = p2.lerp (t0, p3);
693   Point p012 = p01.lerp (t0, p12);
694   Point p123 = p12.lerp (t0, p23);
695   Point p0123 = p012.lerp (t0, p123);
696 
697   Point q01 = p0.lerp (t1, p1);
698   Point q12 = p1.lerp (t1, p2);
699   Point q23 = p2.lerp (t1, p3);
700   Point q012 = q01.lerp (t1, q12);
701   Point q123 = q12.lerp (t1, q23);
702   Point q0123 = q012.lerp (t1, q123);
703 
704   return Bezier (p0123,
705 		 p0123 + (p123 - p0123) * ((t1 - t0) / (1 - t0)),
706 		 q0123 + (q012 - q0123) * ((t1 - t0) / t1),
707 		 q0123);
708 }
709 
710 } /* namespace Geometry */
711 } /* namespace GLyphy */
712 
713 #endif /* GLYPHY_GEOMETRY_HH */
714