Rectangle ImageTransform::getMinAreaRectangle(std::vector<Point>& points) { points = getConvexHull(points); Rectangle res; res.area = -1.f; if (points.size() <= 2) { return res; } int i; for (i = 0; i < points.size() - 2; i++) { Rectangle tmp = getMinAreaRectangle(points[i], points[i+1], points); if (tmp.area > 0) { if (res.area < 0) { res = tmp; } else { if (res.area > tmp.area) { res = tmp; } } } } //now consider the last point and the first point Rectangle tmp = getMinAreaRectangle(points[points.size() - 1], points[0], points); if (tmp.area > 0) { if (res.area < 0) { res = tmp; } else { if (res.area > tmp.area) { res = tmp; } } } return res; }
std::vector<glm::vec3> getConvexHull(const std::vector<glm::vec3> &_pts){ std::vector<glm::vec3> pts; pts.assign(_pts.begin(),_pts.end()); return getConvexHull(pts); }
// http://geomalgorithms.com/a12-_hull-3.html // glmPolyline glmPolyline::get2DConvexHull(){ return glmPolyline( getConvexHull(m_points) ); }
//---------------------------------------- void ofxBox2dPolygon::makeConvexPoly() { ofPolyline convex = getConvexHull(ofPolyline::getVertices()); ofPolyline::clear(); ofPolyline::addVertices(convex.getVertices()); bIsTriangulated = false; }
//-------------------------------------------------------------- update void MonsterScene::update(){ //cout << "body count " << box2d.getBodyCount() << endl; //float scalex = 1; //float scaley = 1; // bDebug = panel.getValueB("DEBUG"); // if(panel.getValueB("REBUILD")) { // createBuildingContour(); // panel.setValueB("REBUILD", 0); // } // panel.update(); box2d.update(); // add some balls if(ballCounter >= 20 && ofGetFrameRate() > 30) { // Add Ball every 20 times for(int i=0; i<(int)ofRandom(1, 5); i++) { float bx = (RM->getWidth()/2) + ofRandom(-20, 20); float by = (100 + ofRandom(-20, 20)); //bx -= ((RM->getWidth() - W)/2); //by -= (RM->getHeight() - H); //MonsterBall bub; shared_ptr<MonsterBall> bub = shared_ptr<MonsterBall> (new MonsterBall()); balls.push_back(bub); balls.back()->initTime = ofGetElapsedTimef(); balls.back()->setPhysics(1.0, 0.93, 0.1); // mass - bounce - friction balls.back()->setup(box2d.getWorld(), bx, by, ofRandom(5, 15)); balls.back()->img = &dotImage; } ballCounter = 0; // 0 - 50 probality to add a ton of particles // ok add a bunch if((int)ofRandom(0, 20) == 10 && timeSinceLastBurst > 30) { for(int i=0; i<(int)ofRandom(20, 100); i++) { float bx = ofRandom(0, RM->getWidth());// ofRandom(-520, 520); float by = 500; //bx -= ((RM->getWidth() - W)/2); //by -= (RM->getHeight() - H); //MonsterBall bub; shared_ptr<MonsterBall> bub = shared_ptr<MonsterBall> (new MonsterBall()); bub->initTime = ofGetElapsedTimef(); bub->setPhysics(1.0, 0.93, 0.1); // mass - bounce - friction bub->setup(box2d.getWorld(), bx, by, ofRandom(5, 35)); bub->img = &dotImage; balls.push_back(bub); } if((int)ofRandom(0, 10) == 5) { for(int i=0; i<(int)ofRandom(80, 100); i++) { float bx = ofRandom(0, RM->getWidth());// ofRandom(-520, 520); float by = 500; //bx -= ((RM->getWidth() - W)/2); //by -= (RM->getHeight() - H); //MonsterBall bub; shared_ptr<MonsterBall> bub = shared_ptr<MonsterBall> (new MonsterBall()); bub->initTime = ofGetElapsedTimef(); bub->setPhysics(1.0, 0.93, 0.1); // mass - bounce - friction bub->setup(box2d.getWorld(), bx, by, ofRandom(5, 6)); bub->img = &dotImage; balls.push_back(bub); } } timeSinceLastBurst = 0; } } timeSinceLastBurst ++; ballCounter ++; // --------------------- particles for(int i = 0; i < monsterParticles.size(); i++) { monsterParticles[i]->update(); } for(int i=monsterParticles.size()-1; i>=0; i--) { // sorry time to go away if(monsterParticles[i]->bDead) { //cout << "------------------------------------------" << endl; monsterParticles[i]->cleanUp(); monsterParticles[i]->destroy(); // 2016; monsterParticles.erase(monsterParticles.begin() + i); } ofPoint mpos = monsterParticles[i]->getPosition(); if(mpos.y > RM->getHeight()) { monsterParticles[i]->bDead = true; } } for(int i=balls.size()-1; i>=0; i--) { ofPoint ps = balls[i]->getPosition(); balls[i]->age = ofGetElapsedTimef() - balls[i]->initTime; balls[i]->alphaPct = ballGlow; //panel.getValueF("BALL_GLOW"); balls[i]->sizePct = ballSizePct; //panel.getValueF("BALL_SIZE_PCT"); if(balls[i]->age > maxBallAge){ // 2016 ///panel.getValueF("BALL_AGE")) { balls[i]->color.a -= 10.0; } if(ps.y > RM->getHeight() || balls[i]->color.a <= 0.0 || ps.x < 0 || ps.x >= RM->getWidth()) { balls[i]->destroy(); balls.erase(balls.begin() + i); } } // --------------------- update the monster contour pnts for (int packetId = 0; packetId < 2; packetId++){ for(int i=0; i<cvData[packetId]->blobs.size(); i++) { int lookID = cvData[packetId]->blobs[i].id; for(int j=monsters.size()-1; j>=0; j--) { // yes we match if(monsters[j].id == lookID && monsters[j].packetId == packetId) { ofPolyline line = cvData[packetId]->blobs[i].blob; for (auto & pt : line){ pt = cvData[packetId]->remapForScreen(packetId == 0 ? SCREEN_LEFT : SCREEN_RIGHT, pt); } //line.flagHasChanged(); ofRectangle newRec = line.getBoundingBox(); // newRec.x *= scalex; // newRec.y *= scaley; // newRec.width *= scalex; // newRec.height *= scaley; /* sclContour.assign(tracker->blobs[i].pts.size(), ofPoint()); for(int e=0; e<tracker->blobs[i].pts.size(); e++) { sclContour[e].x = tracker->blobs[i].pts[e].x * scalex; sclContour[e].y = tracker->blobs[i].pts[e].y * scaley; }*/ // the contour (fixed) line.flagHasChanged(); monsters[j].pos.x = line.getCentroid2D().x; monsters[j].pos.y = line.getCentroid2D().y; monsters[j].rect = newRec; //cout << "adding " << newRec << " " << line.getCentroid2D() << endl; // a simple contour //monsters[j].contourSimple.assign(tracker->blobs[i].pts.size(), ofPoint()); ofPolyline simp; ofPolyline smooth; ofPolyline convex; simp.addVertices(line.getVertices()); smooth.addVertices(line.getVertices()); convex.addVertices(line.getVertices()); simp.simplify(0.5); smooth = smooth.getSmoothed(3); monsters[j].contourSimple = simp.getVertices(); monsters[j].contourSmooth = smooth.getVertices(); monsters[j].contourConvex = getConvexHull(convex.getVertices()).getVertices(); //contourAnalysis.simplify(tracker->blobs[i].pts, monsters[j].contourSimple, 0.50); // a smooth contour //monsters[j].contourSmooth.assign(monsters[j].contourSimple.size(), ofPoint()); //contourAnalysis.smooth(monsters[j].contourSimple, monsters[j].contourSmooth, 0.2); // a convex contour //monsters[j].contourConvex.assign(monsters[j].contourSimple.size(), ofPoint()); //contourAnalysis.convexHull(monsters[j].contourSimple, monsters[j].contourConvex); monsters[j].updateContourPnts(line.getVertices()); } } } } // --------------------- Monsters for(int i = 0; i < monsters.size(); i++) { //monsters[i].SCALE = panel.getValueF("SCALE"); monsters[i].bDebug = bDebug; monsters[i].monsterDelayAge = monsterAge; //panel.getValueF("MONSTER_AGE"); monsters[i].update(); } // --------------------- packet info // if(packet.frameNumber >= 0 && !bGotMyFirstPacket) { // printf("got my first packet - %i\n", packet.frameNumber); // bGotMyFirstPacket = true; // // contourAnalysis.setSize(packet.width, packet.height); // //createBuildingContour(); // } }