ofPolyline ofGetResampledSpacing(const ofPolyline& polyline, float spacing) { ofPolyline result; // if more properties are added to ofPolyline, we need to copy them here result.setClosed(polyline.getClosed()); float totalLength = 0; int curStep = 0; int lastPosition = polyline.size() - 1; if(polyline.getClosed()) { lastPosition++; } for(int i = 0; i < lastPosition; i++) { bool repeatNext = i == (int) (polyline.size() - 1); const ofPoint& cur = polyline[i]; const ofPoint& next = repeatNext ? polyline[0] : polyline[i + 1]; ofPoint diff = next - cur; float curSegmentLength = diff.length(); totalLength += curSegmentLength; while(curStep * spacing <= totalLength) { float curSample = curStep * spacing; float curLength = curSample - (totalLength - curSegmentLength); float relativeSample = curLength / curSegmentLength; result.addVertex(cur.getInterpolated(next, relativeSample)); curStep++; } } return result; }
//-------------------------------------------------------------- void drawWithNormals(const ofPolyline& polyline, int zeroX, int zeroY, bool drawContours) { for (int i = 0; i < (int) polyline.size(); i++) { bool repeatNext = i == (int) polyline.size() - 1; const ofPoint& cur = polyline[i]; const ofPoint& next = repeatNext ? polyline[0] : polyline[i + 1]; float angle = atan2f(next.y - cur.y, next.x - cur.x) * RAD_TO_DEG; float distance = cur.distance(next); if (repeatNext) { ofSetColor(255, 0, 255); } glPushMatrix(); glTranslatef(cur.x + zeroX, cur.y + zeroY, 0); ofRotate(angle); // ofLine(0, 0, 0, distance); ofLine(0, 0, distance, 0); ofLine(0, distance, distance, distance); if (drawContours) { for (int i = distance; i < distance * 3; i += 5) { ofLine(0, 0, i, 0); ofLine(0, i, i, i); } } glPopMatrix(); } }
void contourToConvexHull(ofPolyline &src, ofPolyline &dst) { dst.clear(); vector<hPoint> P(src.size()); for(int i = 0; i < src.size(); i++) { P[i].x = src[i].x; P[i].y = src[i].y; } int n = src.size(), k = 0; vector<hPoint> H(2*n); // Sort points lexicographically sort(P.begin(), P.end()); // Build lower hull for (int i = 0; i < n; i++) { while (k >= 2 && cross(H[k-2], H[k-1], P[i]) <= 0) k--; H[k++] = P[i]; } // Build upper hull for (int i = n-2, t = k+1; i >= 0; i--) { while (k >= t && cross(H[k-2], H[k-1], P[i]) <= 0) k--; H[k++] = P[i]; } H.resize(k); for(int i = 0; i < H.size(); i++) { dst.addVertex(H[i].x + 500, H[i].y); } }
vector<cv::Point2f> toCv(const ofPolyline& polyline) { vector<cv::Point2f> contour(polyline.size()); for(int i = 0; i < polyline.size(); i++) { contour[i].x = polyline[i].x; contour[i].y = polyline[i].y; } return contour; }
vector<cv::Point2f> toCv(const ofPolyline& polyline) { // if polyline.getVertices() were const, this could wrap toCv(vec<vec2f>) vector<cv::Point2f> contour(polyline.size()); for(int i = 0; i < polyline.size(); i++) { contour[i].x = polyline[i].x; contour[i].y = polyline[i].y; } return contour; }
// Backported from oF-dev branch on github float ShapeUtils::polylineArea(const ofPolyline &poly) { if (poly.size() < 2) return 0; float area = 0; for (int i = 0; i < (int) poly.size() - 1; i++) { area += poly[i].x * poly[i+1].y - poly[i+1].x * poly[i].y; } area += poly[poly.size()-1].x * poly[0].y - poly[0].x * poly[poly.size()-1].y; return 0.5 * area; }
void ropeMesh::draw(ofPolyline stroke){ if (stroke.hasChanged()) { mesh.clear(); mesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP); vector < ofPoint > pts = stroke.getVertices(); for (int i = 0; i < pts.size(); i++){ int i_m_1 = MAX(i-1,0); int i_p_1 = MIN(i+1, pts.size()-1); ofPoint pta = pts[i_m_1]; ofPoint ptb = pts[i]; ofPoint ptc = pts[i_p_1]; ofPoint diff = ptc - pta; float angle = atan2(diff.y, diff.x); angle += PI/2; float width = 3; //diff.length(); ofPoint offsetA; offsetA.x = ptb.x + width * cos(angle); offsetA.y = ptb.y + width * sin(angle); ofPoint offsetB; offsetB.x = ptb.x - width * cos(angle); offsetB.y = ptb.y - width * sin(angle); ofSetColor(123,94,65); ofLine(offsetA, offsetB); mesh.addVertex(offsetA); mesh.addVertex(offsetB); } ofSetColor(197,155,108); ofFill(); mesh.draw(); ofSetRectMode(OF_RECTMODE_CENTER); if (stroke.size()>0) { top[num].draw(stroke.getVertices()[stroke.size()-1], width, height); } } }
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); } }
// Backported from oF-dev branch on github ofPoint ShapeUtils::getCentroid2D(const ofPolyline &poly) { ofPoint centroid; for(int i=0;i<(int)poly.size()-1;i++){ centroid.x += (poly[i].x + poly[i+1].x) * (poly[i].x*poly[i+1].y - poly[i+1].x*poly[i].y); centroid.y += (poly[i].y + poly[i+1].y) * (poly[i].x*poly[i+1].y - poly[i+1].x*poly[i].y); } centroid.x += (poly[poly.size()-1].x + poly[0].x) * (poly[poly.size()-1].x*poly[0].y - poly[0].x*poly[poly.size()-1].y); centroid.y += (poly[poly.size()-1].y + poly[0].y) * (poly[poly.size()-1].x*poly[0].y - poly[0].x*poly[poly.size()-1].y); float area = ShapeUtils::polylineArea(poly); centroid.x /= (6*area); centroid.y /= (6*area); return centroid; }
glmPolyline toGlm(const ofPolyline &_poly){ glmPolyline poly; for (int i = 0; i < _poly.size(); i++) { poly.add(toGlm(_poly[i])); } return poly; }
//-------------------------------------------------------------- // Code by Theo from URL above //-------------------------------------------------------------- // http://www.openframeworks.cc/forum/viewtopic.php?f=9&t=1443 //-------------------------------------------------------------- bool phdPointInsidePolygon(ofPolyline & _points, float px, float py) { int N = _points.size(); if (N == 0) return false; int counter = 0; int i; double xinters; ofPoint p1, p2; p1 = _points[0]; for (int i = 1; i <= N; i++) { p2 = _points[i % N]; if (py > MIN(p1.y,p2.y)) { if (py <= MAX(p1.y,p2.y)) { if (px <= MAX(p1.x,p2.x)) { if (p1.y != p2.y) { xinters = (py-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x; if (p1.x == p2.x || px <= xinters) counter++; } } } } p1 = p2; } if (counter % 2 == 0) return false; else return true; }
void ofxPolyline2Mesh::updateShape(const ofPolyline &polyline) { shape.clear(); norm.clear(); for (int i = 0; i < polyline.size(); i++) { shape.push_back(polyline[i]); } if (polyline.isClosed()) shape.push_back(polyline[0]); const ofVec3f V(0, 0, -1); for (int i = 0; i < shape.size() - 1; i++) { const ofVec3f& p1 = shape[i]; const ofVec3f& p2 = shape[i + 1]; const ofVec3f& n21 = (p2 - p1).normalized(); norm.push_back(n21.crossed(V)); } { const ofVec3f& p1 = shape[shape.size() - 1]; const ofVec3f& p2 = shape[0]; const ofVec3f& n21 = (p2 - p1).normalized(); norm.push_back(n21.crossed(V)); } current_segments.resize(shape.size()); last_segments.resize(shape.size()); }
ofRectangle ofGetBoundingBox(const ofPolyline& polyline) { ofRectangle box; int n = polyline.size(); if(n > 0) { const ofPoint& first = polyline[0]; // inititally, use width and height as max x and max y box.set(first.x, first.y, first.x, first.y); for(int i = 0; i < n; i++) { const ofPoint& cur = polyline[i]; if(cur.x < box.x) { box.x = cur.x; } if(cur.x > box.width) { box.width = cur.x; } if(cur.y < box.y) { box.y = cur.y; } if(cur.y > box.height) { box.height = cur.y; } } // later, we make width and height relative box.width -= box.x; box.height -= box.y; } return box; }
ofPolyline ofGetSmoothed(const ofPolyline& polyline, int smoothingSize, float smoothingShape) { ofPolyline result = polyline; if(!polyline.getClosed()) { ofLog( OF_LOG_ERROR, "ofSmooth() currently only supports closed ofPolylines." ); return polyline; } // precompute weights and normalization vector<float> weights; float weightSum = 0; weights.push_back(1); // center weight // side weights for(int i = 1; i <= smoothingSize; i++) { float curWeight = ofMap(i, 0, smoothingSize, 1, smoothingShape); weights.push_back(curWeight); weightSum += curWeight; } float weightNormalization = 1 / (1 + 2 * weightSum); // use weights to make weighted averages of neighbors int n = polyline.size(); for(int i = 0; i < n; i++) { for(int j = 1; j <= smoothingSize; j++) { int leftPosition = (n + i - j) % n; int rightPosition = (i + j) % n; const ofPoint& left = polyline[leftPosition]; const ofPoint& right = polyline[rightPosition]; result[i] += (left + right) * weights[j]; } result[i] *= weightNormalization; } return result; }
// // send ofPolyline to laser cutter // bool ofxEpilog::send(ofPolyline vector_vertexes) { if(vector_vertexes.size() == 0) return false; ofBuffer buffer; buffer.append(createPayloadHeader(getMachineProfile(), getOutputConfig())); // end raster part regardless of it's empty buffer.append(PCL_RASTER_END); // begin HPGL commands (vector part) buffer.append(HPGL_START); buffer.append(HPGL_VECTOR_INIT + HPGL_CMD_DELIMITER); // create vector part and append to the buffer buffer.append(createPayloadVectorBody(vector_vertexes, getOutputConfig())); if(!keep_alive) buffer.append(createPayloadFooter()); // end the session if(pjl_file.get() != NULL) pjl_file->writeFromBuffer(buffer); return tcp_client.sendRaw(buffer); }
void testApp::oscSendContour(int label, const ofPolyline &polyline){ ofxOscMessage m; stringstream ss; ss<<"/contour"; m.setAddress(ss.str()); int size = polyline.size(); m.addIntArg(label); m.addIntArg(size); cout<<"contour: "<<label<<" size: "<<size<<endl; const ofRectangle& rect = polyline.getBoundingBox(); m.addIntArg(rect.getTopLeft().x); m.addIntArg(rect.getTopLeft().y); m.addIntArg(rect.getBottomRight().x); m.addIntArg(rect.getBottomRight().y); ofPolyline newLine = polyline.getResampledByCount(100); cout<<"resized to "<<newLine.size()<<endl; // newLine.draw(); if(bSendContours){ const vector<ofPoint> points = newLine.getVertices(); for(int i=0; i< newLine.size(); i++){ m.addFloatArg(points[i].x); m.addFloatArg(points[i].y); } } sender.sendMessage(m); }
bool ShapeUtils::isRectangle(const ofPolyline &poly, float angle) { if (poly.size() != 4) { return false; } float delta = cos((90 - angle) * PI / 180); // Make sure it's a rectangle ofVec2f top = ofVec2f(poly[1].x - poly[0].x, poly[1].y - poly[0].y); ofVec2f right = ofVec2f(poly[2].x - poly[1].x, poly[2].y - poly[1].y); ofVec2f bottom = ofVec2f(poly[3].x - poly[2].x, poly[3].y - poly[2].y); ofVec2f left = ofVec2f(poly[0].x - poly[3].x, poly[0].y - poly[3].y); top.normalize(); right.normalize(); bottom.normalize(); left.normalize(); bool isRect = abs(top.dot(right)) < delta && abs(right.dot(bottom)) < delta && abs(bottom.dot(left)) < delta && abs(left.dot(top)) < delta; return isRect; }
// Backported from oF-dev branch on github bool ShapeUtils::inside(const ofPolyline &polyline, float x, float y) { int counter = 0; int i; double xinters; ofPoint p1,p2; int N = polyline.size(); if (N == 0) { return false; } p1 = polyline[0]; for (i=1;i<=N;i++) { p2 = polyline[i % N]; if (y > MIN(p1.y,p2.y)) { if (y <= MAX(p1.y,p2.y)) { if (x <= MAX(p1.x,p2.x)) { if (p1.y != p2.y) { xinters = (y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x; if (p1.x == p2.x || x <= xinters) counter++; } } } } p1 = p2; } if (counter % 2 == 0) return false; else return true; }
// code example referenced from 3d/cameraRibbonExample ofMesh ofApp::polylineToRibbonMesh(ofPolyline& polyline, float thickness) { ofMesh mesh; mesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP); for(int i = 1; i < polyline.size(); i++){ //find this point and the next point ofVec3f thisPoint = polyline[i-1]; ofVec3f nextPoint = polyline[i]; //get the direction from one to the next. //the ribbon should fan out from this direction ofVec3f direction = (nextPoint - thisPoint); //get the distance from one point to the next //float distance = direction.length(); //get the normalized direction. normalized vectors always have a length of one //and are really useful for representing directions as opposed to something with length ofVec3f unitDirection = direction.normalized(); //find both directions to the left and to the right ofVec3f toTheLeft = unitDirection.getRotated(-90, ofVec3f(0,0,1)); ofVec3f toTheRight = unitDirection.getRotated(90, ofVec3f(0,0,1)); //calculate the points to the left and to the right //by extending the current point in the direction of left/right by the length ofVec3f leftPoint = thisPoint+toTheLeft * thickness; ofVec3f rightPoint = thisPoint+toTheRight * thickness; // fill mesh mesh.addVertex(leftPoint); mesh.addVertex(rightPoint); // draw the end? same orintation as previous // only need this if the end needs to join to the beginning if(i == polyline.size()-1) { ofVec3f firstLeft = mesh.getVertex(0); ofVec3f firstRight = mesh.getVertex(1); mesh.addVertex(firstLeft); mesh.addVertex(firstRight); } } return mesh; }
int phdPointOverVertex(ofPolyline & _points, double px, double py) { for(int i = 0; i < _points.size(); i++) { if(fabs(_points[i].x - px) < 5 && fabs(_points[i].y - py) < 5) { return i; } } return -1; }
//---------------------------------------- void ofxBox2dEdge::addVertexes(ofPolyline &polyline) { for (int i=0; i<polyline.size(); i++) { ofPolyline::addVertex(polyline[i].x, polyline[i].y); } // Temporary hack to ensure it's flagged as changed, until we // switch to OF 0.8.0. setClosed(isClosed()); }
//---------------------------------------------------------- void ofTessellator::tessellateToPolylines( const ofPolyline& src, ofPolyWindingMode polyWindingMode, vector<ofPolyline>& dstpoly, bool bIs2D){ if (src.size() > 0) { ofPolyline& polyline = const_cast<ofPolyline&>(src); tessAddContour(cacheTess, bIs2D ? 2 : 3, &polyline.getVertices()[0], sizeof(glm::vec3), polyline.size()); } performTessellation( polyWindingMode, dstpoly, bIs2D ); }
// a much faster but less accurate version would check distances to vertices first, // which assumes vertices are evenly spaced ofPoint ofGetClosestPoint(const ofPolyline& polyline, const ofPoint& target, unsigned int* nearestIndex) { if(polyline.size() < 2) { if(nearestIndex != NULL) { nearestIndex = 0; } return target; } float distance = 0; ofPoint nearestPoint; unsigned int nearest = 0; float normalizedPosition = 0; unsigned int lastPosition = polyline.size() - 1; if(polyline.getClosed()) { lastPosition++; } for(int i = 0; i < (int) lastPosition; i++) { bool repeatNext = i == (int) (polyline.size() - 1); const ofPoint& cur = polyline[i]; const ofPoint& next = repeatNext ? polyline[0] : polyline[i + 1]; float curNormalizedPosition = 0; ofPoint curNearestPoint = ofGetClosestPoint(cur, next, target, &curNormalizedPosition); float curDistance = curNearestPoint.distance(target); if(i == 0 || curDistance < distance) { distance = curDistance; nearest = i; nearestPoint = curNearestPoint; normalizedPosition = curNormalizedPosition; } } if(nearestIndex != NULL) { if(normalizedPosition > .5) { nearest++; if(nearest == polyline.size()) { nearest = 0; } } *nearestIndex = nearest; } return nearestPoint; }
void ofCairoRenderer::draw(ofPolyline & poly){ cairo_new_path(cr); for(int i=0;i<(int)poly.size();i++){ cairo_line_to(cr,poly.getVertices()[i].x,poly.getVertices()[i].y); } if(poly.isClosed()) cairo_close_path(cr); cairo_stroke( cr ); }
vector< ofPoint > utility::findClosestPoints(ofPolyline one, ofPolyline two) { float shortestDist = INFINITY; vector< ofPoint > closest; closest.resize(2); for (int i = 0; i < one.size(); ++i) { for (int j = i; j < two.size(); ++j) { float dsquared = ofDistSquared(one[i].x, one[i].y, two[j].x, two[j].y); if(dsquared <= shortestDist) { closest[0] = one[i]; closest[1] = two[j]; } } } return closest; }
//---------------------------------------------------------- void ofGLRenderer::draw(ofPolyline & poly){ // use smoothness, if requested: if (bSmoothHinted) startSmoothing(); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, sizeof(ofVec3f), &poly.getVertices()[0].x); glDrawArrays(poly.isClosed()?GL_LINE_LOOP:GL_LINE_STRIP, 0, poly.size()); // use smoothness, if requested: if (bSmoothHinted) endSmoothing(); }
ofPath testApp::getPathFromPolyline(ofPolyline polyLine) { ofPath path; for (int i=0; i < polyLine.size(); i++) { path.lineTo(polyLine[i]); } return path; }
ofPolyline utility::transform(ofPolyline input, int dx, int dy, float z, int r) { ofPolyline output; for (int i = 0; i < input.size(); ++i) { ofPoint pt = input[i]; float tx = pt.x * z + dx; float ty = pt.y * z + dy; output.addVertex(ofPoint(tx, ty)); } return output; }
//-------------------------------------------------------------- void drawWithNormals(const ofPolyline& polyline) { for(int i=0; i< (int) polyline.size(); i++ ) { bool repeatNext = i == (int)polyline.size() - 1; const ofPoint& cur = polyline[i]; const ofPoint& next = repeatNext ? polyline[0] : polyline[i + 1]; float angle = atan2f(next.y - cur.y, next.x - cur.x) * RAD_TO_DEG; float distance = cur.distance(next); if(repeatNext) { ofSetColor(255, 0, 255); } glPushMatrix(); glTranslatef(cur.x, cur.y, 0); ofRotate(angle); ofDrawLine(0, 0, 0, distance); ofDrawLine(0, 0, distance, 0); glPopMatrix(); } }
ofBuffer ofxEpilog::createPayloadVectorBody(ofPolyline vector_vertexes, OutputConfig &out_conf) { ofBuffer buffer; // add vector vertexes if(vector_vertexes.size() > 0) { for(int i=0; i<vector_vertexes.size(); i++) { // update parameters of vector process buffer.append(createPayloadVectorParams(out_conf)); if(out_conf.enable_laser_emit && i != 0) buffer.append(HPGL_VECTOR_PEN_DOWN); // PD else buffer.append(HPGL_VECTOR_PEN_UP); // PU // convert to HPGL vector format from ofPolyline (unit:inch) ofPoint p = vector_vertexes[i]; buffer.append(ofToString( floor((out_conf.dpi/MM_PER_INCH) * p.x) ) + "," + ofToString( floor((out_conf.dpi/MM_PER_INCH) * p.y)) + ";"); } } return buffer; }