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