Author: aaime Date: 2012-04-15 17:06:18 -0700 (Sun, 15 Apr 2012) New Revision: 38667 Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSGeocodeProcess.java trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSMeasureProcess.java trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSSegmentProcess.java trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSGeocodeProcessTest.java trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSMeasureProcessTest.java trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSSegmentProcessTest.java trunk/modules/unsupported/process-feature/src/test/resources/org/geotools/process/feature/gs/test-data/lrssimple.properties Modified: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java Log: [GEOT-4096] Contribute three LRS WPS processes, patch by David R Robison Modified: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java 2012-04-15 23:54:54 UTC (rev 38666) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -61,7 +61,10 @@ UnionFeatureCollection.class, UniqueProcess.class, VectorZonalStatistics.class, - TransformProcess.class); + TransformProcess.class, + LRSGeocodeProcess.class, + LRSMeasureProcess.class, + LRSSegmentProcess.class); } } Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSGeocodeProcess.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSGeocodeProcess.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSGeocodeProcess.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,193 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2011, Open Source Geospatial Foundation (OSGeo) + * (C) 2001-2007 TOPP - www.openplans.org. + * + * This library 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 2.1 of the License. + * + * This library 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. + */ +package org.geotools.process.feature.gs; + +import java.util.logging.Logger; + +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.feature.FeatureIterator; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.geotools.feature.simple.SimpleFeatureTypeBuilder; +import org.geotools.process.ProcessException; +import org.geotools.process.factory.DescribeParameter; +import org.geotools.process.factory.DescribeProcess; +import org.geotools.process.factory.DescribeResult; +import org.geotools.process.gs.GSProcess; +import org.geotools.util.logging.Logging; +import org.opengis.feature.Feature; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.AttributeDescriptor; +import org.opengis.feature.type.FeatureType; +import org.opengis.feature.type.PropertyDescriptor; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.linearref.LengthIndexedLine; + +@DescribeProcess(title = "LRSGeocode", description = "Translate LRS measure to geocoded point") +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/NearestProcess.java $ + */ +public class LRSGeocodeProcess implements GSProcess { + private static final Logger LOGGER = Logging.getLogger(LRSGeocodeProcess.class); + + private final GeometryFactory geometryFactory = new GeometryFactory(); + + /** + * Process the input data set. + * + * @param featureCollection the data set + * @param crs the CRS + * @param point the given point + * @return the snapped to feature + * @throws ProcessException error + */ + @DescribeResult(name = "result", description = "The geocoded point") + public FeatureCollection execute( + @DescribeParameter(name = "features", description = "The features to search") FeatureCollection featureCollection, + @DescribeParameter(name = "from_measure_attb", description = "The feature attribue holding the features starting measure") String fromMeasureAttb, + @DescribeParameter(name = "to_measure_attb", description = "The feature attribue holding the features ending measure") String toMeasureAttb, + @DescribeParameter(name = "measure", description = "The LRS measure") Double measure) + throws ProcessException { + FeatureCollection results = FeatureCollections.newCollection(); + try { + if (featureCollection == null || featureCollection.size() == 0) { + LOGGER.info("No features provided in request"); + return results; + } + if (fromMeasureAttb == null + || featureCollection.getSchema().getDescriptor(fromMeasureAttb) == null) { + throw new ProcessException( + "The from_measure_attb parameter was not provided or not defined in schema"); + } + if (toMeasureAttb == null + || featureCollection.getSchema().getDescriptor(toMeasureAttb) == null) { + throw new ProcessException("The to_measure_attb parameter was not provided"); + } + if (measure == null) { + throw new ProcessException("The measure parameter was not provided"); + } + SimpleFeatureType targetFeatureType = createTargetFeatureType(featureCollection + .getSchema()); + + FeatureIterator<Feature> featureIterator = null; + try { + featureIterator = featureCollection.features(); + Feature feature = featureIterator.next(); + Double featureFromMeasure = (Double) feature.getProperty(fromMeasureAttb) + .getValue(); + Double featureToMeasure = (Double) feature.getProperty(toMeasureAttb).getValue(); + LengthIndexedLine lengthIndexedLine = new LengthIndexedLine((Geometry) feature + .getDefaultGeometryProperty().getValue()); + double featureLength = featureToMeasure - featureFromMeasure; + double startOffset = measure - featureFromMeasure; + double calcLength = ((Geometry) feature.getDefaultGeometryProperty().getValue()) + .getLength(); + if (calcLength == 0) { + LOGGER.info("Edge feature has zero length"); + return results; + } + if (featureLength == 0) { + LOGGER.info("Requested feature has zero length"); + return results; + } + Coordinate point = lengthIndexedLine.extractPoint(startOffset * calcLength + / featureLength); + results.add(createTargetFeature(feature, targetFeatureType, point)); + } finally { + if (featureIterator != null) + featureIterator.close(); + } + return results; + } catch (ProcessException e) { + throw e; + } catch (Throwable e) { + LOGGER.warning("Error executing method: " + e); + throw new ProcessException("Error executing method: " + e, e); + } + } + + /** + * Create the modified feature type. + * + * @param sourceFeatureType the source feature type + * @return the modified feature type + * @throws ProcessException errror + */ + private SimpleFeatureType createTargetFeatureType(FeatureType sourceFeatureType) + throws ProcessException { + try { + SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder(); + typeBuilder.setName(sourceFeatureType.getName().getLocalPart()); + typeBuilder.setNamespaceURI(sourceFeatureType.getName().getNamespaceURI()); + AttributeDescriptor geomAttbType = sourceFeatureType.getGeometryDescriptor(); + for (PropertyDescriptor attbType : sourceFeatureType.getDescriptors()) { + if (attbType.equals(geomAttbType)) { + typeBuilder.add(geomAttbType.getLocalName(), Point.class); + } else { + typeBuilder.add((AttributeDescriptor) attbType); + } + } + typeBuilder + .setDefaultGeometry(sourceFeatureType.getGeometryDescriptor().getLocalName()); + return typeBuilder.buildFeatureType(); + } catch (Exception e) { + LOGGER.warning("Error creating type: " + e); + throw new ProcessException("Error creating type: " + e, e); + } + } + + /** + * Create the modified feature. + * + * @param feature the source feature + * @param targetFeatureType the modified feature type + * @param nearestDistance the snap distance + * @param nearestBearing the snap bearing + * @return the modified feature + * @throws ProcessException error + */ + private SimpleFeature createTargetFeature(Feature feature, SimpleFeatureType targetFeatureType, + Coordinate geocodePoint) throws ProcessException { + try { + AttributeDescriptor geomAttbType = targetFeatureType.getGeometryDescriptor(); + Object[] attributes = new Object[targetFeatureType.getAttributeCount()]; + for (int i = 0; i < attributes.length; i++) { + AttributeDescriptor attbType = targetFeatureType.getAttributeDescriptors().get(i); + if (attbType.equals(geomAttbType)) { + Point point = geometryFactory.createPoint(geocodePoint); + point.setSRID(4326); + attributes[i] = point; + } else { + attributes[i] = feature.getProperty(attbType.getName()).getValue(); + } + } + return SimpleFeatureBuilder.build(targetFeatureType, attributes, feature + .getIdentifier().getID()); + } catch (Exception e) { + LOGGER.warning("Error creating feature: " + e); + throw new ProcessException("Error creating feature: " + e, e); + } + } +} Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSMeasureProcess.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSMeasureProcess.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSMeasureProcess.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,257 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2011, Open Source Geospatial Foundation (OSGeo) + * (C) 2001-2007 TOPP - www.openplans.org. + * + * This library 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 2.1 of the License. + * + * This library 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. + */ +package org.geotools.process.feature.gs; + +import java.util.logging.Logger; + +import javax.measure.converter.UnitConverter; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.feature.FeatureIterator; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.geotools.feature.simple.SimpleFeatureTypeBuilder; +import org.geotools.measure.Measure; +import org.geotools.process.ProcessException; +import org.geotools.process.factory.DescribeParameter; +import org.geotools.process.factory.DescribeProcess; +import org.geotools.process.factory.DescribeResult; +import org.geotools.process.gs.GSProcess; +import org.geotools.referencing.CRS; +import org.geotools.referencing.crs.DefaultGeographicCRS; +import org.geotools.util.logging.Logging; +import org.opengis.feature.Feature; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.AttributeDescriptor; +import org.opengis.feature.type.FeatureType; +import org.opengis.feature.type.GeometryDescriptor; +import org.opengis.feature.type.PropertyDescriptor; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.MathTransform; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.linearref.LengthIndexedLine; +import com.vividsolutions.jts.operation.distance.DistanceOp; + +@DescribeProcess(title = "LRSGeocode", description = "Translate geocoded point to LRS measure") +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/NearestProcess.java $ + */ +public class LRSMeasureProcess implements GSProcess { + private static final Logger LOGGER = Logging.getLogger(LRSMeasureProcess.class); + + private final GeometryFactory geometryFactory = new GeometryFactory(); + + /** + * Process the input data set. + * + * @param featureCollection the data set + * @param crs the CRS + * @param point the given point + * @return the snapped to feature + * @throws ProcessException error + */ + @DescribeResult(name = "result", description = "The LRS measure") + public FeatureCollection execute( + @DescribeParameter(name = "features", description = "The features to search") FeatureCollection featureCollection, + @DescribeParameter(name = "from_measure_attb", description = "The feature attribue holding the features starting measure") String fromMeasureAttb, + @DescribeParameter(name = "to_measure_attb", description = "The feature attribue holding the features ending measure") String toMeasureAttb, + @DescribeParameter(name = "point", description = "The point to search from") Point point, + @DescribeParameter(name = "crs", min = 0, description = "The coordinate reference system of the collection and point (will use the collection one if not provided") CoordinateReferenceSystem crs) + throws ProcessException { + FeatureCollection results = FeatureCollections.newCollection(); + try { + if (featureCollection == null || featureCollection.size() == 0) { + LOGGER.info("No features provided in request"); + return results; + } + if (crs == null) { + GeometryDescriptor gd = featureCollection.getSchema().getGeometryDescriptor(); + if (gd != null) { + crs = gd.getCoordinateReferenceSystem(); + } + } + if (crs == null) { + throw new ProcessException( + "The CRS parameter was not provided and the feature collection does not have a default one either"); + } + if (fromMeasureAttb == null + || featureCollection.getSchema().getDescriptor(fromMeasureAttb) == null) { + throw new ProcessException( + "The from_measure_attb parameter was not provided or not defined in schema"); + } + if (toMeasureAttb == null + || featureCollection.getSchema().getDescriptor(toMeasureAttb) == null) { + throw new ProcessException("The to_measure_attb parameter was not provided"); + } + if (point == null) { + throw new ProcessException("The point parameter was not provided"); + } + + CoordinateReferenceSystem epsg4326; + try { + epsg4326 = CRS.decode("EPSG:4326"); + } catch (Exception e) { + throw new ProcessException("Unknown CRS code: EPSG:4326", e); + } + MathTransform crsTransform = CRS.findMathTransform(crs, epsg4326); + + FeatureType targetFeatureType = createTargetFeatureType(featureCollection.getSchema()); + Unit fromUnit = SI.METER; + Unit toUnit = Unit.valueOf("mi"); + UnitConverter unitConvert = fromUnit.getConverterTo(toUnit); + Feature nearestFeature = null; + double nearestDistance = 9e9; + Coordinate[] nearestCoords = null; + FeatureIterator<Feature> featureIterator = null; + try { + featureIterator = featureCollection.features(); + while (featureIterator.hasNext()) { + SimpleFeature f = (SimpleFeature) featureIterator.next(); + if (f.getDefaultGeometryProperty().getValue() == null) + continue; + DistanceOp op = new DistanceOp(point, (Geometry) f.getDefaultGeometryProperty() + .getValue()); + Coordinate[] co = op.closestPoints(); + double[] co0 = new double[] { co[0].x, co[0].y, }; + double[] co1 = new double[] { co[1].x, co[1].y, }; + double[] geo0 = new double[2]; + double[] geo1 = new double[2]; + crsTransform.transform(co0, 0, geo0, 0, 1); + crsTransform.transform(co1, 0, geo1, 0, 1); + + // get distance + Measure m = DefaultGeographicCRS.WGS84.distance(geo0, geo1); + if (m.doubleValue() > nearestDistance) + continue; + nearestFeature = f; + nearestDistance = m.doubleValue(); + nearestCoords = co; + } + } finally { + if (featureIterator != null) + featureIterator.close(); + } + if (nearestFeature != null) { + LengthIndexedLine lengthIndexedLine = new LengthIndexedLine( + (Geometry) nearestFeature.getDefaultGeometryProperty().getValue()); + double lineIndex = lengthIndexedLine.indexOf(nearestCoords[1]); + double lineLength = ((Geometry) nearestFeature.getDefaultGeometryProperty() + .getValue()).getLength(); + Double featureFromMeasure = (Double) nearestFeature.getProperty(fromMeasureAttb) + .getValue(); + Double featureToMeasure = (Double) nearestFeature.getProperty(toMeasureAttb) + .getValue(); + double lrsMeasure = featureFromMeasure + (featureToMeasure - featureFromMeasure) + * lineIndex / lineLength; + nearestFeature.getDefaultGeometryProperty().setValue( + geometryFactory.createPoint(new Coordinate(nearestCoords[1].x, + nearestCoords[1].y))); + results.add(createTargetFeature(nearestFeature, + (SimpleFeatureType) targetFeatureType, lrsMeasure)); + return results; + } + return results; + } catch (ProcessException e) { + throw e; + } catch (Throwable e) { + LOGGER.warning("Error executing method: " + e); + throw new ProcessException("Error executing method: " + e, e); + } + } + + /** + * Create the modified feature type. + * + * @param sourceFeatureType the source feature type + * @return the modified feature type + * @throws ProcessException errror + */ + private SimpleFeatureType createTargetFeatureType(FeatureType sourceFeatureType) + throws ProcessException { + try { + SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder(); + typeBuilder.setName(sourceFeatureType.getName().getLocalPart()); + typeBuilder.setNamespaceURI(sourceFeatureType.getName().getNamespaceURI()); + for (PropertyDescriptor attbType : sourceFeatureType.getDescriptors()) { + typeBuilder.add((AttributeDescriptor) attbType); + } + typeBuilder.minOccurs(1).maxOccurs(1).nillable(false).add("lrs_measure", Double.class); + typeBuilder + .setDefaultGeometry(sourceFeatureType.getGeometryDescriptor().getLocalName()); + return typeBuilder.buildFeatureType(); + } catch (Exception e) { + LOGGER.warning("Error creating type: " + e); + throw new ProcessException("Error creating type: " + e, e); + } + } + + /** + * Create the modified feature. + * + * @param feature the source feature + * @param targetFeatureType the modified feature type + * @param nearestDistance the snap distance + * @param nearestBearing the snap bearing + * @return the modified feature + * @throws ProcessException error + */ + private SimpleFeature createTargetFeature(Feature feature, SimpleFeatureType targetFeatureType, + Double lrsMeasure) throws ProcessException { + try { + AttributeDescriptor lrsMeasureAttbType = targetFeatureType.getDescriptor("lrs_measure"); + Object[] attributes = new Object[targetFeatureType.getAttributeCount()]; + for (int i = 0; i < attributes.length; i++) { + AttributeDescriptor attbType = targetFeatureType.getAttributeDescriptors().get(i); + if (attbType.equals(lrsMeasureAttbType)) { + attributes[i] = lrsMeasure; + } else { + attributes[i] = feature.getProperty(attbType.getName()).getValue(); + } + } + return SimpleFeatureBuilder.build(targetFeatureType, attributes, feature + .getIdentifier().getID()); + } catch (Exception e) { + LOGGER.warning("Error creating feature: " + e); + throw new ProcessException("Error creating feature: " + e, e); + } + } + + /** + * Calculate the bearing between two points. + * + * @param coords the points + * @return the bearing + */ + private double calcBearing(Coordinate[] coords) { + double y = Math.sin(coords[1].x - coords[0].x) * Math.cos(coords[1].y); + double x = Math.cos(coords[0].y) * Math.sin(coords[1].y) - Math.sin(coords[0].y) + * Math.cos(coords[1].y) * Math.cos(coords[1].x - coords[0].x); + double brng = ((Math.atan2(y, x) * 180.0 / Math.PI) + 360) % 360; + return brng; + } + +} Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSSegmentProcess.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSSegmentProcess.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSSegmentProcess.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,226 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2011, Open Source Geospatial Foundation (OSGeo) + * (C) 2001-2007 TOPP - www.openplans.org. + * + * This library 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 2.1 of the License. + * + * This library 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. + */ +package org.geotools.process.feature.gs; + +import java.util.logging.Logger; + +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.feature.FeatureIterator; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.geotools.process.ProcessException; +import org.geotools.process.factory.DescribeParameter; +import org.geotools.process.factory.DescribeProcess; +import org.geotools.process.factory.DescribeResult; +import org.geotools.process.gs.GSProcess; +import org.geotools.util.logging.Logging; +import org.opengis.feature.Feature; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.AttributeDescriptor; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.LineString; +import com.vividsolutions.jts.geom.MultiLineString; +import com.vividsolutions.jts.linearref.LengthIndexedLine; +import com.vividsolutions.jts.operation.linemerge.LineMerger; + +@DescribeProcess(title = "LRSSegment", description = "Return a segment geometry for a LRM measure range") +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/NearestProcess.java $ + */ +public class LRSSegmentProcess implements GSProcess { + private static final Logger LOGGER = Logging.getLogger(LRSSegmentProcess.class); + + private final GeometryFactory geometryFactory = new GeometryFactory(); + + /** + * Process the input data set. + * + * @param featureCollection the data set + * @param crs the CRS + * @param point the given point + * @return the snapped to feature + * @throws ProcessException error + */ + @DescribeResult(name = "result", description = "The segment geometry") + public FeatureCollection execute( + @DescribeParameter(name = "features", description = "The features to search") FeatureCollection featureCollection, + @DescribeParameter(name = "from_measure_attb", description = "The feature attribue holding the features starting measure") String fromMeasureAttb, + @DescribeParameter(name = "to_measure_attb", description = "The feature attribue holding the features ending measure") String toMeasureAttb, + @DescribeParameter(name = "from_measure", description = "The from LRS measure") Double fromMeasure, + @DescribeParameter(name = "to_measure", description = "The to LRS measure") Double toMeasure) + throws ProcessException { + FeatureCollection results = FeatureCollections.newCollection(); + try { + if (featureCollection == null || featureCollection.size() == 0) { + LOGGER.info("No features provided in request"); + return results; + } + if (fromMeasureAttb == null + || featureCollection.getSchema().getDescriptor(fromMeasureAttb) == null) { + throw new ProcessException( + "The from_measure_attb parameter was not provided or not defined in schema"); + } + if (toMeasureAttb == null + || featureCollection.getSchema().getDescriptor(toMeasureAttb) == null) { + throw new ProcessException("The to_measure_attb parameter was not provided"); + } + if (fromMeasure == null) { + throw new ProcessException("The from_measure parameter was not provided"); + } + if (toMeasure == null) { + throw new ProcessException("The to_measure parameter was not provided"); + } + if (fromMeasure.doubleValue() == toMeasure.doubleValue()) { + LOGGER.info("Zero length segment requested"); + return results; + } + + FeatureIterator<Feature> featureIterator = null; + Feature firstFeature = null; + try { + LineMerger lineMerger = new LineMerger(); + if (toMeasure.doubleValue() > fromMeasure.doubleValue()) { + featureIterator = featureCollection.features(); + while (featureIterator.hasNext()) { + Feature feature = featureIterator.next(); + if (firstFeature == null) + firstFeature = feature; + Double featureFromMeasure = (Double) feature.getProperty(fromMeasureAttb) + .getValue(); + Double featureToMeasure = (Double) feature.getProperty(toMeasureAttb) + .getValue(); + + if (fromMeasure < featureToMeasure && toMeasure > featureFromMeasure) { + try { + if (fromMeasure <= featureFromMeasure + && toMeasure >= featureToMeasure) { + lineMerger.add((Geometry) feature.getDefaultGeometryProperty() + .getValue()); + } else if (fromMeasure > featureFromMeasure + && toMeasure < featureToMeasure) { + LengthIndexedLine lengthIndexedLine = new LengthIndexedLine( + (Geometry) feature.getDefaultGeometryProperty() + .getValue()); + double featureLength = featureToMeasure - featureFromMeasure; + double startOffset = fromMeasure - featureFromMeasure; + double stopOffset = toMeasure - featureFromMeasure; + double calcLength = ((Geometry) feature + .getDefaultGeometryProperty().getValue()).getLength(); + if (calcLength == 0 || featureLength == 0) + continue; + Geometry extracted = lengthIndexedLine.extractLine(startOffset + * calcLength / featureLength, stopOffset * calcLength + / featureLength); + if (!extracted.isEmpty()) + lineMerger.add(extracted); + } else if (fromMeasure > featureFromMeasure) { + LengthIndexedLine lengthIndexedLine = new LengthIndexedLine( + (Geometry) feature.getDefaultGeometryProperty() + .getValue()); + double featureLength = featureToMeasure - featureFromMeasure; + double startOffset = fromMeasure - featureFromMeasure; + double calcLength = ((Geometry) feature + .getDefaultGeometryProperty().getValue()).getLength(); + if (calcLength == 0 || featureLength == 0) + continue; + Geometry extracted = lengthIndexedLine.extractLine(startOffset + * calcLength / featureLength, calcLength); + if (!extracted.isEmpty()) + lineMerger.add(extracted); + } else { + LengthIndexedLine lengthIndexedLine = new LengthIndexedLine( + (Geometry) feature.getDefaultGeometryProperty() + .getValue()); + double featureLength = featureToMeasure - featureFromMeasure; + double stopOffset = toMeasure - featureFromMeasure; + double calcLength = ((Geometry) feature + .getDefaultGeometryProperty().getValue()).getLength(); + if (calcLength == 0 || featureLength == 0) + continue; + Geometry extracted = lengthIndexedLine.extractLine(0, + stopOffset * calcLength / featureLength); + if (extracted.isEmpty() || extracted.getLength() == 0.0) { + LOGGER.info("Empty segment: featureFromMeasure=" + + featureFromMeasure + " featureToMeasure:" + + featureToMeasure + " toMeasure:" + toMeasure + + " fromMeasure:" + fromMeasure); + } else { + lineMerger.add(extracted); + } + } + } catch (Exception e) { + LOGGER.warning("Error merging line strings: " + e + + " featureFromMeasure=" + featureFromMeasure + + " featureToMeasure:" + featureToMeasure + " toMeasure:" + + toMeasure + " fromMeasure:" + fromMeasure); + } + } + } + results.add(createTargetFeature(firstFeature, (SimpleFeatureType) firstFeature + .getType(), new MultiLineString((LineString[]) lineMerger + .getMergedLineStrings().toArray(new LineString[0]), geometryFactory))); + } + } finally { + if (featureIterator != null) + featureIterator.close(); + } + return results; + } catch (ProcessException e) { + throw e; + } catch (Throwable e) { + LOGGER.warning("Error executing method: " + e); + throw new ProcessException("Error executing method: " + e, e); + } + } + + /** + * Create the modified feature. + * + * @param feature the source feature + * @param targetFeatureType the modified feature type + * @param nearestDistance the snap distance + * @param nearestBearing the snap bearing + * @return the modified feature + * @throws ProcessException error + */ + private SimpleFeature createTargetFeature(Feature feature, SimpleFeatureType targetFeatureType, + MultiLineString multiLineString) throws ProcessException { + try { + AttributeDescriptor geomAttbType = targetFeatureType.getGeometryDescriptor(); + Object[] attributes = new Object[targetFeatureType.getAttributeCount()]; + for (int i = 0; i < attributes.length; i++) { + AttributeDescriptor attbType = targetFeatureType.getAttributeDescriptors().get(i); + if (attbType.equals(geomAttbType)) { + attributes[i] = multiLineString; + } else { + attributes[i] = feature.getProperty(attbType.getName()).getValue(); + } + } + return SimpleFeatureBuilder.build(targetFeatureType, attributes, feature + .getIdentifier().getID()); + } catch (Exception e) { + LOGGER.warning("Error creating feature: " + e); + throw new ProcessException("Error creating feature: " + e, e); + } + } +} Added: trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSGeocodeProcessTest.java =================================================================== --- trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSGeocodeProcessTest.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSGeocodeProcessTest.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,150 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2012, Open Source Geospatial Foundation (OSGeo) + * + * This library 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 2.1 of the License. + * + * This library 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. + */ +package org.geotools.process.feature.gs; + +import java.io.File; +import java.io.IOException; + +import org.geotools.data.DataStore; +import org.geotools.data.property.PropertyDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.process.ProcessException; +import org.geotools.test.TestData; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.opengis.feature.Feature; + +import com.vividsolutions.jts.geom.Point; + +/** + * + * + * @source $URL$ + */ +public class LRSGeocodeProcessTest { + private DataStore featureSource; + + @Before + public void setup() throws IOException { + File file = TestData.file(this, null); + featureSource = new PropertyDataStore(file); + } + + @After + public void tearDown() { + featureSource.dispose(); + } + + @Test + public void testBadParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs_bad", "to_lrs", 1.0); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", 1.0); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testnullParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, null, "to_lrs", 1.0); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNullParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", null, 1.0); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadMeasure() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", null); + Assert.fail("Expected error from bad measure value"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNoFeaturesGiven() throws Exception { + LRSGeocodeProcess process = new LRSGeocodeProcess(); + FeatureCollection origional = FeatureCollections.newCollection(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 1.0); + Assert.assertEquals(0, result.size()); + } + + @Test + public void testGoodGeocode() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 1.0); + Assert.assertEquals(1, result.size()); + Feature feature = result.features().next(); + Point point = (Point) feature.getDefaultGeometryProperty().getValue(); + Assert.assertEquals(1.0, point.getX(), 0.0); + Assert.assertEquals(0.0, point.getY(), 0.0); + } + +} Added: trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSMeasureProcessTest.java =================================================================== --- trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSMeasureProcessTest.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSMeasureProcessTest.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,164 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2012, Open Source Geospatial Foundation (OSGeo) + * + * This library 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 2.1 of the License. + * + * This library 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. + */ +package org.geotools.process.feature.gs; + +import java.io.File; +import java.io.IOException; + +import org.geotools.data.DataStore; +import org.geotools.data.property.PropertyDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.process.ProcessException; +import org.geotools.test.TestData; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.opengis.feature.Feature; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Point; + +/** + * + * + * @source $URL$ + */ +public class LRSMeasureProcessTest { + private DataStore featureSource; + + private final GeometryFactory geometryFactory = new GeometryFactory(); + + @Before + public void setup() throws IOException { + File file = TestData.file(this, null); + featureSource = new PropertyDataStore(file); + } + + @After + public void tearDown() { + featureSource.dispose(); + } + + @Test + public void testBadParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + try { + FeatureCollection result = process.execute(origional, "from_lrs_bad", "to_lrs", point, + null); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", point, + null); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testnullParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + try { + FeatureCollection result = process.execute(origional, null, "to_lrs", point, null); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNullParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", null, point, null); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadPoint() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", null, + null); + Assert.fail("Expected error from bad measure value"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNoFeaturesGiven() throws Exception { + LRSMeasureProcess process = new LRSMeasureProcess(); + FeatureCollection origional = FeatureCollections.newCollection(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", point, null); + Assert.assertEquals(0, result.size()); + } + + @Test + public void testGoodMeasure() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", point, null); + Assert.assertEquals(1, result.size()); + Feature feature = result.features().next(); + Assert.assertNotNull(feature.getProperty("lrs_measure")); + Assert.assertNotNull(feature.getProperty("lrs_measure").getValue()); + Double measure = (Double) feature.getProperty("lrs_measure").getValue(); + Assert.assertEquals(1.0, measure, 0.0); + } + +} Added: trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSSegmentProcessTest.java =================================================================== --- trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSSegmentProcessTest.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSSegmentProcessTest.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,205 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2012, Open Source Geospatial Foundation (OSGeo) + * + * This library 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 2.1 of the License. + * + * This library 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. + */ +package org.geotools.process.feature.gs; + +import java.io.File; +import java.io.IOException; + +import org.geotools.data.DataStore; +import org.geotools.data.property.PropertyDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.process.ProcessException; +import org.geotools.test.TestData; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.opengis.feature.Feature; + +import com.vividsolutions.jts.geom.MultiLineString; + +/** + * + * + * @source $URL$ + */ +public class LRSSegmentProcessTest { + private DataStore featureSource; + + @Before + public void setup() throws IOException { + File file = TestData.file(this, null); + featureSource = new PropertyDataStore(file); + } + + @After + public void tearDown() { + featureSource.dispose(); + } + + @Test + public void testBadParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs_bad", "to_lrs", 1.0, + 2.0); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", 1.0, + 2.0); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testnullParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, null, "to_lrs", 1.0, 2.0); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNullParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", null, 1.0, 2.0); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadFromMeasure() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", null, + 2.0); + Assert.fail("Expected error from bad measure value"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadToMeasure() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", 1.0, + null); + Assert.fail("Expected error from bad measure value"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNoFeaturesGiven() throws Exception { + LRSSegmentProcess process = new LRSSegmentProcess(); + FeatureCollection origional = FeatureCollections.newCollection(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 1.0, 2.0); + Assert.assertEquals(0, result.size()); + } + + @Test + public void testSegmentInOneFeature() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 0.5, 1.5); + Assert.assertEquals(1, result.size()); + Feature feature = result.features().next(); + MultiLineString segment = (MultiLineString) feature.getDefaultGeometryProperty().getValue(); + Assert.assertEquals(2, segment.getNumPoints()); + Assert.assertEquals(0.5, segment.getCoordinates()[0].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[0].y, 0.0); + Assert.assertEquals(1.5, segment.getCoordinates()[1].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[1].y, 0.0); + } + + @Test + public void testSegmentInTwoFeature() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 0.5, 3.5); + Assert.assertEquals(1, result.size()); + Feature feature = result.features().next(); + MultiLineString segment = (MultiLineString) feature.getDefaultGeometryProperty().getValue(); + Assert.assertEquals(3, segment.getNumPoints()); + Assert.assertEquals(0.5, segment.getCoordinates()[0].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[0].y, 0.0); + Assert.assertEquals(3.5, segment.getCoordinates()[2].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[2].y, 0.0); + } + + @Test + public void testSegmentInThreeFeature() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 0.5, 5.5); + Assert.assertEquals(1, result.size()); + Feature feature = result.features().next(); + MultiLineString segment = (MultiLineString) feature.getDefaultGeometryProperty().getValue(); + Assert.assertEquals(4, segment.getNumPoints()); + Assert.assertEquals(0.5, segment.getCoordinates()[0].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[0].y, 0.0); + Assert.assertEquals(5.5, segment.getCoordinates()[3].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[3].y, 0.0); + } + +} Added: trunk/modules/unsupported/process-feature/src/test/resources/org/geotools/process/feature/gs/test-data/lrssimple.properties =================================================================== --- trunk/modules/unsupported/process-feature/src/test/resources/org/geotools/process/feature/gs/test-data/lrssimple.properties (rev 0) +++ trunk/modules/unsupported/process-feature/src/test/resources/org/geotools/process/feature/gs/test-data/lrssimple.properties 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,4 @@ +_=the_geom:MultiLineString:srid=4326,from_lrs:java.lang.Double,to_lrs:java.lang.Double,str1:String +lrssimple.1=MULTILINESTRING ((0 0, 2 0))|0.0|2.0|lrs a +lrssimple.2=MULTILINESTRING ((2 0, 4 0))|2.0|4.0|lrs b +lrssimple.3=MULTILINESTRING ((4 0, 6 0))|4.0|6.0|lrs c |