GEOS: opOverlay.h Source File

- Main Page
- Namespaces
- Classes
- Files
- Related Pages

# opOverlay.h

    00001 /**********************************************************************
    00002  * $Id: opOverlay.h,v 1.8.2.1.2.1 2005/11/30 11:18:07 strk Exp $
    00003  *
    00004  * GEOS - Geometry Engine Open Source
    00005  * http://geos.refractions.net
    00006  *
    00007  * Copyright (C) 2001-2002 Vivid Solutions Inc.
    00008  *
    00009  * This is free software; you can redistribute and/or modify it under
    00010  * the terms of the GNU Lesser General Public Licence as published
    00011  * by the Free Software Foundation.
    00012  * See the COPYING file for more information.
    00013  *
    00014  **********************************************************************/
    00015
    00016
    00017 #ifndef GEOS_OPOVERLAY_H
    00018 #define GEOS_OPOVERLAY_H
    00019
    00020 #include <memory>
    00021 #include <string>
    00022 #include <vector>
    00023 #include <set>
    00024 #include <map>
    00025 #include <geos/platform.h>
    00026 #include <geos/operation.h>
    00027 #include <geos/geomgraph.h>
    00028 #include <geos/geosAlgorithm.h>
    00029
    00030 using namespace std;
    00031
    00032 namespace geos {
    00033
    00034 class ElevationMatrixCell {
    00035 public:
    00036         ElevationMatrixCell();
    00037         ~ElevationMatrixCell();
    00038         void add(const Coordinate &c);
    00039         void add(double z);
    00040         double getAvg(void) const;
    00041         double getTotal(void) const;
    00042         string print() const;
    00043 private:
    00044         set<double>zvals;
    00045         double ztot;
    00046 };
    00047
    00048 /*
    00049  */
    00050 class ElevationMatrix {
    00051 public:
    00052         ElevationMatrix(const Envelope &extent, unsigned int rows,
    00053                 unsigned int cols);
    00054         ~ElevationMatrix();
    00055         void add(const Geometry *geom);
    00056         void elevate(Geometry *geom) const;
    00057         // set Z value for each cell w/out one
    00058         double getAvgElevation() const;
    00059         ElevationMatrixCell &getCell(const Coordinate &c);
    00060         const ElevationMatrixCell &getCell(const Coordinate &c) const;
    00061         string print() const;
    00062 private:
    00063         void add(const CoordinateSequence *cs);
    00064         void add(const Coordinate &c);
    00065         Envelope env;
    00066         unsigned int cols;
    00067         unsigned int rows;
    00068         double cellwidth;
    00069         double cellheight;
    00070         mutable bool avgElevationComputed;
    00071         mutable double avgElevation;
    00072         vector<ElevationMatrixCell>cells;
    00073 };
    00074
    00075 class ElevationMatrixFilter: public CoordinateFilter
    00076 {
    00077 public:
    00078         ElevationMatrixFilter(const ElevationMatrix *em);
    00079         ~ElevationMatrixFilter();
    00080         void filter_rw(Coordinate *c);
    00081         void filter_ro(const Coordinate *c) {};
    00082 private:
    00083         const ElevationMatrix *em;
    00084         double avgElevation;
    00085 };
    00086
    00087 /*
    00088  * Computes the overlay of two {@link Geometry}s.  The overlay
    00089  * can be used to determine any boolean combination of the geometries.
    00090  */
    00091 class OverlayOp: public GeometryGraphOperation {
    00092
    00093 public:
    00094
    00095         /*
    00096          * The spatial functions supported by this class.
    00097          * These operations implement various boolean combinations of
    00098          * the resultants of the overlay.
    00099          */
    00100         enum {
    00101                 INTERSECTION=1,
    00102                 UNION,
    00103                 DIFFERENCE,
    00104                 SYMDIFFERENCE
    00105         };
    00106
    00107         static Geometry* overlayOp(const Geometry *geom0, const Geometry *geom1,int opCode); //throw(TopologyException *);
    00108
    00109         static bool isResultOfOp(Label *label,int opCode);
    00110
    00111         /*
    00112          * This method will handle arguments of Location.NULL correctly
    00113          *
    00114          * @return true if the locations correspond to the opCode
    00115          */
    00116         static bool isResultOfOp(int loc0,int loc1,int opCode);
    00117
    00118         OverlayOp(const Geometry *g0, const Geometry *g1);
    00119
    00120         virtual ~OverlayOp();
    00121
    00122         Geometry* getResultGeometry(int funcCode);
    00123                 // throw(TopologyException *);
    00124
    00125         PlanarGraph* getGraph();
    00126
    00127         /*
    00128          * This method is used to decide if a point node should be included
    00129          * in the result or not.
    00130          *
    00131          * @return true if the coord point is covered by a result Line
    00132          * or Area geometry
    00133          */
    00134         bool isCoveredByLA(const Coordinate& coord);
    00135
    00136         /*
    00137          * This method is used to decide if an L edge should be included
    00138          * in the result or not.
    00139          *
    00140          * @return true if the coord point is covered by a result Area geometry
    00141          */
    00142         bool isCoveredByA(const Coordinate& coord);
    00143
    00144         /*
    00145          * @return true if the coord is located in the interior or boundary of
    00146          * a geometry in the list.
    00147          */
    00148
    00149 protected:
    00150
    00151         /*
    00152          * Insert an edge from one of the noded input graphs.
    00153          * Checks edges that are inserted to see if an
    00154          * identical edge already exists.
    00155          * If so, the edge is not inserted, but its label is merged
    00156          * with the existing edge.
    00157          */
    00158         void insertUniqueEdge(Edge *e);
    00159
    00160 private:
    00161         PointLocator *ptLocator;
    00162         const GeometryFactory *geomFact;
    00163         Geometry *resultGeom;
    00164         PlanarGraph *graph;
    00165         EdgeList *edgeList;
    00166         vector<Polygon*> *resultPolyList;
    00167         vector<LineString*> *resultLineList;
    00168         vector<Point*> *resultPointList;
    00169         void computeOverlay(int opCode); // throw(TopologyException *);
    00170         void insertUniqueEdges(vector<Edge*> *edges);
    00171
    00172         /*
    00173          * If either of the GeometryLocations for the existing label is
    00174          * exactly opposite to the one in the labelToMerge,
    00175          * this indicates a dimensional collapse has happened.
    00176          * In this case, convert the label for that Geometry to a Line label
    00177          */
    00178         //Not needed
    00179         //void checkDimensionalCollapse(Label labelToMerge, Label existingLabel);
    00180         /*
    00181          * Update the labels for edges according to their depths.
    00182          * For each edge, the depths are first normalized.
    00183          * Then, if the depths for the edge are equal,
    00184          * this edge must have collapsed into a line edge.
    00185          * If the depths are not equal, update the label
    00186          * with the locations corresponding to the depths
    00187          * (i.e. a depth of 0 corresponds to a Location of EXTERIOR,
    00188          * a depth of 1 corresponds to INTERIOR)
    00189          */
    00190         void computeLabelsFromDepths();
    00191
    00192         /*
    00193          * If edges which have undergone dimensional collapse are found,
    00194          * replace them with a new edge which is a L edge
    00195          */
    00196         void replaceCollapsedEdges();
    00197
    00198         /*
    00199          * Copy all nodes from an arg geometry into this graph.
    00200          * The node label in the arg geometry overrides any previously
    00201          * computed label for that argIndex.
    00202          * (E.g. a node may be an intersection node with
    00203          * a previously computed label of BOUNDARY,
    00204          * but in the original arg Geometry it is actually
    00205          * in the interior due to the Boundary Determination Rule)
    00206          */
    00207         void copyPoints(int argIndex);
    00208
    00209         /*
    00210          * Compute initial labelling for all DirectedEdges at each node.
    00211          * In this step, DirectedEdges will acquire a complete labelling
    00212          * (i.e. one with labels for both Geometries)
    00213          * only if they
    00214          * are incident on a node which has edges for both Geometries
    00215          */
    00216         void computeLabelling(); // throw(TopologyException *);
    00217
    00218         /*
    00219          * For nodes which have edges from only one Geometry incident on them,
    00220          * the previous step will have left their dirEdges with no
    00221          * labelling for the other Geometry.
    00222          * However, the sym dirEdge may have a labelling for the other
    00223          * Geometry, so merge the two labels.
    00224          */
    00225         void mergeSymLabels();
    00226
    00227         void updateNodeLabelling();
    00228
    00229         /*
    00230          * Incomplete nodes are nodes whose labels are incomplete.
    00231          * (e.g. the location for one Geometry is NULL).
    00232          * These are either isolated nodes,
    00233          * or nodes which have edges from only a single Geometry incident
    00234          * on them.
    00235          *
    00236          * Isolated nodes are found because nodes in one graph which
    00237          * don't intersect nodes in the other are not completely
    00238          * labelled by the initial process of adding nodes to the nodeList.
    00239          * To complete the labelling we need to check for nodes that
    00240          * lie in the interior of edges, and in the interior of areas.
    00241          *
    00242          * When each node labelling is completed, the labelling of the
    00243          * incident edges is updated, to complete their labelling as well.
    00244          */
    00245         void labelIncompleteNodes();
    00246
    00247         /*
    00248          * Label an isolated node with its relationship to the target geometry.
    00249          */
    00250         void labelIncompleteNode(Node *n,int targetIndex);
    00251
    00252         /*
    00253          * Find all edges whose label indicates that they are in the result
    00254          * area(s), according to the operation being performed.
    00255          * Since we want polygon shells to be
    00256          * oriented CW, choose dirEdges with the interior of the result
    00257          * on the RHS.
    00258          * Mark them as being in the result.
    00259          * Interior Area edges are the result of dimensional collapses.
    00260          * They do not form part of the result area boundary.
    00261          */
    00262         void findResultAreaEdges(int opCode);
    00263
    00264         /*
    00265          * If both a dirEdge and its sym are marked as being in the result,
    00266          * cancel them out.
    00267          */
    00268         void cancelDuplicateResultEdges();
    00269
    00270         bool isCovered(const Coordinate& coord,vector<Geometry*> *geomList);
    00271         bool isCovered(const Coordinate& coord,vector<Polygon*> *geomList);
    00272         bool isCovered(const Coordinate& coord,vector<LineString*> *geomList);
    00273
    00274         /*
    00275          * Build a Geometry containing all Geometries in the given vectors.
    00276          * Takes element's ownership, vector control is left to caller.
    00277          */
    00278         Geometry* computeGeometry(vector<Point*> *nResultPointList,
    00279                               vector<LineString*> *nResultLineList,
    00280                               vector<Polygon*> *nResultPolyList);
    00281
    00282         /* Caches for memory management */
    00283         vector<Edge *>dupEdges;
    00284
    00285         /*
    00286          * Merge Z values of node with those of the segment or vertex in
    00287          * the given Polygon it is on.
    00288          */
    00289         int mergeZ(Node *n, const Polygon *poly) const;
    00290
    00291         /*
    00292          * Merge Z values of node with those of the segment or vertex in
    00293          * the given LineString it is on.
    00294          * @returns 1 if an intersection is found, 0 otherwise.
    00295          */
    00296         int mergeZ(Node *n, const LineString *line) const;
    00297
    00298         /*
    00299          * Average Z of input geometries
    00300          */
    00301         double avgz[2];
    00302         bool avgzcomputed[2];
    00303
    00304         double getAverageZ(int targetIndex);
    00305         static double getAverageZ(const Polygon *poly);
    00306
    00307         ElevationMatrix *elevationMatrix;
    00308
    00309 };
    00310
    00311 /*
    00312  * A ring of {@link Edge}s with the property that no node
    00313  * has degree greater than 2.  These are the form of rings required
    00314  * to represent polygons under the OGC SFS spatial data model.
    00315  *
    00316  * @see com.vividsolutions.jts.operation.overlay.MaximalEdgeRing
    00317  */
    00318 class MinimalEdgeRing: public EdgeRing {
    00319 public:
    00320         MinimalEdgeRing(DirectedEdge *start, const GeometryFactory *geometryFactory,CGAlgorithms *cga);
    00321         virtual ~MinimalEdgeRing();
    00322         DirectedEdge* getNext(DirectedEdge *de);
    00323         void setEdgeRing(DirectedEdge *de,EdgeRing *er);
    00324 };
    00325
    00326 /*
    00327  * A ring of {@link edges} which may contain nodes of degree > 2.
    00328  * A MaximalEdgeRing may represent two different spatial entities:
    00329  * <ul>
    00330  * <li>a single polygon possibly containing inversions (if the ring is oriented CW)
    00331  * <li>a single hole possibly containing exversions (if the ring is oriented CCW)
    00332  * </ul>
    00333  * If the MaximalEdgeRing represents a polygon,
    00334  * the interior of the polygon is strongly connected.
    00335  * <p>
    00336  * These are the form of rings used to define polygons under some spatial data models.
    00337  * However, under the OGC SFS model, {@link MinimalEdgeRings} are required.
    00338  * A MaximalEdgeRing can be converted to a list of MinimalEdgeRings using the
    00339  * {@link #buildMinimalRings() } method.
    00340  *
    00341  * @see com.vividsolutions.jts.operation.overlay.MinimalEdgeRing
    00342  */
    00343
    00344 class MaximalEdgeRing: public EdgeRing {
    00345 public:
    00346         MaximalEdgeRing(DirectedEdge *start, const GeometryFactory *geometryFactory, CGAlgorithms *cga);
    00347         virtual ~MaximalEdgeRing();
    00348         DirectedEdge* getNext(DirectedEdge *de);
    00349         void setEdgeRing(DirectedEdge* de,EdgeRing* er);
    00350         vector<MinimalEdgeRing*>* buildMinimalRings();
    00351         void linkDirectedEdgesForMinimalEdgeRings();
    00352 };
    00353
    00354 /*
    00355  * Constructs {@link Point}s from the nodes of an overlay graph.
    00356  */
    00357 class PointBuilder {
    00358 private:
    00359
    00360         OverlayOp *op;
    00361         const GeometryFactory *geometryFactory;
    00362         void extractNonCoveredResultNodes(int opCode);
    00363
    00364         /*
    00365          * Converts non-covered nodes to Point objects and adds them to
    00366          * the result.
    00367          *
    00368          * A node is covered if it is contained in another element Geometry
    00369          * with higher dimension (e.g. a node point might be contained in
    00370          * a polygon, in which case the point can be eliminated from
    00371          * the result).
    00372          *
    00373          * @param n the node to test
    00374          */
    00375         void filterCoveredNodeToPoint(const Node *);
    00376
    00377         vector<Point*> *resultPointList;
    00378
    00379 public:
    00380
    00381         PointBuilder(OverlayOp *newOp,
    00382                 const GeometryFactory *newGeometryFactory,
    00383                 PointLocator *newPtLocator=NULL);
    00384
    00385         /*
    00386          * @return a list of the Points in the result of the specified
    00387          * overlay operation
    00388          */
    00389         vector<Point*>* build(int opCode);
    00390 };
    00391
    00392 /*
    00393  * Forms JTS LineStrings out of a the graph of DirectedEdge
    00394  * created by an OverlayOp.
    00395  *
    00396  */
    00397 class LineBuilder {
    00398 public:
    00399         LineBuilder(OverlayOp *newOp,
    00400                 const GeometryFactory *newGeometryFactory,
    00401                 PointLocator *newPtLocator);
    00402
    00403         ~LineBuilder();
    00404
    00405         /*
    00406          * @return a list of the LineStrings in the result of the
    00407          * specified overlay operation
    00408          */
    00409         vector<LineString*>* build(int opCode);
    00410
    00411         /*
    00412          * Find and mark L edges which are "covered" by the result area
    00413          * (if any).
    00414          * L edges at nodes which also have A edges can be checked by
    00415          * checking their depth at that node.
    00416          * L edges at nodes which do not have A edges can be checked by
    00417          * doing a point-in-polygon test with the previously computed
    00418          * result areas.
    00419          */
    00420         void collectLineEdge(DirectedEdge *de,int opCode,vector<Edge*>* edges);
    00421
    00422         /*
    00423          * Collect edges from Area inputs which should be in the result but
    00424          * which have not been included in a result area.
    00425          * This happens ONLY:
    00426          * <ul>
    00427          * <li>during an intersection when the boundaries of two
    00428          * areas touch in a line segment
    00429          * <li> OR as a result of a dimensional collapse.
    00430          * </ul>
    00431          */
    00432         void collectBoundaryTouchEdge(DirectedEdge *de,int opCode,vector<Edge*>* edges);
    00433
    00434 private:
    00435         OverlayOp *op;
    00436         const GeometryFactory *geometryFactory;
    00437         PointLocator *ptLocator;
    00438         vector<Edge*>* lineEdgesList;
    00439         vector<LineString*>* resultLineList;
    00440         void findCoveredLineEdges();
    00441         void collectLines(int opCode);
    00442         void buildLines(int opCode);
    00443         void labelIsolatedLines(vector<Edge*> *edgesList);
    00444
    00445         /*
    00446          * Label an isolated node with its relationship to the target geometry.
    00447          */
    00448         void labelIsolatedLine(Edge *e,int targetIndex);
    00449
    00450         /*
    00451          * If the given CoordinateSequence has mixed 3d/2d vertexes
    00452          * set Z for all vertexes missing it.
    00453          * The Z value is interpolated between 3d vertexes and copied
    00454          * from a 3d vertex to the end.
    00455          */
    00456         void propagateZ(CoordinateSequence *cs);
    00457 };
    00458
    00459 /*
    00460  * Forms {@link Polygon}s out of a graph of {@link DirectedEdge}s.
    00461  * The edges to use are marked as being in the result Area.
    00462  * <p>
    00463  *
    00464  */
    00465 class PolygonBuilder {
    00466 public:
    00467         PolygonBuilder(const GeometryFactory *newGeometryFactory, CGAlgorithms *newCga);
    00468         ~PolygonBuilder();
    00474         void add(PlanarGraph *graph); // throw(TopologyException *);
    00480         void add(vector<DirectedEdge*> *dirEdges,vector<Node*> *nodes); // throw(TopologyException *);
    00481         vector<Geometry*>* getPolygons();
    00482         bool containsPoint(Coordinate& p);
    00483 private:
    00484         const GeometryFactory *geometryFactory;
    00485         CGAlgorithms *cga;
    00486 //      List dirEdgeList; //Doesn't seem to be used at all
    00487 //      NodeMap *nodes;
    00488         vector<EdgeRing*> *shellList;
    00492         vector<MaximalEdgeRing*>* buildMaximalEdgeRings(vector<DirectedEdge*> *dirEdges);
    00493         vector<MaximalEdgeRing*>* buildMinimalEdgeRings(vector<MaximalEdgeRing*> *maxEdgeRings,
    00494                                                                                                 vector<EdgeRing*> *newShellList,
    00495                                                                                                 vector<EdgeRing*> *freeHoleList);
    00506         EdgeRing* findShell(vector<MinimalEdgeRing*>* minEdgeRings);
    00518         void placePolygonHoles(EdgeRing *shell,vector<MinimalEdgeRing*> *minEdgeRings);
    00526         void sortShellsAndHoles(vector<MaximalEdgeRing*> *edgeRings,
    00527                                                                                                 vector<EdgeRing*> *newShellList,
    00528                                                                                                 vector<EdgeRing*> *freeHoleList);
    00540         void placeFreeHoles(vector<EdgeRing*>* newShellList, vector<EdgeRing*> *freeHoleList);
    00555         EdgeRing* findEdgeRingContaining(EdgeRing *testEr,vector<EdgeRing*> *newShellList);
    00556         vector<Geometry*>* computePolygons(vector<EdgeRing*> *newShellList);
    00562 };
    00563
    00564
    00565 /*
    00566  * Creates nodes for use in the {@link PlanarGraph}s constructed during
    00567  * overlay operations.
    00568  *
    00569  */
    00570 class OverlayNodeFactory: public NodeFactory {
    00571 public:
    00572 //      OverlayNodeFactory() {};
    00573         Node* createNode(Coordinate coord);
    00574 };
    00575
    00576 /*
    00577  * Nodes a set of edges.
    00578  * Takes one or more sets of edges and constructs a
    00579  * new set of edges consisting of all the split edges created by
    00580  * noding the input edges together
    00581  */
    00582 class EdgeSetNoder {
    00583 private:
    00584         LineIntersector *li;
    00585         vector<Edge*>* inputEdges;
    00586 public:
    00587         EdgeSetNoder(LineIntersector *newLi);
    00588         ~EdgeSetNoder();
    00589         void addEdges(vector<Edge*> *edges);
    00590         vector<Edge*>* getNodedEdges();
    00591 };
    00592
    00593
    00594 } // namespace geos
    00595
    00596 #endif
    00597
    00598 /**********************************************************************
    00599  * $Log: opOverlay.h,v $
    00600  * Revision 1.8.2.1.2.1  2005/11/30 11:18:07  strk
    00601  * Fixed doxygen warnings
    00602  *
    00603  * Revision 1.8.2.1  2005/06/28 01:07:11  strk
    00604  * improved extraction of result points in overlay op
    00605  *
    00606  * Revision 1.8  2004/12/08 13:54:43  strk
    00607  * gcc warnings checked and fixed, general cleanups.
    00608  *
    00609  * Revision 1.7  2004/11/23 16:22:49  strk
    00610  * Added ElevationMatrix class and components to do post-processing draping of overlayed geometries.
    00611  *
    00612  * Revision 1.6  2004/11/22 15:51:52  strk
    00613  * Added interpolation of containing geometry's average Z for point_in_poly case.
    00614  *
    00615  * Revision 1.5  2004/11/20 18:17:26  strk
    00616  * Added Z propagation for overlay lines output.
    00617  *
    00618  * Revision 1.4  2004/11/20 17:16:10  strk
    00619  * Handled Z merging for point on polygon boundary case.
    00620  *
    00621  * Revision 1.3  2004/10/21 22:29:54  strk
    00622  * Indentation changes and some more COMPUTE_Z rules
    00623  *
    00624  * Revision 1.2  2004/07/19 13:19:31  strk
    00625  * Documentation fixes
    00626  *
    00627  * Revision 1.1  2004/07/02 13:20:42  strk
    00628  * Header files moved under geos/ dir.
    00629  *
    00630  * Revision 1.18  2004/07/01 14:12:44  strk
    00631  *
    00632  * Geometry constructors come now in two flavors:
    00633  *      - deep-copy args (pass-by-reference)
    00634  *      - take-ownership of args (pass-by-pointer)
    00635  * Same functionality is available through GeometryFactory,
    00636  * including buildGeometry().
    00637  *
    00638  * Revision 1.17  2004/06/30 20:59:13  strk
    00639  * Removed GeoemtryFactory copy from geometry constructors.
    00640  * Enforced const-correctness on GeometryFactory arguments.
    00641  *
    00642  * Revision 1.16  2004/05/03 10:43:42  strk
    00643  * Exception specification considered harmful - left as comment.
    00644  *
    00645  * Revision 1.15  2004/04/10 08:40:01  ybychkov
    00646  * "operation/buffer" upgraded to JTS 1.4
    00647  *
    00648  * Revision 1.14  2004/03/29 06:59:24  ybychkov
    00649  * "noding/snapround" package ported (JTS 1.4);
    00650  * "operation", "operation/valid", "operation/relate" and "operation/overlay" upgraded to JTS 1.4;
    00651  * "geom" partially upgraded.
    00652  *
    00653  * Revision 1.13  2004/03/19 09:48:45  ybychkov
    00654  * "geomgraph" and "geomgraph/indexl" upgraded to JTS 1.4
    00655  *
    00656  * Revision 1.12  2003/11/12 18:02:56  strk
    00657  * Added throw specification. Fixed leaks on exceptions.
    00658  *
    00659  * Revision 1.11  2003/11/12 16:14:56  strk
    00660  * Added some more throw specifications and cleanup on exception (leaks removed).
    00661  *
    00662  * Revision 1.10  2003/11/07 01:23:42  pramsey
    00663  * Add standard CVS headers licence notices and copyrights to all cpp and h
    00664  * files.
    00665  *
    00666  *
    00667  **********************************************************************/