void BlockEdgeDetectorT::getContoursLeftRight(cv::Mat binaryImage, vector<cv::Point2f>& contour) { cv::Mat img = binaryImage; int imgwidth = img.cols; int imgheight = img.rows; //边界追踪 cv::Point startpoint; //寻找第一个点 for (int i = 0; i < imgheight; i++)//行 { bool flag = 0; //循环查找边界 for (int j = imgwidth - 1; j > 0; j--)//列 { if (img.ptr<uchar>(i)[j] > 0) { startpoint.y = i; startpoint.x = j; flag = 1; break; } } if (flag) break; } contour.clear(); contour.push_back(startpoint); cv::Point v[8]; v[0] = cv::Point(-1, -1);//左上 v[1] = cv::Point(0, -1);//上 v[2] = cv::Point(1, -1);//右上 v[3] = cv::Point(1, 0);//右 v[4] = cv::Point(1, 1);//右下 v[5] = cv::Point(0, 1);//下 v[6] = cv::Point(-1, 1);//左下 v[7] = cv::Point(-1, 0);//左 while (true) { cv::Point lastpoint(contour[contour.size() - 1]); cv::Point lastlastpoint = lastpoint; if (contour.size() > 1) lastlastpoint = contour[contour.size() - 2]; //追到边界时退出 if (lastpoint.x == 0 || lastpoint.x == (imgwidth - 1) || lastpoint.y == (imgheight - 1)) break; //寻找上一点的右边那一点(八邻域范围) int start = 0; for (int i = 0; i < 8; i++) { if ((lastpoint + v[i]) == lastlastpoint) { if (i == 7) start = 0; else start = i + 1; break; } } int count = 0; bool flag = 0;//当取到v[7]时,表示边界追踪开始往左,则退出。 while (true) { int i = count + start; if (i >= 8) i -= 8; cv::Point nextpoint = lastpoint + v[i]; if (//nextpoint != lastlastpoint && nextpoint.x >= 0 && nextpoint.y >= 0 && nextpoint.x < imgwidth && nextpoint.y < imgheight && img.ptr<uchar>(nextpoint.y)[nextpoint.x] > 0) { if (i == 7) flag = 1; contour.push_back(nextpoint); break; } count++; if (count >= 8) break; } if (flag) break; } //平滑滤波 //for (size_t i = 1; i < contour.size() - 1; i++) //{ // contour[i].x = (contour[i - 1].x + contour[i + 1].x) / 2; // contour[i].y = (contour[i - 1].y + contour[i + 1].y) / 2; //} //for (size_t i = 1; i < contour.size() - 1; i++) //{ // contour[i].x = (contour[i - 1].x + contour[i + 1].x) / 2; // contour[i].y = (contour[i - 1].y + contour[i + 1].y) / 2; //} //for (int i = 0; i < contour.size(); i++) //{ // contour[i].y = 30 + contour[i].y - ((int)(p_block->UpLine.k*(i - 0)) + contour[0].y); //} #ifdef BED_OUTPUT_DEBUG_INFO //验证绘图 cv::Mat draw(imgheight, imgwidth, CV_8U, cv::Scalar(0)); for (int i = 0; i < contour.size(); i++) { draw.ptr<uchar>((int)contour[i].y)[(int)contour[i].x] = 255; } #endif int s = contour.size(); }
// splits points with more than 7 neibs void Mesh::splitVertex() { for (int i = 0; i < (int)pts.size(); i++){ Vertex &p = pts[i]; int n1 = p.neib.size(); if( n1 <= 7 ) continue; int n2 = n1/2; n1 = n1 - n2; sortNeigbor(i); const Vertex &p2 = pts[p.neib[0]]; // double size = sizeFace(p.x, p.y); double size = Metric::distance(p.x, p.y, p2.x, p2.y); addVertex(p.x+0.1*size, p.y); Vertex &pv = pts.back(); int vert = lastpoint(); pv.neib.push_back(-1); for (const int nei : p.neib) { Vertex &pn = pts[nei]; if (!pn.skip_neib) { pn.neib.clear(); pn.neib.push_back(-1); } } int lab = -1; for(int j = 0; j < n1 - 1; j++) { Triangle &tr = tri[p.neibTria[j]]; if (lab == -1) lab = tr.label; if (lab != tr.label) throw std::logic_error("aniAFT: different materials inside region"); changeTria(p.neibTria[j], p.neib[j+1], p.neib[j], i); } for(int j = n1; j < n1 + n2 - 1; j++) { Triangle &tr = tri[p.neibTria[j]]; if (lab != tr.label) throw std::logic_error("aniAFT: different materials inside region"); changeTria(p.neibTria[j], p.neib[j+1], p.neib[j], vert); } { int it = p.neibTria[n1 - 1]; Triangle &tr = tri[it]; if (lab != tr.label) throw std::logic_error("aniAFT: different materials inside region"); changeTria(it, p.neib[n1-1], i, vert); } { int it = p.neibTria[n1 + n2 - 1]; Triangle &tr = tri[it]; if (lab != tr.label) throw std::logic_error("aniAFT: different materials inside region"); changeTria(it, p.neib[n1], p.neib[n1-1], vert); } addTria(p.neib[n1+n2-1], vert, i, lab); addTria(p.neib[n1+n2-1], i, p.neib[0],lab); } calcNeigTria(); calcNeigbor(); for(int i=0; i<5; i++) smoothing(); }
// Creatures 2 collision finding void Agent::findCollisionInDirection(unsigned int i, class MetaRoom *m, Point src, int &dx, int &dy, Point &deltapt, double &delta, bool &collided, bool followrooms) { src.x = (int)src.x; src.y = (int)src.y; if (m->wraparound()) { if (src.x > m->x() + m->width() || (dx > 0 && src.x == m->x() + m->width())) src.x -= m->width(); else if (src.x < m->x() || (dx < 0 && src.x == m->x())) src.x += m->width(); } // TODO: caching rooms affects behaviour - work out if that's a problem shared_ptr<Room> room = roomcache[i].lock(); if (!room || !room->containsPoint(src.x, src.y)) { room = bestRoomAt(src.x, src.y, i, m, shared_ptr<Room>()); roomcache[i] = room; } if (!room) { // out of room system if (!displaycore) unhandledException(boost::str(boost::format("out of room system at (%f, %f)") % src.x % src.y), false); falling = false; displaycore = true; return; } int lastdirection = 0; bool steep = abs(dy) > abs(dx); int signdx = dx < 0 ? -1 : 1; int signdy = dy < 0 ? -1 : 1; Line l(Point(0,0),Point(dx,dy)); Point lastpoint(0,0); Vehicle *vehicle = 0; if (invehicle) vehicle = dynamic_cast<Vehicle *>(invehicle.get()); for (int loc = 0; loc <= abs(steep ? dy : dx); loc++) { Point p = steep ? l.pointAtY(loc*signdy) : l.pointAtX(loc*signdx); p.x = (int)p.x; p.y = (int)p.y; if (vehicle) { if (src.x + p.x < vehicle->x + vehicle->cabinleft) { lastdirection = 0; collided = true; break; } if (src.x + p.x > vehicle->x + vehicle->cabinright) { lastdirection = 1; collided = true; break; } if (src.y + p.y < vehicle->y + vehicle->cabintop) { lastdirection = 2; collided = true; break; } if (src.y + p.y > vehicle->y + vehicle->cabinbottom) { lastdirection = 3; collided = true; break; } lastpoint = p; continue; } bool trycollisions = false; bool endofroom = false; if (src.x + p.x < room->x_left) { if (i != 1 && dx < 0) { trycollisions = true; lastdirection = 0; } endofroom = true; } if (src.x + p.x > room->x_right) { if (i != 0 && dx > 0) { trycollisions = true; lastdirection = 1; } endofroom = true; } if (src.y + p.y < room->y_left_ceiling) { if (i != 3 && dy < 0) { trycollisions = true; lastdirection = 2; } endofroom = true; } if (src.y + p.y > room->y_left_floor) { if (i != 2 && dy > 0) { trycollisions = true; lastdirection = 3; } endofroom = true; } // find the next room, if necessary, and work out whether we should move into it or break out if (endofroom) { if (m->wraparound()) { if (dx > 0 && src.x + p.x >= m->x() + m->width()) src.x -= m->width(); else if (dx < 0 && src.x + p.x <= m->x()) src.x += m->width(); } shared_ptr<Room> newroom = bestRoomAt(src.x + p.x, src.y + p.y, i, m, room); bool collision = false; // collide if we're out of the room system if (!newroom) { collision = true; } // collide if there's no new room connected to this one else if (room->doors.find(newroom) == room->doors.end()) { collision = true; } // collide if the PERM between this room and the new room is smaller than or equal to our size else if (size.getInt() > room->doors[newroom]->perm) { collision = true; } if (collision && (trycollisions || (!newroom))) { collided = true; break; } // move to the new room and keep going! room = newroom; } if (room->floorpoints.size() && i == 3 && dy >= 0 && size.getInt() > room->floorvalue.getInt()) { // TODO: Hack! // TODO: we don't check floorYatX isn't returning a 'real' room floor, but floorpoints should cover the whole floor anyway int floory = room->floorYatX(src.x + p.x); // never collide when the top point of an object is below the floor. Point top = boundingBoxPoint(2); // TODO: consider steep floors if (src.y + p.y > floory && top.y < floory) { collided = true; lastdirection = 3; break; } } if ((!followrooms) && endofroom) break; lastpoint = p; } double length2 = (lastpoint.x * lastpoint.x) + (lastpoint.y * lastpoint.y); if (length2 < delta) { // TODO: !followrooms is a horrible way to detect a non-physics call if (collided && followrooms) lastcollidedirection = lastdirection; deltapt = lastpoint; delta = length2; } }
// print a path via a sequence of fline(), fcont(), fbezier3() operations, // terminating with a final endpath() void drvplot::print_coords() { Point lastpoint(0, 0); const Point & firstpoint = pathElement(0).getPoint(0); bool currently_at_lastpoint = false; bool last_was_endpath = false; // since libplot/libplotter doesn't (yet) support sub-paths, // all paths that we draw will be of the form // moveto {lineto,curveto}+ {closepath} // where {}+ means one or more repetitions, and {} means optional. for (unsigned int n = 0; n < numberOfElementsInPath(); n++) { const basedrawingelement & elem = pathElement(n); switch (elem.getType()) { case moveto: { const Point & p = elem.getPoint(0); lastpoint = p; currently_at_lastpoint = false; last_was_endpath = false; } break; case lineto: { const Point & p = elem.getPoint(0); if (currently_at_lastpoint) (void)plotter->fcont(p.x_ + x_offset, p.y_ + y_offset); else (void)plotter->fline(lastpoint.x_ + x_offset, lastpoint.y_ + y_offset, p.x_ + x_offset, p.y_ + y_offset); lastpoint = p; currently_at_lastpoint = true; last_was_endpath = false; } break; case curveto: { const Point & p1 = lastpoint; const Point & p2 = elem.getPoint(0); const Point & p3 = elem.getPoint(1); const Point & p4 = elem.getPoint(2); (void)plotter->fbezier3(p1.x_ + x_offset, p1.y_ + y_offset, p2.x_ + x_offset, p2.y_ + y_offset, p3.x_ + x_offset, p3.y_ + y_offset, p4.x_ + x_offset, p4.y_ + y_offset); lastpoint = p4; currently_at_lastpoint = true; last_was_endpath = false; } break; case closepath: if (currently_at_lastpoint) /* have drawn at least one segment */ { (void)plotter->fcont(firstpoint.x_ + x_offset, firstpoint.y_ + y_offset); (void)plotter->endpath(); currently_at_lastpoint = true; last_was_endpath = true; } break; default: errf << "\t\tFatal: unexpected case in drvlplot " << endl; abort(); break; } } if (last_was_endpath == false) (void)plotter->endpath(); }