Corrected closure for area

Added closure for centroid
Modified/fixed closing iterator (didn't compile for MSVC 2010)


[SVN r62172]
This commit is contained in:
Barend Gehrels 2010-05-24 13:54:32 +00:00
parent 04d8c000be
commit 5fb11344e4
11 changed files with 147 additions and 61 deletions

View File

@ -18,6 +18,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c07_custom_ring_pointer_exa
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c08_custom_non_std_example", "c08_custom_non_std_example.vcproj", "{C215F131-F021-4155-A96E-BB2D91918A17}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c08_custom_non_std_example", "c08_custom_non_std_example.vcproj", "{C215F131-F021-4155-A96E-BB2D91918A17}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c09_custom_fusion_example", "c09_custom_fusion_example.vcproj", "{DA36AD55-E448-43DE-A974-EA765AE3967A}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
@ -60,6 +62,10 @@ Global
{C215F131-F021-4155-A96E-BB2D91918A17}.Debug|Win32.Build.0 = Debug|Win32 {C215F131-F021-4155-A96E-BB2D91918A17}.Debug|Win32.Build.0 = Debug|Win32
{C215F131-F021-4155-A96E-BB2D91918A17}.Release|Win32.ActiveCfg = Release|Win32 {C215F131-F021-4155-A96E-BB2D91918A17}.Release|Win32.ActiveCfg = Release|Win32
{C215F131-F021-4155-A96E-BB2D91918A17}.Release|Win32.Build.0 = Release|Win32 {C215F131-F021-4155-A96E-BB2D91918A17}.Release|Win32.Build.0 = Release|Win32
{DA36AD55-E448-43DE-A974-EA765AE3967A}.Debug|Win32.ActiveCfg = Debug|Win32
{DA36AD55-E448-43DE-A974-EA765AE3967A}.Debug|Win32.Build.0 = Debug|Win32
{DA36AD55-E448-43DE-A974-EA765AE3967A}.Release|Win32.ActiveCfg = Release|Win32
{DA36AD55-E448-43DE-A974-EA765AE3967A}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -31,7 +31,6 @@
#include <boost/geometry/strategies/concepts/area_concept.hpp> #include <boost/geometry/strategies/concepts/area_concept.hpp>
#include <boost/geometry/util/closure_as_bool.hpp>
#include <boost/geometry/util/math.hpp> #include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/order_as_direction.hpp> #include <boost/geometry/util/order_as_direction.hpp>
#include <boost/geometry/util/closeable_view.hpp> #include <boost/geometry/util/closeable_view.hpp>
@ -122,7 +121,7 @@ struct ring_area
typedef closeable_view typedef closeable_view
< <
rview_type const, rview_type const,
Closure == closed Closure == open // close it if it is open
> view_type; > view_type;
typedef typename boost::range_iterator<view_type const>::type iterator_type; typedef typename boost::range_iterator<view_type const>::type iterator_type;

View File

@ -15,16 +15,19 @@
#include <boost/range.hpp> #include <boost/range.hpp>
#include <boost/geometry/algorithms/distance.hpp> #include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/exception.hpp> #include <boost/geometry/core/exception.hpp>
#include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp> #include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp> #include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/strategies/centroid.hpp> #include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/concepts/centroid_concept.hpp> #include <boost/geometry/strategies/concepts/centroid_concept.hpp>
#include <boost/geometry/util/closeable_view.hpp>
#include <boost/geometry/util/copy.hpp> #include <boost/geometry/util/copy.hpp>
#include <boost/geometry/util/for_each_coordinate.hpp> #include <boost/geometry/util/for_each_coordinate.hpp>
@ -182,41 +185,34 @@ inline bool range_ok(Range const& range, Point& centroid)
/*! /*!
\brief Calculate the centroid of a ring. \brief Calculate the centroid of a ring.
*/ */
template<typename Ring, typename Strategy> template<typename Ring, closure_selector Closure, typename Strategy>
struct centroid_ring_state struct centroid_ring_state
{ {
static inline void apply(Ring const& ring, static inline void apply(Ring const& ring,
Strategy const& strategy, typename Strategy::state_type& state) Strategy const& strategy, typename Strategy::state_type& state)
{ {
typedef typename boost::range_iterator<Ring const>::type iterator_type; typedef closeable_view
iterator_type it = boost::begin(ring); <
Ring const,
Closure == open // close it if it is open
> 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++; for (iterator_type previous = it++;
it != boost::end(ring); it != end;
previous = it++) ++previous, ++it)
{ {
Strategy::apply(*previous, *it, state); Strategy::apply(*previous, *it, state);
} }
/* using segment_iterator: nice, well looking, but much slower...
normal iterator: 0.156 s
segment iterator: 1.985 s...
typedef segment_iterator
<
typename boost::range_iterator<Ring const>::type,
typename point_type<Ring>::type
> iterator_type;
iterator_type it(boost::begin(ring), boost::end(ring));
iterator_type end(boost::end(ring));
for(; it != end; ++it)
{
Strategy::apply(it->first, it->second, state);
}
*/
} }
}; };
template<typename Ring, typename Point, typename Strategy> template<typename Ring, typename Point, closure_selector Closure, typename Strategy>
struct centroid_ring struct centroid_ring
{ {
static inline void apply(Ring const& ring, Point& centroid, static inline void apply(Ring const& ring, Point& centroid,
@ -228,6 +224,7 @@ struct centroid_ring
centroid_ring_state centroid_ring_state
< <
Ring, Ring,
Closure,
Strategy Strategy
>::apply(ring, strategy, state); >::apply(ring, strategy, state);
Strategy::result(state, centroid); Strategy::result(state, centroid);
@ -279,7 +276,7 @@ struct centroid_linestring
\note Because outer ring is clockwise, inners are counter clockwise, \note Because outer ring is clockwise, inners are counter clockwise,
triangle approach is OK and works for polygons with rings. triangle approach is OK and works for polygons with rings.
*/ */
template<typename Polygon, typename Strategy> template<typename Polygon, closure_selector Closure, typename Strategy>
struct centroid_polygon_state struct centroid_polygon_state
{ {
static inline void apply(Polygon const& poly, static inline void apply(Polygon const& poly,
@ -288,6 +285,7 @@ struct centroid_polygon_state
typedef centroid_ring_state typedef centroid_ring_state
< <
typename ring_type<Polygon>::type, typename ring_type<Polygon>::type,
Closure,
Strategy Strategy
> per_ring; > per_ring;
@ -305,7 +303,7 @@ struct centroid_polygon_state
} }
}; };
template<typename Polygon, typename Point, typename Strategy> template<typename Polygon, typename Point, closure_selector Closure, typename Strategy>
struct centroid_polygon struct centroid_polygon
{ {
static inline void apply(Polygon const& poly, Point& centroid, static inline void apply(Polygon const& poly, Point& centroid,
@ -317,6 +315,7 @@ struct centroid_polygon
centroid_polygon_state centroid_polygon_state
< <
Polygon, Polygon,
Closure,
Strategy Strategy
>::apply(poly, strategy, state); >::apply(poly, strategy, state);
Strategy::result(state, centroid); Strategy::result(state, centroid);
@ -338,6 +337,7 @@ template
typename Tag, typename Tag,
typename Geometry, typename Geometry,
typename Point, typename Point,
closure_selector Closure,
typename Strategy typename Strategy
> >
struct centroid {}; struct centroid {};
@ -346,9 +346,10 @@ template
< <
typename Geometry, typename Geometry,
typename Point, typename Point,
closure_selector Closure,
typename Strategy typename Strategy
> >
struct centroid<point_tag, Geometry, Point, Strategy> struct centroid<point_tag, Geometry, Point, Closure, Strategy>
: detail::centroid::centroid_point<Geometry, Point, Strategy> : detail::centroid::centroid_point<Geometry, Point, Strategy>
{}; {};
@ -356,25 +357,26 @@ template
< <
typename Box, typename Box,
typename Point, typename Point,
closure_selector Closure,
typename Strategy typename Strategy
> >
struct centroid<box_tag, Box, Point, Strategy> struct centroid<box_tag, Box, Point, Closure, Strategy>
: detail::centroid::centroid_box<Box, Point, Strategy> : detail::centroid::centroid_box<Box, Point, Strategy>
{}; {};
template <typename Ring, typename Point, typename Strategy> template <typename Ring, typename Point, closure_selector Closure, typename Strategy>
struct centroid<ring_tag, Ring, Point, Strategy> struct centroid<ring_tag, Ring, Point, Closure, Strategy>
: detail::centroid::centroid_ring<Ring, Point, Strategy> : detail::centroid::centroid_ring<Ring, Point, Closure, Strategy>
{}; {};
template <typename Linestring, typename Point, typename Strategy> template <typename Linestring, typename Point, closure_selector Closure, typename Strategy>
struct centroid<linestring_tag, Linestring, Point, Strategy> struct centroid<linestring_tag, Linestring, Point, Closure, Strategy>
: detail::centroid::centroid_linestring<Linestring, Point, Strategy> : detail::centroid::centroid_linestring<Linestring, Point, Strategy>
{}; {};
template <typename Polygon, typename Point, typename Strategy> template <typename Polygon, typename Point, closure_selector Closure, typename Strategy>
struct centroid<polygon_tag, Polygon, Point, Strategy> struct centroid<polygon_tag, Polygon, Point, Closure, Strategy>
: detail::centroid::centroid_polygon<Polygon, Point, Strategy> : detail::centroid::centroid_polygon<Polygon, Point, Closure, Strategy>
{}; {};
} // namespace dispatch } // namespace dispatch
@ -405,6 +407,7 @@ inline void centroid(Geometry const& geometry, Point& c,
typename tag<Geometry>::type, typename tag<Geometry>::type,
Geometry, Geometry,
Point, Point,
geometry::closure<Geometry>::value,
Strategy Strategy
>::apply(geometry, c, strategy); >::apply(geometry, c, strategy);
} }

View File

@ -16,6 +16,7 @@
#include <boost/range.hpp> #include <boost/range.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/ring_type.hpp> #include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/exterior_ring.hpp>
@ -114,12 +115,21 @@ struct correct_ring
if (boost::size(r) > 2) if (boost::size(r) > 2)
{ {
// check if closed, if not, close it // check if closed, if not, close it
if (geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1))) bool const disjoint = geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1));
closure_selector s = geometry::closure<Ring>::value;
if (disjoint && (s == closed))
{ {
// Close it
point_type first; point_type first;
geometry::copy_coordinates(*boost::begin(r), first); geometry::copy_coordinates(*boost::begin(r), first);
*(std::back_inserter(r)++) = first; *(std::back_inserter(r)++) = first;
} }
if (! disjoint && geometry::closure<Ring>::value != closed)
{
// Open it, TODO!
std::cout << "TODO";
}
} }
// Check area // Check area
Predicate predicate; Predicate predicate;

View File

@ -220,7 +220,8 @@ struct transform_range
{ {
typedef typename point_type<Range2>::type point_type; typedef typename point_type<Range2>::type point_type;
geometry::clear(range2); // Should NOT be done here!
// geometry::clear(range2);
return transform_range_out<point_type>(range1, return transform_range_out<point_type>(range1,
std::back_inserter(range2), strategy); std::back_inserter(range2), strategy);
} }

View File

@ -86,7 +86,29 @@ struct point_order< linear_ring<P, V, true, Closed, A> >
static const order_selector value = clockwise; static const order_selector value = clockwise;
}; };
template
<
typename P,
template<typename, typename> class V,
bool PointOrder,
template<typename> class A
>
struct closure< linear_ring<P, V, PointOrder, true, A> >
{
static const closure_selector value = closed;
};
template
<
typename P,
template<typename, typename> class V,
bool PointOrder,
template<typename> class A
>
struct closure< linear_ring<P, V, PointOrder, false, A> >
{
static const closure_selector value = open;
};
} // namespace traits } // namespace traits

