//---------------------------------------------------------- void ofPolyline::quadBezierTo(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, int curveResolution){ curveVertices.clear(); for(int i=0; i <= curveResolution; i++){ double t = (double)i / (double)(curveResolution); double a = (1.0 - t)*(1.0 - t); double b = 2.0 * t * (1.0 - t); double c = t*t; double x = a * x1 + b * x2 + c * x3; double y = a * y1 + b * y2 + c * y3; double z = a * z1 + b * z2 + c * z3; points.push_back(ofPoint(x, y, z)); } flagHasChanged(); }
//---------------------------------------------------------- void ofPolyline::curveTo( const ofPoint & to, int curveResolution ){ curveVertices.push_back(to); if (curveVertices.size() == 4){ float x0 = curveVertices[0].x; float y0 = curveVertices[0].y; float z0 = curveVertices[0].z; float x1 = curveVertices[1].x; float y1 = curveVertices[1].y; float z1 = curveVertices[1].z; float x2 = curveVertices[2].x; float y2 = curveVertices[2].y; float z2 = curveVertices[2].z; float x3 = curveVertices[3].x; float y3 = curveVertices[3].y; float z3 = curveVertices[3].z; float t,t2,t3; float x,y,z; for (int i = 0; i < curveResolution; i++){ t = (float)i / (float)(curveResolution-1); t2 = t * t; t3 = t2 * t; x = 0.5f * ( ( 2.0f * x1 ) + ( -x0 + x2 ) * t + ( 2.0f * x0 - 5.0f * x1 + 4 * x2 - x3 ) * t2 + ( -x0 + 3.0f * x1 - 3.0f * x2 + x3 ) * t3 ); y = 0.5f * ( ( 2.0f * y1 ) + ( -y0 + y2 ) * t + ( 2.0f * y0 - 5.0f * y1 + 4 * y2 - y3 ) * t2 + ( -y0 + 3.0f * y1 - 3.0f * y2 + y3 ) * t3 ); z = 0.5f * ( ( 2.0f * z1 ) + ( -z0 + z2 ) * t + ( 2.0f * z0 - 5.0f * z1 + 4 * z2 - z3 ) * t2 + ( -z0 + 3.0f * z1 - 3.0f * z2 + z3 ) * t3 ); points.push_back(ofPoint(x,y,z)); } curveVertices.pop_front(); } flagHasChanged(); }
//---------------------------------------------------------- void ofPolyline::bezierTo( const ofPoint & cp1, const ofPoint & cp2, const ofPoint & to, int curveResolution ){ // if, and only if poly vertices has points, we can make a bezier // from the last point curveVertices.clear(); // the resolultion with which we computer this bezier // is arbitrary, can we possibly make it dynamic? if (size() > 0){ float x0 = points[size()-1].x; float y0 = points[size()-1].y; float z0 = points[size()-1].z; float ax, bx, cx; float ay, by, cy; float az, bz, cz; float t, t2, t3; float x, y, z; // polynomial coefficients cx = 3.0f * (cp1.x - x0); bx = 3.0f * (cp2.x - cp1.x) - cx; ax = to.x - x0 - cx - bx; cy = 3.0f * (cp1.y - y0); by = 3.0f * (cp2.y - cp1.y) - cy; ay = to.y - y0 - cy - by; cz = 3.0f * (cp1.z - z0); bz = 3.0f * (cp2.z - cp1.z) - cz; az = to.z - z0 - cz - bz; for (int i = 0; i < curveResolution; i++){ t = (float)i / (float)(curveResolution-1); t2 = t * t; t3 = t2 * t; x = (ax * t3) + (bx * t2) + (cx * t) + x0; y = (ay * t3) + (by * t2) + (cy * t) + y0; z = (az * t3) + (bz * t2) + (cz * t) + z0; points.push_back(ofPoint(x,y,z)); } } flagHasChanged(); }
//---------------------------------------- void ofxBox2dPolygon::create(b2World * b2dworld) { if(size() <= 3) { ofLog(OF_LOG_NOTICE, "need at least 3 points: %i\n", (int)size()); return; } if (body != NULL) { b2dworld->DestroyBody(body); body = NULL; } // create the body from the world (1) b2BodyDef bd; bd.type = density <= 0.0 ? b2_staticBody : b2_dynamicBody; body = b2dworld->CreateBody(&bd); if(bIsTriangulated) { b2PolygonShape shape; b2FixtureDef fixture; b2Vec2 verts[3]; ofVec2f a, b, c; for (int i=0; i<triangles.size(); i++) { a = triangles[i].a; b = triangles[i].b; c = triangles[i].c; verts[0].Set(a.x/OFX_BOX2D_SCALE, a.y/OFX_BOX2D_SCALE); verts[1].Set(b.x/OFX_BOX2D_SCALE, b.y/OFX_BOX2D_SCALE); verts[2].Set(c.x/OFX_BOX2D_SCALE, c.y/OFX_BOX2D_SCALE); shape.Set(verts, 3); fixture.density = density; fixture.restitution = bounce; fixture.friction = friction; fixture.shape = &shape; body->CreateFixture(&fixture); } } else { makeConvexPoly(); vector<ofPoint> pts = ofPolyline::getVertices(); vector<b2Vec2>verts; for (int i=0; i<MIN((int)pts.size(), b2_maxPolygonVertices); i++) { verts.push_back(screenPtToWorldPt(pts[i])); } b2PolygonShape shape; shape.Set(&verts[0], verts.size()-1); fixture.shape = &shape; fixture.density = density; fixture.restitution = bounce; fixture.friction = friction; body->CreateFixture(&fixture); } vector<ofPoint> pts = ofPolyline::getVertices(); mesh.clear(); ofPath path; ofPoint center = getCentroid2D(); for (int i=0; i<pts.size(); i++) { ofPoint p(pts[i].x, pts[i].y); p -= center; path.lineTo(p); } mesh = path.getTessellation(); mesh.setUsage(GL_STATIC_DRAW); flagHasChanged(); alive = true; }
//---------------------------------------------------------- void ofPolyline::setClosed( bool tf ) { bClosed = tf; flagHasChanged(); }
//---------------------------------------------------------- void ofPolyline::resize(size_t size){ points.resize(size); flagHasChanged(); }
//---------------------------------------------------------- ofPoint& ofPolyline::operator[] (int index) { flagHasChanged(); return points[index]; }
//-------------------------------------------------- void ofPolyline::setRightVector(ofVec3f v) { rightVector = v; flagHasChanged(); }
//---------------------------------------------------------- void ofPolyline::insertVertex(const ofPoint &p, int index) { curveVertices.clear(); points.insert(points.begin()+index, p); flagHasChanged(); }
//---------------------------------------------------------- void ofPolyline::addVertices(const ofPoint* verts, int numverts) { curveVertices.clear(); points.insert( points.end(), verts, verts + numverts ); flagHasChanged(); }
//---------------------------------------------------------- void ofPolyline::addVertices(const vector<ofPoint>& verts) { curveVertices.clear(); points.insert( points.end(), verts.begin(), verts.end() ); flagHasChanged(); }
//---------------------------------------------------------- void ofPolyline::addVertex(float x, float y, float z) { curveVertices.clear(); addVertex(ofPoint(x,y,z)); flagHasChanged(); }
//---------------------------------------------------------- void ofPolyline::addVertex(const ofPoint& p) { curveVertices.clear(); points.push_back(p); flagHasChanged(); }
//---------------------------------------------------------- void ofPolyline::arc(const ofPoint & center, float radiusX, float radiusY, float angleBegin, float angleEnd, bool clockwise, int circleResolution){ if(circleResolution<=1) circleResolution=2; setCircleResolution(circleResolution); points.reserve(points.size()+circleResolution); const float epsilon = 0.0001f; const size_t nCirclePoints = circlePoints.size(); float segmentArcSize = M_TWO_PI / (float)nCirclePoints; // convert angles to radians and wrap them into the range 0-M_TWO_PI and float angleBeginRad = wrapAngle(ofDegToRad(angleBegin)); float angleEndRad = wrapAngle(ofDegToRad(angleEnd)); while(angleBeginRad >= angleEndRad) angleEndRad += M_TWO_PI; // determine the directional angle delta float d = clockwise ? angleEndRad - angleBeginRad : angleBeginRad - angleEndRad; // find the shortest angle delta, clockwise delta direction yeilds POSITIVE values float deltaAngle = atan2(sin(d),cos(d)); // establish the remaining angle that we have to work through float remainingAngle = deltaAngle; // if the delta angle is in the CCW direction OR the start and stop angles are // effectively the same adjust the remaining angle to be a be a full rotation if(deltaAngle < 0 || abs(deltaAngle) < epsilon) remainingAngle += M_TWO_PI; ofPoint radii(radiusX,radiusY); ofPoint point; int currentLUTIndex = 0; bool isFirstPoint = true; // special case for the first point while(remainingAngle > 0) { if(isFirstPoint) { // TODO: should this be the exact point on the circle or // should it be an intersecting point on the line that connects two // surrounding LUT points? // // get the EXACT first point requested (for points that // don't fall precisely on a LUT entry) point = ofPoint(cos(angleBeginRad),sin(angleBeginRad)); // set up the get any in between points from the LUT float ratio = angleBeginRad / M_TWO_PI * (float)nCirclePoints; currentLUTIndex = clockwise ? (int)ceil(ratio) : (int)floor(ratio); float lutAngleAtIndex = currentLUTIndex * segmentArcSize; // the angle between the beginning angle and the next angle in the LUT table float d = clockwise ? (lutAngleAtIndex - angleBeginRad) : (angleBeginRad - lutAngleAtIndex); float firstPointDelta = atan2(sin(d),cos(d)); // negative is in the clockwise direction // if the are "equal", get the next one CCW if(abs(firstPointDelta) < epsilon) { currentLUTIndex = clockwise ? (currentLUTIndex + 1) : (currentLUTIndex - 1); firstPointDelta = segmentArcSize; // we start at the next lut point } // start counting from the offset remainingAngle -= firstPointDelta; isFirstPoint = false; } else { point = ofPoint(circlePoints[currentLUTIndex].x,circlePoints[currentLUTIndex].y); if(clockwise) { currentLUTIndex++; // go to the next LUT point remainingAngle -= segmentArcSize; // account for next point // if the angle overshoots, then the while loop will fail next time } else { currentLUTIndex--; // go to the next LUT point remainingAngle -= segmentArcSize; // account for next point // if the angle overshoots, then the while loop will fail next time } } // keep the current lut index in range if(clockwise) { currentLUTIndex = currentLUTIndex % nCirclePoints; } else { if(currentLUTIndex < 0) currentLUTIndex = nCirclePoints + currentLUTIndex; } // add the point to the poly line point = point * radii + center; points.push_back(point); // if the next LUT point moves us past the end angle then // add a a point a the exact end angle and call it finished if(remainingAngle < epsilon) { point = ofPoint(cos(angleEndRad),sin(angleEndRad)); point = point * radii + center; points.push_back(point); remainingAngle = 0; // call it finished, the next while loop test will fail } } flagHasChanged(); }
//---------------------------------------------------------- void ofPolyline::clear() { setClosed(false); points.clear(); curveVertices.clear(); flagHasChanged(); }
//---------------------------------------------------------- vector<ofPoint> & ofPolyline::getVertices(){ flagHasChanged(); return points; }