/** * */ package es.axios.lib.geometry.split; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; import es.axios.lib.geometry.util.GeometryList; /** * Provides utility method to manipulate rings * <p> * </p> * @author Mauricio Pazos (www.axios.es) * @author Aritz Davila (www.axios.es) * @since 1.3.0 */ final class RingUtil { private RingUtil(){ // private for utility class. } public static List<LineString> ringToSegmentList( LinearRing ring ) { GeometryFactory gf = ring.getFactory(); List<LineString> segmentList = new GeometryList<LineString>(); Coordinate[] ringCoords = ring.getCoordinates(); for( int i = 0; i < ringCoords.length - 1; i++ ) { LineString segment = gf.createLineString(new Coordinate[]{ringCoords[i], ringCoords[i+1]}); segmentList.add(segment); } return segmentList; } /** * Transform the segment list to a ring. * * @param adaptedRingSegmentList * * @return a new ring */ public static LinearRing segmentListToRing( List<LineString> adaptedRingSegmentList ) { List<Coordinate> coordList = new LinkedList<Coordinate>(); for( LineString line: adaptedRingSegmentList ) { // insert the line coordinate in the final coordinate array Coordinate[] lineCoords = line.getCoordinates(); for( int i = 0; i < lineCoords.length; i++ ) { if (!coordList.contains(lineCoords[i])) { coordList.add(lineCoords[i]); } } } // add the first coordinate has last coordinate in order to close the ring coordList.add(coordList.get(0)); Coordinate[] linearRingCoords = coordList.toArray(new Coordinate[ coordList.size() ]); GeometryFactory factory = adaptedRingSegmentList.get(0).getFactory(); LinearRing ring = factory.createLinearRing(linearRingCoords); return ring; } /** * Close the given line forming a ring and return its coordinates. * * @param coordinates * Line coordinates * @return An array coordinates forming a closed line, a ring. */ public static Coordinate[] builRing(Coordinate[] coordinates) { final int length = coordinates.length; Coordinate[] closed = Arrays.copyOf(coordinates, length +1); closed[length] = coordinates[0]; return closed; } /** * Go through the rings, for each ring, calculate if there is an * intersection with the provided segment. If that's true, calculates the * distance of this intersection respect the beginning of the segment. Map * each ring which it's closest distance. * * @param rings * @param segment * @param lineSegment * @return A map with each ring and it's closest distance. */ public static Map<LinearRing, Double> setRingWithClosestIntersectionDistance( final List<LinearRing> rings, final Geometry segment, final Coordinate[] lineSegment) { Map<LinearRing, Double> ringsDistance = new HashMap<LinearRing, Double>(); for (LinearRing eachRing : rings) { Geometry intersection = eachRing.intersection(segment); int numGeometries = intersection.getNumGeometries(); double distance; // if the intersection is found, return; if (numGeometries == 1) { // calculate the distance and put this ring with its distance. Coordinate intersectionPoint = intersection.getCoordinate(); distance = SplitUtil.calculateDistanceFromFirst(intersectionPoint, lineSegment[0], lineSegment[1]); ringsDistance.put(eachRing, Math.abs(distance)); } else if (numGeometries > 1) { // calculate the closest distance, and put this ring with the // closest distance. double minDistance = Double.MAX_VALUE; // find the closest one to coordinate[i] for (int j = 0; j < intersection.getNumGeometries(); j++) { Coordinate curPoint = intersection.getGeometryN(j).getCoordinate(); distance = SplitUtil.calculateDistanceFromFirst(curPoint, lineSegment[0], lineSegment[1]); if (Math.abs(distance) < minDistance) { minDistance = Math.abs(distance); } } ringsDistance.put(eachRing, Math.abs(minDistance)); } } return ringsDistance; } }