inline bool point_on_path(double x,double y,Iter start,Iter end, double tol) { double x0=boost::get<0>(*start); double y0=boost::get<1>(*start); double x1 = 0; double y1 = 0; while (++start != end) { if ( boost::get<2>(*start) == SEG_MOVETO) { x0 = boost::get<0>(*start); y0 = boost::get<1>(*start); continue; } x1=boost::get<0>(*start); y1=boost::get<1>(*start); double distance = point_to_segment_distance(x,y,x0,y0,x1,y1); if (distance < tol) return true; x0=x1; y0=y1; } return false; }
bool hit_test(PathType & path, double x, double y, double tol) { bool inside=false; double x0 = 0; double y0 = 0; double x1 = 0; double y1 = 0; path.rewind(0); unsigned command = path.vertex(&x0, &y0); if (command == SEG_END) { return false; } unsigned count = 0; mapnik::geometry_type::types geom_type = static_cast<mapnik::geometry_type::types>(path.type()); while (SEG_END != (command = path.vertex(&x1, &y1))) { if (command == SEG_CLOSE) { continue; } ++count; if (command == SEG_MOVETO) { x0 = x1; y0 = y1; continue; } switch(geom_type) { case mapnik::geometry_type::types::Polygon: { if ((((y1 <= y) && (y < y0)) || ((y0 <= y) && (y < y1))) && (x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1)) inside=!inside; break; } case mapnik::geometry_type::types::LineString: { double distance = point_to_segment_distance(x,y,x0,y0,x1,y1); if (distance < tol) return true; break; } default: break; } x0 = x1; y0 = y1; } // TODO - handle multi-point? if (count == 0) // one vertex { return distance(x, y, x0, y0) <= tol; } return inside; }