/** * H2GIS is a library that brings spatial support to the H2 Database Engine * <http://www.h2database.com>. H2GIS is developed by CNRS * <http://www.cnrs.fr/>. * * This code is part of the H2GIS project. H2GIS is free software; * you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; * version 3.0 of the License. * * H2GIS is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details <http://www.gnu.org/licenses/>. * * * For more information, please consult: <http://www.h2gis.org/> * or contact directly: info_at_h2gis.org */ package org.h2gis.functions.spatial.distance; import com.vividsolutions.jts.geom.*; import org.h2gis.api.DeterministicScalarFunction; import java.util.HashSet; import java.util.Set; /** * ST_LocateAlong returns a MULTIPOINT containing points along the line * segments of the given geometry matching the specified segment length * fraction and offset distance. A positive offset places the point to the left * of the segment (with the ordering given by Coordinate traversal); a negative * offset to the right. For areal elements, only exterior rings are supported. * * @author Adam Gouge * @author Erwan Bocher */ public class ST_LocateAlong extends DeterministicScalarFunction { public ST_LocateAlong() { addProperty(PROP_REMARKS, "Returns a MULTIPOINT containing points along " + "the line segments of the given geometry matching the specified " + "segment length fraction and offset distance. A positive offset " + "places the point to the left of the segment (with the ordering " + "given by Coordinate traversal); a negative offset to the right. " + "For areal elements, only exterior rings are supported."); } @Override public String getJavaStaticMethod() { return "locateAlong"; } /** * Returns a MULTIPOINT containing points along the line segments of the * given geometry matching the specified segment length fraction and offset * distance. * * @param geom Geometry * @param segmentLengthFraction Segment length fraction * @param offsetDistance Offset distance * @return A MULTIPOINT containing points along the line segments of the * given geometry matching the specified segment length fraction and offset * distance */ public static MultiPoint locateAlong(Geometry geom, double segmentLengthFraction, double offsetDistance) { if (geom == null) { return null; } if (geom.getDimension() == 0) { return null; } Set<Coordinate> result = new HashSet<Coordinate>(); for (int i = 0; i < geom.getNumGeometries(); i++) { Geometry subGeom = geom.getGeometryN(i); if (subGeom instanceof Polygon) { // Ignore hole result.addAll(computePoints(((Polygon) subGeom).getExteriorRing().getCoordinates(), segmentLengthFraction, offsetDistance)); } else if (subGeom instanceof LineString) { result.addAll(computePoints(subGeom.getCoordinates(), segmentLengthFraction, offsetDistance)); } } return geom.getFactory().createMultiPoint( result.toArray(new Coordinate[result.size()])); } private static Set<Coordinate> computePoints(Coordinate[] coords, double segmentLengthFraction, double offsetDistance) { Set<Coordinate> pointsToAdd = new HashSet<Coordinate>(); for (int j = 0; j < coords.length - 1; j++) { LineSegment segment = new LineSegment(coords[j], coords[j + 1]); pointsToAdd.add(segment.pointAlongOffset(segmentLengthFraction, offsetDistance)); } return pointsToAdd; } }