View File

@ -13,7 +13,6 @@
#include <boost/iterator/iterator_adaptor.hpp> #include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_categories.hpp>
#include <boost/geometry/iterators/base.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -29,15 +28,14 @@ namespace boost { namespace geometry
*/ */
template <typename Range> template <typename Range>
struct closing_iterator struct closing_iterator
: public detail::iterators::iterator_base : public boost::iterator_adaptor
< <
closing_iterator<Range>, closing_iterator<Range>,
typename boost::range_iterator<Range>::type, typename boost::range_iterator<Range>::type,
boost::forward_traversal_tag boost::use_default,
> boost::forward_traversal_tag
>
{ {
friend class boost::iterator_core_access;
explicit inline closing_iterator(Range& range) explicit inline closing_iterator(Range& range)
: m_range(range) : m_range(range)
, m_beyond(false) , m_beyond(false)
@ -55,15 +53,15 @@ struct closing_iterator
this->base_reference() = m_end; this->base_reference() = m_end;
} }
inline bool equal(closing_iterator const& other) const private:
friend class boost::iterator_core_access;
inline bool equal(closing_iterator<Range> const& other) const
{ {
return this->base() == other.base() return this->base() == other.base()
&& this->m_beyond == other.m_beyond; && this->m_beyond == other.m_beyond;
} }
private:
inline void increment() inline void increment()
{ {
if (m_beyond) if (m_beyond)

View File

@ -103,9 +103,10 @@ template
< <
typename MultiPolygon, typename MultiPolygon,
typename Point, typename Point,
closure_selector Closure,
typename Strategy typename Strategy
> >
struct centroid<multi_polygon_tag, MultiPolygon, Point, Strategy> struct centroid<multi_polygon_tag, MultiPolygon, Point, Closure, Strategy>
: detail::centroid::centroid_multi : detail::centroid::centroid_multi
< <
MultiPolygon, MultiPolygon,
@ -114,6 +115,7 @@ struct centroid<multi_polygon_tag, MultiPolygon, Point, Strategy>
detail::centroid::centroid_polygon_state detail::centroid::centroid_polygon_state
< <
typename boost::range_value<MultiPolygon>::type, typename boost::range_value<MultiPolygon>::type,
Closure,
Strategy Strategy
> >
> >
@ -124,9 +126,10 @@ template
< <
typename MultiPoint, typename MultiPoint,
typename Point, typename Point,
closure_selector Closure,
typename Strategy typename Strategy
> >
struct centroid<multi_point_tag, MultiPoint, Point, Strategy> struct centroid<multi_point_tag, MultiPoint, Point, Closure, Strategy>
: detail::centroid::centroid_multi : detail::centroid::centroid_multi
< <
MultiPoint, MultiPoint,

View File

@ -43,6 +43,11 @@ void test_2d()
",3.7 1.6,3.4 1.2,2.8 1.8,2.4 1.7,2 1.3))", ",3.7 1.6,3.4 1.2,2.8 1.8,2.4 1.7,2 1.3))",
4.06923363095238, 1.65055803571429); 4.06923363095238, 1.65055803571429);
// open / closed
test_centroid<boost::geometry::linear_ring<P, std::vector, true, true> >(
"POLYGON((1 1,2 2,3 1,2 0,1 1))", 2.0, 1.0);
test_centroid<boost::geometry::linear_ring<P, std::vector, true, false> >(
"POLYGON((1 1,2 2,3 1,2 0))", 2.0, 1.0);
test_centroid<boost::geometry::box<P> >("POLYGON((1 2,3 4))", 2, 3); test_centroid<boost::geometry::box<P> >("POLYGON((1 2,3 4))", 2, 3);
test_centroid<P>("POINT(3 3)", 3, 3); test_centroid<P>("POINT(3 3)", 3, 3);

