inline return_type operator()(P const& p, Segment const& s) const { assert_dimension_equal<P, Segment>(); /* Algorithm POINT v(x2 - x1, y2 - y1); POINT w(px - x1, py - y1); c1 = w . v c2 = v . v b = c1 / c2 RETURN POINT(x1 + b * vx, y1 + b * vy); */ typedef typename boost::remove_const < typename point_type<Segment>::type >::type segment_point_type; segment_point_type v, w; // TODO // ASSUMPTION: segment // SOLVE THIS USING OTHER FUNCTIONS using get<,> copy_coordinates(s.second, v); copy_coordinates(p, w); subtract_point(v, s.first); subtract_point(w, s.first); Strategy strategy; coordinate_type c1 = dot_product(w, v); if (c1 <= 0) { return strategy(p, s.first); } coordinate_type c2 = dot_product(v, v); if (c2 <= c1) { return strategy(p, s.second); } // Even in case of char's, we have to turn to a point<double/float> // because of the division. coordinate_type b = c1 / c2; // Note that distances with integer coordinates do NOT work because // - the project point is integer // - if we solve that, the used distance_strategy cannot handle double points segment_point_type projected; copy_coordinates(s.first, projected); multiply_value(v, b); add_point(projected, v); return strategy(p, projected); }
inline return_type apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const { assert_dimension_equal<Point, PointOfSegment>(); /* Algorithm POINT v(x2 - x1, y2 - y1); POINT w(px - x1, py - y1); c1 = w . v c2 = v . v b = c1 / c2 RETURN POINT(x1 + b * vx, y1 + b * vy); */ // Take here the first point type. It should have a default constructor. // That is not required for the second point type. Point v, w; copy_coordinates(p2, v); copy_coordinates(p, w); subtract_point(v, p1); subtract_point(w, p1); Strategy strategy; coordinate_type zero = coordinate_type(); coordinate_type c1 = dot_product(w, v); if (c1 <= zero) { return strategy.apply(p, p1); } coordinate_type c2 = dot_product(v, v); if (c2 <= c1) { return strategy.apply(p, p2); } // Even in case of char's, we have to turn to a point<double/float> // because of the division. typedef typename geometry::select_most_precise<coordinate_type, double>::type divisor_type; divisor_type b = c1 / c2; // Note that distances with integer coordinates do NOT work because // - the project point is integer // - if we solve that, the used distance_strategy cannot handle double points PointOfSegment projected; copy_coordinates(p1, projected); multiply_value(v, b); add_point(projected, v); return strategy.apply(p, projected); }
static inline void apply(G& geometry, P const& point, int , int ) { typename point_type<G>::type point_type; copy_coordinates(point, point_type); geometry.push_back(point_type); }
inline bool range_ok(Range const& range, Point& centroid) { std::size_t const n = boost::size(range); if (n > 1) { return true; } else if (n <= 0) { #if defined(CENTROID_WITH_CATCH) throw centroid_exception(); #endif return false; } else // if (n == 1) { // Take over the first point in a "coordinate neutral way" copy_coordinates(range.front(), centroid); return false; } return true; }
OutputIterator clip_linestring_with_box(Box const& b, Linestring const& linestring, OutputIterator out, Strategy const& strategy) { if (boost::begin(linestring) == boost::end(linestring)) { return out; } typedef typename point_type<OutputLinestring>::type point_type; OutputLinestring line_out; typedef typename boost::range_const_iterator<Linestring>::type iterator_type; iterator_type vertex = boost::begin(linestring); for(iterator_type previous = vertex++; vertex != boost::end(linestring); previous = vertex++) { point_type p1, p2; copy_coordinates(*previous, p1); copy_coordinates(*vertex, p2); // Clip the segment. Five situations: // 1. Segment is invisible, finish line if any (shouldn't occur) // 2. Segment is completely visible. Add (p1)-p2 to line // 3. Point 1 is invisible (clipped), point 2 is visible. Start new line from p1-p2... // 4. Point 1 is visible, point 2 is invisible (clipped). End the line with ...p2 // 5. Point 1 and point 2 are both invisible (clipped). Start/finish an independant line p1-p2 // // This results in: // a. if p1 is clipped, start new line // b. if segment is partly or completely visible, add the segment // c. if p2 is clipped, end the line bool c1 = false; bool c2 = false; segment<point_type> s(p1, p2); if (!strategy.clip_segment(b, s, c1, c2)) { strategy.apply(line_out, out); } else { // a. If necessary, finish the line and add a start a new one if (c1) { strategy.apply(line_out, out); } // b. Add p1 only if it is the first point, then add p2 if (boost::empty(line_out)) { geometry::append(line_out, p1); } geometry::append(line_out, p2); // c. If c2 is clipped, finish the line if (c2) { strategy.apply(line_out, out); } } } // Add last part strategy.apply(line_out, out); return out; }
static inline void apply(Point const& point, PointCentroid& centroid, Strategy const&) { copy_coordinates(point, centroid); }