static inline OutputIterator apply(Geometry const& geometry, OutputIterator out, Strategy const& strategy) { typename Strategy::state_type state; strategy.apply(geometry, state); strategy.result(state, out, Order == clockwise); return out; }
static inline typename default_length_result<Segment>::type apply( Segment const& segment, Strategy const& strategy) { typedef typename point_type<Segment>::type point_type; point_type p1, p2; geometry::detail::assign_point_from_index<0>(segment, p1); geometry::detail::assign_point_from_index<1>(segment, p2); return strategy.apply(p1, p2); }
static inline typename return_type<Strategy>::type apply(Point const& point, Segment const& segment, Strategy const& strategy) { typename point_type<Segment>::type p[2]; geometry::detail::assign_point_from_index<0>(segment, p[0]); geometry::detail::assign_point_from_index<1>(segment, p[1]); return strategy.apply(point, p[0], p[1]); }
static inline void apply(Point const& point, PointTransformer const& transformer, Strategy const& strategy, typename Strategy::state_type& state) { geofeatures_boost::ignore_unused(strategy); strategy.apply(static_cast<Point const&>(transformer.apply(point)), state); }
static inline void apply(Point const& point, Segment const& segment, Strategy const& strategy, Result& result) { typename point_type<Segment>::type p[2]; geometry::detail::assign_point_from_index<0>(segment, p[0]); geometry::detail::assign_point_from_index<1>(segment, p[1]); strategy.apply(point, p[0], p[1], result); }
static inline bool apply(Geometry1 const& source, Geometry2& target, Strategy const& strategy) { typedef typename point_type<Geometry1>::type point_type1; typedef typename point_type<Geometry2>::type point_type2; point_type1 source_point[2]; geometry::detail::assign_point_from_index<0>(source, source_point[0]); geometry::detail::assign_point_from_index<1>(source, source_point[1]); point_type2 target_point[2]; if (strategy.apply(source_point[0], target_point[0]) && strategy.apply(source_point[1], target_point[1])) { geometry::detail::assign_point_to_index<0>(target_point[0], target); geometry::detail::assign_point_to_index<1>(target_point[1], target); return true; } return false; }
static inline typename strategy::distance::services::return_type < Strategy, typename point_type<Box1>::type, typename point_type<Box2>::type >::type apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { boost::ignore_unused(strategy); return strategy.apply(box1, box2); }
static void apply(ApplyMethod) { // 1: inspect and define both arguments of apply typedef typename parameter_type_of < ApplyMethod, 0 >::type ptype1; typedef typename parameter_type_of < ApplyMethod, 1 >::type ptype2; // 2) must define meta-function return_type typedef typename strategy::distance::services::return_type < Strategy, ptype1, ptype2 >::type rtype; // 3) must define meta-function "comparable_type" typedef typename strategy::distance::services::comparable_type < Strategy >::type ctype; // 4) must define meta-function "tag" typedef typename strategy::distance::services::tag < Strategy >::type tag; // 5) must implement apply with arguments Strategy* str = 0; ptype1 *p1 = 0; ptype2 *p2 = 0; rtype r = str->apply(*p1, *p2); // 6) must define (meta)struct "get_comparable" with apply ctype c = strategy::distance::services::get_comparable < Strategy >::apply(*str); // 7) must define (meta)struct "result_from_distance" with apply r = strategy::distance::services::result_from_distance < Strategy, ptype1, ptype2 >::apply(*str, 1.0); boost::ignore_unused_variable_warning(str); boost::ignore_unused_variable_warning(c); boost::ignore_unused_variable_warning(r); }
static inline void apply(Range const& range, OutputIterator out, Distance const& max_distance, Strategy const& strategy) { if (pdalboost::size(range) <= 2 || max_distance < 0) { std::copy(pdalboost::begin(range), pdalboost::end(range), out); } else { strategy.apply(range, out, max_distance); } }
static inline OutputIterator apply(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, TurnInfo const& , Strategy const& strategy, RobustPolicy const& robust_policy, OutputIterator out) { typedef typename TurnInfo::point_type turn_point_type; typedef policies::relate::segments_intersection_points < segment_intersection_points < turn_point_type, typename geometry::segment_ratio_type < turn_point_type, RobustPolicy >::type > > policy_type; typedef model::referring_segment<Point1 const> segment_type1; typedef model::referring_segment<Point2 const> segment_type2; Point1 const& pi = range_p.at(0); Point1 const& pj = range_p.at(1); Point2 const& qi = range_q.at(0); Point2 const& qj = range_q.at(1); segment_type1 p1(pi, pj); segment_type2 q1(qi, qj); typedef typename geometry::robust_point_type < Point1, RobustPolicy >::type robust_point_type; robust_point_type pi_rob, pj_rob, qi_rob, qj_rob; geometry::recalculate(pi_rob, pi, robust_policy); geometry::recalculate(pj_rob, pj, robust_policy); geometry::recalculate(qi_rob, qi, robust_policy); geometry::recalculate(qj_rob, qj, robust_policy); typename policy_type::return_type result = strategy.apply(p1, q1, policy_type(), robust_policy, pi_rob, pj_rob, qi_rob, qj_rob); for (std::size_t i = 0; i < result.count; i++) { TurnInfo tp; geometry::convert(result.intersections[i], tp.point); *out++ = tp; } return out; }
static void apply(ApplyMethod) { // 1) inspect and define both arguments of apply typedef typename parameter_type_of < ApplyMethod, 0 >::type ptype; typedef typename parameter_type_of < ApplyMethod, 1 >::type sptype; namespace services = strategy::distance::services; // 2) must define meta-function "tag" typedef typename services::tag<Strategy>::type tag; BOOST_MPL_ASSERT_MSG ((boost::is_same < tag, strategy_tag_distance_point_segment >::value), INCORRECT_STRATEGY_TAG, (types<tag>)); // 3) must define meta-function "return_type" typedef typename services::return_type < Strategy, ptype, sptype >::type rtype; // 4) must define meta-function "comparable_type" typedef typename services::comparable_type<Strategy>::type ctype; // 5) must implement apply with arguments Strategy *str = 0; ptype *p = 0; sptype *sp1 = 0; sptype *sp2 = 0; rtype r = str->apply(*p, *sp1, *sp2); // 6) must define (meta-)struct "get_comparable" with apply ctype cstrategy = services::get_comparable<Strategy>::apply(*str); // 7) must define (meta-)struct "result_from_distance" with apply r = services::result_from_distance < Strategy, ptype, sptype >::apply(*str, rtype(1.0)); boost::ignore_unused(str, r, cstrategy); }
static inline typename distance_result < typename point_type<Range1>::type, typename point_type<Range2>::type, Strategy >::type apply(Range1 const& r1, Range2 const& r2, Strategy const& strategy) { typedef typename distance_result < typename point_type<Range1>::type, typename point_type<Range2>::type, Strategy >::type result_type; typedef typename boost::range_size<Range1>::type size_type; boost::geometry::detail::throw_on_empty_input(r1); boost::geometry::detail::throw_on_empty_input(r2); size_type const n = boost::size(r1); result_type dis_max = 0; #ifdef BOOST_GEOMETRY_ENABLE_SIMILARITY_RTREE namespace bgi = boost::geometry::index; typedef typename point_type<Range1>::type point_t; typedef bgi::rtree<point_t, bgi::linear<4> > rtree_type; rtree_type rtree(boost::begin(r2), boost::end(r2)); point_t res; #endif for (size_type i = 0 ; i < n ; i++) { #ifdef BOOST_GEOMETRY_ENABLE_SIMILARITY_RTREE size_type found = rtree.query(bgi::nearest(range::at(r1, i), 1), &res); result_type dis_min = strategy.apply(range::at(r1,i), res); #else result_type dis_min = point_range::apply(range::at(r1, i), r2, strategy); #endif if (dis_min > dis_max ) { dis_max = dis_min; } } return dis_max; }
inline bool point_in_range(Strategy& strategy, State& state, Point const& point, Iterator begin, Iterator end) { boost::ignore_unused(strategy); Iterator it = begin; for (Iterator previous = it++; it != end; ++previous, ++it) { if (! strategy.apply(point, *previous, *it, state)) { // We're probably on the boundary return false; } } return true; }
static void apply() { Strategy *str = 0; state_type *st = 0; // 4) must implement a static method apply, // getting two segment-points spoint_type const* sp = 0; str->apply(*sp, *sp, *st); // 5) must implement a static method result // getting the centroid point_type *c = 0; bool r = str->result(*st, *c); boost::ignore_unused_variable_warning(str); boost::ignore_unused_variable_warning(r); }
static inline void apply(Ring const& ring, Strategy const& strategy, typename Strategy::state_type& state) { typedef typename closeable_view<Ring const, Closure>::type view_type; typedef typename boost::range_iterator<view_type const>::type iterator_type; view_type view(ring); iterator_type it = boost::begin(view); iterator_type end = boost::end(view); for (iterator_type previous = it++; it != end; ++previous, ++it) { strategy.apply(*previous, *it, state); } }
void time_compare_s(int const n) { boost::timer t; P p1, p2; bg::assign_values(p1, 1, 1); bg::assign_values(p2, 2, 2); Strategy strategy; typename bg::strategy::distance::services::return_type<Strategy, P, P>::type s = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { bg::set<0>(p2, bg::get<0>(p2) + 0.001); s += strategy.apply(p1, p2); } } std::cout << "s: " << s << " t: " << t.elapsed() << std::endl; }
static inline typename Strategy::return_type apply(Ring const& ring, Strategy const& strategy) { BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy<Strategy>) ); assert_dimension<Ring, 2>(); // Ignore warning (because using static method sometimes) on strategy boost::ignore_unused_variable_warning(strategy); // An open ring has at least three points, // A closed ring has at least four points, // if not, there is no (zero) area if (int(boost::size(ring)) < core_detail::closure::minimum_ring_size<Closure>::value) { return typename Strategy::return_type(); } typedef typename reversible_view<Ring const, Direction>::type rview_type; typedef typename closeable_view < rview_type const, Closure >::type view_type; typedef typename boost::range_iterator<view_type const>::type iterator_type; rview_type rview(ring); view_type view(rview); typename Strategy::state_type state; iterator_type it = boost::begin(view); iterator_type end = boost::end(view); for (iterator_type previous = it++; it != end; ++previous, ++it) { strategy.apply(*previous, *it, state); } return strategy.result(state); }
inline bool point_in_section(Strategy& strategy, State& state, Point const& point, CoordinateType const& point_y, Iterator begin, Iterator end, int direction) { if (direction == 0) { // Not a monotonic section, or no change in Y-direction return point_in_range(strategy, state, point, begin, end); } // We're in a monotonic section in y-direction Iterator it = begin; for (Iterator previous = it++; it != end; ++previous, ++it) { // Depending on sections.direction we can quit for this section CoordinateType const previous_y = geometry::get<1>(*previous); if (direction == 1 && point_y < previous_y) { // Section goes upwards, y increases, point is is below section return true; } else if (direction == -1 && point_y > previous_y) { // Section goes downwards, y decreases, point is above section return true; } if (! strategy.apply(point, *previous, *it, state)) { // We're probably on the boundary return false; } } return true; }
void test_2d(std::string const& wkt_p, std::string const& wkt_sp1, std::string const& wkt_sp2, T expected_distance, T expected_comparable_distance, Strategy strategy, ComparableStrategy comparable_strategy) { P1 p; P2 sp1, sp2; bg::read_wkt(wkt_p, p); bg::read_wkt(wkt_sp1, sp1); bg::read_wkt(wkt_sp2, sp2); BOOST_CONCEPT_ASSERT ( (bg::concept::PointSegmentDistanceStrategy<Strategy, P1, P2>) ); BOOST_CONCEPT_ASSERT ( (bg::concept::PointSegmentDistanceStrategy<ComparableStrategy, P1, P2>) ); { typedef typename bg::strategy::distance::services::return_type<Strategy, P1, P2>::type return_type; return_type d = strategy.apply(p, sp1, sp2); test_check_close(d, expected_distance, 0.001); } // Test combination with the comparable strategy { typedef typename bg::strategy::distance::services::return_type<ComparableStrategy, P1, P2>::type return_type; return_type d = comparable_strategy.apply(p, sp1, sp2); test_check_close(d, expected_comparable_distance, 0.01); } }
void time_compare_s(int const n) { typedef bg::model::box<P> box_type; boost::timer t; P p; box_type b; bg::assign_values(b, 0, 0, 1, 1); bg::assign_values(p, 2, 2); Strategy strategy; typename bg::strategy::distance::services::return_type < Strategy, P, box_type >::type s = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { bg::set<0>(p, bg::get<0>(p) + 0.001); s += strategy.apply(p, b); } } std::cout << "s: " << s << " t: " << t.elapsed() << std::endl; }
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { assert_dimension_equal<Box1, Box2>(); ::boost::ignore_unused_variable_warning(strategy); return strategy.apply(box1, box2); }
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) { ::boost::ignore_unused_variable_warning(strategy); return strategy.apply(point, box); }
OutputIterator clip_range_with_box(Box const& b, Range const& range, RobustPolicy const&, OutputIterator out, Strategy const& strategy) { if (boost::begin(range) == boost::end(range)) { return out; } typedef typename point_type<OutputLinestring>::type point_type; OutputLinestring line_out; typedef typename boost::range_iterator<Range const>::type iterator_type; iterator_type vertex = boost::begin(range); for(iterator_type previous = vertex++; vertex != boost::end(range); ++previous, ++vertex) { point_type p1, p2; geometry::convert(*previous, p1); geometry::convert(*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; model::referring_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)) { detail::overlay::append_no_duplicates(line_out, p1, true); } detail::overlay::append_no_duplicates(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 bool apply(Segment const& segment, Box const& box, Strategy const& azimuth_strategy) { assert_dimension_equal<Segment, Box>(); typedef typename point_type<Segment>::type segment_point_type; typedef typename cs_tag<Segment>::type segment_cs_type; segment_point_type p0, p1; geometry::detail::assign_point_from_index<0>(segment, p0); geometry::detail::assign_point_from_index<1>(segment, p1); // Simplest cases first // Case 1: if box contains one of segment's endpoints then they are not disjoint if (! disjoint_point_box(p0, box) || ! disjoint_point_box(p1, box)) { return false; } // Case 2: disjoint if bounding boxes are disjoint typedef typename coordinate_type<segment_point_type>::type CT; segment_point_type p0_normalized = geometry::detail::return_normalized<segment_point_type>(p0); segment_point_type p1_normalized = geometry::detail::return_normalized<segment_point_type>(p1); CT lon1 = geometry::get_as_radian<0>(p0_normalized); CT lat1 = geometry::get_as_radian<1>(p0_normalized); CT lon2 = geometry::get_as_radian<0>(p1_normalized); CT lat2 = geometry::get_as_radian<1>(p1_normalized); if (lon1 > lon2) { swap(lon1, lat1, lon2, lat2); } //Compute alp1 outside envelope and pass it to envelope_segment_impl //in order for it to be used later in the algorithm CT alp1; azimuth_strategy.apply(lon1, lat1, lon2, lat2, alp1); geometry::model::box<segment_point_type> box_seg; geometry::detail::envelope::envelope_segment_impl<segment_cs_type> ::template apply<geometry::radian>(lon1, lat1, lon2, lat2, box_seg, azimuth_strategy, alp1); if (disjoint_box_box(box, box_seg)) { return true; } // Case 3: test intersection by comparing angles CT a_b0, a_b1, a_b2, a_b3; CT b_lon_min = geometry::get_as_radian<geometry::min_corner, 0>(box); CT b_lat_min = geometry::get_as_radian<geometry::min_corner, 1>(box); CT b_lon_max = geometry::get_as_radian<geometry::max_corner, 0>(box); CT b_lat_max = geometry::get_as_radian<geometry::max_corner, 1>(box); azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_min, a_b0); azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_min, a_b1); azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_max, a_b2); azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_max, a_b3); bool b0 = alp1 > a_b0; bool b1 = alp1 > a_b1; bool b2 = alp1 > a_b2; bool b3 = alp1 > a_b3; // if not all box points on the same side of the segment then // there is an intersection if (!(b0 && b1 && b2 && b3) && (b0 || b1 || b2 || b3)) { return false; } // Case 4: The only intersection case not covered above is when all four // points of the box are above (below) the segment in northern (southern) // hemisphere. Then we have to compute the vertex of the segment CT vertex_lat; CT lat_sum = lat1 + lat2; if ((b0 && b1 && b2 && b3 && lat_sum > CT(0)) || (!(b0 && b1 && b2 && b3) && lat_sum < CT(0))) { CT b_lat_below; //latitude of box closest to equator if (lat_sum > CT(0)) { vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(box_seg); b_lat_below = b_lat_min; } else { vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(box_seg); b_lat_below = b_lat_max; } //optimization TODO: computing the spherical longitude should suffice for // the majority of cases CT vertex_lon = geometry::formula::vertex_longitude<CT, CS_Tag> ::apply(lon1, lat1, lon2, lat2, vertex_lat, alp1, azimuth_strategy); // Check if the vertex point is within the band defined by the // minimum and maximum longitude of the box; if yes, then return // false if the point is above the min latitude of the box; return // true in all other cases if (vertex_lon >= b_lon_min && vertex_lon <= b_lon_max && std::abs(vertex_lat) > std::abs(b_lat_below)) { return false; } } return true; }
static inline void apply(Point const& point, Strategy const& strategy, typename Strategy::state_type& state) { strategy.apply(point, state); }
static inline bool apply(Point1 const& p1, Point2& p2, Strategy const& strategy) { return strategy.apply(p1, p2); }
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { assert_dimension_equal<Box1, Box2>(); return strategy.apply(box1, box2); }
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) { return strategy.apply(point, box); }
static inline bool apply(Point const& point, NSphere const& nsphere, Strategy const& strategy) { assert_dimension_equal<Point, NSphere>(); boost::ignore_unused_variable_warning(strategy); return strategy.apply(point, nsphere); }
static inline bool apply(NSphere const& nsphere, Box const& box, Strategy const& strategy) { assert_dimension_equal<NSphere, Box>(); boost::ignore_unused_variable_warning(strategy); return strategy.apply(nsphere, box); }