@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 = "point", description = "Point whose location to measure") Point point,
@DescribeParameter(name = "crs", min = 0, description = "Coordinate reference system to use for input (default is the input collection CRS)") CoordinateReferenceSystem crs)
throws ProcessException {
DefaultFeatureCollection results = new DefaultFeatureCollection();
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) {