Cinder  0.8.6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Path2d.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010, The Barbarian Group
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
6  the following conditions are met:
7 
8  * Redistributions of source code must retain the above copyright notice, this list of conditions and
9  the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
11  the following disclaimer in the documentation and/or other materials provided with the distribution.
12 
13  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
14  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
15  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
16  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
17  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
19  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20  POSSIBILITY OF SUCH DAMAGE.
21 */
22 
23 #pragma once
24 
25 #include "cinder/Vector.h"
26 #include "cinder/BSpline.h"
27 #include "cinder/Rect.h"
28 #include "cinder/Exception.h"
29 #include "cinder/MatrixAffine2.h"
30 
31 #include <vector>
32 
33 namespace cinder {
34 
35 class Path2d {
36  public:
37  Path2d() {}
38  explicit Path2d( const BSpline<Vec2f> &spline, float subdivisionStep = 0.01f );
39 
41  void moveTo( const Vec2f &p );
43  void moveTo( float x, float y ) { moveTo( Vec2f( x, y ) ); }
44  void lineTo( const Vec2f &p );
45  void lineTo( float x, float y ) { lineTo( Vec2f( x, y ) ); }
46  void quadTo( const Vec2f &p1, const Vec2f &p2 );
47  void quadTo( float x1, float y1, float x2, float y2 ) { quadTo( Vec2f( x1, y1 ), Vec2f( x2, y2 ) ); }
48  void curveTo( const Vec2f &p1, const Vec2f &p2, const Vec2f &p3 );
49  void curveTo( float x1, float y1, float x2, float y2, float x3, float y3 ) { curveTo( Vec2f( x1, y1 ), Vec2f( x2, y2 ), Vec2f( x3, y3 ) ); }
50  void arc( const Vec2f &center, float radius, float startRadians, float endRadians, bool forward = true );
51  void arc( float centerX, float centerY, float radius, float startRadians, float endRadians, bool forward = true ) { arc( Vec2f( centerX, centerY ), radius, startRadians, endRadians, forward ); }
52  void arcTo( const Vec2f &p, const Vec2f &t, float radius );
53  void arcTo( float x, float y, float tanX, float tanY, float radius) { arcTo( Vec2f( x, y ), Vec2f( tanX, tanY ), radius ); }
54 
56  void close() { mSegments.push_back( CLOSE ); }
57  bool isClosed() const { return ( mSegments.size() > 1 ) && mSegments.back() == CLOSE; }
58 
60  void reverse();
61 
62  bool empty() const { return mPoints.empty(); }
63  void clear() { mSegments.clear(); mPoints.clear(); }
64  size_t getNumSegments() const { return mSegments.size(); }
65  size_t getNumPoints() const { return mPoints.size(); }
66 
68  Vec2f getPosition( float t ) const;
70  Vec2f getSegmentPosition( size_t segment, float t ) const;
72  Vec2f getTangent( float t ) const;
74  Vec2f getSegmentTangent( size_t segment, float t ) const;
75 
77  void getSegmentRelativeT( float t, size_t *segment, float *relativeT ) const;
78 
79  std::vector<Vec2f> subdivide( float approximationScale = 1.0f ) const;
80 
82  void scale( const Vec2f &amount, Vec2f scaleCenter = Vec2f::zero() );
84  void transform( const MatrixAffine2f &matrix );
86  Path2d transformCopy( const MatrixAffine2f &matrix ) const;
87 
88 
89  const std::vector<Vec2f>& getPoints() const { return mPoints; }
90  std::vector<Vec2f>& getPoints() { return mPoints; }
91  const Vec2f& getPoint( size_t point ) const { return mPoints[point]; }
92  Vec2f& getPoint( size_t point ) { return mPoints[point]; }
93  const Vec2f& getCurrentPoint() const { return mPoints.back(); }
94  void setPoint( size_t index, const Vec2f &p ) { mPoints[index] = p; }
95 
97  static const int sSegmentTypePointCounts[];
98  SegmentType getSegmentType( size_t segment ) const { return mSegments[segment]; }
99 
100  const std::vector<SegmentType>& getSegments() const { return mSegments; }
101  std::vector<SegmentType>& getSegments() { return mSegments; }
102 
103  void removeSegment( size_t segment );
104 
106  Rectf calcBoundingBox() const;
108  Rectf calcPreciseBoundingBox() const;
109 
111  bool contains( const Vec2f &pt ) const;
112 
114  float calcLength() const;
116  float calcSegmentLength( size_t segment, float minT = 0, float maxT = 1 ) const;
117 
119  float calcNormalizedTime( float relativeTime, bool wrap = true, float tolerance = 1.0e-03f, int maxIterations = 16 ) const;
121  float calcTimeForDistance( float distance, bool wrap = true, float tolerance = 1.0e-03f, int maxIterations = 16 ) const;
122 
123 
124  static int calcQuadraticBezierMonotoneRegions( const Vec2f p[3], float resultT[2] );
125  static Vec2f calcQuadraticBezierPos( const Vec2f p[3], float t );
126  static Vec2f calcQuadraticBezierDerivative( const Vec2f p[3], float t );
127  static int calcCubicBezierMonotoneRegions( const Vec2f p[4], float resultT[4] );
128  static Vec2f calcCubicBezierPos( const Vec2f p[4], float t );
129  static Vec2f calcCubicBezierDerivative( const Vec2f p[4], float t );
130 
132  float segmentSolveTimeForDistance( size_t segment, float segmentLength, float segmentRelativeDistance, float tolerance, int maxIterations ) const;
133 
134  friend class Shape2d;
135  friend class Path2dCalcCache;
136 
137  friend std::ostream& operator<<( std::ostream &out, const Path2d &p );
138  private:
139  void arcHelper( const Vec2f &center, float radius, float startRadians, float endRadians, bool forward );
140  void arcSegmentAsCubicBezier( const Vec2f &center, float radius, float startRadians, float endRadians );
141  void subdivideQuadratic( float distanceToleranceSqr, const Vec2f &p1, const Vec2f &p2, const Vec2f &p3, int level, std::vector<Vec2f> *result ) const;
142  void subdivideCubic( float distanceToleranceSqr, const Vec2f &p1, const Vec2f &p2, const Vec2f &p3, const Vec2f &p4, int level, std::vector<Vec2f> *result ) const;
143 
144  std::vector<Vec2f> mPoints;
145  std::vector<SegmentType> mSegments;
146 };
147 
148 inline std::ostream& operator<<( std::ostream &out, const Path2d &p )
149 {
150  if( p.mPoints.empty() )
151  return out;
152 
153  out << "M " << p.mPoints[0].x << " " << p.mPoints[0].y << " ";
154 
155  size_t pt = 1;
156  for( size_t s = 0; s < p.mSegments.size(); ++s ) {
157  if( p.mSegments[s] == Path2d::LINETO ) {
158  out << "L " << p.mPoints[pt].x << " " << p.mPoints[pt].y << " ";
159  pt++;
160  }
161  else if( p.mSegments[s] == Path2d::QUADTO ) {
162  out << "Q " << p.mPoints[pt].x << " " << p.mPoints[pt].y << " " << p.mPoints[pt+1].x << " " << p.mPoints[pt+1].y << " ";
163  pt += 2;
164  }
165  else if( p.mSegments[s] == Path2d::CUBICTO ) {
166  out << "C " << p.mPoints[pt].x << " " << p.mPoints[pt].y << " " << p.mPoints[pt+1].x << " " << p.mPoints[pt+1].y << " " << p.mPoints[pt+2].x << " " << p.mPoints[pt+2].y << " ";
167  pt += 3;
168  }
169  else {
170  out << "Z ";
171  }
172 
173  }
174 
175  return out;
176 }
177 
180  public:
181  Path2dCalcCache( const Path2d &path );
182 
183  const Path2d& getPath2d() const { return mPath; }
184  float getLength() const { return mLength; }
185 
187  float calcNormalizedTime( float relativeTime, bool wrap = true, float tolerance = 1.0e-03f, int maxIterations = 16 ) const;
189  float calcTimeForDistance( float distance, bool wrap = true, float tolerance = 1.0e-03f, int maxIterations = 16 ) const;
191  Vec2f getPosition( float t ) const { return mPath.getPosition( t ); }
192 
193  private:
194  Path2d mPath;
195  float mLength;
196  std::vector<float> mSegmentLengths;
197 };
198 
199 class Path2dExc : public Exception {
200 };
201 
202 } // namespace cinder
void lineTo(float x, float y)
Definition: Path2d.h:45
std::vector< Vec2f > subdivide(float approximationScale=1.0f) const
Definition: Path2d.cpp:468
GLuint GLenum matrix
Definition: GLee.h:10032
Path2d()
Definition: Path2d.h:37
void curveTo(float x1, float y1, float x2, float y2, float x3, float y3)
Definition: Path2d.h:49
static int calcQuadraticBezierMonotoneRegions(const Vec2f p[3], float resultT[2])
Definition: Path2d.cpp:694
Definition: Path2d.h:96
GLenum GLint GLint y
Definition: GLee.h:987
GLint level
Definition: GLee.h:1161
float calcTimeForDistance(float distance, bool wrap=true, float tolerance=1.0e-03f, int maxIterations=16) const
Calculates a t-value corresponding to arc length distance. If wrap then the t-value loops inside the ...
Definition: Path2d.cpp:1133
bool empty() const
Definition: Path2d.h:62
Vec2< float > Vec2f
Definition: Vector.h:1314
void getSegmentRelativeT(float t, size_t *segment, float *relativeT) const
Stores into segment the segment # associated with t, and if relativeT is not NULL, the t relative to its segment, in the range [0,1]
Definition: Path2d.cpp:362
void arcTo(const Vec2f &p, const Vec2f &t, float radius)
Definition: Path2d.cpp:254
float getLength() const
Definition: Path2d.h:184
const Vec2f & getPoint(size_t point) const
Definition: Path2d.h:91
bool contains(const Vec2f &pt) const
Returns whether the point pt is contained within the boundaries of the path.
Definition: Path2d.cpp:906
float calcLength() const
Calculates the length of the Path2d.
Definition: Path2d.cpp:941
void arc(const Vec2f &center, float radius, float startRadians, float endRadians, bool forward=true)
Definition: Path2d.cpp:178
std::vector< SegmentType > & getSegments()
Definition: Path2d.h:101
Rectf calcBoundingBox() const
Returns the bounding box around all control points. As with Shape2d, note this is not necessarily the...
Definition: Path2d.cpp:681
static Vec2< float > zero()
Definition: Vector.h:295
GLuint index
Definition: GLee.h:2259
void clear()
Definition: Path2d.h:63
Definition: Path2d.h:96
const Path2d & getPath2d() const
Definition: Path2d.h:183
static int calcCubicBezierMonotoneRegions(const Vec2f p[4], float resultT[4])
Definition: Path2d.cpp:726
const std::vector< Vec2f > & getPoints() const
Definition: Path2d.h:89
std::vector< Vec2f > & getPoints()
Definition: Path2d.h:90
Definition: Path2d.h:96
static Vec2f calcCubicBezierPos(const Vec2f p[4], float t)
Definition: Path2d.cpp:756
const Vec2f & getCurrentPoint() const
Definition: Path2d.h:93
Definition: Path2d.h:96
static Vec2f calcQuadraticBezierDerivative(const Vec2f p[3], float t)
Definition: Path2d.cpp:719
void setPoint(size_t index, const Vec2f &p)
Definition: Path2d.h:94
Vec2f getTangent(float t) const
Returns the tangent on the curve at parameter t, which lies in the range [0,1]
Definition: Path2d.cpp:398
float calcSegmentLength(size_t segment, float minT=0, float maxT=1) const
Calculates the length of a specific segment in the range [minT,maxT], where minT and maxT range from ...
Definition: Path2d.cpp:970
Vec2f getPosition(float t) const
Returns the point on the curve at parameter t, which lies in the range [0,1]
Definition: Path2d.h:191
Definition: Path2d.h:96
Vec2f getSegmentTangent(size_t segment, float t) const
Returns the point in segment # segment in the range [0,getNumSegments()) at parameter t in the range ...
Definition: Path2d.cpp:440
Vec2f getPosition(float t) const
Returns the point on the curve at parameter t, which lies in the range [0,1]
Definition: Path2d.cpp:390
Accelerates the calculation of various operations on Path2d. Useful if doing repeated calculations...
Definition: Path2d.h:179
Path2dCalcCache(const Path2d &path)
Definition: Path2d.cpp:1093
Rectf calcPreciseBoundingBox() const
Returns the precise bounding box around the curve itself. Slower to calculate than calcBoundingBox()...
Definition: Path2d.cpp:777
static Vec2f calcCubicBezierDerivative(const Vec2f p[4], float t)
Definition: Path2d.cpp:766
GLenum GLint x
Definition: GLee.h:987
Path2d transformCopy(const MatrixAffine2f &matrix) const
Returns a copy transformed by matrix.
Definition: Path2d.cpp:673
void arc(float centerX, float centerY, float radius, float startRadians, float endRadians, bool forward=true)
Definition: Path2d.h:51
Definition: Path2d.h:199
void arcTo(float x, float y, float tanX, float tanY, float radius)
Definition: Path2d.h:53
void transform(const MatrixAffine2f &matrix)
Transforms the Path2d by matrix.
Definition: Path2d.cpp:667
Definition: BSpline.h:103
GLfloat GLfloat p
Definition: GLee.h:8473
Vec2f & getPoint(size_t point)
Definition: Path2d.h:92
bool isClosed() const
Definition: Path2d.h:57
std::ostream & operator<<(std::ostream &lhs, const ColorT< float > &rhs)
Definition: Color.cpp:203
void moveTo(float x, float y)
Sets the start point of the path to (x, y ). This is the only legal first command, and only legal as the first command.
Definition: Path2d.h:43
SegmentType getSegmentType(size_t segment) const
Definition: Path2d.h:98
Definition: Path2d.h:35
void quadTo(const Vec2f &p1, const Vec2f &p2)
Definition: Path2d.cpp:157
float calcNormalizedTime(float relativeTime, bool wrap=true, float tolerance=1.0e-03f, int maxIterations=16) const
Calculates the t-value corresponding to relativeTime in the range [0,1) within epsilon of tolerance...
Definition: Path2d.cpp:1100
static Vec2f calcQuadraticBezierPos(const Vec2f p[3], float t)
Definition: Path2d.cpp:713
void reverse()
Reverses the order of the path's points, inverting its winding order.
Definition: Path2d.cpp:327
void close()
Closes the path, by drawing a straight line from the first to the last point. This is only legal as t...
Definition: Path2d.h:56
void quadTo(float x1, float y1, float x2, float y2)
Definition: Path2d.h:47
Definition: Exception.h:32
size_t getNumPoints() const
Definition: Path2d.h:65
void removeSegment(size_t segment)
Definition: Path2d.cpp:350
void moveTo(const Vec2f &p)
Sets the start point of the path to p. This is the only legal first command, and only legal as the fi...
Definition: Path2d.cpp:140
void scale(const Vec2f &amount, Vec2f scaleCenter=Vec2f::zero())
Scales the Path2d by amount.x on X and amount.y on Y around the center scaleCenter.
Definition: Path2d.cpp:661
void curveTo(const Vec2f &p1, const Vec2f &p2, const Vec2f &p3)
Definition: Path2d.cpp:167
Vec2f getSegmentPosition(size_t segment, float t) const
Returns the point in segment # segment in the range [0,getNumSegments()) at parameter t in the range ...
Definition: Path2d.cpp:406
float calcNormalizedTime(float relativeTime, bool wrap=true, float tolerance=1.0e-03f, int maxIterations=16) const
Calculates the t value corresponding to relativeTime in the range [0,1) within epsilon of tolerance...
Definition: Path2d.cpp:997
void lineTo(const Vec2f &p)
Definition: Path2d.cpp:148
GLdouble GLdouble t
Definition: GLee.h:1426
GLdouble s
Definition: GLee.h:1378
size_t getNumSegments() const
Definition: Path2d.h:64
GLclampf f
Definition: GLee.h:15307
friend std::ostream & operator<<(std::ostream &out, const Path2d &p)
Definition: Path2d.h:148
const std::vector< SegmentType > & getSegments() const
Definition: Path2d.h:100
static const int sSegmentTypePointCounts[]
Definition: Path2d.h:97
Definition: Shape2d.h:34
SegmentType
Definition: Path2d.h:96
float calcTimeForDistance(float distance, bool wrap=true, float tolerance=1.0e-03f, int maxIterations=16) const
Calculates a t-value corresponding to arc length distance. If wrap then the t-value loops inside the ...
Definition: Path2d.cpp:1028
float segmentSolveTimeForDistance(size_t segment, float segmentLength, float segmentRelativeDistance, float tolerance, int maxIterations) const
Solves the time corresponding to segmentRelativeDistance (a measure of arc length). Generally you should use calcNormalizedTime() or calcTimeForDistance() instead.
Definition: Path2d.cpp:1052