1 /**********************************************************************
2  *
3  * GEOS - Geometry Engine Open Source
4  * http://geos.osgeo.org
5  *
6  * Copyright (C) 2009      Sandro Santilli <strk@kbt.io>
7  *
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.
12  *
13  **********************************************************************
14  *
15  * Last port: algorithm/BoundaryNodeRule.java rev 1.4 (JTS-1.10)
16  *
17  **********************************************************************/
18 
19 #include <geos/algorithm/BoundaryNodeRule.h>
20 
21 namespace geos {
22 namespace algorithm { // geos.algorithm
23 
24 // These classes are public in JTS, and under the BoundaryNodeRule
25 // namespace. In GEOS they are hidden and only accessible as singleton
26 // from BoundaryNodeRule static const references
27 //
28 namespace {
29 
30 /**
31  * A {@link BoundaryNodeRule} specifies that points are in the
32  * boundary of a lineal geometry iff
33  * the point lies on the boundary of an odd number
34  * of components.
35  * Under this rule {@link LinearRing}s and closed
36  * {@link LineString}s have an empty boundary.
37  * <p>
38  * This is the rule specified by the <i>OGC SFS</i>,
39  * and is the default rule used in JTS.
40  *
41  * @author Martin Davis
42  * @version 1.7
43  */
44 class Mod2BoundaryNodeRule : public BoundaryNodeRule {
45 public:
46     bool
isInBoundary(int boundaryCount) const47     isInBoundary(int boundaryCount) const override
48     {
49         // the "Mod-2 Rule"
50         return boundaryCount % 2 == 1;
51     }
52 };
53 
54 
55 /**
56  * A {@link BoundaryNodeRule} which specifies that any points
57  * which are endpoints
58  * of lineal components are in the boundary of the
59  * parent geometry.
60  * This corresponds to the "intuitive" topological definition
61  * of boundary.
62  * Under this rule {@link LinearRing}s have a non-empty boundary
63  * (the common endpoint of the underlying LineString).
64  * <p>
65  * This rule is useful when dealing with linear networks.
66  * For example, it can be used to check
67  * whether linear networks are correctly noded.
68  * The usual network topology constraint is that linear segments may
69  * touch only at endpoints.
70  * In the case of a segment touching a closed segment (ring) at one
71  * point,
72  * the Mod2 rule cannot distinguish between the permitted case of
73  * touching at the
74  * node point and the invalid case of touching at some other interior
75  * (non-node) point.
76  * The EndPoint rule does distinguish between these cases,
77  * so is more appropriate for use.
78  *
79  * @author Martin Davis
80  * @version 1.7
81  */
82 class EndPointBoundaryNodeRule : public BoundaryNodeRule {
83     bool
isInBoundary(int boundaryCount) const84     isInBoundary(int boundaryCount) const override
85     {
86         return boundaryCount > 0;
87     }
88 };
89 
90 /**
91  * A {@link BoundaryNodeRule} which determines that only
92  * endpoints with valency greater than 1 are on the boundary.
93  * This corresponds to the boundary of a {@link MultiLineString}
94  * being all the "attached" endpoints, but not
95  * the "unattached" ones.
96  *
97  * @author Martin Davis
98  * @version 1.7
99  */
100 class MultiValentEndPointBoundaryNodeRule : public BoundaryNodeRule {
101     bool
isInBoundary(int boundaryCount) const102     isInBoundary(int boundaryCount) const override
103     {
104         return boundaryCount > 1;
105     }
106 };
107 
108 /**
109  * A {@link BoundaryNodeRule} which determines that only
110  * endpoints with valency of exactly 1 are on the boundary.
111  * This corresponds to the boundary of a {@link MultiLineString}
112  * being all the "unattached" endpoints.
113  *
114  * @author Martin Davis
115  * @version 1.7
116  */
117 class MonoValentEndPointBoundaryNodeRule : public BoundaryNodeRule {
118     bool
isInBoundary(int boundaryCount) const119     isInBoundary(int boundaryCount) const override
120     {
121         return boundaryCount == 1;
122     }
123 };
124 
125 Mod2BoundaryNodeRule mod2Rule;
126 EndPointBoundaryNodeRule endPointRule;
127 MultiValentEndPointBoundaryNodeRule multiValentRule;
128 MonoValentEndPointBoundaryNodeRule monoValentRule;
129 
130 } // anonymous namespace
131 
132 //const BoundaryNodeRule& BoundaryNodeRule::MOD2_BOUNDARY_RULE = mod2Rule;
133 const BoundaryNodeRule&
getBoundaryRuleMod2()134 BoundaryNodeRule::getBoundaryRuleMod2()
135 {
136     return mod2Rule;
137 }
138 
139 //const BoundaryNodeRule& BoundaryNodeRule::ENDPOINT_BOUNDARY_RULE = endPointRule;
140 const BoundaryNodeRule&
getBoundaryEndPoint()141 BoundaryNodeRule::getBoundaryEndPoint()
142 {
143     return endPointRule;
144 }
145 
146 //const BoundaryNodeRule& BoundaryNodeRule::MULTIVALENT_ENDPOINT_BOUNDARY_RULE = multiValentRule;
147 const BoundaryNodeRule&
getBoundaryMultivalentEndPoint()148 BoundaryNodeRule::getBoundaryMultivalentEndPoint()
149 {
150     return multiValentRule;
151 }
152 
153 //const BoundaryNodeRule& BoundaryNodeRule::MONOVALENT_ENDPOINT_BOUNDARY_RULE = monoValentRule;
154 const BoundaryNodeRule&
getBoundaryMonovalentEndPoint()155 BoundaryNodeRule::getBoundaryMonovalentEndPoint()
156 {
157     return monoValentRule;
158 }
159 
160 //const BoundaryNodeRule& BoundaryNodeRule::OGC_SFS_BOUNDARY_RULE = BoundaryNodeRule::MOD2_BOUNDARY_RULE;
161 const BoundaryNodeRule&
getBoundaryOGCSFS()162 BoundaryNodeRule::getBoundaryOGCSFS()
163 {
164     return getBoundaryRuleMod2();
165 }
166 
167 } // namespace geos.algorithm
168 } // namespace geos
169 
170