1 /**********************************************************************
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
6 * Copyright (C) 2006 Refractions Research Inc.
8 * This is free software; you can redistribute and/or modify it under
9 * the terms of the GNU Lesser General Public Licence as published
10 * by the Free Software Foundation.
11 * See the COPYING file for more information.
13 ***********************************************************************
15 * Last port: operation/overlay/validate/OverlayResultValidator.java rev. 1.4 (JTS-1.10)
17 **********************************************************************/
19 #include <geos/operation/overlay/validate/OverlayResultValidator.h>
20 #include <geos/operation/overlay/validate/FuzzyPointLocator.h>
21 #include <geos/operation/overlay/validate/OffsetPointGenerator.h>
22 #include <geos/operation/overlay/snap/GeometrySnapper.h>
23 #include <geos/geom/CoordinateSequence.h>
24 #include <geos/geom/MultiPoint.h>
25 #include <geos/geom/GeometryFactory.h>
26 #include <geos/geom/CoordinateSequenceFactory.h>
31 #include <memory> // for auto_ptr
32 #include <algorithm> // for std::min etc.
39 #include <iomanip> // for setprecision
43 #define USE_ELEVATION_MATRIX 1
44 #define USE_INPUT_AVGZ 0
47 using namespace geos::geom
;
48 using namespace geos::geomgraph
;
49 using namespace geos::algorithm
;
52 namespace operation
{ // geos.operation
53 namespace overlay
{ // geos.operation.overlay
54 namespace validate
{ // geos.operation.overlay.validate
56 namespace { // anonymous namespace
59 isArea(const Geometry
& g
)
61 GeometryTypeId type
= g
.getGeometryTypeId();
62 if ( type
== GEOS_POLYGON
) return true;
63 if ( type
== GEOS_MULTIPOLYGON
) return true;
65 cerr
<< "OverlayResultValidator: one of the geoms being checked is not a POLYGON or MULTIPOLYGON, blindly returning a positive answer (is valid)" << endl
;
71 toMultiPoint(vector
<Coordinate
>& coords
)
73 const GeometryFactory
& gf
= *(GeometryFactory::getDefaultInstance());
74 const CoordinateSequenceFactory
& csf
=
75 *(gf
.getCoordinateSequenceFactory());
77 auto_ptr
< vector
<Coordinate
> > nc ( new vector
<Coordinate
>(coords
) );
78 auto_ptr
<CoordinateSequence
> cs(csf
.create(nc
.release()));
80 auto_ptr
<MultiPoint
> mp ( gf
.createMultiPoint(*cs
) );
85 } // anonymous namespace
90 OverlayResultValidator::isValid(const Geometry
& geom0
, const Geometry
& geom1
,
91 OverlayOp::OpCode opCode
,
92 const Geometry
& result
)
94 OverlayResultValidator
validator(geom0
, geom1
, result
);
95 return validator
.isValid(opCode
);
99 OverlayResultValidator::OverlayResultValidator(
100 const Geometry
& geom0
,
101 const Geometry
& geom1
,
102 const Geometry
& result
)
104 boundaryDistanceTolerance(
105 computeBoundaryDistanceTolerance(geom0
, geom1
)
110 fpl0(g0
, boundaryDistanceTolerance
),
111 fpl1(g1
, boundaryDistanceTolerance
),
112 fplres(gres
, boundaryDistanceTolerance
),
119 OverlayResultValidator::isValid(OverlayOp::OpCode overlayOp
)
121 // The check only works for areal geoms
122 #if 0 // now that FuzzyPointLocator extracts polygonal geoms,
123 // there should be no problem here
124 if ( ! isArea(g0
) ) return true;
125 if ( ! isArea(g1
) ) return true;
126 if ( ! isArea(gres
) ) return true;
133 if (! testValid(overlayOp
) )
136 cerr
<< "OverlayResultValidator:" << endl
137 << "Points:" << *toMultiPoint(testCoords
) << endl
138 << "Geom0: " << g0
<< endl
139 << "Geom1: " << g1
<< endl
140 << "Reslt: " << gres
<< endl
141 << "Locat: " << getInvalidLocation()
153 OverlayResultValidator::addTestPts(const Geometry
& g
)
155 OffsetPointGenerator
ptGen(g
, 5 * boundaryDistanceTolerance
);
156 auto_ptr
< vector
<geom::Coordinate
> > pts
= ptGen
.getPoints();
157 testCoords
.insert(testCoords
.end(), pts
->begin(), pts
->end());
162 OverlayResultValidator::addVertices(const Geometry
& g
)
164 // TODO: optimize this by not copying coordinates
165 // and pre-allocating memory
166 auto_ptr
<CoordinateSequence
> cs ( g
.getCoordinates() );
167 const vector
<Coordinate
>* coords
= cs
->toVector();
168 testCoords
.insert(testCoords
.end(), coords
->begin(), coords
->end());
173 OverlayResultValidator::testValid(OverlayOp::OpCode overlayOp
)
175 for (size_t i
=0, n
=testCoords
.size(); i
<n
; ++i
)
177 Coordinate
& pt
= testCoords
[i
];
178 if (! testValid(overlayOp
, pt
)) {
179 invalidLocation
= pt
;
188 OverlayResultValidator::testValid(OverlayOp::OpCode overlayOp
,
189 const Coordinate
& pt
)
191 std::vector
<geom::Location::Value
> location(3);
193 location
[0] = fpl0
.getLocation(pt
);
194 location
[1] = fpl1
.getLocation(pt
);
195 location
[2] = fplres
.getLocation(pt
);
198 cerr
<< setprecision(10) << "Point " << pt
<< endl
199 << "Loc0: " << location
[0] << endl
200 << "Loc1: " << location
[1] << endl
201 << "Locr: " << location
[2] << endl
;
205 * If any location is on the Boundary, can't deduce anything,
206 * so just return true
208 if ( find(location
.begin(), location
.end(), Location::BOUNDARY
) != location
.end() )
211 cerr
<< "OverlayResultValidator: testpoint " << pt
<< " is on the boundary, blindly returning a positive answer (is valid)" << endl
;
216 return isValidResult(overlayOp
, location
);
221 OverlayResultValidator::isValidResult(OverlayOp::OpCode overlayOp
,
222 std::vector
<geom::Location::Value
>& location
)
224 bool expectedInterior
= OverlayOp::isResultOfOp(location
[0],
225 location
[1], overlayOp
);
227 bool resultInInterior
= (location
[2] == Location::INTERIOR
);
229 bool isValid
= ! (expectedInterior
^ resultInInterior
);
236 OverlayResultValidator::computeBoundaryDistanceTolerance(
237 const geom::Geometry
& g0
, const geom::Geometry
& g1
)
239 using geos::operation::overlay::snap::GeometrySnapper
;
241 return (std::min
)(GeometrySnapper::computeSizeBasedSnapTolerance(g0
),
242 GeometrySnapper::computeSizeBasedSnapTolerance(g1
));
245 } // namespace geos.operation.overlay.validate
246 } // namespace geos.operation.overlay
247 } // namespace geos.operation
250 /**********************************************************************
252 **********************************************************************/