grid_traits( const boost::tuple<coordinate_type, coordinate_type, coordinate_type, coordinate_type>& bounds, const coordinate_type& cellWidth ) : m_xmin( boost::get<e_xmin>(bounds) ) , m_xmax( boost::get<e_xmax>( bounds ) ) , m_ymin( boost::get<e_ymin>( bounds ) ) , m_ymax( boost::get<e_ymax>( bounds ) ) , m_cellWidth( cellWidth ) , m_cellWidthDivisor(constants::one<dimensionless_type>() / cellWidth ) { GEOMETRIX_ASSERT( cellWidth > constants::zero<coordinate_type>()); GEOMETRIX_ASSERT( m_xmin < m_xmax && m_ymin < m_ymax ); m_numberXCells = boost::numeric_cast<boost::uint32_t>((m_xmax - m_xmin) * m_cellWidthDivisor) + 1; m_numberYCells = boost::numeric_cast<boost::uint32_t>((m_ymax - m_ymin) * m_cellWidthDivisor) + 1; }
grid_traits( const coordinate_type& xmin, const coordinate_type& xmax, const coordinate_type& ymin, const coordinate_type& ymax, const coordinate_type& cellWidth ) : m_xmin(xmin) , m_xmax(xmax) , m_ymin(ymin) , m_ymax(ymax) , m_cellWidth(cellWidth) , m_cellWidthDivisor(constants::one<dimensionless_type>()/cellWidth) { GEOMETRIX_ASSERT( cellWidth > constants::zero<coordinate_type>()); GEOMETRIX_ASSERT( xmin < xmax && ymin < ymax ); m_numberXCells = boost::numeric_cast<boost::uint32_t>( (m_xmax - m_xmin) * m_cellWidthDivisor ) + 1; m_numberYCells = boost::numeric_cast<boost::uint32_t>((m_ymax - m_ymin) * m_cellWidthDivisor ) + 1; }
inline typename result_of::point_polygon_closest_point<Point, typename PolygonCollection::value_type>::type point_polygon_collection_closest_point(const Point& p, const PolygonCollection& polygons) { using polygon_t = typename PolygonCollection::value_type; using access = point_sequence_traits<polygon_t>; using segment_type = segment<typename geometric_traits<polygon_t>::point_type>; using distance_sqrd_type = typename result_of::point_segment_distance_sqrd<Point, segment_type>::type; auto distance = std::numeric_limits<distance_sqrd_type>::infinity(); std::size_t minSegmentI, minSegmentJ; polygon_t const* pgon = nullptr; for (const auto& poly : polygons) { auto size = access::size(poly); for (std::size_t i = size - 1, j = 0; j < size; i = j++) { auto ldistance = point_segment_distance_sqrd(p, access::get_point(poly, i), access::get_point(poly, j)); if (ldistance < distance) { pgon = &poly; distance = ldistance; minSegmentI = i; minSegmentJ = j; } } } GEOMETRIX_ASSERT(pgon); return point_segment_closest_point(p, access::get_point(*pgon, minSegmentI), access::get_point(*pgon, minSegmentJ)); }
data_type& get_cell(const Point& point) { BOOST_CONCEPT_ASSERT(( Point2DConcept<Point> )); GEOMETRIX_ASSERT( is_contained( point ) ); boost::uint32_t i = m_gridTraits.get_x_index(get<0>(point)); boost::uint32_t j = m_gridTraits.get_y_index(get<1>(point)); return get_cell(i,j); }
inline void ramer_douglas_peucker_algorithm(const Polyline& poly, Polyline& nPoly, std::size_t start, std::size_t end, const Length& epsilon) { using access = point_sequence_traits<Polyline>; using point_t = typename access::point_type; using length_t = typename geometric_traits<point_t>::arithmetic_type; using dimensionless_t = typename geometric_traits<point_t>::dimensionless_type; using vector_t = vector<dimensionless_t, dimension_of<point_t>::value>; using line_t = line<point_t, vector_t>; // Find the point with the maximum distance auto dmax = constants::zero<length_t>(); boost::optional<std::size_t> index; if ((start + 2) < end) { line_t l(access::get_point(poly, start), access::get_point(poly, end - 1)); for (std::size_t i = start + 1; (i + 1) < end; ++i) { auto d = point_line_distance(access::get_point(poly, i), l); if (d > dmax) { index = i; dmax = d; } } } // If max distance is greater than epsilon, recursively simplify if (dmax > epsilon) { GEOMETRIX_ASSERT(index); ramer_douglas_peucker_algorithm(poly, nPoly, start, *index, epsilon); access::pop_back(nPoly); ramer_douglas_peucker_algorithm(poly, nPoly, *index, end, epsilon); } else { GEOMETRIX_ASSERT((start + 1) != end); access::push_back(nPoly, access::get_point(poly,start)); access::push_back(nPoly, access::get_point(poly, end-1)); } }
//! Convenience border point accessor. sequence_type operator[](std::size_t i) const { GEOMETRIX_ASSERT(i < 4); switch (i) { case 0: return m_low; case 1: return construct<sequence_type>(get<0>(m_high), get<1>(m_low)); case 2: return m_high; case 3: return construct<sequence_type>(get<0>(m_low), get<1>(m_high)); }; throw std::out_of_range("box has 4 points"); }
//! Convenience border point accessor. point_type operator[](std::size_t i) const { GEOMETRIX_ASSERT(i < 4); switch (i) { case 0: return get_right_backward_point(); case 1: return get_right_forward_point(); case 2: return get_left_forward_point(); case 3: return get_left_backward_point(); }; throw std::out_of_range("box has 4 points"); }
inline typename result_of::normal_at_index<Index,Vector>::type normal_at_index( const Vector& v ) { BOOST_CONCEPT_ASSERT(( VectorConcept<Vector> )); GEOMETRIX_ASSERT(magnitude(v) != 0); return arithmetic_promote( get<Index>(v) ) / magnitude( v ); }
inline orientation_type point_polyline_orientation(const Point& p, const Polyline& pline, const NumberComparisonPolicy& cmp) { BOOST_CONCEPT_ASSERT((PointSequenceConcept<Polyline>)); BOOST_CONCEPT_ASSERT((NumberComparisonPolicyConcept<NumberComparisonPolicy>)); using access = point_sequence_traits<Polyline>; GEOMETRIX_ASSERT(access::size(pline) > 1); using length_t = typename select_arithmetic_type_from_sequences<Point, typename access::point_type>::type; using area_t = decltype(std::declval<length_t>() * std::declval<length_t>()); using dimensionless_t = decltype(std::declval<length_t>() / std::declval<length_t>()); using vector_t = vector<length_t, dimension_of<Point>::value>; auto minDistance = (std::numeric_limits<area_t>::max)(); std::size_t segIndex; for (std::size_t i = 0, j = 1; j < access::size(pline); i = j++) { auto d2 = point_segment_distance_sqrd(p, access::get_point(pline, i), access::get_point(pline, j)); if (d2 < minDistance) { minDistance = d2; segIndex = i; } } if (cmp.greater_than(minDistance, constants::zero<area_t>())) { GEOMETRIX_ASSERT(minDistance < (std::numeric_limits<area_t>::max)()); auto pi = access::get_point(pline, segIndex); auto pj = access::get_point(pline, segIndex + 1); dimensionless_t t; point_segment_closest_point_and_param(p, pi, pj, t); if (t > constants::zero<dimensionless_t>() && t < constants::one<dimensionless_t>()) return get_orientation(pi, pj, p, cmp); else if (cmp.equals(t, constants::zero<dimensionless_t>())) { //! Closest point is a vertex i. if (segIndex != 0) { auto ph = access::get_point(pline, segIndex - 1); auto o = get_orientation(ph, pi, pj, cmp); if (o == oriented_left) { vector_t vpi = p - pi; vector_t lo = pj - pi; vector_t hi = ph - pi; if (is_vector_between(lo, hi, vpi, false, cmp)) return oriented_left; else return oriented_right; } else if (o == oriented_right) { vector_t vpi = p - pi; vector_t hi = pj - pi; vector_t lo = ph - pi; if (is_vector_between(lo, hi, vpi, false, cmp)) return oriented_right; else return oriented_left; } else return get_orientation(pi, pj, p, cmp); } else return get_orientation(pi, pj, p, cmp); } else { //! pj is the closest. if ((segIndex + 2) < access::size(pline)) { auto pk = access::get_point(pline, segIndex + 2); auto o = get_orientation(pi, pj, pk, cmp); if (o == oriented_left) { vector_t vpj = p - pj; vector_t lo = pk - pj; vector_t hi = pi - pj; if (is_vector_between(lo, hi, vpj, false, cmp)) return oriented_left; else return oriented_right; } else if (o == oriented_right) { vector_t vpj = p - pj; vector_t hi = pk - pj; vector_t lo = pi - pj; if (is_vector_between(lo, hi, vpj, false, cmp)) return oriented_right; else return oriented_left; } else return get_orientation(pi, pj, p, cmp); } else return get_orientation(pi, pj, p, cmp); } } return oriented_collinear; }
boost::uint32_t get_y_index(coordinate_type y) const { GEOMETRIX_ASSERT( y >= m_ymin && y <= m_ymax ); return static_cast<boost::uint32_t>((y - m_ymin) * m_cellWidthDivisor); }
boost::uint32_t get_x_index(coordinate_type x) const { GEOMETRIX_ASSERT( x >= m_xmin && x <= m_xmax ); return static_cast<boost::uint32_t>((x - m_xmin) * m_cellWidthDivisor); }