1 /*
2  * Copyright (c) 2019 Martin Davis.
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.operation.overlayng;
13 
14 import org.locationtech.jts.algorithm.locate.IndexedPointInAreaLocator;
15 import org.locationtech.jts.algorithm.locate.PointOnGeometryLocator;
16 import org.locationtech.jts.geom.Coordinate;
17 import org.locationtech.jts.geom.Envelope;
18 import org.locationtech.jts.geom.Geometry;
19 import org.locationtech.jts.geom.Location;
20 
21 /**
22  * Manages the input geometries for an overlay operation.
23  * The second geometry is allowed to be null,
24  * to support for instance precision reduction.
25  *
26  * @author Martin Davis
27  *
28  */
29 class InputGeometry {
30 
31   //private static final PointLocator ptLocator = new PointLocator();
32 
33   private Geometry[] geom = new Geometry[2];
34   private PointOnGeometryLocator ptLocatorA;
35   private PointOnGeometryLocator ptLocatorB;
36   private boolean[] isCollapsed = new boolean[2];
37 
InputGeometry(Geometry geomA, Geometry geomB)38   public InputGeometry(Geometry geomA, Geometry geomB) {
39     geom = new Geometry[] { geomA, geomB };
40   }
41 
isSingle()42   public boolean isSingle() {
43     return geom[1] == null;
44   }
45 
getDimension(int index)46   public int getDimension(int index) {
47     if (geom[index] == null) return -1;
48     return geom[index].getDimension();
49   }
50 
getGeometry(int geomIndex)51   public Geometry getGeometry(int geomIndex) {
52     return geom[geomIndex];
53   }
54 
getEnvelope(int geomIndex)55   public Envelope getEnvelope(int geomIndex) {
56     return geom[geomIndex].getEnvelopeInternal();
57   }
58 
isEmpty(int geomIndex)59   public boolean isEmpty(int geomIndex) {
60     return geom[geomIndex].isEmpty();
61   }
62 
isArea(int geomIndex)63   public boolean isArea(int geomIndex) {
64     return geom[geomIndex] != null && geom[geomIndex].getDimension() == 2;
65   }
66 
67   /**
68    * Gets the index of an input which is an area,
69    * if one exists.
70    * Otherwise returns -1.
71    * If both inputs are areas, returns the index of the first one (0).
72    *
73    * @return the index of an area input, or -1
74    */
getAreaIndex()75   public int getAreaIndex() {
76     if (getDimension(0) == 2) return 0;
77     if (getDimension(1) == 2) return 1;
78     return -1;
79   }
80 
isLine(int geomIndex)81   public boolean isLine(int geomIndex) {
82     return getDimension(geomIndex) == 1;
83   }
84 
isAllPoints()85   public boolean isAllPoints() {
86     return getDimension(0) == 0
87         && geom[1] != null && getDimension(1) == 0;
88   }
89 
hasPoints()90   public boolean hasPoints() {
91     return getDimension(0) == 0 || getDimension(1) == 0;
92   }
93 
94   /**
95    * Tests if an input geometry has edges.
96    * This indicates that topology needs to be computed for them.
97    *
98    * @param geomIndex
99    * @return true if the input geometry has edges
100    */
hasEdges(int geomIndex)101   public boolean hasEdges(int geomIndex) {
102     return geom[geomIndex] != null && geom[geomIndex].getDimension() > 0;
103   }
104 
105   /**
106    * Determines the location within an area geometry.
107    * This allows disconnected edges to be fully
108    * located.
109    *
110    * @param geomIndex the index of the geometry
111    * @param pt the coordinate to locate
112    * @return the location of the coordinate
113    *
114    * @see Location
115    */
locatePointInArea(int geomIndex, Coordinate pt)116   public int locatePointInArea(int geomIndex, Coordinate pt) {
117     // Assert: only called if dimension(geomIndex) = 2
118 
119     if ( isCollapsed[geomIndex])
120       return Location.EXTERIOR;
121 
122 
123     //return ptLocator.locate(pt, geom[geomIndex]);
124 
125     //*
126     // this check is required because IndexedPointInAreaLocator can't handle empty polygons
127     if (getGeometry(geomIndex).isEmpty()
128         || isCollapsed[geomIndex])
129       return Location.EXTERIOR;
130 
131     PointOnGeometryLocator ptLocator = getLocator(geomIndex);
132     return ptLocator.locate(pt);
133     //*/
134   }
135 
getLocator(int geomIndex)136   private PointOnGeometryLocator getLocator(int geomIndex) {
137     if (geomIndex == 0) {
138       if (ptLocatorA == null)
139         ptLocatorA = new IndexedPointInAreaLocator(getGeometry(geomIndex));
140       return ptLocatorA;
141     }
142     else {
143       if (ptLocatorB == null)
144         ptLocatorB = new IndexedPointInAreaLocator(getGeometry(geomIndex));
145       return ptLocatorB;
146     }
147   }
148 
setCollapsed(int geomIndex, boolean isGeomCollapsed)149   public void setCollapsed(int geomIndex, boolean isGeomCollapsed) {
150     isCollapsed[geomIndex] = isGeomCollapsed;
151   }
152 
153 
154 }
155