2
// --------------------------------------------------------------------
3
// Geometric primitives
4
// --------------------------------------------------------------------
7
This file is part of the extensible drawing editor Ipe.
8
Copyright (C) 1993-2004 Otfried Cheong
10
Ipe is free software; you can redistribute it and/or modify it
11
under the terms of the GNU General Public License as published by
12
the Free Software Foundation; either version 2 of the License, or
13
(at your option) any later version.
15
As a special exception, you have permission to link Ipe with the
16
CGAL library and distribute executables, as long as you follow the
17
requirements of the Gnu General Public License in regard to all of
18
the software in the executable aside from CGAL.
20
Ipe is distributed in the hope that it will be useful, but WITHOUT
21
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
23
License for more details.
25
You should have received a copy of the GNU General Public License
26
along with Ipe; if not, you can find it at
27
"http://www.gnu.org/copyleft/gpl.html", or write to the Free
28
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
39
// --------------------------------------------------------------------
41
/*! \var typedef double IpeScalar
43
* Type of coordinates in IpeVectors.
45
typedef double IpeScalar;
48
Maximum of two values.
51
inline T IpeMax(const T &lhs, const T &rhs)
53
return (lhs > rhs) ? lhs : rhs;
57
Minimum of two values.
60
inline T IpeMin(const T &lhs, const T &rhs)
62
return (lhs < rhs) ? lhs : rhs;
68
inline double IpeAbs(double val)
70
return (val > 0) ? val : -val;
78
// const double IpePi = 3.1415926535897932385;
79
#define IpePi 3.1415926535897932385
80
/*! \var double IpeTwoPi
82
* The constant 2 * pi.
84
// const double IpeTwoPi = 6.2831853071795862;
85
#define IpeTwoPi 6.2831853071795862
86
/*! \var double IpeHalfPi
88
* The constant pi / 2.
90
// const double IpeHalfPi = 1.5707963267948966;
91
#define IpeHalfPi 1.5707963267948966
93
// --------------------------------------------------------------------
95
class IPE_EXPORT IpeAngle {
97
//! Construct uninitialized angle.
98
inline explicit IpeAngle() { /* nothing */ }
99
//! Construct an angle (in radians).
100
inline IpeAngle(double alpha) : iAlpha(alpha) { }
101
//! Construct an angle in degrees.
102
inline static IpeAngle Degrees(double alpha) {
103
return IpeAngle(alpha * IpePi / 180.0); }
104
//! Return value (in radians).
105
inline operator double() const { return iAlpha; }
106
double Degrees() const;
107
IpeAngle Normalize(double lowlimit);
108
bool LiesBetween(IpeAngle small, IpeAngle large) const;
113
// --------------------------------------------------------------------
115
class IPE_EXPORT IpeVector {
117
//! Uninitialized vector.
118
IpeVector() { /* no initialization */ }
119
explicit IpeVector(IpeAngle alpha);
120
//! Construct a vector.
121
explicit IpeVector(IpeScalar x, IpeScalar y) : iX(x), iY(y) { }
122
//! Return square of Euclidean length
123
inline double SqLen() const;
125
IpeAngle Angle() const;
126
IpeVector Normalized() const;
127
IpeVector Orthogonal() const;
128
double Factorize(IpeVector &unit) const;
130
inline bool operator==(const IpeVector &rhs) const;
131
inline bool operator!=(const IpeVector &rhs) const;
132
inline void operator+=(const IpeVector &rhs);
133
inline void operator-=(const IpeVector &rhs);
134
inline void operator*=(double rhs);
135
inline IpeVector operator+(const IpeVector &rhs) const;
136
inline IpeVector operator-(const IpeVector &rhs) const;
137
inline IpeVector operator*(double rhs) const;
139
static IpeVector Zero;
143
//! Vector coordinates are public.
149
IPE_EXPORT IpeStream &operator<<(IpeStream &stream, const IpeVector &rhs);
151
// --------------------------------------------------------------------
153
class IPE_EXPORT IpeRect {
155
//! Create empty rectangle.
156
explicit IpeRect() : iMin(1,0), iMax(-1,0) { }
157
//! Create rectangle containing just the point \a c.
158
explicit IpeRect(const IpeVector &c) : iMin(c), iMax(c) { }
159
explicit IpeRect(const IpeVector &c1, const IpeVector &c2);
161
//! True if rectangle is empty.
162
int IsEmpty() const { return iMin.iX > iMax.iX; }
163
//! Return top right corner.
164
inline IpeVector Max() const { return iMax; }
165
//! Return bottom left corner.
166
inline IpeVector Min() const { return iMin; }
167
//! Return top left corner.
168
inline IpeVector TopLeft() const { return IpeVector(iMin.iX, iMax.iY); }
169
//! Return bottom right corner.
170
inline IpeVector BottomRight() const { return IpeVector(iMax.iX, iMin.iY); }
172
IpeScalar Width() const { return iMax.iX - iMin.iX; }
174
IpeScalar Height() const { return iMax.iY - iMin.iY; }
175
void AddPoint(const IpeVector &rhs);
176
void AddRect(const IpeRect &rhs);
177
bool Contains(const IpeVector &rhs) const;
178
bool Contains(const IpeRect &rhs) const;
179
bool CertainClearance(const IpeVector &v, double bound) const;
180
bool Intersects(const IpeRect &rhs) const;
182
IpeVector iMin; //!< Lower-left corner.
183
IpeVector iMax; //!< Top-right corner.
186
IPE_EXPORT IpeStream &operator<<(IpeStream &stream, const IpeRect &rhs);
188
// --------------------------------------------------------------------
190
class IPE_EXPORT IpeLine {
192
//! Create default line (x-axis).
193
explicit IpeLine() : iP(0.0, 0.0), iDir(1.0, 0.0) { }
194
explicit IpeLine(const IpeVector &p, const IpeVector &dir);
195
static IpeLine Through(const IpeVector &p, const IpeVector &q);
196
double Side(const IpeVector &p) const;
197
inline IpeVector Normal() const;
198
double Distance(const IpeVector &v) const;
199
bool Intersects(const IpeLine &line, IpeVector &pt);
200
IpeVector Project(const IpeVector &v) const;
201
inline IpeVector Dir() const;
204
//! Point on the line.
207
IpeVector iDir; // unit vector
210
// --------------------------------------------------------------------
212
class IPE_EXPORT IpeSegment {
214
//! Create default segment
215
IpeSegment() : iP(0.0, 0.0), iQ(1.0, 0.0) { }
216
explicit IpeSegment(const IpeVector &p, const IpeVector &q)
218
inline IpeLine Line() const;
219
double Distance(const IpeVector &v, double bound) const;
220
double Distance(const IpeVector &v) const;
221
bool Project(const IpeVector &v, IpeVector &projection) const;
222
bool Intersects(const IpeSegment &seg, IpeVector &pt) const;
223
bool Intersects(const IpeLine &l, IpeVector &pt) const;
232
// --------------------------------------------------------------------
234
class IPE_EXPORT IpeBezier {
236
//! Default constructor, uninitialized curve.
237
inline IpeBezier() { /* nothing */ }
238
inline IpeBezier(const IpeVector &p0, const IpeVector &p1,
239
const IpeVector &p2, const IpeVector &p3);
240
IpeVector Point(double t) const;
241
double Distance(const IpeVector &v, double bound);
242
bool Straight(double precision) const;
243
void Subdivide(IpeBezier &l, IpeBezier &r) const;
244
void Approximate(double precision, std::vector<IpeVector> &result) const;
245
IpeRect BBox() const;
246
static IpeBezier QuadBezier(const IpeVector &p0, const IpeVector &p1,
247
const IpeVector &p2);
248
static void Spline(int n, const IpeVector *v,
249
std::vector<IpeBezier> &result);
250
static void ClosedSpline(int n, const IpeVector *v,
251
std::vector<IpeBezier> &result);
252
bool Intersects(const IpeLine &l, IpeVector &pt) const;
253
bool Intersects(const IpeSegment &l, IpeVector &pt) const;
258
// --------------------------------------------------------------------
260
class IPE_EXPORT IpeLinear {
263
explicit IpeLinear(IpeAngle angle);
264
inline explicit IpeLinear(double m11, double m21, double m12, double m22);
265
explicit IpeLinear(IpeString str);
266
IpeLinear Inverse() const;
267
inline bool IsIdentity() const;
268
inline IpeVector operator*(const IpeVector &rhs) const;
269
inline bool operator==(const IpeLinear &rhs) const;
274
IPE_EXPORT IpeStream &operator<<(IpeStream &stream, const IpeLinear &rhs);
276
// --------------------------------------------------------------------
278
class IPE_EXPORT IpeMatrix {
281
inline IpeMatrix(const IpeLinear &linear);
282
inline explicit IpeMatrix(const IpeLinear &linear, const IpeVector &t);
283
inline explicit IpeMatrix(double m11, double m21, double m12, double m22,
284
double t1, double t2);
285
inline explicit IpeMatrix(const IpeVector &v);
286
explicit IpeMatrix(IpeString str);
287
IpeMatrix Inverse() const;
288
inline IpeVector operator*(const IpeVector &rhs) const;
289
inline IpeBezier operator*(const IpeBezier &rhs) const;
290
inline IpeVector Translation() const;
291
inline IpeLinear Linear() const;
292
inline bool IsIdentity() const;
293
inline bool operator==(const IpeMatrix &rhs) const;
298
IPE_EXPORT IpeStream &operator<<(IpeStream &stream, const IpeMatrix &rhs);
300
// --------------------------------------------------------------------
302
class IPE_EXPORT IpeArc {
304
//! Construct unit circle.
305
inline IpeArc() : iAlpha(0.0), iBeta(0.0) { /* nothing */ }
306
inline IpeArc(const IpeMatrix &m, IpeAngle alpha, IpeAngle beta);
307
inline IpeArc(const IpeMatrix &m);
308
IpeArc(const IpeMatrix &m0, const IpeVector &begp, const IpeVector &endp);
309
double Distance(const IpeVector &v, double bound);
310
double Distance(const IpeVector &v, double bound,
311
IpeVector &pos, IpeAngle &angle);
312
IpeRect BBox() const;
313
bool Intersects(const IpeLine &l, IpeVector &pt) const;
314
bool Intersects(const IpeSegment &l, IpeVector &pt) const;
321
// --------------------------------------------------------------------
323
//! Return square of vector's length.
324
inline double IpeVector::SqLen() const
326
return (iX * iX + iY * iY);
330
inline bool IpeVector::operator==(const IpeVector &rhs) const
332
return iX == rhs.iX && iY == rhs.iY;
336
inline bool IpeVector::operator!=(const IpeVector &rhs) const
338
return iX != rhs.iX || iY != rhs.iY;
342
inline void IpeVector::operator+=(const IpeVector &rhs)
344
iX += rhs.iX; iY += rhs.iY;
347
//! Vector-subtraction.
348
inline void IpeVector::operator-=(const IpeVector &rhs)
350
iX -= rhs.iX; iY -= rhs.iY;
353
//! Multiply vector by scalar.
354
inline void IpeVector::operator*=(double rhs)
356
iX *= rhs; iY *= rhs;
360
inline IpeVector IpeVector::operator+(const IpeVector &rhs) const
362
IpeVector result = *this; result += rhs; return result;
365
//! Vector-subtraction.
366
inline IpeVector IpeVector::operator-(const IpeVector &rhs) const
368
IpeVector result = *this; result -= rhs; return result;
372
inline IpeVector IpeVector::operator*(double rhs) const
374
IpeVector result = *this; result *= rhs; return result;
377
//! Scalar * vector. \relates IpeVector
378
inline IpeVector operator*(double lhs, const IpeVector &rhs)
380
return IpeVector(lhs * rhs.iX, lhs * rhs.iY);
383
//! Dotproduct of two vectors. \relates IpeVector
384
inline double Dot(const IpeVector &lhs, const IpeVector &rhs)
386
return lhs.iX * rhs.iX + lhs.iY * rhs.iY;
389
//! Return a normal vector pointing to the left of the directed line.
390
inline IpeVector IpeLine::Normal() const
392
return IpeVector(-iDir.iY, iDir.iX);
395
//! Return direction of line.
396
inline IpeVector IpeLine::Dir() const
401
//! Return directed line supporting the segment.
402
inline IpeLine IpeSegment::Line() const
404
return IpeLine(iP, (iQ - iP).Normalized());
407
//! Unary minus for IpeVector.
408
inline IpeVector operator-(const IpeVector &rhs)
413
//! Constructor with four control points.
414
inline IpeBezier::IpeBezier(const IpeVector &p0, const IpeVector &p1,
415
const IpeVector &p2, const IpeVector &p3)
417
iV[0] = p0; iV[1] = p1; iV[2] = p2; iV[3] = p3;
420
//! Transform Bezier spline.
421
inline IpeBezier IpeMatrix::operator*(const IpeBezier &rhs) const
423
return IpeBezier(*this * rhs.iV[0], *this * rhs.iV[1],
424
*this * rhs.iV[2], *this * rhs.iV[3]);
427
//! Construct with given parameters.
428
inline IpeArc::IpeArc(const IpeMatrix &m, IpeAngle alpha, IpeAngle beta)
429
: iM(m), iAlpha(alpha), iBeta(beta)
434
//! Construct an ellipse
435
inline IpeArc::IpeArc(const IpeMatrix &m)
436
: iM(m), iAlpha(0.0), iBeta(0.0)
441
// --------------------------------------------------------------------
443
//! Create identity matrix.
444
inline IpeLinear::IpeLinear()
450
//! Create linear matrix with given coefficients.
451
inline IpeLinear::IpeLinear(double m11, double m21, double m12, double m22)
453
iA[0] = m11; iA[1] = m21; iA[2] = m12; iA[3] = m22;
456
//! Linear matrix times vector.
457
inline IpeVector IpeLinear::operator*(const IpeVector &rhs) const
459
return IpeVector(iA[0] * rhs.iX + iA[2] * rhs.iY,
460
iA[1] * rhs.iX + iA[3] * rhs.iY);
463
//! Is this the identity matrix?
464
inline bool IpeLinear::IsIdentity() const
466
return (iA[0] == 1.0 && iA[1] == 0.0 &&
467
iA[2] == 0.0 && iA[3] == 1.0);
470
//! Linear matrix multiplication.
471
inline IpeLinear operator*(const IpeLinear &lhs, const IpeLinear &rhs)
474
m.iA[0] = lhs.iA[0] * rhs.iA[0] + lhs.iA[2] * rhs.iA[1];
475
m.iA[1] = lhs.iA[1] * rhs.iA[0] + lhs.iA[3] * rhs.iA[1];
476
m.iA[2] = lhs.iA[0] * rhs.iA[2] + lhs.iA[2] * rhs.iA[3];
477
m.iA[3] = lhs.iA[1] * rhs.iA[2] + lhs.iA[3] * rhs.iA[3];
481
//! Check for equality of two linear matrices.
482
inline bool IpeLinear::operator==(const IpeLinear &rhs) const
484
return (iA[0] == rhs.iA[0] && iA[1] == rhs.iA[1] &&
485
iA[2] == rhs.iA[2] && iA[3] == rhs.iA[3]);
488
// --------------------------------------------------------------------
490
//! Create matrix with given coefficients.
491
inline IpeMatrix::IpeMatrix(double m11, double m21, double m12, double m22,
492
double t1, double t2)
494
iA[0] = m11; iA[1] = m21; iA[2] = m12; iA[3] = m22;
495
iA[4] = t1; iA[5] = t2;
498
//! Create linear matrix.
499
inline IpeMatrix::IpeMatrix(const IpeLinear &linear)
501
iA[0] = linear.iA[0]; iA[1] = linear.iA[1];
502
iA[2] = linear.iA[2]; iA[3] = linear.iA[3];
506
inline IpeMatrix::IpeMatrix(const IpeLinear &linear, const IpeVector &t)
508
iA[0] = linear.iA[0]; iA[1] = linear.iA[1];
509
iA[2] = linear.iA[2]; iA[3] = linear.iA[3];
510
iA[4] = t.iX; iA[5] = t.iY;
513
//! Matrix times vector.
514
inline IpeVector IpeMatrix::operator*(const IpeVector &rhs) const
516
return IpeVector(iA[0] * rhs.iX + iA[2] * rhs.iY + iA[4],
517
iA[1] * rhs.iX + iA[3] * rhs.iY + iA[5]);
520
//! Is this the identity matrix?
521
inline bool IpeMatrix::IsIdentity() const
523
return (iA[0] == 1.0 && iA[1] == 0.0 &&
524
iA[2] == 0.0 && iA[3] == 1.0 &&
525
iA[4] == 0.0 && iA[5] == 0.0);
528
//! Create identity matrix.
529
inline IpeMatrix::IpeMatrix()
532
iA[1] = iA[2] = iA[4] = iA[5] = 0.0;
535
//! Matrix multiplication.
536
inline IpeMatrix operator*(const IpeMatrix &lhs, const IpeMatrix &rhs)
539
m.iA[0] = lhs.iA[0] * rhs.iA[0] + lhs.iA[2] * rhs.iA[1];
540
m.iA[1] = lhs.iA[1] * rhs.iA[0] + lhs.iA[3] * rhs.iA[1];
541
m.iA[2] = lhs.iA[0] * rhs.iA[2] + lhs.iA[2] * rhs.iA[3];
542
m.iA[3] = lhs.iA[1] * rhs.iA[2] + lhs.iA[3] * rhs.iA[3];
543
m.iA[4] = lhs.iA[0] * rhs.iA[4] + lhs.iA[2] * rhs.iA[5] + lhs.iA[4];
544
m.iA[5] = lhs.iA[1] * rhs.iA[4] + lhs.iA[3] * rhs.iA[5] + lhs.iA[5];
548
//! Create translation matrix.
549
inline IpeMatrix::IpeMatrix(const IpeVector &v)
557
//! Return translation component.
558
inline IpeVector IpeMatrix::Translation() const
560
return IpeVector(iA[4], iA[5]);
563
//! Check for equality of two matrices.
564
inline bool IpeMatrix::operator==(const IpeMatrix &rhs) const
566
return (iA[0] == rhs.iA[0] && iA[1] == rhs.iA[1] && iA[2] == rhs.iA[2] &&
567
iA[3] == rhs.iA[3] && iA[4] == rhs.iA[4] && iA[5] == rhs.iA[5]);
570
//! Return linear transformation component of this affine transformation.
571
inline IpeLinear IpeMatrix::Linear() const
573
return IpeLinear(iA[0], iA[1], iA[2], iA[3]);
576
// --------------------------------------------------------------------
579
inline IpeArc operator*(const IpeMatrix &lhs, const IpeArc &rhs)
581
return IpeArc(lhs * rhs.iM, rhs.iAlpha, rhs.iBeta);
584
// --------------------------------------------------------------------