void Context::appendPath( const cinder::Path2d &path ) { size_t point = 0; if( path.empty() ) return; moveTo( path.getPoint( point++ ) ); for( size_t seg = 0; seg < path.getNumSegments(); ++seg ) { switch( path.getSegmentType( seg ) ) { case Path2d::LINETO: lineTo( path.getPoint( point++ ) ); break; case Path2d::QUADTO: { const Vec2f &spl0( path.getPoint( point - 1 ) ); const Vec2f &spl1( path.getPoint( point + 0 ) ); const Vec2f &spl2( path.getPoint( point + 1 ) ); curveTo( spl0 + (spl1 - spl0) / 3.0f * 2.0f, spl1 + (spl2 - spl1) / 3.0f, spl2 ); point += 2; } break; case Path2d::CUBICTO: curveTo( path.getPoint( point ), path.getPoint( point + 1 ), path.getPoint( point + 2 ) ); point += 3; break; case Path2d::CLOSE: closePath(); break; } } }
void Path2DSamplesApp::drawPath( const cinder::Path2d &path ) { gl::color( Color( 1, 0 ,0 ) ); // draw path gl::draw( path ); //draw points gl::color( 1, 1, 0 ); for( int i = 0; i < path.getPoints().size(); i++ ) { vec2 point = path.getPoint( i ); gl::drawSolidRect( Rectf( -2.0, -2.0, 2.0, 2.0 ) + point ); // gl::drawLine( path.getPosition( t ), mPath.getPosition( t ) + normalize( mPath.getTangent( t ) ) * 80.0f ); } // draw point along the curve gl::color( 1, 0, 1 ); float pos = ( getElapsedSeconds() * 0.25f ); pos -= floor( pos ); vec2 pt = path.getPosition( pos ); gl::drawSolidCircle( pt, 4.0 ); gl::drawLine( pt, pt + normalize(path.getTangent( pos )) * 25.0f ); gl::drawLine( pt, pt - normalize(path.getTangent( pos )) * 25.0f ); // // gl::color( 0, 1, 1 ); // pt = path.getTangent( pos ); // gl::drawSolidCircle( pt, 4.0 ); //draw lines between points depending on their segment type gl::color( 1, 0, 1 ); int ptCount = 0; for( int i = 0; i < path.getSegments().size(); i++ ) { auto segment = path.getSegments()[i]; // console() << " --- " << segment << " --- "<< endl; auto points = path.getPoints(); // if segment type == Path2d::SegmentType::CUBICTO // draw lines between if( segment == Path2d::SegmentType::QUADTO ) { vec2 pt1 = path.getPoints()[ptCount]; vec2 pt2 = path.getPoints()[ptCount + 1]; vec2 pt3 = path.getPoints()[ptCount + 2]; if( segment == Path2d::SegmentType::QUADTO ) { gl::drawLine( pt1, pt2 ); gl::drawLine( pt2, pt3 ); } } if( segment == Path2d::SegmentType::CUBICTO ) { vec2 pt1 = path.getPoints()[ptCount + 0]; vec2 pt2 = path.getPoints()[ptCount + 1]; vec2 pt3 = path.getPoints()[ptCount + 2]; vec2 pt4 = path.getPoints()[ptCount + 3]; gl::drawLine( pt1, pt2 ); gl::drawLine( pt3, pt4 ); } // path.getSegmentTangent(size_t segment, float t) // console() << segment << endl; // vec2 point = path.getPoint( i ); // gl::drawSolidRect( Rectf( -2.0, -2.0, 2.0, 2.0 ) + point ); /*if( segment == Path2d::SegmentType::MOVETO || segment == Path2d::SegmentType::LINETO ) ptCount += 1; if( segment == Path2d::SegmentType::CUBICTO ) ptCount += 3; if( segment == Path2d::SegmentType::QUADTO ) ptCount += 2;*/ ptCount += path.sSegmentTypePointCounts[segment]; } gl::color( 1, 1, 1, 0.2 ); // gl::drawSolidRect( path.calcBoundingBox() ); // box around everything (including points) gl::drawSolidRect( path.calcPreciseBoundingBox() ); // box around just the path itself // gl::drawStrokedRect(path.calcPreciseBoundingBox()); // calculate length of path gl::drawString( "length: " + to_string( path.calcLength() ), vec2( 0.0, -10.0 ) ); // not sure what these do /*static int calcQuadraticBezierMonotoneRegions( const vec2 p[3], float resultT[2] ); static vec2 calcQuadraticBezierPos( const vec2 p[3], float t ); static vec2 calcQuadraticBezierDerivative( const vec2 p[3], float t ); static int calcCubicBezierMonotoneRegions( const vec2 p[4], float resultT[4] ); static vec2 calcCubicBezierPos( const vec2 p[4], float t ); static vec2 calcCubicBezierDerivative( const vec2 p[4], float t );*/ { gl::color( 0, 0, 0 ); // float time = path.calcNormalizedTime( getElapsedSeconds() * 0.25 ); // should this be used when getting position based on time? float time = path.calcTimeForDistance( getElapsedSeconds() * 20.0 ); // distance based. so 100 is 100 pixels along the path. It loops. Returns a time // console() << getElapsedSeconds() * 20.0 << " " << time << endl; vec2 pos = path.getPosition( time ); gl::drawSolidCircle( pos, 2.0 ); } // subdivides curves into points. You can construct a simplified curve that way auto subdivided = path.subdivide( 0.1 ); for( auto d : subdivided ) { gl::color( 0, 1, 1 ); gl::drawStrokedCircle( d, 3.0 ); } // move over a bit and dot affine matric copies and rotate { gl::ScopedMatrices mtrx; gl::translate( path.calcBoundingBox().getWidth(), 0 ); for( int i = 0; i < 8; i++ ){ MatrixAffine2<float> affineMtrx; affineMtrx.scale( 0.25 ); affineMtrx.rotate( ( ( M_PI * 2) / 8 ) * i ); auto pathCopy = path.transformCopy( affineMtrx ); gl::draw( pathCopy ); } } // //path.calcSegmentLength( segment number, min, max ) // highlight 0.25 - 0.75 or each segment // path.getSegmentRelativeT(float t, size_t *segment, float *relativeT) // used internally when getting positions. tangents, etx //path.segmentSolveTimeForDistance(size_t segment, float segmentLength, float segmentRelativeDistance, float tolerance, int maxIterations) // should use calcNormalizedTime or calcTimeForDistance // Path2d article // simple drawing // drawing and adding points after // drawing and then moving handles // idea: draw path that then controls sound - pitch, volume, and other stuff - using the curve }