1 //////////////////////////////////////////////////////////////////////
2 
3 struct Matrixf;
4 
5 static const double TWOPI = 2 * M_PI;
6 static const double DEGRAD = M_PI / 180.0;
7 
8 //////////////////////////////////////////////////////////////////////
9 
10 //inline Pointf Pointf_0     ()                                 { return Pointf(0, 0); }
11 //inline Pointf Pointf_X     ()                                 { return Pointf(1, 0); }
12 //inline Pointf Pointf_Y     ()                                 { return Pointf(0, 1); }
13 //inline Pointf Pointf_RX    ()                                 { return Pointf(-1, 1); }
14 //inline Pointf Pointf_RY    ()                                 { return Pointf(1, -1); }
15 
fpmin(Pointf p,Pointf q)16 inline Pointf fpmin        (Pointf p, Pointf q)               { return Pointf(min(p.x, q.x), min(p.y, q.y)); }
fpmax(Pointf p,Pointf q)17 inline Pointf fpmax        (Pointf p, Pointf q)               { return Pointf(max(p.x, q.x), max(p.y, q.y)); }
fpminmax(Pointf p,Pointf mn,Pointf mx)18 inline Pointf fpminmax     (Pointf p, Pointf mn, Pointf mx)   { return Pointf(minmax(p.x, mn.x, mx.x), minmax(p.y, mn.y, mx.y)); }
19 
fpmin(Pointf p)20 inline double fpmin        (Pointf p)                         { return min(p.x, p.y); }
fpmax(Pointf p)21 inline double fpmax        (Pointf p)                         { return max(p.x, p.y); }
fpabsmin(Pointf p)22 inline double fpabsmin     (Pointf p)                         { return min(fabs(p.x), fabs(p.y)); }
fpabsmax(Pointf p)23 inline double fpabsmax     (Pointf p)                         { return max(fabs(p.x), fabs(p.y)); }
24 
25 // temporary fix by Mirek Fidler:
26 //inline double ScalarProduct(Sizef a, Sizef b) { return a.cx * b.cx + a.cy * b.cy; }
27 //inline double VectorProduct(Sizef a, Sizef b) { return a.cx * b.cy - a.cy * b.cx; }
28 //inline double Squared(Sizef a)             { return a.cx * a.cx + a.cy * a.cy; }
29 //inline double Length(Sizef a)              { return hypot(a.cx, a.cy); }
30 
31 //inline int    ScalarProduct(Size a, Size b) { return a.cx * b.cx + a.cy * b.cy; }
32 //inline int    VectorProduct(Size a, Size b) { return a.cx * b.cy - a.cy * b.cx; }
33 //inline int    Squared(Size a)             { return a.cx * a.cx + a.cy * a.cy; }
34 //inline double Length(Size a)              { return hypot(a.cx, a.cy); }
35 
36 
Move(const Pointf & p,double dx,double dy)37 inline Pointf Move         (const Pointf& p, double dx, double dy)   { return Pointf(p.x + dx, p.y + dy); }
Mid(const Pointf & p,const Pointf & q,double wt)38 inline Pointf Mid          (const Pointf& p, const Pointf& q, double wt) { return p + (q - p) * wt; }
Squared(const Pointf & p,const Pointf & q)39 inline double Squared      (const Pointf& p, const Pointf& q)        { return Squared(q - p); }
40 Pointf        Length       (const Pointf& p, double l);
UnitV(const Pointf & p)41 inline Pointf UnitV        (const Pointf& p)                         { return Length(p, 1); }
Rotated(const Pointf & p,double a)42 inline Pointf Rotated      (const Pointf& p, double a)               { double s = sin(a), c = cos(a); return Pointf(p.x * c - p.y * s, p.x * s + p.y * c); }
Rotated(const Pointf & p,double angle,const Pointf & c)43 inline Pointf Rotated      (const Pointf& p, double angle, const Pointf& c) { return c + Rotated(p - c, angle); }
44 Pointf        Project      (const Pointf& p, const Pointf& a, const Pointf& b);
45 Pointf        Bezier2      (const Pointf& a, const Pointf& b, const Pointf& c, double t);
46 double        Bezier2Length(const Pointf& a, const Pointf& b, const Pointf& c, double t);
47 Sizef         Bezier2Tangent(const Pointf& a, const Pointf& b, const Pointf& c, double t);
48 Sizef         Orthogonal   (const Sizef& p, const Sizef& against);
49 Sizef         Orthonormal  (const Sizef& p, const Sizef& against);
50 Sizef         FarthestAxis (const Sizef& p);
Reversed(const Pointf & p)51 inline Pointf Reversed     (const Pointf& p)                         { return Pointf(-p.x, -p.y); }
ReversedX(const Pointf & p)52 inline Pointf ReversedX    (const Pointf& p)                         { return Pointf(-p.x, p.y); }
ReversedY(const Pointf & p)53 inline Pointf ReversedY    (const Pointf& p)                         { return Pointf(p.x, -p.y); }
54 //inline Pointf Abs          (Pointf p)                         { return Pointf(fabs(p.x), fabs(p.y)); }
Left(const Pointf & p)55 inline Pointf Left         (const Pointf& p)                         { return Pointf(-p.y, p.x); }
Right(const Pointf & p)56 inline Pointf Right        (const Pointf& p)                         { return Pointf(p.y, -p.x); }
57 
Bearing(const Pointf & p,const Pointf & c)58 inline double Bearing      (const Pointf& p, const Pointf& c) { return Bearing(p - c); }
Select(const Pointf & p,const Pointf & A,const Pointf & B)59 inline bool   Select       (const Pointf& p, const Pointf& A, const Pointf& B) { return Squared(p - A) < Squared(p - B); }
60 
61 inline double operator ^   (const Pointf& p, const Pointf& q) { return p.x * q.x + p.y * q.y; }
62 inline double operator %   (const Pointf& p, const Pointf& q) { return p.x * q.y - p.y * q.x; }
63 inline double operator |   (const Pointf& p, const Pointf& q) { return Distance(p, q); }
64 
PolarPointf(double a)65 inline Pointf PolarPointf  (double a)                         { return Pointf(cos(a), sin(a)); }
PolarPointf(double r,double a)66 inline Pointf PolarPointf  (double r, double a)               { return Pointf(r * cos(a), r * sin(a)); }
PolarPointf(const Pointf & c,double r,double a)67 inline Pointf PolarPointf  (const Pointf& c, double r, double a) { return Pointf(c.x + r * cos(a), c.y + r * sin(a)); }
68 
PointfToPoint(const Pointf & p)69 inline Point  PointfToPoint(const Pointf& p)                  { return Point(fround(p.x), fround(p.y)); }
PointfToSize(const Pointf & p)70 inline Size   PointfToSize (const Pointf& p)                  { return Size(fround(p.x), fround(p.y)); }
71 
72 //////////////////////////////////////////////////////////////////////
73 
74 //inline Sizef  Sizef_0      ()                                 { return Sizef(0, 0); }
75 //inline Sizef  Sizef_X      ()                                 { return Sizef(1, 0); }
76 //inline Sizef  Sizef_Y      ()                                 { return Sizef(0, 1); }
77 //inline Sizef  Sizef_RX     ()                                 { return Sizef(-1, 1); }
78 //inline Sizef  Sizef_RY     ()                                 { return Sizef(1, -1); }
79 
fpmin(const Sizef & p,const Sizef & q)80 inline Sizef  fpmin        (const Sizef& p, const Sizef& q)     { return Sizef(min(p.cx, q.cx), min(p.cy, q.cy)); }
fpmax(const Sizef & p,const Sizef & q)81 inline Sizef  fpmax        (const Sizef& p, const Sizef& q)     { return Sizef(max(p.cx, q.cx), max(p.cy, q.cy)); }
fpminmax(const Sizef & p,const Sizef & mn,const Sizef & mx)82 inline Sizef  fpminmax     (const Sizef& p, const Sizef& mn, const Sizef& mx) { return Sizef(minmax(p.cx, mn.cx, mx.cx), minmax(p.cy, mn.cy, mx.cy)); }
83 
fpmin(const Sizef & p)84 inline double fpmin        (const Sizef& p)                     { return min(p.cx, p.cy); }
fpmax(const Sizef & p)85 inline double fpmax        (const Sizef& p)                     { return max(p.cx, p.cy); }
AbsMin(const Sizef & p)86 inline double AbsMin       (const Sizef& p)                     { return min(fabs(p.cx), fabs(p.cy)); }
AbsMax(const Sizef & p)87 inline double AbsMax       (const Sizef& p)                     { return max(fabs(p.cx), fabs(p.cy)); }
88 
Mid(const Sizef & p,const Sizef & q)89 inline Sizef  Mid          (const Sizef& p, const Sizef& q)     { return Sizef((p.cx + q.cx) / 2, (p.cy + q.cy) / 2); }
90 //inline double Squared      (Sizef p)                          { return p.cx * p.cx + p.cy * p.cy; }
Squared(const Sizef & p,const Sizef & q)91 inline double Squared      (const Sizef& p, const Sizef& q)     { return Squared(q - p); }
92 //inline double Length       (Sizef p)                          { return sqrt(Squared(p)); }
93 Sizef         Length       (const Sizef& p, double l);
UnitV(const Sizef & p)94 inline Sizef  UnitV        (const Sizef& p)                     { return Length(p, 1); }
Reversed(const Sizef & s)95 inline Sizef  Reversed     (const Sizef& s)                     { return Sizef(-s.cx, -s.cy); }
ReversedX(const Sizef & s)96 inline Sizef  ReversedX    (const Sizef& s)                     { return Sizef(-s.cx, s.cy); }
ReversedY(const Sizef & s)97 inline Sizef  ReversedY    (const Sizef& s)                     { return Sizef(s.cx, -s.cy); }
Abs(const Sizef & s)98 inline Sizef  Abs          (const Sizef& s)                     { return Sizef(fabs(s.cx), fabs(s.cy)); }
Left(const Sizef & s)99 inline Sizef  Left         (const Sizef& s)                     { return Sizef(-s.cy, s.cx); }
Right(const Sizef & s)100 inline Sizef  Right        (const Sizef& s)                     { return Sizef(s.cy, -s.cx); }
101 
SizefToPoint(const Sizef & s)102 inline Point  SizefToPoint (const Sizef& s)                     { return Point(fround(s.cx), fround(s.cy)); }
SizefToSize(const Sizef & s)103 inline Size   SizefToSize  (const Sizef& s)                     { return Size(fround(s.cx), fround(s.cy)); }
104 
105 //////////////////////////////////////////////////////////////////////
106 // Rectf::
107 
108 //inline Rectf  Rectf_0()                                       { return Rectf(0, 0, 0, 0); }
109 //inline Rectf  Rectf_1()                                       { return Rectf(0, 0, 1, 1); }
110 
111 //////////////////////////////////////////////////////////////////////
112 
113 inline Rectf  operator *   (const Rectf& r, double f)         { return Rectf(r.left * f, r.top * f, r.right * f, r.bottom * f); }
114 inline Rectf  operator *   (const Rectf& r, const Sizef& s)   { return Rectf(r.left * s.cx, r.top * s.cy, r.right * s.cx, r.bottom * s.cy); }
115 inline Rectf  operator *   (const Rectf& r, const Pointf& p)  { return Rectf(r.left * p.x, r.top * p.y, r.right * p.x, r.bottom * p.y); }
116 inline Rectf  operator *   (const Rectf& r, const Rectf& s)   { return Rectf(r.left * s.left, r.top * s.top, r.right * s.right, r.bottom * s.bottom); }
117 
118 inline Rectf  operator /   (const Rectf& r, double f)         { return Rectf(r.left / f, r.top / f, r.right / f, r.bottom / f); }
119 inline Rectf  operator /   (const Rectf& r, const Sizef& s)   { return Rectf(r.left / s.cx, r.top / s.cy, r.right / s.cx, r.bottom / s.cy); }
120 inline Rectf  operator /   (const Rectf& r, const Pointf& p)  { return Rectf(r.left / p.x, r.top / p.y, r.right / p.x, r.bottom / p.y); }
121 inline Rectf  operator /   (const Rectf& r, const Rectf& s)   { return Rectf(r.left / s.left, r.top / s.top, r.right / s.right, r.bottom / s.bottom); }
122 
123 extern Rectf& SetUnion     (Rectf& rc, const Pointf& pt);
GetUnion(const Rectf & rc,const Pointf & p)124 inline Rectf  GetUnion     (const Rectf& rc, const Pointf& p) { Rectf tmp = rc; return SetUnion(tmp, p); }
125 extern Rectf  GetUnion     (const Array<Pointf>& pt);
126 extern Rectf& SetMinMaxMove(Rectf& rc, const Rectf& outer_rc);
GetMinMaxMove(const Rectf & rc,const Rectf & outer_rc)127 inline Rectf  GetMinMaxMove(const Rectf& rc, const Rectf& outer_rc) { Rectf tmp = rc; return SetMinMaxMove(tmp, outer_rc); }
128 extern double Distance     (const Rectf& rc, const Pointf& pt);
Diagonal(const Rectf & rc)129 inline double Diagonal     (const Rectf& rc)                  { return Length(rc.Size()); }
Area(const Rectf & rc)130 inline double Area         (const Rectf& rc)                  { return rc.Width() * rc.Height(); }
PointfRectf(const Pointf & pt)131 inline Rectf  PointfRectf  (const Pointf& pt)                 { return Rectf(pt.x, pt.y, pt.x, pt.y); }
SortRectf(const Pointf & p,const Pointf & q)132 inline Rectf  SortRectf    (const Pointf& p, const Pointf& q) { return Rectf(fpmin(p, q), fpmax(p, q)); }
RectfToRect(const Rectf & rc)133 inline Rect   RectfToRect  (const Rectf& rc)                  { return Rect(fround(rc.left), fround(rc.top), fround(rc.right), fround(rc.bottom)); }
134 
fpminmax(const Pointf & p,const Rectf & rc)135 inline Pointf fpminmax     (const Pointf& p, const Rectf& rc) { return Pointf(minmax(p.x, rc.left, rc.right), minmax(p.y, rc.top, rc.bottom)); }
136 
137 //////////////////////////////////////////////////////////////////////
138 //////////////////////////////////////////////////////////////////////
139 
140 const Matrixf& Matrixf_0();
141 const Matrixf& Matrixf_1();
142 const Matrixf& Matrixf_Null();
143 const Matrixf& Matrixf_MirrorX(); // mirror around X axis
144 const Matrixf& Matrixf_MirrorY(); // mirror around Y axis
145 
146 //////////////////////////////////////////////////////////////////////
147 
148 struct Matrixf : Moveable<Matrixf>
149 {
150 	Pointf x, y, a;
151 
MatrixfMatrixf152 	Matrixf()                                         { *this = Matrixf_1(); }
MatrixfMatrixf153 	Matrixf(const Nuller&) : a(Null)                  {}
xMatrixf154 	Matrixf(Pointf x, Pointf y, Pointf a = Pointf(0, 0)) : x(x), y(y), a(a) {}
MatrixfMatrixf155 	Matrixf(const Matrixf& (*fn)())                   { *this = fn(); }
MatrixfMatrixf156 	Matrixf(double xx, double xy, double yx, double yy, double ax, double ay)
157 		: x(xx, xy), y(yx, yy), a(ax, ay) {}
158 
IsIdentityMatrixf159 	bool             IsIdentity() const                    { return x.x == 1 && x.y == 0 && y.x == 0 && y.y == 1 && a.x == 0 && a.y == 0; }
IsZeroMatrixf160 	bool             IsZero() const                        { return x.x == 0 && x.y == 0 && y.x == 0 && y.y == 0 && a.x == 0 && a.y == 0; }
161 
FixMatrixf162 	void             Fix(Pointf vector)                    { a = vector - vector.x * x - vector.y * y; }
163 	Matrixf&         operator *= (const Matrixf& another);
164 
165 	String           ToString() const;
166 };
167 
168 //template DumpType<Matrixf>;
169 
170 extern Matrixf  MatrixfMove   (Pointf vector);
171 extern Matrixf  MatrixfRotate (double angle, Pointf fix = Pointf(0, 0));
172 extern Matrixf  MatrixfScale  (double scale, Pointf fix = Pointf(0, 0));
173 extern Matrixf  MatrixfScale  (Pointf scale, Pointf fix = Pointf(0, 0));
174 extern Matrixf  MatrixfScale  (const Rectf& src, const Rectf& dest);
175 extern Matrixf  MatrixfMirror (Pointf A, Pointf B);
176 extern Matrixf  MatrixfAffine (Pointf src1, Pointf dest1, Pointf src2, Pointf dest2);
177 extern Matrixf  MatrixfAffine (Pointf src1, Pointf dest1, Pointf src2, Pointf dest2, Pointf src3, Pointf dest3);
178 
179 extern Matrixf  MatrixfInverse(const Matrixf& mx);
Determinant(const Matrixf & mx)180 inline double   Determinant   (const Matrixf& mx)                         { return mx.x % mx.y; }
IsReversing(const Matrixf & mx)181 inline bool     IsReversing   (const Matrixf& mx)                         { return Determinant(mx) < 0; }
182 extern double   MatrixfMeasure(const Matrixf& mx);
183 
184 template<>
IsNull(const Matrixf & mx)185 inline bool     IsNull        (const Matrixf& mx)                         { return IsNull(mx.a); }
186 inline bool     operator ==   (const Matrixf& m1, const Matrixf& m2)      { return m1.x == m2.x && m1.y == m2.y && m1.a == m2.a; }
187 inline bool     operator !=   (const Matrixf& m1, const Matrixf& m2)      { return !(m1 == m2); }
188 
189 inline Pointf   operator %    (Pointf vector, const Matrixf& matrix)      { return vector.x * matrix.x + vector.y * matrix.y; }
190 extern Pointf   operator *    (Pointf point,  const Matrixf& matrix);
191 extern Pointf   operator /    (Pointf point,  const Matrixf& matrix);
192 extern Rectf    operator *    (const Rectf& rect, const Matrixf& matrix);
193 extern Rectf    operator /    (const Rectf& rect, const Matrixf& matrix);
194 
195 inline Pointf&  operator %=   (Pointf& point, const Matrixf& matrix)      { return point = point % matrix; }
196 inline Pointf&  operator *=   (Pointf& point, const Matrixf& matrix)      { return point = point * matrix; }
197 
198 inline Matrixf  operator *    (const Matrixf& m1, const Matrixf& m2)      { return Matrixf(m1) *= m2; }
199 inline Matrixf  operator /    (const Matrixf& m1, const Matrixf& m2)      { return m1 * MatrixfInverse(m2); }
200 
201 //////////////////////////////////////////////////////////////////////
202 // set distance of point from an object
203 
204 double          Distance      (Pointf X, Pointf A, Pointf B, double *arg = NULL);
205 double          Distance      (Pointf X, Pointf A, Pointf B, double bulge, double *arg = NULL);
206 double          Distance      (Pointf X, Pointf C, double radius, double *arg = NULL);
207 
208 //////////////////////////////////////////////////////////////////////
209 // set intersection with rectangle
210 
211 bool            Crosses       (const Rectf& R, Pointf A, Pointf B);
212 bool            Crosses       (const Rectf& R, Pointf A, Pointf B, double bulge);
213 bool            Crosses       (const Rectf& R, Pointf C, double radius);
214 
215 //////////////////////////////////////////////////////////////////////
216 // set intersection with polygon
217 
218 enum { CMP_OUT = -1, CMP_SECT = 0, CMP_IN = +1 };
219 
220 int             ContainsPoints(const Array<Pointf>& polygon, const Array<Pointf>& points);
221 int             ContainsPoints(const Array<Pointf>& polygon, const Vector<int>& polyend, const Array<Pointf>& points);
222 int             ContainsPoint (const Array<Pointf>& polygon, Pointf pt);
223 int             ContainsPoint (const Array<Pointf>& polygon, const Vector<int>& polyend, Pointf pt);
224 int             ContainsPoly  (const Array<Pointf>& chkpoly, const Array<Pointf>& polygon, const Vector<int>& polyend, bool closed);
225 int             ContainsPoly  (const Array<Pointf>& chkpoly, const Array<Pointf>& polygon, bool closed);
226 
227 //////////////////////////////////////////////////////////////////////
228 
229 bool            ClipLine      (Pointf& A, Pointf& B, const Rectf& box);
230 bool            ClipLine      (Pointf& A, Pointf& B, const Rect& box);
231 bool            ClipLine      (Point& A, Point& B, const Rect& box);
232 
233 //////////////////////////////////////////////////////////////////////
234 
235 Vector<int>     ConvexHullOrder(const Vector<Point>& pt);
236 Vector<int>     ConvexHullOrder(const Array<Pointf>& pt);
237 
238 //////////////////////////////////////////////////////////////////////
239 
240 Rectf           GetBoundingBox(const Array<Pointf>& vertices);
241 Rect            GetBoundingBox(const Point *vertices, int vertex_count);
242 Rect            GetBoundingBox(const Vector<Point>& vertices);
243 
244 void            SplitPolygon  (const Point *vertices, int vertex_count, const int *counts, int count_count,
245 	Vector<Point>& out_vertices, Vector<int>& out_counts, Rect clip = Null, int max_trace_points = 8000);
246 void            SplitPolygon  (const Vector<Point>& vertices, const Vector<int>& counts,
247 	Vector<Point>& out_vertices, Vector<int>& out_counts, Rect clip = Null, int max_trace_points = 8000);
248 void            SplitPolygon  (Array<Pointf>::ConstIterator vertices, int vertex_count, const int *counts, int count_count,
249 	Array<Pointf>& out_vertices, Vector<int>& out_counts, const Rectf& clip = Null, int max_trace_points = 8000);
250 void            SplitPolygon  (const Array<Pointf>& vertices, const Vector<int>& counts,
251 	Array<Pointf>& out_vertices, Vector<int>& out_counts, const Rectf& clip = Null, int max_trace_points = 8000);
252 
253 //////////////////////////////////////////////////////////////////////
254 
255 extern double   Vec_outer_tolerance; // maximum reasonable coordinate value
256 extern double   Vec_tolerance;       // linear tolerance
257 extern double   Vec_ang_tolerance;   // angular tolerance
258 
259 extern bool     VecTolEq      (double x, double y);
260 extern bool     VecTolEq      (Pointf a, Pointf b);
261 
262 //////////////////////////////////////////////////////////////////////
263 
264 class VecLine
265 {
266 public:
267 	VecLine();
VecLine(Pointf A,Pointf B)268 	VecLine(Pointf A, Pointf B) : A(A), B(B) {}
VecLine(double x1,double y1,double x2,double y2)269 	VecLine(double x1, double y1, double x2, double y2) : A(x1, y1), B(x2, y2) {}
270 
271 	String        ToString() const;
272 
273 	VecLine&      SetNull();
274 
Length()275 	double        Length() const { return A | B; }
276 	Pointf        Mid()    const;
277 	Pointf        Right()  const;
278 	Pointf        Left()   const;
279 	Pointf        Vector() const;
280 
281 	double        GetArg(Pointf pt) const;
282 	Pointf        GetPointAt(double arg) const;
283 
284 	VecLine       Reversed() const;
285 	VecLine&      SetReversed();
286 
287 	Pointf        Intersect(VecLine another) const;
288 	VecLine&      SetClip(const Rectf& rect);
Clip(const Rectf & rect)289 	VecLine       Clip(const Rectf& rect) const            { return VecLine(*this).SetClip(rect); }
290 
291 	double        Distance(Pointf point, double *arg = NULL) const;
292 
IsNullInstance()293 	bool          IsNullInstance() const                   { return IsNull(A); }
294 
295 	// algorithms
296 	static Pointf GetPointAt(Pointf A, Pointf B, double arg);
297 
298 public:
299 	Pointf        A, B;
300 };
301 
302 //template BitWiseType<VecLine>;
303 //template DumpType<VecLine>;
304 
305 inline Pointf  operator & (VecLine l1, VecLine l2)          { return l1.Intersect(l2); }
306 inline VecLine operator & (VecLine line, const Rectf& rect) { return line.Clip(rect); }
307 inline double  operator | (VecLine ln, Pointf pt)           { return ln.Distance(pt); }
308 inline double  operator | (Pointf pt, VecLine ln)           { return ln.Distance(pt); }
309 
310 //////////////////////////////////////////////////////////////////////
311 
312 class VecArc : public VecLine
313 {
314 public:
315 	VecArc();
VecLine(line)316 	VecArc(VecLine line, double bulge = 0) : VecLine(line), bulge(bulge) {}
VecLine(A,B)317 	VecArc(Pointf A, Pointf B, double bulge = 0) : VecLine(A, B), bulge(bulge) {}
318 	VecArc(double x1, double y1, double x2, double y2, double bulge = 0)
VecLine(x1,y1,x2,y2)319 		: VecLine(x1, y1, x2, y2), bulge(bulge) {}
320 
321 	String        ToString() const;
322 
323 	Pointf        ArcMid() const;
324 	double        ArcLength() const;
325 
326 	VecArc        Reversed() const;
327 	VecArc&       SetReversed();
328 
329 	Pointf        GetPointAt(double t) const;
330 	Rectf         GetBoundingBox() const;
331 
332 	// arc algorithms
333 	static Pointf ArcMid(Pointf P, Pointf Q, double l, double h);
334 	static double ArcLength(Pointf P, Pointf Q, double l, double h);
335 	static void   Bisect(Pointf P, Pointf Q, double l, double h,
336 		Pointf& centre, double& ll, double& hh);
337 	static Pointf GetPointAt(Pointf P, Pointf Q, double l, double h, double t);
338 
339 public:
340 	double        bulge;
341 };
342 
343 //template BitWiseType<VecArc>;
344 //template DumpType<VecArc>;
345 
346 //////////////////////////////////////////////////////////////////////
347 
348 /*
349 struct VecVertex : public Pointf
350 {
351 	VecVertex();
352 	VecVertex(Pointf point, double bulge = 0) : Pointf(point), bulge(bulge) {}
353 	VecVertex(double x, double y, double bulge = 0) : Pointf(x, y), bulge(bulge) {}
354 
355 	String Dump() const;
356 
357 	double bulge; // bulge of segment __ENDING AT THIS VERTEX__
358 };
359 
360 template BitWiseType<VecVertex>;
361 template DumpType<VecVertex>;
362 */
363 
364 //////////////////////////////////////////////////////////////////////
365 
366 /*
367 class VecCurve : public Vector<VecVertex>
368 {
369 public:
370 	typedef Vector<VecVertex> Base;
371 
372 	VecCurve();
373 	VecCurve(const VecCurve& another, int);
374 
375 	void       Add(const VecVertex& vertex);
376 	void       Add(Pointf point); // can be used as lineto callback for Arc::Iterator
377 	void       Add(Pointf point, double bulge);
378 	void       Add(double x, double y, double bulge = 0);
379 
380 	VecArc     Segment(int i) const;
381 
382 	Vector<Pointf> Check() const; // find self-intersections; empty return value = OK
383 
384 	String     Dump() const;
385 };
386 
387 template class DeepCopyOption<VecCurve>;
388 template DumpType<VecCurve>;
389 */
390 
391 //////////////////////////////////////////////////////////////////////
392 
393 #ifdef p
394 #undef p
395 #endif
396 
397 class VecArcInfo : public VecArc
398 {
399 public:
400 	VecArcInfo();
VecArcInfo(Pointf p,Pointf q)401 	VecArcInfo(Pointf p, Pointf q)                                  { Set(p, q); }
VecArcInfo(Pointf p,Pointf q,Pointf x)402 	VecArcInfo(Pointf p, Pointf q, Pointf x)                        { Set(p, q, x); }
VecArcInfo(Pointf p,Pointf q,double bulge)403 	VecArcInfo(Pointf p, Pointf q, double bulge)                    { Set(p, q, bulge); }
VecArcInfo(Pointf c,double r,double a,double b)404 	VecArcInfo(Pointf c, double r, double a, double b)              { Set(c, r, a, b); }
VecArcInfo(Pointf c,double r)405 	VecArcInfo(Pointf c, double r)                                  { Set(c, r); }
VecArcInfo(Pointf c,Pointf a,Pointf b,bool anticlockwise)406 	VecArcInfo(Pointf c, Pointf a, Pointf b, bool anticlockwise)    { Set(c, a, b, anticlockwise); }
VecArcInfo(const VecArc & arc)407 	VecArcInfo(const VecArc& arc)                                   { Set(arc); }
VecArcInfo(const VecArcInfo & arc)408 	VecArcInfo(const VecArcInfo& arc)                               { *this = arc; }
409 
410 	String      ToString() const;
411 
412 	void        Set(Pointf P, Pointf Q);
413 	void        Set(Pointf P, Pointf Q, Pointf X);
414 	void        Set(Pointf P, Pointf Q, double bulge);
415 	void        Set(Pointf C, double r, double a, double b);
416 	void        Set(Pointf C, double r);
417 	void        Set(Pointf C, Pointf A, Pointf B, bool anticlockwise);
418 
Set(const VecArc & arc)419 	void        Set(const VecArc& arc)                              { Set(arc.A, arc.B, arc.bulge); }
420 
421 	void        Move(Pointf offset);
422 
IsCircle()423 	bool        IsCircle() const   { return circle; }
IsCurved()424 	bool        IsCurved() const   { return curved; }
IsReversed()425 	bool        IsReversed() const { return reversed; }
426 
427 	double      Length() const;
428 	Pointf      CentreOfMass() const;
429 
430 	bool        ContainsBearing(double bearing) const;
431 	double      Distance(Pointf point, double *arg = NULL) const;
432 	bool        Crosses(const Rectf& rect) const;
433 	Pointf      GetPointAt(double t) const;
434 	double      GetMaxDistance(Pointf point, Pointf *farthest = NULL) const;
435 
436 	double      GetArg(double bearing) const;
437 	double      GetArg(Pointf point) const;
438 	VecArcInfo  Subset(double start, double end) const;
439 
440 	Rectf       GetBoundingBox() const;
441 
442 	double      GetAngle() const; // oriented included angle
443 	double      GetStartTangent() const;
444 	double      GetEndTangent() const;
445 	Pointf      GetStartDir() const;
446 	Pointf      GetEndDir() const;
447 
448 	VecArcInfo  Offset(double dist) const;
449 
Reversed()450 	VecArcInfo  Reversed() const                                    { return VecArcInfo(*this).SetReversed(); }
451 	VecArcInfo& SetReversed();
452 
453 	Pointf      C;        // centre of circle (Null when not bulged)
454 	double      bow;      // bow length
455 	double      alpha;    // start angle (rad); most clockwise point on arc
456 	double      beta;     // end angle (rad); most anticlockwise point on arc
457 	double      radius;   // circle radius (Null when not bulged)
458 	bool        curved;   // true = it's an arc, false = it's a circle
459 	bool        reversed; // true = arc has been entered as clockwise
460 	bool        circle;   // true = it's a full circle
461 };
462 
463 //////////////////////////////////////////////////////////////////////
464 
465 class VecIntersection
466 {
467 public:
VecIntersection()468 	VecIntersection() { count = 0; }
469 
470 	void   Mirror();
Nothing()471 	bool   Nothing() { count = 0; return false; }
472 	void   Remove(int index);
473 
474 	bool   LL(const Pointf& P1, const Pointf& Q1, const Pointf& P2, const Pointf& Q2);
475 	bool   LC(const Pointf& P1, const Pointf& Q1, const Pointf& C2, double r2);
476 	bool   LA(const Pointf& P1, const Pointf& Q1, const VecArcInfo& a2);
477 	bool   CC(const Pointf& C1, double r1, const Pointf& C2, double r2);
478 	bool   CA(const Pointf& C1, double r1, const VecArcInfo& a2);
479 	bool   AA(const VecArcInfo& a1, const VecArcInfo& a2);
480 
IsEmpty()481 	bool   IsEmpty() const  { return count == 0; }
GetCount()482 	int    GetCount() const { return count; }
483 
484 public:
485 	int    count; // number of intersections
486 	double t[2], u[2];
487 
488 protected:
489 	void   CheckBearing(double *hints, const VecArcInfo& a);
490 };
491 
492 //////////////////////////////////////////////////////////////////////
493 
494 class VecArcIterator
495 {
496 public:
497 	typedef Callback1<Pointf>     DrawProc;
498 	typedef Gate<Pointf, double>  ArcProc;
499 
500 	VecArcIterator(const VecArc& arc, DrawProc _lineto);
501 	VecArcIterator(Pointf start, Pointf end, double bulge, DrawProc _lineto);
502 
Level(int _level)503 	VecArcIterator& Level(int _level)              { level = _level; return *this; }
Precision(double prec)504 	VecArcIterator& Precision(double prec  )       { precision = prec; return *this; }
Clip(const Rectf & rect,DrawProc _mv)505 	VecArcIterator& Clip(const Rectf& rect, DrawProc _mv) { clip = rect; moveto = _mv; return *this; }
ArcTo(ArcProc _arc)506 	VecArcIterator& ArcTo(ArcProc _arc)            { arcto = _arc; return *this; }
507 
508 	void            Go(); // recurse the arc
509 
510 public:
511 	double          arclen;    // degenerate to simple arc under such length
512 	int             level;     // maximum # segments = 2 ^ level
513 	double          precision; // degenerate to line whenever |bulge| <= precision
514 	VecArc          arc;       // arc to interpolate
515 	Rectf           clip;      // clipping rectangle
516 	DrawProc        moveto;    // moveto callback (needed only when clipping is on)
517 	DrawProc        lineto;    // lineto callback
518 	ArcProc         arcto;     // simple arcto callback
519 
520 protected:
521 	enum
522 	{
523 		CF_XL = 001,
524 		CF_XG = 002,
525 		CF_YL = 010,
526 		CF_YG = 020,
527 
528 		DEFAULT_LEVEL = 10,
529 	};
530 
531 	Pointf          last;      // last iteration point
532 	int             last_clip; // clipping status of last vertex
533 
534 	int             GetClip(Pointf point) const;
535 	void            Recurse(Pointf to, double l, double h, int depth, int next_flclip);
536 };
537 
538 //////////////////////////////////////////////////////////////////////
539