Example #1
0
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
}