Interface BoundaryNodeRule

  1 /*
  2  * Copyright (c) 2016 Vivid Solutions.
  3  *
  4  * All rights reserved. This program and the accompanying materials
  5  * are made available under the terms of the Eclipse Public License 2.0
  6  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
  7  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
  8  * and the Eclipse Distribution License is available at
  9  *
 10  * http://www.eclipse.org/org/documents/edl-v10.php.
 11  */
 12 package org.locationtech.jts.algorithm;
 13  
 14 import org.locationtech.jts.geom.LineString;
 15 import org.locationtech.jts.geom.Lineal;
 16 import org.locationtech.jts.geom.LinearRing;
 17 import org.locationtech.jts.geom.MultiLineString;
 18 import org.locationtech.jts.operation.BoundaryOp;
 19 import org.locationtech.jts.operation.IsSimpleOp;
 20 import org.locationtech.jts.operation.relate.RelateOp;
 21  
 22 /**
 23  * An interface for rules which determine whether node points
 24  * which are in boundaries of {@link Lineal} geometry components
 25  * are in the boundary of the parent geometry collection.
 26  * The SFS specifies a single kind of boundary node rule,
 27  * the {@link Mod2BoundaryNodeRule} rule.
 28  * However, other kinds of Boundary Node Rules are appropriate
 29  * in specific situations (for instance, linear network topology
 30  * usually follows the {@link EndPointBoundaryNodeRule}.)
 31  * Some JTS operations 
 32  * (such as {@link RelateOp}, {@link BoundaryOp} and {@link IsSimpleOp})
 33  * allow the BoundaryNodeRule to be specified,
 34  * and respect the supplied rule when computing the results of the operation.
 35  * <p>
 36  * An example use case for a non-SFS-standard Boundary Node Rule is
 37  * that of checking that a set of {@link LineString}s have 
 38  * valid linear network topology, when turn-arounds are represented
 39  * as closed rings.  In this situation, the entry road to the
 40  * turn-around is only valid when it touches the turn-around ring
 41  * at the single (common) endpoint.  This is equivalent 
 42  * to requiring the set of <tt>LineString</tt>s to be 
 43  * <b>simple</b> under the {@link EndPointBoundaryNodeRule}.
 44  * The SFS-standard {@link Mod2BoundaryNodeRule} is not 
 45  * sufficient to perform this test, since it
 46  * states that closed rings have <b>no</b> boundary points.
 47  * <p>
 48  * This interface and its subclasses follow the <tt>Strategy</tt> design pattern.
 49  *
 50  * @author Martin Davis
 51  * @version 1.7
 52  *
 53  * @see RelateOp
 54  * @see BoundaryOp
 55  * @see IsSimpleOp
 56  * @see PointLocator
 57  */
 58 public interface BoundaryNodeRule
 59 {
 60  
 61     /**
 62      * Tests whether a point that lies in <tt>boundaryCount</tt>
 63      * geometry component boundaries is considered to form part of the boundary
 64      * of the parent geometry.
 65      * 
 66      * @param boundaryCount the number of component boundaries that this point occurs in
 67      * @return true if points in this number of boundaries lie in the parent boundary
 68      */
 69   boolean isInBoundary(int boundaryCount);
 70  
 71   /**
 72    * The Mod-2 Boundary Node Rule (which is the rule specified in the OGC SFS).
 73    * @see Mod2BoundaryNodeRule
 74    */
 75   public static final BoundaryNodeRule MOD2_BOUNDARY_RULE = new Mod2BoundaryNodeRule();
 76  
 77   /**
 78    * The Endpoint Boundary Node Rule.
 79    * @see EndPointBoundaryNodeRule
 80    */
 81   public static final BoundaryNodeRule ENDPOINT_BOUNDARY_RULE = new EndPointBoundaryNodeRule();
 82  
 83   /**
 84    * The MultiValent Endpoint Boundary Node Rule.
 85    * @see MultiValentEndPointBoundaryNodeRule
 86    */
 87   public static final BoundaryNodeRule MULTIVALENT_ENDPOINT_BOUNDARY_RULE = new MultiValentEndPointBoundaryNodeRule();
 88  
 89   /**
 90    * The Monovalent Endpoint Boundary Node Rule.
 91    * @see MonoValentEndPointBoundaryNodeRule
 92    */
 93   public static final BoundaryNodeRule MONOVALENT_ENDPOINT_BOUNDARY_RULE = new MonoValentEndPointBoundaryNodeRule();
 94  
 95   /**
 96    * The Boundary Node Rule specified by the OGC Simple Features Specification,
 97    * which is the same as the Mod-2 rule.
 98    * @see Mod2BoundaryNodeRule
 99    */
100   public static final BoundaryNodeRule OGC_SFS_BOUNDARY_RULE = MOD2_BOUNDARY_RULE;
101  
102   /**
103    * A {@link BoundaryNodeRule} specifies that points are in the
104    * boundary of a lineal geometry iff
105    * the point lies on the boundary of an odd number
106    * of components.
107    * Under this rule {@link LinearRing}s and closed
108    * {@link LineString}s have an empty boundary.
109    * <p>
110    * This is the rule specified by the <i>OGC SFS</i>,
111    * and is the default rule used in JTS.
112    *
113    * @author Martin Davis
114    * @version 1.7
115    */
116   public static class Mod2BoundaryNodeRule
117       implements BoundaryNodeRule
118   {
119     public boolean isInBoundary(int boundaryCount)
120     {
121       // the "Mod-2 Rule"
122       return boundaryCount % 2 == 1;
123     }
124   }
125  
126   /**
127    * A {@link BoundaryNodeRule} which specifies that any points which are endpoints
128    * of lineal components are in the boundary of the
129    * parent geometry.
130    * This corresponds to the "intuitive" topological definition
131    * of boundary.
132    * Under this rule {@link LinearRing}s have a non-empty boundary
133    * (the common endpoint of the underlying LineString).
134    * <p>
135    * This rule is useful when dealing with linear networks.
136    * For example, it can be used to check
137    * whether linear networks are correctly noded.
138    * The usual network topology constraint is that linear segments may touch only at endpoints.
139    * In the case of a segment touching a closed segment (ring) at one point,
140    * the Mod2 rule cannot distinguish between the permitted case of touching at the
141    * node point and the invalid case of touching at some other interior (non-node) point.
142    * The EndPoint rule does distinguish between these cases,
143    * so is more appropriate for use.
144    *
145    * @author Martin Davis
146    * @version 1.7
147    */
148   public static class EndPointBoundaryNodeRule
149       implements BoundaryNodeRule
150   {
151     public boolean isInBoundary(int boundaryCount)
152     {
153       return boundaryCount > 0;
154     }
155   }
156  
157   /**
158    * A {@link BoundaryNodeRule} which determines that only
159    * endpoints with valency greater than 1 are on the boundary.
160    * This corresponds to the boundary of a {@link MultiLineString}
161    * being all the "attached" endpoints, but not
162    * the "unattached" ones.
163    *
164    * @author Martin Davis
165    * @version 1.7
166    */
167   public static class MultiValentEndPointBoundaryNodeRule
168       implements BoundaryNodeRule
169   {
170     public boolean isInBoundary(int boundaryCount)
171     {
172       return boundaryCount > 1;
173     }
174   }
175  
176   /**
177    * A {@link BoundaryNodeRule} which determines that only
178    * endpoints with valency of exactly 1 are on the boundary.
179    * This corresponds to the boundary of a {@link MultiLineString}
180    * being all the "unattached" endpoints.
181    *
182    * @author Martin Davis
183    * @version 1.7
184    */
185   public static class MonoValentEndPointBoundaryNodeRule
186       implements BoundaryNodeRule
187   {
188     public boolean isInBoundary(int boundaryCount)
189     {
190       return boundaryCount == 1;
191     }
192   }
193  
194  
195 }
196