// define this if you're using VisualC++ so that your program doesn't crash // due to dynamic_cast errors // //#define IM_USING_STUPID_WINDOWS #include #include #include #include #include using namespace std; typedef CGAL::Cartesian R; typedef CGAL::Polygon_traits_2 Traits; typedef CGAL::Point_2 PointC2; typedef CGAL::Segment_2 Segment; typedef CGAL::Bbox_2 Bbox; typedef CGAL::Polygon_2 > Polygon; typedef CGAL::Polygon_2 >::Vertex_iterator VertexIterator; typedef CGAL::Polygon_2 >::Edge_const_iterator EdgeIterator; typedef CGAL::Object Object ; // possible results for the bounding box/polygon intersection routine enum bbpResult {overlap, inside, outside}; bbpResult bbox_poly_int(Bbox& b, Polygon& p); int main() { // create a polygon and put some points in it Polygon p; p.push_back(PointC2(0,0)); p.push_back(PointC2(4,0)); p.push_back(PointC2(4,4)); p.push_back(PointC2(2,2)); p.push_back(PointC2(0,4)); CGAL::set_pretty_mode(std::cout); std::cout << "created the polygon p:" << std::endl; std::cout << p << std::endl; std::cout << std::endl; // create some bounding boxes that will represent cells that we'll // check for intersection // // the arguments to the constructor are (xmin, ymin, xmax, ymax) // (these arguments are actually doubles) Bbox c[9]; c[0] = Bbox(1,0,2,1); c[1] = Bbox(4,1,5,2); c[2] = Bbox(5,2,6,4); c[3] = Bbox(4,4,5,5); c[4] = Bbox(2.1, 2.9, 3.1, 3.9); c[5] = Bbox(-0.5, 3.5, 0.5, 4.5); c[6] = Bbox(-0.5, 2.5, 2, 3.5); c[7] = Bbox(-1,0,5,5); c[8] = Bbox(-1,-1,5,0); for (int k=0; k<9; k++) { cout << "\nChecking cell " << k << std::endl; switch (bbox_poly_int(c[k], p)) { case inside: cout << "Cell " << k << " is inside the polygon\n"; break; case overlap: cout << "Cell " << k << " overlaps the polygon\n"; break; case outside: cout << "Cell " << k << " lies completely outside the polygon\n"; break; } } return 0; } bbpResult bbox_poly_int(Bbox& b, Polygon& p) { // if the bounding boxes don't overlap, then the bbox must be // outside the polygon if (!CGAL::do_overlap(b, p.bbox())) return outside; // Otherwise if any/all corners of the bounding box lie inside the // polygon, then there is an intersection... int inPts = 0; int outPts = 0; PointC2 b1(b.xmin(),b.ymin()); PointC2 b2(b.xmax(),b.ymin()); PointC2 b3(b.xmax(),b.ymax()); PointC2 b4(b.xmin(),b.ymax()); CGAL::Bounded_side bs; bs = p.bounded_side(b1); if (bs == CGAL::ON_BOUNDED_SIDE) inPts++; else if (bs == CGAL::ON_UNBOUNDED_SIDE) outPts++; bs = p.bounded_side(b2); if (bs == CGAL::ON_BOUNDED_SIDE) inPts++; else if (bs == CGAL::ON_UNBOUNDED_SIDE) outPts++; bs = p.bounded_side(b3); if (bs == CGAL::ON_BOUNDED_SIDE) inPts++; else if (bs == CGAL::ON_UNBOUNDED_SIDE) outPts++; bs = p.bounded_side(b4); if (bs == CGAL::ON_BOUNDED_SIDE) inPts++; else if (bs == CGAL::ON_UNBOUNDED_SIDE) outPts++; // cout << "There are " << inPts << " bbox vertices inside the polygon.\n"; // cout << "There are " << outPts << " bbox vertices outside the polygon.\n"; // if no corners are outside, then the bounding box is completely // inside the polygon. note that under this case, the corners may // be in the interior or on the boundary. if (outPts == 0) return inside; // otherwise if any corner is inside, then the bounding box and the // polygon overlap if (inPts > 0) return overlap; // if any vertices of the polygon lie inside the bbox, then the bbox // and the polygon overlap Polygon bb; bb.push_back(b1); // create a polygon for the bbox bb.push_back(b2); bb.push_back(b3); bb.push_back(b4); for (VertexIterator vi = p.vertices_begin(); vi != p.vertices_end(); ++vi) if (bb.bounded_side(*vi) == CGAL::ON_BOUNDED_SIDE) return overlap; #ifndef IM_USING_STUPID_WINDOWS // otherwise, we need to check if any of the line segments of the // bounding box overlap the polygon edges. If so, the bounding box // and the polygon overlap; otherwise, there is no intersection. // // this is sort of complicated to get right because of the question // of how to handle the cases where the boundary of the bbox // intersects the boundary of the polygon. There are a number of // weird cases, but with the assumption that the polygon is convex, // I believe the following procedure is correct: // // - For each edge of the polygon, intersect it with the four bbox edges // - if the result is a line segment, continue on to the next // polygon edge // - if the result is a point (and not and endpoint of the bbox edge // or the polygon edge), then the bounding box intersects the // polygon, so return "overlap". // - Return "outside" // for (EdgeIterator ei = p.edges_begin(); ei != p.edges_end(); ++ei) { Object result; PointC2 pt; Segment s; // std::cout << "cheking polygon edge " << *ei << std::endl; // cout << " checking bbox edge from " << b1 << " to " << b2 << endl; result= CGAL::intersection(*ei, Segment(b1,b2)); if (CGAL::assign(s, result)) continue; if (CGAL::assign(pt, result) && !CGAL::do_intersect(*ei,b1) && !CGAL::do_intersect(*ei,b2) && !CGAL::do_intersect(Segment(b1,b2), (*ei).start()) && !CGAL::do_intersect(Segment(b1,b2), (*ei).end())) return overlap; // cout << " checking bbox edge from " << b2 << " to " << b3 << endl; result = CGAL::intersection(*ei, Segment(b2,b3)); if (CGAL::assign(s, result)) continue; if (CGAL::assign(pt, result) && !CGAL::do_intersect(*ei,b2) && !CGAL::do_intersect(*ei,b3) && !CGAL::do_intersect(Segment(b2,b3), (*ei).start()) && !CGAL::do_intersect(Segment(b2,b3), (*ei).end())) return overlap; // cout << " checking bbox edge from " << b3 << " to " << b4 << endl; result = CGAL::intersection(*ei, Segment(b3,b4)); if (CGAL::assign(s, result)) continue; if (CGAL::assign(pt, result) && !CGAL::do_intersect(*ei,b3) && !CGAL::do_intersect(*ei,b4) && !CGAL::do_intersect(Segment(b3,b4), (*ei).start()) && !CGAL::do_intersect(Segment(b3,b4), (*ei).end())) return overlap; // cout << " checking bbox edge from " << b4 << " to " << b1 << endl; result = CGAL::intersection(*ei, Segment(b4,b1)); if (CGAL::assign(s, result)) continue; if (CGAL::assign(pt, result) && !CGAL::do_intersect(*ei,b4) && !CGAL::do_intersect(*ei,b1) && !CGAL::do_intersect(Segment(b4,b1), (*ei).start()) && !CGAL::do_intersect(Segment(b4,b1), (*ei).end())) return overlap; } // no intersections, so the bounding box is completely outside the // polygon return outside; #else // // here's the version that will compile and run OK under VisualC++ // for (EdgeIterator ei = p.edges_begin(); ei != p.edges_end(); ++ei) { Object result; PointC2 pt; Segment s; // std::cout << "cheking polygon edge " << *ei << std::endl; // cout << " checking bbox edge from " << b1 << " to " << b2 << endl; result= CGAL::intersection(*ei, Segment(b1,b2)); if (!result.is_empty() && !CGAL::do_intersect(*ei,b1) && !CGAL::do_intersect(*ei,b2) && !CGAL::do_intersect(Segment(b1,b2), (*ei).start()) && !CGAL::do_intersect(Segment(b1,b2), (*ei).end())) return overlap; // cout << " checking bbox edge from " << b2 << " to " << b3 << endl; result = CGAL::intersection(*ei, Segment(b2,b3)); if (!result.is_empty() && !CGAL::do_intersect(*ei,b2) && !CGAL::do_intersect(*ei,b3) && !CGAL::do_intersect(Segment(b2,b3), (*ei).start()) && !CGAL::do_intersect(Segment(b2,b3), (*ei).end())) return overlap; // cout << " checking bbox edge from " << b3 << " to " << b4 << endl; result = CGAL::intersection(*ei, Segment(b3,b4)); if (!result.is_empty() && !CGAL::do_intersect(*ei,b3) && !CGAL::do_intersect(*ei,b4) && !CGAL::do_intersect(Segment(b3,b4), (*ei).start()) && !CGAL::do_intersect(Segment(b3,b4), (*ei).end())) return overlap; // cout << " checking bbox edge from " << b4 << " to " << b1 << endl; result = CGAL::intersection(*ei, Segment(b4,b1)); if (!result.is_empty() && !CGAL::do_intersect(*ei,b4) && !CGAL::do_intersect(*ei,b1) && !CGAL::do_intersect(Segment(b4,b1), (*ei).start()) && !CGAL::do_intersect(Segment(b4,b1), (*ei).end())) return overlap; } // no intersections, so the bounding box is completely outside the // polygon return outside; #endif }