Fix OverlayNG line ordering
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
a5890d8f9e
commit
7c2f400cb8
|
|
@ -59,32 +59,23 @@ namespace overlayng { // geos.operation.overlayng
|
|||
* This ensures that the overlay output line direction will be as consistent
|
||||
* as possible with input lines.
|
||||
*
|
||||
* The merger also preserves the order of the edges in the input.
|
||||
* This means that for polygon-line overlay
|
||||
* the result lines will be in the same order as in the input
|
||||
* (possibly with multiple result lines for a single input line).
|
||||
*
|
||||
* @author mdavis
|
||||
*
|
||||
*/
|
||||
class GEOS_DLL EdgeMerger {
|
||||
|
||||
private:
|
||||
|
||||
|
||||
// Members
|
||||
std::vector<Edge*>& edges;
|
||||
std::map<EdgeKey, Edge*> edgeMap;
|
||||
|
||||
public:
|
||||
|
||||
// Methods
|
||||
EdgeMerger(std::vector<Edge*>& p_edges);
|
||||
|
||||
static std::vector<Edge*> merge(std::vector<Edge*>& edges);
|
||||
|
||||
std::vector<Edge*> merge();
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace geos.operation.overlayng
|
||||
} // namespace geos.operation
|
||||
} // namespace geos
|
||||
|
||||
|
|
|
|||
|
|
@ -23,23 +23,12 @@ namespace geos { // geos
|
|||
namespace operation { // geos.operation
|
||||
namespace overlayng { // geos.operation.overlayng
|
||||
|
||||
EdgeMerger::EdgeMerger(std::vector<Edge*>& p_edges)
|
||||
: edges(p_edges) {}
|
||||
|
||||
/*public static */
|
||||
std::vector<Edge*>
|
||||
EdgeMerger::merge(std::vector<Edge*>& edges)
|
||||
{
|
||||
EdgeMerger merger(edges);
|
||||
return merger.merge();
|
||||
}
|
||||
|
||||
|
||||
/*public static */
|
||||
std::vector<Edge*>
|
||||
EdgeMerger::merge()
|
||||
{
|
||||
std::vector<Edge*> mergedEdges;
|
||||
std::map<EdgeKey, Edge*> edgeMap;
|
||||
|
||||
for (Edge* edge : edges) {
|
||||
EdgeKey edgeKey(edge);
|
||||
|
|
@ -47,6 +36,7 @@ EdgeMerger::merge()
|
|||
if (it == edgeMap.end()) {
|
||||
// this is the first (and maybe only) edge for this line
|
||||
edgeMap[edgeKey] = edge;
|
||||
mergedEdges.push_back(edge);
|
||||
//Debug.println("edge added: " + edge);
|
||||
//Debug.println(edge.toLineString());
|
||||
}
|
||||
|
|
@ -69,11 +59,6 @@ EdgeMerger::merge()
|
|||
//Debug.println(edge.toLineString());
|
||||
}
|
||||
}
|
||||
|
||||
// copy map values into return vector
|
||||
for (auto it: edgeMap) {
|
||||
mergedEdges.push_back(it.second);
|
||||
}
|
||||
return mergedEdges;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Test Suite for geos::index::chain::MonotoneChainBuilder class.
|
||||
|
||||
#include <tut/tut.hpp>
|
||||
#include <utility.h>
|
||||
// geos
|
||||
#include <geos/io/WKTReader.h>
|
||||
#include <geos/io/WKTWriter.h>
|
||||
|
|
@ -46,28 +47,14 @@ void object::test<1>
|
|||
std::string wkt2("POLYGON((0.1 0.1, 4.0 0.1, 4.0 1.9, 0.1 1.9, 0.1 0.1))");
|
||||
std::unique_ptr<geos::geom::Geometry> g2(wktreader.read(wkt2));
|
||||
|
||||
// POLYGON ((2.0 1.9, 4.0 1.9, 4.0 0.1, 2.0 0.1, 2.0 1.9))
|
||||
double x[5] = {2.0, 4.0, 4.0, 2.0, 2.0};
|
||||
double y[5] = {1.9, 1.9, 0.1, 0.1, 1.9};
|
||||
auto result = g2->difference(g1.get());
|
||||
result->normalize();
|
||||
|
||||
auto g3 = g2->difference(g1.get());
|
||||
auto cs = g3->getCoordinates();
|
||||
|
||||
// std::string wkt3 = wktwriter.write(g3.get());
|
||||
// std::cout << wkt3 << std::endl;
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
auto csx = cs->getOrdinate(i, 0);
|
||||
auto csy = cs->getOrdinate(i, 1);
|
||||
// std::cout << csx << ", " << csy << std::endl;
|
||||
// std::cout << x[i] << ", " << y[i] << std::endl;
|
||||
ensure_equals("x", csx, x[i], 0.01);
|
||||
ensure_equals("y", csy, y[i], 0.01);
|
||||
}
|
||||
std::string wktExpected("POLYGON ((2 0.1, 2 1.9, 4 1.9, 4 0.1, 2 0.1))");
|
||||
std::unique_ptr<geos::geom::Geometry> expected(wktreader.read(wktExpected));
|
||||
|
||||
ensure_equals_geometry(expected.get(), result.get());
|
||||
}
|
||||
|
||||
|
||||
} // namespace tut
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,24 @@ struct test_overlayng_data {
|
|||
ensure_equals_geometry(geom_expected.get(), geom_result.get());
|
||||
}
|
||||
|
||||
void
|
||||
testOverlayExact(const std::string& a, const std::string& b, const std::string& expected, int opCode, double scaleFactor)
|
||||
{
|
||||
std::unique_ptr<PrecisionModel> pm;
|
||||
if (scaleFactor > 0)
|
||||
pm.reset(new PrecisionModel(scaleFactor));
|
||||
else
|
||||
pm.reset(new PrecisionModel());
|
||||
|
||||
std::unique_ptr<Geometry> geom_a = r.read(a);
|
||||
std::unique_ptr<Geometry> geom_b = r.read(b);
|
||||
std::unique_ptr<Geometry> geom_expected = r.read(expected);
|
||||
std::unique_ptr<Geometry> geom_result = OverlayNG::overlay(geom_a.get(), geom_b.get(), opCode, pm.get());
|
||||
// std::string wkt_result = w.write(geom_result.get());
|
||||
// std::cout << std::endl << wkt_result << std::endl;
|
||||
ensure_equals_exact_geometry(geom_expected.get(), geom_result.get(), 0);
|
||||
}
|
||||
|
||||
void
|
||||
testOverlayNoOpt(const std::string& a, const std::string& b, const std::string& expected, int opCode, double scaleFactor)
|
||||
{
|
||||
|
|
@ -531,4 +549,14 @@ void object::test<42> ()
|
|||
testOverlay(a, b, exp, OverlayNG::INTERSECTION, 0);
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
void object::test<43> ()
|
||||
{
|
||||
std::string a = "POLYGON ((1 1, 1 9, 9 9, 9 7, 3 7, 3 3, 9 3, 9 1, 1 1))";
|
||||
std::string b = "MULTILINESTRING ((2 10, 2 0), (4 10, 4 0))";
|
||||
std::string exp = "MULTILINESTRING ((2 9, 2 1), (4 9, 4 7), (4 3, 4 1))";
|
||||
testOverlay(a, b, exp, OverlayNG::INTERSECTION, 0);
|
||||
}
|
||||
|
||||
} // namespace tut
|
||||
|
|
|
|||
|
|
@ -327,6 +327,49 @@ ensure_equals_geometry_xyz(const T *lhs_in,
|
|||
ensure_equals_exact_geometry_xyz(g1.get(), g2.get(), tolerance);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks for geometries exactly equal in XY only
|
||||
*/
|
||||
|
||||
template <typename T> inline void ensure_equals_exact_geometry(const T *lhs_in, const T *rhs_in, double tolerance = 0.0);
|
||||
|
||||
template <>
|
||||
inline void
|
||||
ensure_equals_exact_geometry(const geos::geom::Geometry *lhs_in,
|
||||
const geos::geom::Geometry *rhs_in,
|
||||
double tolerance)
|
||||
{
|
||||
assert(nullptr != lhs_in);
|
||||
assert(nullptr != rhs_in);
|
||||
|
||||
using geos::geom::Point;
|
||||
using geos::geom::LineString;
|
||||
using geos::geom::Polygon;
|
||||
using geos::geom::CoordinateSequence;
|
||||
using geos::geom::GeometryCollection;
|
||||
|
||||
ensure_equals("type id do not match",
|
||||
lhs_in->getGeometryTypeId(), rhs_in->getGeometryTypeId());
|
||||
|
||||
if (const Point* gpt1 = dynamic_cast<const Point *>(lhs_in)) {
|
||||
const Point *gpt2 = static_cast<const Point *>(rhs_in);
|
||||
return ensure_equals_dims( gpt1->getCoordinatesRO(), gpt2->getCoordinatesRO(), 2, tolerance);
|
||||
}
|
||||
else if (const LineString* gln1 = dynamic_cast<const LineString *>(lhs_in)) {
|
||||
const LineString *gln2 = static_cast<const LineString *>(rhs_in);
|
||||
return ensure_equals_dims( gln1->getCoordinatesRO(), gln2->getCoordinatesRO(), 2, tolerance);
|
||||
}
|
||||
else if (dynamic_cast<const Polygon *>(lhs_in)) {
|
||||
assert("Not implemented yet" == 0);
|
||||
}
|
||||
else if (const GeometryCollection* gc1 = dynamic_cast<const GeometryCollection *>(lhs_in)) {
|
||||
const GeometryCollection *gc2 = static_cast<const GeometryCollection *>(rhs_in);
|
||||
for (unsigned int i = 0; i < gc1->getNumGeometries(); i++) {
|
||||
ensure_equals_exact_geometry(gc1->getGeometryN(i), gc2->getGeometryN(i), tolerance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Utility functions
|
||||
//
|
||||
|
|
@ -353,4 +396,3 @@ struct wkb_hex_decoder {
|
|||
} // namespace tut
|
||||
|
||||
#endif // #ifndef GEOS_TUT_UTILITY_H_INCLUDED
|
||||
|
||||
|
|
|
|||
|
|
@ -1312,6 +1312,7 @@ XMLTester::parseTest(const tinyxml2::XMLNode* node)
|
|||
|
||||
else if(opName == "union") {
|
||||
GeomPtr gRes(parseGeometry(opRes, "expected"));
|
||||
gRes->normalize();
|
||||
|
||||
profile.start();
|
||||
|
||||
|
|
@ -1324,6 +1325,7 @@ XMLTester::parseTest(const tinyxml2::XMLNode* node)
|
|||
}
|
||||
|
||||
profile.stop();
|
||||
gRealRes->normalize();
|
||||
|
||||
success = checkOverlaySuccess(*gRes, *gRealRes);
|
||||
|
||||
|
|
@ -2414,4 +2416,3 @@ main(int argC, char* argV[])
|
|||
* Revision 1.29 2006/03/17 14:56:39 strk
|
||||
* Fixed filename normalizer for sql output
|
||||
**********************************************************************/
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue