source: trunk/source/headers/geos/operation/overlay/OverlayOp.h@ 1820

Last change on this file since 1820 was 1820, checked in by mloskot, 18 years ago

Set svn:keyword property for Id keyword expansion.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/plain
File size: 10.6 KB
Line 
1/**********************************************************************
2 * $Id: OverlayOp.h 1820 2006-09-06 16:54:23Z mloskot $
3 *
4 * GEOS - Geometry Engine Open Source
5 * http://geos.refractions.net
6 *
7 * Copyright (C) 2006 Refractions Research Inc.
8 *
9 * This is free software; you can redistribute and/or modify it under
10 * the terms of the GNU Lesser General Public Licence as published
11 * by the Free Software Foundation.
12 * See the COPYING file for more information.
13 *
14 **********************************************************************/
15
16#ifndef GEOS_OP_OVERLAY_OVERLAYOP_H
17#define GEOS_OP_OVERLAY_OVERLAYOP_H
18
19#include <geos/operation/GeometryGraphOperation.h> // for inheritance
20#include <geos/geomgraph/EdgeList.h> // for composition
21#include <geos/algorithm/PointLocator.h> // for composition
22#include <geos/geomgraph/PlanarGraph.h> // for inline (GeometryGraph->PlanarGraph)
23
24#include <vector>
25
26// Forward declarations
27namespace geos {
28 namespace geom {
29 class Geometry;
30 class Coordinate;
31 class GeometryFactory;
32 class Polygon;
33 class LineString;
34 class Point;
35 }
36 namespace geomgraph {
37 class Label;
38 class Edge;
39 class Node;
40 }
41 namespace operation {
42 namespace overlay {
43 class ElevationMatrix;
44 }
45 }
46}
47
48namespace geos {
49namespace operation { // geos::operation
50namespace overlay { // geos::operation::overlay
51
52/// Computes the overlay of two Geometry.
53//
54/// The overlay can be used to determine any
55/// boolean combination of the geometries.
56///
57class OverlayOp: public GeometryGraphOperation {
58
59public:
60
61 /// The spatial functions supported by this class.
62 //
63 /// These operations implement various boolean combinations of
64 /// the resultants of the overlay.
65 ///
66 enum OpCode {
67 opINTERSECTION=1,
68 opUNION,
69 opDIFFERENCE,
70 opSYMDIFFERENCE
71 };
72
73 static geom::Geometry* overlayOp(const geom::Geometry *geom0,
74 const geom::Geometry *geom1,
75 OpCode opCode);
76 //throw(TopologyException *);
77
78 static bool isResultOfOp(geomgraph::Label *label, OpCode opCode);
79
80 /// This method will handle arguments of Location.NULL correctly
81 //
82 /// @return true if the locations correspond to the opCode
83 ///
84 static bool isResultOfOp(int loc0, int loc1, OpCode opCode);
85
86 /// Construct an OverlayOp with the given Geometry args.
87 //
88 /// Ownership of passed args will remain to caller, and
89 /// the OverlayOp won't change them in any way.
90 ///
91 OverlayOp(const geom::Geometry *g0, const geom::Geometry *g1);
92
93 virtual ~OverlayOp(); // FIXME: virtual ?
94
95 geom::Geometry* getResultGeometry(OpCode funcCode);
96 // throw(TopologyException *);
97
98 geomgraph::PlanarGraph& getGraph() { return graph; }
99
100 /** \brief
101 * This method is used to decide if a point node should be included
102 * in the result or not.
103 *
104 * @return true if the coord point is covered by a result Line
105 * or Area geometry
106 */
107 bool isCoveredByLA(const geom::Coordinate& coord);
108
109 /** \brief
110 * This method is used to decide if an L edge should be included
111 * in the result or not.
112 *
113 * @return true if the coord point is covered by a result Area geometry
114 */
115 bool isCoveredByA(const geom::Coordinate& coord);
116
117 /*
118 * @return true if the coord is located in the interior or boundary of
119 * a geometry in the list.
120 */
121
122protected:
123
124 /** \brief
125 * Insert an edge from one of the noded input graphs.
126 *
127 * Checks edges that are inserted to see if an
128 * identical edge already exists.
129 * If so, the edge is not inserted, but its label is merged
130 * with the existing edge.
131 */
132 void insertUniqueEdge(geomgraph::Edge *e);
133
134private:
135
136 algorithm::PointLocator ptLocator;
137
138 const geom::GeometryFactory *geomFact;
139
140 geom::Geometry *resultGeom;
141
142 geomgraph::PlanarGraph graph;
143
144 geomgraph::EdgeList edgeList;
145
146 std::vector<geom::Polygon*> *resultPolyList;
147
148 std::vector<geom::LineString*> *resultLineList;
149
150 std::vector<geom::Point*> *resultPointList;
151
152 void computeOverlay(OpCode opCode); // throw(TopologyException *);
153
154 void insertUniqueEdges(std::vector<geomgraph::Edge*> *edges);
155
156 /*
157 * If either of the GeometryLocations for the existing label is
158 * exactly opposite to the one in the labelToMerge,
159 * this indicates a dimensional collapse has happened.
160 * In this case, convert the label for that Geometry to a Line label
161 */
162 //Not needed
163 //void checkDimensionalCollapse(geomgraph::Label labelToMerge, geomgraph::Label existingLabel);
164
165 /** \brief
166 * Update the labels for edges according to their depths.
167 *
168 * For each edge, the depths are first normalized.
169 * Then, if the depths for the edge are equal,
170 * this edge must have collapsed into a line edge.
171 * If the depths are not equal, update the label
172 * with the locations corresponding to the depths
173 * (i.e. a depth of 0 corresponds to a Location of EXTERIOR,
174 * a depth of 1 corresponds to INTERIOR)
175 */
176 void computeLabelsFromDepths();
177
178 /** \brief
179 * If edges which have undergone dimensional collapse are found,
180 * replace them with a new edge which is a L edge
181 */
182 void replaceCollapsedEdges();
183
184 /** \brief
185 * Copy all nodes from an arg geometry into this graph.
186 *
187 * The node label in the arg geometry overrides any previously
188 * computed label for that argIndex.
189 * (E.g. a node may be an intersection node with
190 * a previously computed label of BOUNDARY,
191 * but in the original arg Geometry it is actually
192 * in the interior due to the Boundary Determination Rule)
193 */
194 void copyPoints(int argIndex);
195
196 /** \brief
197 * Compute initial labelling for all DirectedEdges at each node.
198 *
199 * In this step, DirectedEdges will acquire a complete labelling
200 * (i.e. one with labels for both Geometries)
201 * only if they
202 * are incident on a node which has edges for both Geometries
203 */
204 void computeLabelling(); // throw(TopologyException *);
205
206 /**
207 * For nodes which have edges from only one Geometry incident on them,
208 * the previous step will have left their dirEdges with no
209 * labelling for the other Geometry.
210 * However, the sym dirEdge may have a labelling for the other
211 * Geometry, so merge the two labels.
212 */
213 void mergeSymLabels();
214
215 void updateNodeLabelling();
216
217 /**
218 * Incomplete nodes are nodes whose labels are incomplete.
219 *
220 * (e.g. the location for one Geometry is NULL).
221 * These are either isolated nodes,
222 * or nodes which have edges from only a single Geometry incident
223 * on them.
224 *
225 * Isolated nodes are found because nodes in one graph which
226 * don't intersect nodes in the other are not completely
227 * labelled by the initial process of adding nodes to the nodeList.
228 * To complete the labelling we need to check for nodes that
229 * lie in the interior of edges, and in the interior of areas.
230 *
231 * When each node labelling is completed, the labelling of the
232 * incident edges is updated, to complete their labelling as well.
233 */
234 void labelIncompleteNodes();
235
236 /** \brief
237 * Label an isolated node with its relationship to the target geometry.
238 */
239 void labelIncompleteNode(geomgraph::Node *n, int targetIndex);
240
241 /** \brief
242 * Find all edges whose label indicates that they are in the result
243 * area(s), according to the operation being performed.
244 *
245 * Since we want polygon shells to be
246 * oriented CW, choose dirEdges with the interior of the result
247 * on the RHS.
248 * Mark them as being in the result.
249 * Interior Area edges are the result of dimensional collapses.
250 * They do not form part of the result area boundary.
251 */
252 void findResultAreaEdges(OpCode opCode);
253
254 /**
255 * If both a dirEdge and its sym are marked as being in the result,
256 * cancel them out.
257 */
258 void cancelDuplicateResultEdges();
259
260 /**
261 * @return true if the coord is located in the interior or boundary of
262 * a geometry in the list.
263 */
264 bool isCovered(const geom::Coordinate& coord,
265 std::vector<geom::Geometry*> *geomList);
266
267 /**
268 * @return true if the coord is located in the interior or boundary of
269 * a geometry in the list.
270 */
271 bool isCovered(const geom::Coordinate& coord,
272 std::vector<geom::Polygon*> *geomList);
273
274 /**
275 * @return true if the coord is located in the interior or boundary of
276 * a geometry in the list.
277 */
278 bool isCovered(const geom::Coordinate& coord,
279 std::vector<geom::LineString*> *geomList);
280
281 /**
282 * Build a Geometry containing all Geometries in the given vectors.
283 * Takes element's ownership, vector control is left to caller.
284 */
285 geom::Geometry* computeGeometry(
286 std::vector<geom::Point*> *nResultPointList,
287 std::vector<geom::LineString*> *nResultLineList,
288 std::vector<geom::Polygon*> *nResultPolyList);
289
290 /// Caches for memory management
291 std::vector<geomgraph::Edge *>dupEdges;
292
293 /** \brief
294 * Merge Z values of node with those of the segment or vertex in
295 * the given Polygon it is on.
296 */
297 int mergeZ(geomgraph::Node *n, const geom::Polygon *poly) const;
298
299 /**
300 * Merge Z values of node with those of the segment or vertex in
301 * the given LineString it is on.
302 * @returns 1 if an intersection is found, 0 otherwise.
303 */
304 int mergeZ(geomgraph::Node *n, const geom::LineString *line) const;
305
306 /**
307 * Average Z of input geometries
308 */
309 double avgz[2];
310 bool avgzcomputed[2];
311
312 double getAverageZ(int targetIndex);
313 static double getAverageZ(const geom::Polygon *poly);
314
315 ElevationMatrix *elevationMatrix;
316
317 /// Throw TopologyException if an obviously wrong result has
318 /// been computed.
319 void checkObviouslyWrongResult(OpCode opCode);
320
321};
322
323/** \brief
324 * OverlayOp::overlayOp Adapter for use with geom::BinaryOp
325 */
326struct overlayOp {
327
328 OverlayOp::OpCode opCode;
329
330 overlayOp(OverlayOp::OpCode code)
331 :
332 opCode(code)
333 {}
334
335 geom::Geometry* operator() (const geom::Geometry* g0,
336 const geom::Geometry* g1)
337 {
338 return OverlayOp::overlayOp(g0, g1, opCode);
339 }
340
341};
342
343} // namespace geos::operation::overlay
344} // namespace geos::operation
345} // namespace geos
346
347#endif // ndef GEOS_OP_OVERLAY_OVERLAYOP_H
348
349/**********************************************************************
350 * $Log$
351 * Revision 1.6 2006/07/05 20:19:29 strk
352 * added checks for obviously wrong result of difference and intersection ops
353 *
354 * Revision 1.5 2006/06/05 15:36:34 strk
355 * Given OverlayOp funx code enum a name and renamed values to have a lowercase prefix. Drop all of noding headers from installed header set.
356 *
357 * Revision 1.4 2006/05/24 15:17:44 strk
358 * Reduced number of installed headers in geos/operation/ subdir
359 *
360 * Revision 1.3 2006/04/14 15:04:36 strk
361 * fixed missing namespace qualification in overlay::overlayOp
362 *
363 * Revision 1.2 2006/04/14 14:35:47 strk
364 * Added overlayOp() adapter for use in templates expecting binary ops
365 *
366 * Revision 1.1 2006/03/17 13:24:59 strk
367 * opOverlay.h header splitted. Reduced header inclusions in operation/overlay implementation files. ElevationMatrixFilter code moved from own file to ElevationMatrix.cpp (ideally a class-private).
368 *
369 **********************************************************************/
370
Note: See TracBrowser for help on using the repository browser.