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.jtslab.clean; 13 14 import java.util.ArrayList; 15 import java.util.List; 16 17 import org.locationtech.jts.geom.Geometry; 18 import org.locationtech.jts.geom.GeometryFactory; 19 import org.locationtech.jts.geom.LinearRing; 20 import org.locationtech.jts.geom.Polygon; 21 import org.locationtech.jts.geom.util.GeometryMapper; 22 import org.locationtech.jts.geom.util.GeometryMapper.MapOp; 23 24 /** 25 * Removes holes which match a given predicate. 26 * 27 * @author Martin Davis 28 * 29 */ 30 public class HoleRemover { 31 32 public interface Predicate { value(Geometry geom)33 boolean value(Geometry geom); 34 } 35 36 private Geometry geom; 37 private Predicate isRemoved; 38 39 /** 40 * Creates a new hole remover instance. 41 * 42 * @param geom the geometry to process 43 */ HoleRemover(Geometry geom, Predicate isRemoved)44 public HoleRemover(Geometry geom, Predicate isRemoved) { 45 this.geom = geom; 46 this.isRemoved = isRemoved; 47 } 48 49 /** 50 * Gets the cleaned geometry. 51 * 52 * @return the geometry with matched holes removed. 53 */ getResult()54 public Geometry getResult() 55 { 56 return GeometryMapper.map(geom, new HoleRemoverMapOp()); 57 } 58 59 private class HoleRemoverMapOp implements MapOp { map(Geometry geom)60 public Geometry map(Geometry geom) { 61 if (geom instanceof Polygon) 62 return PolygonHoleRemover.clean((Polygon) geom, isRemoved); 63 return geom; 64 } 65 } 66 67 private static class PolygonHoleRemover { 68 clean(Polygon poly, Predicate isRemoved)69 public static Polygon clean(Polygon poly, Predicate isRemoved) { 70 PolygonHoleRemover pihr = new PolygonHoleRemover(poly, isRemoved); 71 return pihr.getResult(); 72 } 73 74 private Polygon poly; 75 private Predicate isRemoved; 76 PolygonHoleRemover(Polygon poly, Predicate isRemoved)77 public PolygonHoleRemover(Polygon poly, Predicate isRemoved) { 78 this.poly = poly; 79 this.isRemoved = isRemoved; 80 } 81 getResult()82 public Polygon getResult() 83 { 84 GeometryFactory gf = poly.getFactory(); 85 Polygon shell = gf.createPolygon(poly.getExteriorRing()); 86 87 List holes = new ArrayList(); 88 for (int i = 0; i < poly.getNumInteriorRing(); i++) { 89 LinearRing hole = poly.getInteriorRingN(i); 90 if (! isRemoved.value(hole)) { 91 holes.add(hole); 92 } 93 } 94 // all holes valid, so return original 95 if (holes.size() == poly.getNumInteriorRing()) 96 return poly; 97 98 // return new polygon with covered holes only 99 Polygon result = gf.createPolygon(poly.getExteriorRing(), 100 GeometryFactory.toLinearRingArray(holes)); 101 return result; 102 } 103 104 } 105 } 106