LRSSegmentProcess implements VectorProcess { @DescribeResult(name = "result", description = "Output feature collection") public FeatureCollection execute( @DescribeParameter(name = "features", description = "Input feature collection") FeatureCollection featureCollection, @DescribeParameter(name = "from_measure_attb", description = "Attribute providing start measure of feature") String fromMeasureAttb, @DescribeParameter(name = "to_measure_attb", description = "Attribute providing end measure of feature") String toMeasureAttb, @DescribeParameter(name = "from_measure", description = "Measure for start of segment to extract") Double fromMeasure, @DescribeParameter(name = "to_measure", description = "Measure for end of segment to extract") Double toMeasure) throws ProcessException { DefaultFeatureCollection results = new DefaultFeatureCollection(); 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); } }  @DescribeResult(name = "result", description = "Output feature collection") FeatureCollection execute(
            @DescribeParameter(name = "features", description = "Input feature collection") FeatureCollection featureCollection,
            @DescribeParameter(name = "from_measure_attb", description = "Attribute providing start measure of feature") String fromMeasureAttb,
            @DescribeParameter(name = "to_measure_attb", description = "Attribute providing end measure of feature") String toMeasureAttb,
            @DescribeParameter(name = "from_measure", description = "Measure for start of segment to extract") Double fromMeasure,
            @DescribeParameter(name = "to_measure", description = "Measure for end of segment to extract") Double toMeasure);  }
@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) { } }
@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) { } }
@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) { } }
@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) { } }
@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) { } }
@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) { } }
@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); }