void Plant::makeCorner(ofPolyline *line, ofPolyline &l, int i, float angle, float length){ ofVec2f v = l.getTangentAtIndex(i); ofVec2f p = l.getVertices()[i] + v.rotate(angle)*length; ofVec2f v1 = l.getTangentAtIndex(i-1); ofVec2f pp = l.getVertices()[i-1] + v1.rotate(angle)*length; ofVec2f v2 = l.getTangentAtIndex(i+1); ofVec2f pn = l.getVertices()[i+1] + v2.rotate(angle)*length; ofVec2f deltaPP = p - pp; ofVec2f deltaPN = pn - p; float radius = MIN(pp.distance(p)/3, p.distance(pn)/3); ofVec2f rad = deltaPP.normalize()*radius; ofVec2f rad2 = deltaPN.normalize()*radius; ofVec2f b1 = p + (deltaPP-rad); ofVec2f b2 = p + rad2; line->lineTo(b1); line->bezierTo(b1, p, b2); line->lineTo(b2); // debug points // ofSetColor(ofColor::red); // ofDrawCircle(b2, 2); // // ofSetColor(ofColor::yellow); // ofDrawCircle(b1, 2); // ofSetColor(ofColor::blue); // ofDrawCircle(pp, 2); // // ofSetColor(ofColor::green); // ofDrawCircle(pn, 5); }
void Plant::makeStroke(int i, float min, float max, ofPolyline ¢erLine, ofPolyline *line1, ofPolyline *line2 ){ ofVec2f v = centerLine.getTangentAtIndex(i); float length = ofMap(i, 0, centerLine.size()-1, max, min) ; float angle = 90; float hackValue = 0.8; if(i==0 || i == centerLine.size()-1){ ofVec2f p = centerLine.getVertices()[i] + v.rotate(angle)*length*hackValue; ofVec2f v2 = centerLine.getTangentAtIndex(i); ofVec2f p2 = centerLine.getVertices()[i] + v2.rotate(-angle)*length*hackValue; line1->lineTo(p); line2->lineTo(p2); } if(i>0 && i < centerLine.size()-1){ makeCorner(line1, centerLine, i, angle, length); makeCorner(line2, centerLine, i, -angle, length); } if(i == centerLine.size()-1){ ofVec2f v = centerLine.getTangentAtIndex(i); float length = ofMap(i, 0, centerLine.size()-1, min, min) ; ofVec2f _p2 = centerLine.getVertices()[i] + v.rotate(90)*length*hackValue; ofVec2f _p1 = centerLine.getVertices()[i] + v.rotate(180)*length*hackValue; ofVec2f _p3 = _p1 + (_p2 - _p1)/2; ofVec2f _delta = _p2 - _p1; ofVec2f pCenter = _p3 - _delta.getPerpendicular()*min; ofVec2f pLeft = pCenter - _delta/2; ofVec2f pRight = pCenter + _delta/2; line2->bezierTo(_p1, pLeft, pCenter); line1->bezierTo(_p2, pRight, pCenter); // ofSetColor(ofColor::yellow); // ofDrawCircle(p1, 5); // ofSetColor(ofColor::red); // ofDrawCircle(p2, 5); // ofSetColor(ofColor::blueViolet); // ofDrawCircle(p3, 5); // ofSetColor(ofColor::darkMagenta); // ofDrawCircle(pCenter, 5); // ofSetColor(ofColor::lightPink); // ofDrawCircle(pLeft, 5); // ofSetColor(ofColor::lightSkyBlue); // ofDrawCircle(pRight, 5); } }
//-------------------------------------------------------------- void ofApp::draw(){ if(poly.size() < 2) return; ofPushMatrix(); ofTranslate(ofGetWidth()/2, ofGetHeight()/2); ofRotateY(rotAngle); ofSetColor(255, 255, 255); poly.draw(); ofSetColor(0, 255, 0); ofSetRectMode(OF_RECTMODE_CENTER); glPointSize(5); glBegin(GL_POINTS); for(int i=0; i<poly.size(); i++) { ofPoint p = poly[i]; glVertex3f(p.x, p.y, p.z); } glEnd(); for(int i=0; i<poly.size(); i++) { ofPoint p = poly[i]; ofSetColor(255, 0, 0); ofLine(p, p + poly.getTangentAtIndex(i) * 20); ofSetColor(0, 255, 0); ofLine(p, p + poly.getNormalAtIndex(i) * 20); ofSetColor(0, 128, 255); ofLine(p, p + poly.getRotationAtIndex(i) * 20); } float totalLength = poly.getPerimeter(); float totalArea = poly.getArea(); ofPoint nearestPoint = poly.getClosestPoint(ofPoint(mouseX-ofGetWidth()/2, mouseY-ofGetHeight()/2), &nearestIndex); ofPoint nearestDataPoint = poly[nearestIndex]; float lengthAtIndex = poly.getLengthAtIndex(nearestIndex); ofPoint pointAtIndex = poly.getPointAtIndexInterpolated(nearestIndex); ofPoint pointAtLength = poly.getPointAtLength(lengthAtIndex); ofPoint pointAtPercent = poly.getPointAtPercent(lengthAtIndex / totalLength); float indexAtLength = poly.getIndexAtLength(lengthAtIndex); float sinTime = ofMap(sin(ofGetElapsedTimef() * 0.5), -1, 1, 0, 1); float sinIndex = sinTime * (poly.isClosed() ? poly.size() : (poly.size()-1)); // sinTime mapped to indices direct float sinIndexLength = poly.getIndexAtPercent(sinTime); // sinTime mapped to indices based on length float lengthAtIndexSin = poly.getLengthAtIndexInterpolated(sinIndex); ofPoint pointAtIndexSin = poly.getPointAtIndexInterpolated(sinIndex); ofPoint pointAtPercentSin = poly.getPointAtPercent(sinTime); float angleAtIndex = poly.getAngleAtIndex(nearestIndex); float angleAtIndexSin = poly.getAngleAtIndexInterpolated(sinIndex); ofVec3f rotAtIndex = poly.getRotationAtIndex(nearestIndex); ofVec3f rotAtIndexSin = poly.getRotationAtIndexInterpolated(sinIndex); float rotMagAtIndex = rotAtIndex.length(); float rotMagAtIndexSin = rotAtIndexSin.length(); ofVec3f normalAtIndex = poly.getNormalAtIndex(nearestIndex); ofVec3f tangentAtIndexSin = poly.getTangentAtIndexInterpolated(sinIndex); ofVec3f normalAtIndexSin = poly.getNormalAtIndexInterpolated(sinIndex); ofVec3f rotationAtIndexSin = poly.getRotationAtIndexInterpolated(sinIndex); ofNoFill(); ofSetLineWidth(2); ofSetColor(255, 0, 0); ofCircle(nearestPoint, 5); ofSetColor(255, 255, 0); ofCircle(nearestDataPoint, 7); // interpolating on indices { ofPoint p = poly.getPointAtIndexInterpolated(sinIndex); ofSetColor(0, 255, 255); ofCircle(p, 10); ofSetColor(255, 0, 0); ofLine(p, p + poly.getTangentAtIndexInterpolated(sinIndex) * 60); ofSetColor(0, 255, 0); ofLine(p, p + poly.getNormalAtIndexInterpolated(sinIndex) * 60); ofSetColor(0, 128, 255); ofLine(p, p + poly.getRotationAtIndexInterpolated(sinIndex) * 60); } // interpolating on length percentages { ofPoint p = poly.getPointAtIndexInterpolated(sinIndexLength); ofSetColor(255, 0, 255); ofCircle(p, 10); ofSetColor(255, 0, 0); ofLine(p, p + poly.getTangentAtIndexInterpolated(sinIndexLength) * 60); ofSetColor(0, 255, 0); ofLine(p, p + poly.getNormalAtIndexInterpolated(sinIndexLength) * 60); ofSetColor(0, 128, 255); ofLine(p, p + poly.getRotationAtIndexInterpolated(sinIndexLength) * 60); } ofSetColor(255, 255, 255); ofCircle(poly.getCentroid2D(), 20); ofPopMatrix(); stringstream s; s << "Number of points: " << poly.size() << endl; s << "totalLength: " << totalLength << endl; s << endl; s << "nearestIndex: " << nearestIndex << endl; s << "nearestPoint: " << nearestPoint << endl; s << "nearestDataPoint: " << nearestDataPoint << endl; s << endl; s << "lengthAtIndex: " << lengthAtIndex << endl; s << "pointAtIndex: " << pointAtIndex << endl; s << endl; s << "pointAtLength: " << pointAtLength << endl; s << "pointAtPercent: " << pointAtPercent << endl; s << endl; s << "indexAtLength: " << indexAtLength << endl; s << endl; s << "sinTime: " << sinTime << endl; s << "sinIndex: " << sinIndex << endl; s << "sinIndexLength: " << sinIndexLength << endl; s << endl; s << "lengthAtIndexSin: " << lengthAtIndexSin << endl; s << "pointAtIndexSin: " << pointAtIndexSin << endl; s << "pointAtPercentSin: " << pointAtPercentSin << endl; s << endl; s << "angleAtIndex: " << angleAtIndex << endl; s << "angleAtIndexSin: " << angleAtIndexSin << endl; s << endl; s << "rotAtIndex: " << rotAtIndex << endl; s << "rotAtIndexSin: " << rotAtIndexSin << endl; s << endl; s << "rotMagAtIndex: " << rotMagAtIndex << endl; s << "rotMagAtIndexSin: " << rotMagAtIndexSin << endl; s << endl; s << "normalAtIndex: " << normalAtIndex << endl; s << "normalAtIndexSin: " << normalAtIndexSin << endl; ofSetColor(255); ofDrawBitmapString(s.str(), 10, 30); }