View File

@ -67,10 +67,10 @@ template <typename P>
void test_all() void test_all()
{ {
// Define clockwise and counter clockwise polygon // Define clockwise and counter clockwise polygon
std::string cw_ring = std::string cw_ring = "POLYGON((0 0,0 1,1 1,1 0,0 0))";
"POLYGON((0 0,0 1,1 1,1 0,0 0))"; std::string ccw_ring = "POLYGON((0 0,1 0,1 1,0 1,0 0))";
std::string ccw_ring = std::string cw_open_ring = "POLYGON((0 0,0 1,1 1,1 0))";
"POLYGON((0 0,1 0,1 1,0 1,0 0))"; std::string ccw_open_ring = "POLYGON((0 0,1 0,1 1,0 1))";
// already cw_ring // already cw_ring
test_geometry<boost::geometry::linear_ring<P> >(cw_ring, cw_ring); test_geometry<boost::geometry::linear_ring<P> >(cw_ring, cw_ring);
@ -78,9 +78,23 @@ void test_all()
// wrong order // wrong order
test_geometry<boost::geometry::linear_ring<P> >(ccw_ring, cw_ring); test_geometry<boost::geometry::linear_ring<P> >(ccw_ring, cw_ring);
// ccw-ring, input ccw-ring, already correct
test_geometry<boost::geometry::linear_ring<P, std::vector, false> >(ccw_ring, ccw_ring);
// ccw-ring, input cw-ring, corrected
test_geometry<boost::geometry::linear_ring<P, std::vector, false> >(cw_ring, ccw_ring);
// open-ring, input ccw-ring, already correct
test_geometry<boost::geometry::linear_ring<P, std::vector, true, false> >(cw_open_ring, cw_open_ring);
// ccw-ring, input cw-ring, corrected
test_geometry<boost::geometry::linear_ring<P, std::vector, true, false> >(ccw_open_ring, "POLYGON((0 1,1 1,1 0,0 0))");
// not closed // not closed
test_geometry<boost::geometry::linear_ring<P> >( test_geometry<boost::geometry::linear_ring<P> >(
"POLYGON((0 0,1 0,1 1,0 1))", ccw_open_ring,
cw_ring); cw_ring);
// counter clockwise, cw_ring // counter clockwise, cw_ring
@ -99,7 +113,7 @@ void test_all()
cw_ring); cw_ring);
// wrong order & not closed // wrong order & not closed
test_geometry<boost::geometry::polygon<P> >( test_geometry<boost::geometry::polygon<P> >(
"POLYGON((0 0,1 0,1 1,0 1))", ccw_open_ring,
cw_ring); cw_ring);

View File

@ -21,6 +21,30 @@
void test_minimal()
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
typedef boost::geometry::closing_iterator
<
std::vector<int> const
> closing_iterator;
closing_iterator it(v);
closing_iterator end(v, true);
std::ostringstream out;
for (; it != end; ++it)
{
out << *it;
}
BOOST_CHECK_EQUAL(out.str(), "1231");
}
@ -78,6 +102,7 @@ void test_geometry(std::string const& wkt)
template <typename P> template <typename P>
void test_all() void test_all()
{ {
test_minimal();
test_geometry<boost::geometry::linear_ring<P> >("POLYGON((1 1,1 4,4 4,4 1))"); test_geometry<boost::geometry::linear_ring<P> >("POLYGON((1 1,1 4,4 4,4 1))");
} }