inline void move_index(Pieces const& pieces, int& index, int& piece_index, int direction) { BOOST_GEOMETRY_ASSERT(direction == 1 || direction == -1); BOOST_GEOMETRY_ASSERT(piece_index >= 0 && piece_index < static_cast<int>(boost::size(pieces)) ); BOOST_GEOMETRY_ASSERT(index >= 0 && index < static_cast<int>(boost::size(pieces[piece_index].robust_ring))); index += direction; if (direction == -1 && index < 0) { piece_index--; if (piece_index < 0) { piece_index = boost::size(pieces) - 1; } index = boost::size(pieces[piece_index].robust_ring) - 1; } if (direction == 1 && index >= static_cast<int>(boost::size(pieces[piece_index].robust_ring))) { piece_index++; if (piece_index >= static_cast<int>(boost::size(pieces))) { piece_index = 0; } index = 0; } }
static inline void apply(CoordinateType& longitude, CoordinateType& latitude, bool normalize_poles = true) { #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE // normalize latitude if (math::larger(latitude, constants::half_period())) { latitude = normalize_up(latitude); } else if (math::smaller(latitude, -constants::half_period())) { latitude = normalize_down(latitude); } // fix latitude range if (latitude < constants::min_latitude()) { latitude = -constants::half_period() - latitude; longitude -= constants::half_period(); } else if (latitude > constants::max_latitude()) { latitude = constants::half_period() - latitude; longitude -= constants::half_period(); } #endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE // normalize longitude apply(longitude); // finally normalize poles if (normalize_poles) { if (math::equals(math::abs(latitude), constants::max_latitude())) { // for the north and south pole we set the longitude to 0 // (works for both radians and degrees) longitude = CoordinateType(0); } } #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE BOOST_GEOMETRY_ASSERT(! math::larger(constants::min_latitude(), latitude)); BOOST_GEOMETRY_ASSERT(! math::larger(latitude, constants::max_latitude())); #endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE BOOST_GEOMETRY_ASSERT(math::smaller(constants::min_longitude(), longitude)); BOOST_GEOMETRY_ASSERT(! math::larger(longitude, constants::max_longitude())); }
static inline void apply(Point const& point, iterator_type first, iterator_type last, Strategy const& strategy, iterator_type& it_min1, iterator_type& it_min2, Distance& dist_min) { BOOST_GEOMETRY_ASSERT( first != last ); base_type::apply(point, first, last, strategy, it_min1, it_min2, dist_min); iterator_type it_back = --last; Distance const zero = Distance(0); Distance dist = strategy.apply(point, *it_back, *first); if (geometry::math::equals(dist, zero)) { dist_min = zero; it_min1 = it_back; it_min2 = first; } else if (dist < dist_min) { dist_min = dist; it_min1 = it_back; it_min2 = first; } }
static inline void apply(Box const& box, SegmentIdentifier const& seg_id, signed_size_type to_index, RobustPolicy const& robust_policy, RangeOut& current_output) { signed_size_type index = seg_id.segment_index + 1; BOOST_GEOMETRY_ASSERT(index < 5); signed_size_type const count = index <= to_index ? to_index - index + 1 : 5 - index + to_index + 1; // Create array of points, the fifth one closes it boost::array<typename point_type<Box>::type, 5> bp; assign_box_corners_oriented<Reverse>(box, bp); bp[4] = bp[0]; // (possibly cyclic) copy to output // (see comments in ring-version) for (signed_size_type i = 0; i < count; i++, index++) { detail::overlay::append_no_dups_or_spikes(current_output, bp[index % 5], robust_policy); } }
inline Point const& max_corner() const { #if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING) BOOST_GEOMETRY_ASSERT(m_created == 1); #endif return m_max_corner; }
inline bool pj_authset(T const& es, T* APA) { BOOST_GEOMETRY_ASSERT(0 != APA); static const T P00 = .33333333333333333333; static const T P01 = .17222222222222222222; static const T P02 = .10257936507936507936; static const T P10 = .06388888888888888888; static const T P11 = .06640211640211640211; static const T P20 = .01641501294219154443; T t = 0; // if (APA = (double *)pj_malloc(APA_SIZE * sizeof(double))) { APA[0] = es * P00; t = es * es; APA[0] += t * P01; APA[1] = t * P10; t *= es; APA[0] += t * P02; APA[1] += t * P11; APA[2] = t * P20; } return true; }
inline T pj_authlat(T const& beta, const T* APA) { BOOST_GEOMETRY_ASSERT(0 != APA); T const t = beta + beta; return(beta + APA[0] * sin(t) + APA[1] * sin(t + t) + APA[2] * sin(t + t + t)); }
inline bool apply(Turn const& turn) const { BOOST_GEOMETRY_ASSERT(boost::size(m_linestring) > 1); return m_is_closed && turn.method == overlay::method_none && check_segment_indices(turn, boost::size(m_linestring) - 2) && turn.operations[0].fraction.is_zero(); }
template <typename Id> static inline return_type apply(Geometry & geometry, Id const& id) { BOOST_GEOMETRY_ASSERT(0 <= id.multi_index); typedef typename boost::range_size<Geometry>::type size_type; size_type const mi = static_cast<size_type>(id.multi_index); return sub_sub_range::apply(range::at(geometry, mi), id); }
static inline return_type apply(PointOrSegmentIterator first, PointOrSegmentIterator last, Geometry const& geometry, Strategy const& strategy) { namespace sds = strategy::distance::services; BOOST_GEOMETRY_ASSERT( first != last ); if ( geometry::has_one_element(first, last) ) { return dispatch::distance < point_or_segment_type, Geometry, Strategy >::apply(*first, geometry, strategy); } typename sds::return_type < typename sds::comparable_type<Strategy>::type, typename point_type<point_or_segment_type>::type, typename point_type<Geometry>::type >::type cd_min; std::pair < point_or_segment_type, typename selector_type::iterator_type > closest_features = range_to_range::apply(first, last, selector_type::begin(geometry), selector_type::end(geometry), sds::get_comparable < Strategy >::apply(strategy), cd_min); return is_comparable<Strategy>::value ? cd_min : dispatch::distance < point_or_segment_type, typename std::iterator_traits < typename selector_type::iterator_type >::value_type, Strategy >::apply(closest_features.first, *closest_features.second, strategy); }
static inline bool is_boundary_point_of(Point const& point, Linestring const& linestring) { BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1); return ! geometry::equals(range::front(linestring), range::back(linestring)) && (geometry::equals(point, range::front(linestring)) || geometry::equals(point, range::back(linestring))); }
static inline Iterator find_different_from_first(Iterator first, Iterator last) { typedef not_equal_to<typename point_type<Range>::type> not_equal; BOOST_GEOMETRY_ASSERT(first != last); Iterator second = first; ++second; return std::find_if(second, last, not_equal(*first)); }
bool is_endpoint_boundary(point_type const& pt) const { boost::ignore_unused_variable_warning(pt); #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER // may give false positives for INT BOOST_GEOMETRY_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any) && detail::equals::equals_point_point(pt, range::front(geometry)) || (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any) && detail::equals::equals_point_point(pt, range::back(geometry)) ); #endif return has_boundary; }
static inline void apply(Ring const& ring, SegmentIdentifier const& seg_id, signed_size_type to_index, RobustPolicy const& robust_policy, RangeOut& current_output) { typedef typename closeable_view < Ring const, closure<Ring>::value >::type cview_type; typedef typename reversible_view < cview_type const, Reverse ? iterate_reverse : iterate_forward >::type rview_type; typedef typename boost::range_iterator<rview_type const>::type iterator; typedef geometry::ever_circling_iterator<iterator> ec_iterator; cview_type cview(ring); rview_type view(cview); // The problem: sometimes we want to from "3" to "2" // -> end = "3" -> end == begin // This is not convenient with iterators. // So we use the ever-circling iterator and determine when to step out signed_size_type const from_index = seg_id.segment_index + 1; // Sanity check BOOST_GEOMETRY_ASSERT(from_index < static_cast<signed_size_type>(boost::size(view))); ec_iterator it(boost::begin(view), boost::end(view), boost::begin(view) + from_index); // [2..4] -> 4 - 2 + 1 = 3 -> {2,3,4} -> OK // [4..2],size=6 -> 6 - 4 + 2 + 1 = 5 -> {4,5,0,1,2} -> OK // [1..1], travel the whole ring round signed_size_type const count = from_index <= to_index ? to_index - from_index + 1 : static_cast<signed_size_type>(boost::size(view)) - from_index + to_index + 1; for (signed_size_type i = 0; i < count; ++i, ++it) { detail::overlay::append_no_dups_or_spikes(current_output, *it, robust_policy); } }
static inline bool is_closing_point_of(Turn const& turn, Linestring const& linestring) { BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1); return turn.method == overlay::method_none && check_segment_indices(turn, boost::size(linestring) - 2) && geometry::equals(range::front(linestring), range::back(linestring)) && turn.operations[0].fraction.is_zero(); ; }
static inline bool apply(MultiGeometry const& multi, SegmentIdentifier const& seg_id, int offset, PointOut& point) { BOOST_GEOMETRY_ASSERT ( seg_id.multi_index >= 0 && seg_id.multi_index < int(boost::size(multi)) ); // Call the single-version return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, offset, point); }
static inline void apply(Point const& point, iterator_type first, iterator_type last, Strategy const& strategy, iterator_type& it_min1, iterator_type& it_min2, Distance& dist_min) { BOOST_GEOMETRY_ASSERT( first != last ); Distance const zero = Distance(0); iterator_type it = first; iterator_type prev = it++; if (it == last) { it_min1 = it_min2 = first; dist_min = strategy.apply(point, *first, *first); return; } // start with first segment distance dist_min = strategy.apply(point, *prev, *it); iterator_type prev_min_dist = prev; // check if other segments are closer for (++prev, ++it; it != last; ++prev, ++it) { Distance dist = strategy.apply(point, *prev, *it); if (geometry::math::equals(dist, zero)) { dist_min = zero; it_min1 = prev; it_min2 = it; return; } else if (dist < dist_min) { dist_min = dist; prev_min_dist = prev; } } it_min1 = it_min2 = prev_min_dist; ++it_min2; }
static inline void apply(Geometry const& geometry, RangeIterator first, RangeIterator last, Strategy const& strategy, RangeIterator& it_min, Distance& dist_min) { BOOST_GEOMETRY_ASSERT( first != last ); Distance const zero = Distance(0); // start with first distance it_min = first; dist_min = dispatch::distance < Geometry, typename std::iterator_traits<RangeIterator>::value_type, Strategy >::apply(geometry, *it_min, strategy); // check if other elements in the range are closer for (RangeIterator it = ++first; it != last; ++it) { Distance dist = dispatch::distance < Geometry, typename std::iterator_traits<RangeIterator>::value_type, Strategy >::apply(geometry, *it, strategy); if (geometry::math::equals(dist, zero)) { dist_min = dist; it_min = it; return; } else if (dist < dist_min) { dist_min = dist; it_min = it; } } }
static inline void apply(MultiGeometry const& multi_geometry, SegmentIdentifier const& seg_id, signed_size_type to_index, RobustPolicy const& robust_policy, RangeOut& current_output) { BOOST_GEOMETRY_ASSERT ( seg_id.multi_index >= 0 && static_cast<std::size_t>(seg_id.multi_index) < boost::size(multi_geometry) ); // Call the single-version Policy::apply(range::at(multi_geometry, seg_id.multi_index), seg_id, to_index, robust_policy, current_output); }
static inline void output_ranges(container_type const& first, container_type const& second, OutputIterator out, bool closed) { std::copy(boost::begin(first), boost::end(first), out); BOOST_GEOMETRY_ASSERT(closed ? !boost::empty(second) : boost::size(second) > 1); std::copy(++boost::rbegin(second), // skip the first Point closed ? boost::rend(second) : --boost::rend(second), // skip the last Point if open out); typedef typename boost::range_size<container_type>::type size_type; size_type const count = boost::size(first) + boost::size(second) - 1; // count describes a closed case but comparison with min size of closed // gives the result compatible also with open // here core_detail::closure::minimum_ring_size<closed> could be used if (count < 4) { // there should be only one missing *out++ = *boost::begin(first); } }
static inline void apply(CoordinateType& longitude1, CoordinateType& latitude1, CoordinateType& longitude2, CoordinateType& latitude2, bool band) { normalize::apply(longitude1, latitude1, false); normalize::apply(longitude2, latitude2, false); if (math::equals(latitude1, constants::min_latitude()) && math::equals(latitude2, constants::min_latitude())) { // box degenerates to the south pole longitude1 = longitude2 = CoordinateType(0); } else if (math::equals(latitude1, constants::max_latitude()) && math::equals(latitude2, constants::max_latitude())) { // box degenerates to the north pole longitude1 = longitude2 = CoordinateType(0); } else if (band) { // the box is a band between two small circles (parallel // to the equator) on the spheroid longitude1 = constants::min_longitude(); longitude2 = constants::max_longitude(); } else if (longitude1 > longitude2) { // the box crosses the antimeridian, so we need to adjust // the longitudes longitude2 += constants::period(); } #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE BOOST_GEOMETRY_ASSERT(! math::larger(latitude1, latitude2)); BOOST_GEOMETRY_ASSERT(! math::smaller(latitude1, constants::min_latitude())); BOOST_GEOMETRY_ASSERT(! math::larger(latitude2, constants::max_latitude())); #endif BOOST_GEOMETRY_ASSERT(! math::larger(longitude1, longitude2)); BOOST_GEOMETRY_ASSERT(! math::smaller(longitude1, constants::min_longitude())); BOOST_GEOMETRY_ASSERT (! math::larger(longitude2 - longitude1, constants::period())); }
static inline bool handle_internal(Point1 const& /*i1*/, Point1 const& /*j1*/, Point1 const& /*k1*/, Point2 const& i2, Point2 const& j2, Point2 const& /*k2*/, RobustPoint1 const& ri1, RobustPoint1 const& rj1, RobustPoint1 const& /*rk1*/, RobustPoint2 const& ri2, RobustPoint2 const& rj2, RobustPoint2 const& rk2, bool first1, bool last1, bool first2, bool last2, bool ip_i2, bool ip_j2, TurnInfo const& tp_model, IntersectionInfo const& inters, unsigned int ip_index, operation_type & op1, operation_type & op2) { boost::ignore_unused_variable_warning(i2); boost::ignore_unused_variable_warning(j2); boost::ignore_unused_variable_warning(ip_index); boost::ignore_unused_variable_warning(tp_model); if ( !first2 && !last2 ) { if ( first1 ) { #ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR // may this give false positives for INTs? typename IntersectionResult::point_type const& inters_pt = inters.i_info().intersections[ip_index]; BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); #endif if ( ip_i2 ) { // don't output this IP - for the first point of other geometry segment op1 = operation_none; op2 = operation_none; return true; } else if ( ip_j2 ) { side_calculator<RobustPoint1, RobustPoint2, RobustPoint2> side_calc(ri2, ri1, rj1, ri2, rj2, rk2); std::pair<operation_type, operation_type> operations = operations_of_equal(side_calc); // TODO: must the above be calculated? // wouldn't it be enough to check if segments are collinear? if ( operations_both(operations, operation_continue) ) { if ( op1 != operation_union || op2 != operation_union || ! ( G1Index == 0 ? inters.is_spike_q() : inters.is_spike_p() ) ) { // THIS IS WRT THE ORIGINAL SEGMENTS! NOT THE ONES ABOVE! bool opposite = inters.d_info().opposite; op1 = operation_intersection; op2 = opposite ? operation_union : operation_intersection; } } else { BOOST_GEOMETRY_ASSERT(operations_combination(operations, operation_intersection, operation_union)); //op1 = operation_union; //op2 = operation_union; } return true; } // else do nothing - shouldn't be handled this way } else if ( last1 ) { #ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR // may this give false positives for INTs? typename IntersectionResult::point_type const& inters_pt = inters.i_info().intersections[ip_index]; BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); #endif if ( ip_i2 ) { // don't output this IP - for the first point of other geometry segment op1 = operation_none; op2 = operation_none; return true; } else if ( ip_j2 ) { side_calculator<RobustPoint1, RobustPoint2, RobustPoint2> side_calc(ri2, rj1, ri1, ri2, rj2, rk2); std::pair<operation_type, operation_type> operations = operations_of_equal(side_calc); // TODO: must the above be calculated? // wouldn't it be enough to check if segments are collinear? if ( operations_both(operations, operation_continue) ) { if ( op1 != operation_blocked || op2 != operation_union || ! ( G1Index == 0 ? inters.is_spike_q() : inters.is_spike_p() ) ) { // THIS IS WRT THE ORIGINAL SEGMENTS! NOT THE ONES ABOVE! bool second_going_out = inters.i_info().count > 1; op1 = operation_blocked; op2 = second_going_out ? operation_union : operation_intersection; } } else { BOOST_GEOMETRY_ASSERT(operations_combination(operations, operation_intersection, operation_union)); //op1 = operation_blocked; //op2 = operation_union; } return true; } // else do nothing - shouldn't be handled this way } // else do nothing - shouldn't be handled this way } return false; }
static inline bool analyse_segment_and_assign_ip(Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, bool is_p_first, bool is_p_last, bool is_q_first, bool is_q_last, linear_intersections::ip_info const& ip_info, TurnInfo const& tp_model, IntersectionInfo const& inters, unsigned int ip_index, OutputIterator out) { #ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR // may this give false positives for INTs? typename IntersectionResult::point_type const& inters_pt = result.template get<0>().intersections[ip_index]; BOOST_GEOMETRY_ASSERT(ip_info.is_pi == equals::equals_point_point(pi, inters_pt)); BOOST_GEOMETRY_ASSERT(ip_info.is_qi == equals::equals_point_point(qi, inters_pt)); BOOST_GEOMETRY_ASSERT(ip_info.is_pj == equals::equals_point_point(pj, inters_pt)); BOOST_GEOMETRY_ASSERT(ip_info.is_qj == equals::equals_point_point(qj, inters_pt)); #endif // TODO - calculate first/last only if needed bool is_p_first_ip = is_p_first && ip_info.is_pi; bool is_p_last_ip = is_p_last && ip_info.is_pj; bool is_q_first_ip = is_q_first && ip_info.is_qi; bool is_q_last_ip = is_q_last && ip_info.is_qj; bool append_first = EnableFirst && (is_p_first_ip || is_q_first_ip); bool append_last = EnableLast && (is_p_last_ip || is_q_last_ip); operation_type p_operation = ip_info.p_operation; operation_type q_operation = ip_info.q_operation; if ( append_first || append_last ) { bool handled = handle_internal<0>(pi, pj, pk, qi, qj, qk, inters.rpi(), inters.rpj(), inters.rpk(), inters.rqi(), inters.rqj(), inters.rqk(), is_p_first_ip, is_p_last_ip, is_q_first_ip, is_q_last_ip, ip_info.is_qi, ip_info.is_qj, tp_model, inters, ip_index, p_operation, q_operation); if ( !handled ) { handle_internal<1>(qi, qj, qk, pi, pj, pk, inters.rqi(), inters.rqj(), inters.rqk(), inters.rpi(), inters.rpj(), inters.rpk(), is_q_first_ip, is_q_last_ip, is_p_first_ip, is_p_last_ip, ip_info.is_pi, ip_info.is_pj, tp_model, inters, ip_index, q_operation, p_operation); } if ( p_operation != operation_none ) { method_type method = endpoint_ip_method(ip_info.is_pi, ip_info.is_pj, ip_info.is_qi, ip_info.is_qj); turn_position p_pos = ip_position(is_p_first_ip, is_p_last_ip); turn_position q_pos = ip_position(is_q_first_ip, is_q_last_ip); // handle spikes // P is spike and should be handled if ( !is_p_last && ip_info.is_pj // this check is redundant (also in is_spike_p) but faster && inters.i_info().count == 2 && inters.is_spike_p() ) { assign(pi, qi, inters.result(), ip_index, method, operation_blocked, q_operation, p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out); assign(pi, qi, inters.result(), ip_index, method, operation_intersection, q_operation, p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out); } // Q is spike and should be handled else if ( !is_q_last && ip_info.is_qj // this check is redundant (also in is_spike_q) but faster && inters.i_info().count == 2 && inters.is_spike_q() ) { assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_blocked, p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out); assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_intersection, p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out); } // no spikes else { assign(pi, qi, inters.result(), ip_index, method, p_operation, q_operation, p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, false, tp_model, out); } } } return append_last; }
static inline return_type apply(Geometry & g, Id const& id) { BOOST_GEOMETRY_ASSERT(id.multi_index >= 0); typedef typename geofeatures_boost::range_size<Geometry>::type size_type; return range::at(g, static_cast<size_type>(id.multi_index)); }
void check_value(CmpVal const& cmp_val) const { unsigned_type b = base; // a workaround for MinGW - undefined reference base CmpVal val = CmpVal(m_sign) * (CmpVal(m_ms) * CmpVal(b) + CmpVal(m_ls)); BOOST_GEOMETRY_ASSERT(cmp_val == val); }