void Island::draw() { float pointsPerMeter = SceneController::getPointsPerMeter(); auto centerPos = box2d::toCinder( mBody->GetPosition() ) * pointsPerMeter; gl::pushModelView(); gl::translate( centerPos ); Path2d path; path.moveTo( mOuterVerts[0] ); for( int i = 1; i < mOuterVerts.size(); ++i ) path.lineTo( mOuterVerts[i] ); Color color = Color::gray( 0.34f ); color.r *= 1 - mVibrationLevel * 0.5; color.g *= 1 - mVibrationLevel * 0.2; gl::color( color ); gl::drawSolid( path ); for( size_t i = 0; i < mBumpers.size(); i++ ) { Color color = Color::gray( 0.42f ); color.r *= 1 + mBumperVibrationLevels[i]; gl::color( color ); gl::drawSolid( mBumpers[i] ); } gl::popModelView(); }
bool intersect(const Path2d& path) { bool closed = false; for (int i=0; i<path.size()-2 && !closed; i++) { for (int j=i+2; j<path.size()-1 && !closed; j++) { closed = _intersSegmenti(path[i], path[i+1], path[j], path[j+1]) != P2d::none(); } } return closed; }
void Path2DSamplesApp::update() { auto bounds = path6.calcBoundingBox(); for( auto &pt : intersectPts ){ vec2 &pos = pt.first; vec2 &vel = pt.second; pos += vel; if( pos.x > bounds.x2 || pos.x < bounds.x1 ) { pos.x -= vel.x; pt.second.x *= -1.0; } if( pos.y > bounds.y2 || pos.y < bounds.y1 ) { pos.y -= vel.y; pt.second.y *= -1.0; } } // pt.second *= vec2( -1, 1 ); // } /* if( pos.y > bounds.y2 || pos.y < bounds.y1 ) pt.second *= vec2( 1, -1 ); */ // Color ptColor = ( path6.contains( pt ) ) ? Color( 0, 1, 0 ) : Color( 1, 0, 0 ); // gl::color( ptColor ); // gl::drawSolidCircle( pt, 2.0 ); }
bool intersect(const Path2d& path1, const Path2d& path2, const bool overlap, const double eps) { const int len1 = path1.size(); const int len2 = path2.size(); P2d p11 = path1[0]; P2d p12; P2d p21 = path2[0]; P2d p22; for (int i = 1; i < len1; ++i) { p12 = path1[i]; P2d B = p12-p11; for (int j = 1; j < len2; ++j) { p22 = path2[j]; P2d D = p22-p21; D = P2d(D.y, -D.x); double denom = D*B; if (fabs(denom) > eps) { P2d C = p21-p11; double numer = D*C; double t = numer/denom; C = P2d(C.y, -C.x); double u = (B*C)/(-denom); if (overlap) { if ( t >= 0.0 && t <= 1.0 && u <= 1.0 && u >= 0.0 ) { return true; } } else { if ( t > 0.0 && t < 1.0 && u < 1.0 && u > 0.0 ) { return true; } } } p21 = p22; } p11 = p12; } return false; }
std::vector<P2d> _intersections(const Path2d& path1, const Path2d& path2, const bool self_intersect) { std::vector<P2d> rv; if (path1.size() < 2 || path2.size() < 2) return rv; int i1, i2, i2_start; P2d p1a, p1b; P2d p2a, p2b; for(i1 = 0, p1a = path1[i1]; i1 < (path1.size() - 1); p1a = p1b) { ++i1; p1b = path1[i1]; if (!self_intersect) { i2_start = 0; } else { // in casi non degeneri due segmenti consecutivi di una linea non si intersecano i2_start = i1 + 1; if (i2_start >= (path2.size() - 1)) break; } for(i2 = i2_start, p2a = path2[i2]; i2 < (path2.size() - 1); p2a = p2b) { ++i2; p2b = path2[i2]; P2d intr = _intersSegmenti(p1a, p1b, p2a, p2b); if (intr != P2d::none()) { rv.push_back(intr); } } } return rv; }
void ContinuousPathApp::drawCurves(cairo::Context &ctx, Path2d path, float thickness, Color col) { ctx.setLineWidth(thickness); ctx.setSource(col); ctx.newSubPath(); int pointIndex = 0; for (int i=0; i<path.getNumSegments(); i++) { int segType = path.getSegmentType(i); // change jumpIndex depending on the type of segment switch(segType){ case Path2d::CUBICTO: if(i==0) ctx.moveTo(path.getPoint(pointIndex)); // do a curve to using the next 2 points as the curves and the 3rd as the end point ctx.curveTo(path.getPoint(pointIndex+1), path.getPoint(pointIndex+2), path.getPoint(pointIndex+3)); pointIndex += 3; break; case Path2d::MOVETO: // don't do anything with this point ctx.moveTo(path.getPoint(pointIndex)); pointIndex += 0; break; default: pointIndex += 1; break; } } ctx.stroke(); }
Path2d PathFitter::FitCurve(vector<Vec2f> const &d, int startIndex, int endIndex, double error) { if(error == 0.0) throw "error value must be greater than 0.0"; Vec2f tHat1, tHat2; // Unit tangent vectors at endpoints vector<BezierCurve> bezCurves; // The vector that will store the BezierCurve values to be returned once the curve fitting is complete // if startIndex is the beginning of the cur tHat1 = computeLeftTangent(d, startIndex); // if endIndex is the end of the curve tHat2 = computeRightTangent(d, endIndex - 1); FitCubic(d, &bezCurves, startIndex, endIndex - 1, tHat1, tHat2, error); // convert the vector of BezierCurves to a Path2d object Path2d curvePath; curvePath.moveTo(bezCurves[0].pt1.x, bezCurves[0].pt1.y); for(int i=0; i<bezCurves.size(); i++){ curvePath.curveTo(bezCurves[i].c1, bezCurves[i].c2, bezCurves[i].pt2); } return curvePath; }
// Draw each path onto the passed cairo context void PathSimplificationApp::drawPath(cairo::Context &ctx, SmoothPath *smoothPath, int mode) { // initialize the line settings float thickness = 1.0; ctx.setLineWidth( 1.0f ); ctx.setLineCap(cairo::LINE_CAP_ROUND); ctx.setLineJoin(cairo::LINE_JOIN_ROUND); if(smoothPath->inProgress){ // draw lines point to point vector<Vec2f> pathPoints = smoothPath->getPathPoints(); for (int i=1; i<pathPoints.size(); i++) { drawLine(ctx, pathPoints[i-1], pathPoints[i], 1.0, Color(1.0, 0.0, 0.0)); drawCircle(ctx, pathPoints[i], 2, Color(1.0, 0.0, 0.0)); } }else{ // draw smooth lines Path2d path = smoothPath->getCurrentPath(); drawCurves(ctx, path, thickness, Color(255.0, 0.0, 0.0)); int pointIndex = 0; // draw circles at the bezier points for (int i=0; i<path.getNumSegments(); i++) { Vec2f c1 = path.getPoint(pointIndex+1); Vec2f c2 = path.getPoint(pointIndex+2); Vec2f pt1 = path.getPoint(pointIndex); Vec2f pt2 = path.getPoint(pointIndex+3); drawCircle(ctx, c1, 1, Color(1.0f, 1.0f, 0.0f), true); drawCircle(ctx, c2, 1, Color(0.0f, 1.0f, 1.0f)); drawLine(ctx, c1, pt1, 1, Color(1.0, 1.0, 0.0 )); drawLine(ctx, c2, pt2, 1, Color(0.0, 1.0, 1.0 )); pointIndex += 3; } } }
void CanvasContext::rect(float x, float y, float w, float h) { Path2d p; p.moveTo(x, y); p.lineTo(x, y + h); p.lineTo(x + w, y + h); p.lineTo(x + w, y); p.close(); paths.push_back(p); }
void Wall::draw() { float pointsPerMeter = SceneController::getPointsPerMeter(); auto pos = pointsPerMeter * mBody->GetPosition(); Rectf wallRect( pos.x - mWidth, 0, pos.x + mWidth, app::getWindowHeight() ); Path2d vibrationPath; vibrationPath.moveTo( wallRect.getUpperRight() ); // right vibrating wall { Vec2f controlPoint1( wallRect.x2 + mVibrationLevel, wallRect.y1 + wallRect.getHeight() / 3.0f ); Vec2f controlPoint2( wallRect.x2 + mVibrationLevel, wallRect.y1 + wallRect.getHeight() * 2.0f / 3.0f ); vibrationPath.curveTo( controlPoint1, controlPoint2, wallRect.getLowerRight() ); } vibrationPath.lineTo( wallRect.getLowerLeft() ); // left vibrating wall { Vec2f controlPoint1( wallRect.x1 - mVibrationLevel, wallRect.y1 + wallRect.getHeight() * 2.0f / 3.0f ); Vec2f controlPoint2( wallRect.x1 - mVibrationLevel, wallRect.y1 + wallRect.getHeight() / 3.0f ); vibrationPath.curveTo( controlPoint1, controlPoint2, wallRect.getUpperLeft() ); } vibrationPath.close(); ColorA vibrationColor = ColorA::gray( 0.2f, 0.6f ); vibrationColor.g += mVibrationLevel * 0.01f; vibrationColor.b += mVibrationLevel * 0.03f; gl::color( vibrationColor ); gl::drawSolid( vibrationPath ); ColorA wallColor = ColorA::gray( 0.2f, 1.0f ); wallColor.g += mVibrationLevel * 0.01f; wallColor.b += mVibrationLevel * 0.015f; gl::color( wallColor ); gl::drawSolidRect( wallRect ); }
void SeaSurface:: draw(){ float globalOpacityMod = 1.0f; globalOpacityMod = -(offset.y + 6000) * 0.002f; if( globalOpacityMod >= 1.0f ) globalOpacityMod = 1.0f; for(int n = 0; n < rows.size(); n++){ Path2d path; path.moveTo( paths.at(n).at(0) ); for(int i = 1; i < paths.at(n).size(); i++ ) path.lineTo( paths.at(n).at(i) ); path.lineTo( vec2( cinder::app::getWindowWidth(), 0.0 ) ); path.lineTo( vec2( 0.0, 0.0 ) ); path.close(); gl::color(ColorA8u(237,160, 135, rows.at(n)->depth * 20.0f * globalOpacityMod ) ); gl::drawSolid(path); gl::draw(path); } }
void SeaFloor:: draw(){ float globalOpacityMod = 1.0f; globalOpacityMod = (offset.y + 1000) * 0.002f; if( globalOpacityMod >= 1.0f ) globalOpacityMod = 1.0f; for(int n = 0; n < rows.size(); n++){ Path2d path; path.moveTo( paths.at(n).at(0) ); for(int i = 1; i < paths.at(n).size(); i++ ) path.lineTo( paths.at(n).at(i) ); path.lineTo( vec2( cinder::app::getWindowWidth(), cinder::app::getWindowHeight()) ); path.lineTo( vec2( 0.0, cinder::app::getWindowHeight() ) ); path.close(); gl::color(ColorA8u(192,177,139, rows.at(n)->depth * 30.0f * globalOpacityMod ) ); gl::drawSolid(path); gl::draw(path); } }
void Island::makeBumpers() { CI_ASSERT( mOuterVerts.size() == 6 && mInnerVerts.size() == 5 ); mBumpers.clear(); mBumperBoundingBoxes.clear(); mBumperVibrationLevels.clear(); const float padding = 4; const float crookedPaddingPercent = 0.036f; const float boundingBoxExpansion = 1.1f; // left base { Path2d bumper; bumper.moveTo( mOuterVerts[0] ); bumper.lineTo( mOuterVerts[1].x, mOuterVerts[1].y + padding ); bumper.lineTo( mInnerVerts[1].x, mInnerVerts[1].y + padding ); bumper.lineTo( mInnerVerts[0] ); bumper.close(); mBumpers.push_back( bumper ); } // left top { Vec2f offsetOuter = ( mOuterVerts[2] - mOuterVerts[1] ) * crookedPaddingPercent; Vec2f offsetInner = ( Vec2f( mOuterVerts[2].x, mInnerVerts[2].y ) - mInnerVerts[1] ) * crookedPaddingPercent; Path2d bumper; bumper.moveTo( mOuterVerts[1] + offsetOuter ); bumper.lineTo( mOuterVerts[2] ); bumper.lineTo( mOuterVerts[2].x, mInnerVerts[2].y ); bumper.lineTo( mInnerVerts[1] + offsetInner ); bumper.close(); mBumpers.push_back( bumper ); } // right top { Vec2f offsetOuter = ( mOuterVerts[3] - mOuterVerts[4] ) * crookedPaddingPercent; Vec2f offsetInner = ( Vec2f( mOuterVerts[3].x, mInnerVerts[2].y ) - mInnerVerts[3] ) * crookedPaddingPercent; Path2d bumper; bumper.moveTo( mOuterVerts[3] ); bumper.lineTo( mOuterVerts[4] + offsetOuter ); bumper.lineTo( mInnerVerts[3] + offsetInner ); bumper.lineTo( mOuterVerts[3].x, mInnerVerts[2].y ); bumper.close(); mBumpers.push_back( bumper ); } // right base { Path2d bumper; bumper.moveTo( mOuterVerts[4].x, mOuterVerts[4].y + padding ); bumper.lineTo( mOuterVerts[5] ); bumper.lineTo( mInnerVerts[4] ); bumper.lineTo( mInnerVerts[3].x, mInnerVerts[3].y + padding ); bumper.close(); mBumpers.push_back( bumper ); } for( size_t i = 0; i < mBumpers.size(); i++ ) { mBumperVibrationLevels.push_back( 0 ); // calculate an expanded bounding box for each bumper to do hit detection, ensuring that the entire edge is covered. Rectf bbox = mBumpers[i].calcBoundingBox(); Vec2f center = bbox.getCenter(); bbox -= center; bbox *= boundingBoxExpansion; bbox += center; mBumperBoundingBoxes.push_back( bbox ); } }
void Ribbon::draw() { Vec2i normPos1, normPos2; normPos1 = Vec2f::zero(); normPos2 = Vec2f::zero(); for(list<RibbonParticle *>::iterator p = mParticles.begin(); p != mParticles.end(); ++p){ int x1 = (*p)->mPos.x - (*p)->mVel.x; int x2 = (*p)->mPos.x; int y1 = (*p)->mPos.y - (*p)->mVel.y; int y2 = (*p)->mPos.y; // Capture the previous normal positions Vec2i prevNormPos1(normPos1); Vec2i prevNormPos2(normPos2); // If this is the first segment, make the normals the // same as the position (we want it to taper in) if(prevNormPos1 == Vec2i::zero() && prevNormPos2 == Vec2i::zero()){ normPos1 = Vec2i(x1, y1); normPos2 = Vec2i(x2, y2); prevNormPos1 = normPos1; prevNormPos2 = normPos2; }else{ int normX1 = (*p)->mPos.x - ((*p)->mVelNormal.x * 0.5); int normX2 = (*p)->mPos.x + ((*p)->mVelNormal.x * 0.5); int normY1 = (*p)->mPos.y - ((*p)->mVelNormal.y * 0.5); int normY2 = (*p)->mPos.y + ((*p)->mVelNormal.y * 0.5); normPos1 = Vec2i(normX1,normY1); normPos2 = Vec2i(normX2,normY2); } // Draw the shape between the normals Path2d path; path.moveTo(prevNormPos1.x, prevNormPos1.y); path.lineTo(normPos1.x, normPos1.y); path.lineTo(normPos2.x, normPos2.y); path.lineTo(prevNormPos2.x, prevNormPos2.y); path.close(); // float value = ((*p)->mAge / 200.0); // Draw the filled ribbon // Defaults to yellow float red = 1.0; float green = 1.0; float blue = 0.5; if(mAgeConnectedAt > 0){ int lastConnected = mAge - mAgeConnectedAt; if(lastConnected < 20){ if(mCapturedGoal){ red = lastConnected * 0.05; }else{ green = lastConnected * 0.05; } blue = lastConnected * 0.025; } } gl::color(Color(red,green,blue)); gl::drawSolid(path); /* // Draw the surface normal gl::color(Color(1.0-value,0,0)); gl::drawLine(normPos1, normPos2); // Draw a line indicating it's position w/ velocity gl::color(Color::black()); gl::drawLine(Vec2i(x1,y1), Vec2i(x2, y2)); */ } }
void ShapeTesselator::add(const Path2d &path, float approximationScale) { add(path.subdivide(approximationScale)); }
void Path2DSamplesApp::draw() { gl::enableAlphaBlending(); gl::clear( Color( 0, 0, 0 ) ); gl::lineWidth( 1.0 ); { gl::ScopedMatrices mtrx; gl::translate( vec2( 50.0, 50.0 ) ); drawPath( path1 ); } { gl::ScopedMatrices mtrx; gl::translate( vec2( 50.0, 200.0 ) ); drawPath( path2 ); } { gl::ScopedMatrices mtrx; gl::translate( vec2( 50.0, 300.0 ) ); drawPath( path3 ); } { gl::ScopedMatrices mtrx; gl::translate( vec2( 200.0, 300.0 ) ); drawPath( path4 ); } { gl::ScopedMatrices mtrx; gl::translate( vec2( 350.0, 300.0 ) ); drawPath( path5 ); } { gl::ScopedMatrices mtrx; gl::translate( vec2( 50.0, 400.0 ) ); gl::color( Color( 1, 0 ,0 ) ); gl::draw( path6 ); for( auto &pt : intersectPts ){ Color ptColor = ( path6.contains( pt.first ) ) ? Color( 0, 1, 0 ) : Color( 1, 0, 0 ); gl::color( ptColor ); gl::drawSolidCircle( pt.first, 2.0 ); } gl::color( 1, 1, 1, 0.2); gl::drawSolidRect( path6.calcBoundingBox() ); } gl::lineWidth( 2.0 ); { gl::ScopedMatrices mtrx; gl::translate( vec2( 600, 400 ) ); float timePos = ( getElapsedSeconds() * 10.0f ); int amt = 10; for( int i = 0; i < pathCaches.size()-1; i++ ) { auto path1 = pathCaches[i]; Path2dCalcCache path2 = pathCaches[i + 1]; float time = timePos; for( int j = 0; j < amt; j++ ) { time += 20.0; float time1 = path1.calcTimeForDistance( time ); vec2 pt1 = path1.getPosition( time1 ); float time2 = path2.calcTimeForDistance( time ); vec2 pt2 = path2.getPosition( time2 ); gl::color( 1, 1, 1, 1); gl::drawLine( pt1, pt2 ); } gl::color( 1, 1, 1, 0.2); gl::draw(path1.getPath2d()); } } // draw outlines // draw solid // console() << " _ " << endl; gl::pushMatrices(); gl::translate( vec2( 600, 50 ) ); gl::color( 1, 1, 1 ); vec2 toPt = vec2( 100, 100 ); vec2 tanPt = vec2( 0, 50 ); Path2d arcTo1; arcTo1.moveTo( 0, 0 ); arcTo1.arcTo( toPt, tanPt, 100.0 ); gl::draw( arcTo1 ); gl::drawSolidCircle( vec2(0, 0), 3 ); gl::drawSolidCircle( toPt, 3 ); gl::drawSolidCircle( tanPt, 3 ); for( int i = 0; i < arcTo1.getPoints().size(); i++ ) { auto point = arcTo1.getPoints()[i]; gl::color( 1, 0, 0 ); gl::drawSolidCircle( point, 2 ); } gl::popMatrices(); }
// Draw each path onto the passed cairo context void ContinuousPathApp::drawPath(cairo::Context &ctx, SmoothPath *smoothPath, int mode) { // update the drawing points only if the line hasn't been completed Path2d path = smoothPath->getCurrentPath(); vector<Vec2f> pathPoints = smoothPath->getPathPoints(); vector<int> endPoints = smoothPath->getEndPoints(); if(path.getNumPoints() == 0) return; // initialize the line settings float thickness = 1.0; ctx.setLineWidth( 1.0f ); ctx.setLineCap(cairo::LINE_CAP_ROUND); ctx.setLineJoin(cairo::LINE_JOIN_ROUND); Vec2f pt = path.getPoint(0); // draw bezier line if (mode != 5) { // draw the line based on bezier points drawCurves(ctx, path, thickness, Color(255.0, 0.0, 0.0)); } // draw circles at each of the original path points if(mode != 1 && mode != 5){ for (int i=0; i<pathPoints.size(); i++) { Vec2f pt = pathPoints[i]; drawCircle(ctx, pt, 1, Color( 1.0f, 1.0f, 1.0f )); } } int i; int pointIndex = 0; // draw circles at the bezier points for (i=0; i<path.getNumSegments(); i++) { int segType = path.getSegmentType(i); // change jumpIndex depending on the type of segment switch(segType){ case Path2d::CUBICTO: { Vec2f c1 = path.getPoint(pointIndex+1); Vec2f c2 = path.getPoint(pointIndex+2); Vec2f pt1 = path.getPoint(pointIndex); Vec2f pt2 = path.getPoint(pointIndex+3); if (mode == 2 || mode == 3) { if(mode == 2){ for(int j=0; j<endPoints.size(); j++){ if(endPoints[j] == pointIndex){ drawCircle(ctx, pt2, 8, Color(0.0f, 1.0f, 1.0f), true); } } } if(mode == 3){ // draw the control points and tangent lines drawCircle(ctx, c1, 2, Color(1.0f, 1.0f, 0.0f), true); drawCircle(ctx, c2, 2, Color(0.0f, 1.0f, 1.0f)); drawLine(ctx, c1, pt1, 1, Color(1.0, 1.0, 0.0 )); drawLine(ctx, c2, pt2, 1, Color(0.0, 1.0, 1.0 )); } drawCircle(ctx, pt2, 2, Color(1.0f, 0.0f, 1.0f)); drawCircle(ctx, pt1, 2, Color(1.0f, 0.0f, 0.0f), true); } if (mode == 4) { drawLine(ctx, pt1, pt2, 1, Color(1.0, 1.0, 1.0 )); drawCircle(ctx, pt1, 5, Color(1.0, 0.0, 0.0), true); drawCircle(ctx, pt2, 3, Color(1.0, 0.0, 1.0)); } pointIndex += 3; break; } case Path2d::MOVETO: // don't do anything with this point pointIndex += 0; break; default: pointIndex += 1; break; } } if (mode== 5) { // draw a line between the last bezier point and the current point for (i=1; i<pathPoints.size(); i++) { drawLine(ctx, pathPoints[i-1], pathPoints[i], 1.0, Color(1.0, 0.0, 0.0)); } } }
void Path2DSamplesApp::setup() { // lineTo path1.moveTo( vec2( 0.0, 0.0 ) ); path1.lineTo( vec2( 100.0, 100.0 ) ); path1.lineTo( vec2( 200.0, 0.0 ) ); path1.lineTo( vec2( 300.0, 100.0 ) ); path1.lineTo( vec2( 400.0, 0.0 ) ); // quadTo - waves float waveWidth = 100.0; path2.moveTo( vec2( 0.0, 50.0 ) ); for( int i = 0; i < 5; i++ ) { float startX = i * waveWidth; path2.quadTo( vec2( startX, 0.0 ), vec2( startX + waveWidth / 2.0, 0.0 ) ); path2.quadTo( vec2( startX + waveWidth / 2.0, 50.0 ), vec2( startX + waveWidth, 50.0 ) ); } // curveTo path3.moveTo( vec2( 0 ) ); path3.curveTo( vec2( 25.0, 0.0 ), vec2( 50.0, 25.0 ), vec2( 50.0, 50.0 ) ); // arc & arcTo // path4.moveTo( zero<vec2>() ); // path4.arc( vec2( 25.0, 25.0 ), 25.0, 0.0, glm::pi<float> ); path4.arc( vec2( 25.0, 25.0 ), 25.0, 0.0, M_PI ); path5.moveTo( vec2( 0.0, 0.0 ) ); // end point, tangent position, radius path5.arcTo( vec2( 50.0, 50.0 ), vec2( 50.0, 0.0 ), 25.0 ); // path for contains path6.moveTo( vec2( 0.0, 0.0 ) ); path6.quadTo( vec2( 80.0, 30.0), vec2( 100, 50) ); path6.quadTo( vec2( 180.0, 50.0), vec2( 210.0, 20.0) ); path6.quadTo( vec2( 270.0, 10.0), vec2( 280.0, 100.0) ); path6.quadTo( vec2( 200.0, 150.0), vec2( 140.0, 100.0) ); path6.quadTo( vec2( 100.0, 150.0), vec2( 50.0, 80.0) ); path6.close(); // points to look for intersection for( int i = 0; i < 50; i++ ) { auto bounds = path6.calcBoundingBox(); std::pair<vec2, vec2> pair; pair.first = vec2( randFloat( bounds.x1 , bounds.x2), randFloat( bounds.y1, bounds.y2 ) ); pair.second = vec2( randFloat( -1, 1), randFloat( -1, 1) ); intersectPts.push_back( pair ); } // move over a bit and dot affine matrix copies and rotate { int amount = 10; for( int i = 0; i < amount; i++ ){ MatrixAffine2<float> affineMtrx; affineMtrx.scale( 0.3 ); affineMtrx.rotate( ( ( M_PI * 2) / 8 ) * i ); auto pathCopy = path2.transformCopy( affineMtrx ); pathCaches.emplace_back( pathCopy ); } } // snowflake using }
void CanvasContext::moveTo(float x, float y) { Path2d p; p.moveTo(x, y); paths.push_back(p); }
Rectf getBounds() const { return mPath.calcPreciseBoundingBox(); }
void GesichtertauschApp::draw() { glClearColor( 0, 0, 0, 1.0 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); if ( ! mCameraTexture ) { return; } // gl::setMatricesWindow( getWindowSize() ), gl::setMatricesWindow(WINDOW_WIDTH, WINDOW_HEIGHT); gl::enableAlphaBlending(); glScalef(-1.0, 1.0, 1.0); glTranslatef(-WINDOW_WIDTH, 0, 0); /* shader */ // TODO make this more opt'd if (ENABLE_SHADER) { mShader.bind(); const int STEPS = 32; float mThresholds[STEPS];// = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; for (int i=0; i < STEPS; ++i) { mThresholds[i] = float(i) / float(STEPS - 1); } mShader.uniform("thresholds", mThresholds, STEPS); mShader.uniform( "tex0", 0 ); } /* draw the webcam image */ gl::color( BACKGROUND_IMAGE_COLOR ); gl::draw( mCameraTexture, Rectf(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT) ); mCameraTexture.disable(); /* normalize texture coordinates */ Vec2f mNormalizeScale = Vec2f(1.0 / float(WINDOW_WIDTH), 1.0 / float(WINDOW_HEIGHT)); glMatrixMode(GL_TEXTURE); glPushMatrix(); glScalef(mNormalizeScale.x, mNormalizeScale.y, 1.0); glMatrixMode(GL_MODELVIEW); /* draw orgiginal faces */ if (mEntities.size() < 2) { gl::enableAlphaBlending(); mCameraTexture.enableAndBind(); for( vector<FaceEntity>::const_iterator mIter = mEntities.begin(); mIter != mEntities.end(); ++mIter ) { drawEntity(*mIter, FACE_COLOR_UNO); } mCameraTexture.disable(); gl::disableAlphaBlending(); } /* HACK // swap faces */ mCameraTexture.enableAndBind(); if (mEntities.size() >= 2) { const FaceEntity A = mEntities[0]; const FaceEntity B = mEntities[1]; if (A.visible && B.visible) { FaceEntity mEntityA = FaceEntity(); FaceEntity mEntityB = FaceEntity(); mEntityA.border = B.border; mEntityB.border = A.border; mEntityA.slice = A.slice; mEntityB.slice = B.slice; mEntityA.visible = A.visible; mEntityB.visible = B.visible; mEntityA.ID = A.ID; mEntityB.ID = B.ID; drawEntity(mEntityA, FACE_COLOR_DUO); drawEntity(mEntityB, FACE_COLOR_DUO); } } /* restore texture coordinates */ glMatrixMode(GL_TEXTURE); glPopMatrix(); glMatrixMode(GL_MODELVIEW); mCameraTexture.disable(); /* shader */ if (ENABLE_SHADER) { mShader.unbind(); } /* mask */ float MASK_LEFT_TOP = 1; float MASK_LEFT_BOTTOM = 1; float MASK_RIGHT_TOP = 1; float MASK_RIGHT_BOTTOM = 1; gl::color(0, 0, 0, 1); Path2d mPathLeft; mPathLeft.moveTo(0, 0); mPathLeft.lineTo(MASK_LEFT_TOP, 0); mPathLeft.lineTo(MASK_LEFT_BOTTOM, WINDOW_HEIGHT); mPathLeft.lineTo(0, WINDOW_HEIGHT); mPathLeft.close(); gl::drawSolid(mPathLeft); Path2d mPathRight; mPathRight.moveTo(WINDOW_WIDTH, 0); mPathRight.lineTo(WINDOW_WIDTH-MASK_RIGHT_TOP, 0); mPathRight.lineTo(WINDOW_WIDTH-MASK_RIGHT_BOTTOM, WINDOW_HEIGHT); mPathRight.lineTo(WINDOW_WIDTH, WINDOW_HEIGHT); mPathRight.close(); gl::drawSolid(mPathRight); /* draw entity IDs */ const bool DRAW_ENTITY_ID = false; if (DRAW_ENTITY_ID) { for( vector<FaceEntity>::const_iterator mIter = mEntities.begin(); mIter != mEntities.end(); ++mIter ) { const FaceEntity mEntity = *mIter; std::stringstream mStr; mStr << mEntity.ID; gl::drawStringCentered(mStr.str(), mEntity.border.getCenter(), Color(1, 0, 0), mFont); } } /* gooey */ mGui->draw(); }
BlocksInfo blocks(const std::vector<Path2d>& boundaries, double side, bool oddeven) { std::vector<Path2d> paths; std::vector<Path2d> grid; int h, w; int x0, y0, x1, y1; P2d p0, p1, po, pa, pb; for (int j=0,m=boundaries.size(); j<m; j++) { Path2d path = boundaries[j] / side; path.boundingBox(p0, p1, j!=0); paths.push_back(path); } x0 = int(floor(p0.x - side)); y0 = int(floor(p0.y - side)); x1 = int(ceil(p1.x + side)); y1 = int(ceil(p1.y + side)); po.x = x0; po.y = y0; for (int j=0,m=paths.size(); j<m; j++) { paths[j] -= po; /* align to image origin */ } w = x1 - x0; h = y1 - y0; Image<int> image(w, h); image.fastBox(0, 0, w, h, 0); /* zero fill */ if (oddeven) { polyFill(image, 1, paths); polyDraw(image, 1, paths); } else { /* vogliamo solo marcare le aree coperte dai perimetri esterni * senza considerare eventuali fori */ std::vector<Path2d> spath(1); for (int j=0,m=paths.size(); j<m; j++) { spath[0] = paths[j]; polyFill(image, 1, spath); polyDraw(image, 1, spath); } } paths.clear(); int num=0; for(int x=-1; x<w; ++x) { for (int y=-1; y<h; ++y) { if (image.pixel(x, y, 0) != 0) { std::vector<P2d> points; pa.x = (x0 + x) * side; pa.y = (y0 + y) * side; pb.x = pa.x; pb.y = pa.y + side; points.push_back(pa); points.push_back(pb); pa.x = pb.x + side; pa.y = pb.y; points.push_back(pa); pb.x = pa.x; pb.y = pa.y - side; points.push_back(pb); pa.x = pb.x - side; pa.y = pb.y; points.push_back(pa); Path2d block(points); grid.push_back(block); num++; } /* due pixel accanto diversi*/ if (image.pixel(x, y, 0) != image.pixel(x+1, y, 0)) { std::vector<P2d> points; pa.x = (x0 + x + 1) * side; pa.y = (y0 + y) * side; pb.x = pa.x; pb.y = pa.y + side; points.push_back(pa); points.push_back(pb); Path2d block(points); paths.push_back(block); /* due pixel uno sopra l'altro diversi*/ } if (image.pixel(x, y, 0) != image.pixel(x, y+1, 0)) { std::vector<P2d> points; pa.x = (x0 + x) * side; pa.y = (y0 + y + 1) * side; pb.x = pa.x + side; pb.y = pa.y; points.push_back(pa); points.push_back(pb); Path2d block(points); paths.push_back(block); } } } BlocksInfo iblocks(num, paths, grid); return iblocks; }
void Triangulator::addPath( const Path2d &path, float approximationScale ) { vector<vec2> subdivided = path.subdivide( approximationScale ); tessAddContour( mTess.get(), 2, &subdivided[0], sizeof(float) * 2, (int)subdivided.size() ); }