Class BufferCurveMaximumDistanceFinder

  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.operation.buffer.validate;
 13  
 14 import org.locationtech.jts.geom.Coordinate;
 15 import org.locationtech.jts.geom.CoordinateFilter;
 16 import org.locationtech.jts.geom.CoordinateSequence;
 17 import org.locationtech.jts.geom.CoordinateSequenceFilter;
 18 import org.locationtech.jts.geom.Geometry;
 19  
 20 /**
 21  * Finds the approximate maximum distance from a buffer curve to
 22  * the originating geometry.
 23  * This is similar to the Discrete Oriented Hausdorff distance
 24  * from the buffer curve to the input.
 25  * <p>
 26  * The approximate maximum distance is determined by testing
 27  * all vertices in the buffer curve, as well
 28  * as midpoints of the curve segments.
 29  * Due to the way buffer curves are constructed, this
 30  * should be a very close approximation.
 31  * 
 32  * @author mbdavis
 33  *
 34  */
 35 public class BufferCurveMaximumDistanceFinder 
 36 {
 37     private Geometry inputGeom;
 38   private PointPairDistance maxPtDist = new PointPairDistance();
 39  
 40     public BufferCurveMaximumDistanceFinder(Geometry inputGeom)
 41     {
 42         this.inputGeom = inputGeom;
 43     }
 44     
 45     public double findDistance(Geometry bufferCurve)
 46     {
 47     computeMaxVertexDistance(bufferCurve);
 48     computeMaxMidpointDistance(bufferCurve);
 49     return maxPtDist.getDistance();
 50     }
 51     
 52     public PointPairDistance getDistancePoints()
 53     {
 54         return maxPtDist;
 55     }
 56     private void computeMaxVertexDistance(Geometry curve)
 57     {
 58     MaxPointDistanceFilter distFilter = new MaxPointDistanceFilter(inputGeom);
 59     curve.apply(distFilter);
 60     maxPtDist.setMaximum(distFilter.getMaxPointDistance());
 61     }
 62     
 63     private void computeMaxMidpointDistance(Geometry curve)
 64     {
 65     MaxMidpointDistanceFilter distFilter = new MaxMidpointDistanceFilter(inputGeom);
 66     curve.apply(distFilter);
 67     maxPtDist.setMaximum(distFilter.getMaxPointDistance());
 68     }
 69     
 70   public static class MaxPointDistanceFilter implements CoordinateFilter {
 71         private PointPairDistance maxPtDist = new PointPairDistance();
 72         private PointPairDistance minPtDist = new PointPairDistance();
 73         private Geometry geom;
 74  
 75         public MaxPointDistanceFilter(Geometry geom) {
 76             this.geom = geom;
 77         }
 78  
 79         public void filter(Coordinate pt) {
 80             minPtDist.initialize();
 81             DistanceToPointFinder.computeDistance(geom, pt, minPtDist);
 82             maxPtDist.setMaximum(minPtDist);
 83         }
 84  
 85         public PointPairDistance getMaxPointDistance() {
 86             return maxPtDist;
 87         }
 88     }
 89  
 90   public static class MaxMidpointDistanceFilter 
 91       implements CoordinateSequenceFilter 
 92       {
 93         private PointPairDistance maxPtDist = new PointPairDistance();
 94         private PointPairDistance minPtDist = new PointPairDistance();
 95         private Geometry geom;
 96  
 97         public MaxMidpointDistanceFilter(Geometry geom) {
 98             this.geom = geom;
 99         }
100  
101         public void filter(CoordinateSequence seq, int index) 
102         {
103             if (index == 0)
104                 return;
105             
106             Coordinate p0 = seq.getCoordinate(index - 1);
107             Coordinate p1 = seq.getCoordinate(index);
108             Coordinate midPt = new Coordinate(
109                     (p0.x + p1.x)/2,
110                     (p0.y + p1.y)/2);
111             
112             minPtDist.initialize();
113             DistanceToPointFinder.computeDistance(geom, midPt, minPtDist);
114             maxPtDist.setMaximum(minPtDist);
115         }
116  
117         public boolean isGeometryChanged() { return false; }
118         
119         public boolean isDone() { return false; }
120         
121         public PointPairDistance getMaxPointDistance() {
122             return maxPtDist;
123         }
124     }
125  
126 }
127