All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geolatte.geom.MeasureInterpolatingVisitor Maven / Gradle / Ivy

Go to download

This geoLatte-geom library offers a geometry model that conforms to the OGC Simple Features for SQL specification.

The newest version!
/*
 * This file is part of the GeoLatte project.
 *
 *     GeoLatte 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, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     GeoLatte 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.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with GeoLatte.  If not, see .
 *
 * Copyright (C) 2010 - 2012 and Ownership of code is shared by:
 * Qmino bvba - Romeinsestraat 18 - 3001 Heverlee  (http://www.qmino.com)
 * Geovise bvba - Generaal Eisenhowerlei 9 - 2140 Antwerpen (http://www.geovise.com)
 */

package org.geolatte.geom;

import org.geolatte.geom.crs.CoordinateReferenceSystem;

import java.util.ArrayList;
import java.util.List;

/**
 * A GeometryVisitor that derives a Geometry
 * by interpolating on the measure values of the visited Geometries.
 *
 * 

Interpolation is used to determine any points on the 1-dimensional geometry with an m coordinate value * between SM and EM inclusively. The implementation-defined interpolation algorithm is used to estimate * values between measured values, usually using a mathematical function. For example, given a measure * of 6 and a 2-point linestring where the m coordinate value of the start point is 4 and the m coordinate * value of the end point is 8, since 6 is halfway between 4 and 8, the interpolation algorithm would be a * point on the linestring halfway between the start and end points. *

* * @author Karel Maesen, Geovise BVBA * creation-date: 4/10/12 */ public class MeasureInterpolatingVisitor

implements GeometryVisitor

{ private static final String INVALID_TYPE_MSG = "Operation only valid on Point, MultiPoint, LineString, and MultiLineString Geometries."; private final Geometry

geometry; private final double startMeasure; private final double endMeasure; //data structures for the result private final List> positionSequences = new ArrayList>(); private PositionSequenceBuilder

currentBuilder; private boolean sequenceIsEmpty = true; public MeasureInterpolatingVisitor(Geometry

geometry, double startMeasure, double endMeasure) { if (startMeasure <= endMeasure) { this.startMeasure = startMeasure; this.endMeasure = endMeasure; } else { this.startMeasure = endMeasure; this.endMeasure = startMeasure; } this.geometry = geometry; } @Override public void visit(Point

point) { P pos = point.getPosition(); if (pos.getM() >= startMeasure && pos.getM() <= endMeasure) { positionSequences.add(point.getPositions()); } } @Override public void visit(LineString

lineString) { currentBuilder = PositionSequenceBuilders.variableSized(this.geometry.getPositionClass()); P lastAddedPoint = null; LineSegments

segments = new LineSegments

(lineString.getPositions()); for (LineSegment

segment : segments) { P p0 = segment.getStartPosition(); P p1 = segment.getEndPosition(); //determine the interpolation factors //Note: rs and re can be Infinite (when p1 and p0 have the same M-value). double rs = (startMeasure - p0.getM()) / (p1.getM() - p0.getM()); double re = (endMeasure - p0.getM()) / (p1.getM() - p0.getM()); // set rs and re in the coordinate-order (if r1,r2 in (0,1) // so order will be p0 -- p(r1) -- p(r2) -- p1, if // r1, r2 in [0, 1] double r1 = Math.min(rs, re); double r2 = Math.max(rs, re); if (startMeasure <= p0.getM() && p0.getM() <= endMeasure) { lastAddedPoint = addIfNotEqualLast(lastAddedPoint, p0); } else { //p0 not within [startMeasure, endMeasure], so next point to add will not be consecutive with // previously added points (if any!) startNewPointSequenceIfNotEmpty(); if (r1 > 0 && r1 < 1) { lastAddedPoint = addIfNotEqualLast(lastAddedPoint, interpolate(p0, p1, r1)); } } if (startMeasure <= p1.getM() && p1.getM() <= endMeasure) { lastAddedPoint = addIfNotEqualLast(lastAddedPoint, p1); } else { if (r2 > 0 && r2 < 1) { lastAddedPoint = addIfNotEqualLast(lastAddedPoint, interpolate(p0, p1, r2)); } //p1 not within [startMeasure, endMeasure], so next point to add will not be consecutive with // previously added points (if any!) startNewPointSequenceIfNotEmpty(); } } PositionSequence

last = currentBuilder.toPositionSequence(); if (!last.isEmpty()) { positionSequences.add(last); } } private void startNewPointSequenceIfNotEmpty() { if (!sequenceIsEmpty) { positionSequences.add(currentBuilder.toPositionSequence()); currentBuilder = PositionSequenceBuilders.variableSized(this.geometry.getPositionClass()); sequenceIsEmpty = true; } } private P addIfNotEqualLast(P lastPoint, P newPnt) { assert (newPnt != null); if (!newPnt.equals(lastPoint)) { currentBuilder.add(newPnt); lastPoint = newPnt; } return lastPoint; } private P interpolate(P p0, P p1, double r) { int dim = getCrs().getCoordinateDimension(); double[] result = new double[dim]; for (int i = 0; i < dim; i++) { result[i] = p0.getCoordinate(i) + r * (p1.getCoordinate(i) - p0.getCoordinate(i)); } return Positions.mkPosition(getCrs(), result); } @Override public void visit(Polygon

polygon) { throw new IllegalArgumentException(INVALID_TYPE_MSG); } @Override public void visit(AbstractGeometryCollection collection) { } @SuppressWarnings("unchecked") public Geometry

result() { int number0Dimensional = 0; int number1Dimensional = 0; for (PositionSequence

ps : positionSequences) { assert (!ps.isEmpty()); if (ps.size() > 1) { number1Dimensional++; } else { number0Dimensional++; } } if (number0Dimensional == 0 && number1Dimensional == 0) { Position p = Positions.mkPosition(getCrs(), Double.NaN, Double.NaN); return new Point(p, getCrs()); } if (number0Dimensional > 1 && number1Dimensional == 0) { Point

[] pnts = (Point

[])new Point[number0Dimensional]; int i = 0; for (PositionSequence

ps : positionSequences) { pnts[i++] = new Point

(ps, this.geometry.getCoordinateReferenceSystem()); } return new MultiPoint<>(pnts); } if (number0Dimensional == 1 && number1Dimensional == 0) { return new MultiPoint<>( new Point<>(positionSequences.get(0), this.geometry.getCoordinateReferenceSystem())); } if (number0Dimensional == 0 && number1Dimensional >= 1) { LineString

[] lineStrings = (LineString

[])new LineString[number1Dimensional]; int i = 0; for (PositionSequence

ps : positionSequences) { lineStrings[i++] = new LineString

(ps, this.geometry.getCoordinateReferenceSystem()); } return new MultiLineString<>(lineStrings); } if (number0Dimensional > 0 && number1Dimensional > 0) { Geometry

[] geometries = (Geometry

[])new Geometry[number1Dimensional + number0Dimensional]; int i = 0; for (PositionSequence

ps : positionSequences) { if (ps.size() == 1) { geometries[i++] = new Point

(ps, this.geometry.getCoordinateReferenceSystem()); } else { geometries[i++] = new LineString

(ps, this.geometry.getCoordinateReferenceSystem()); } } return new GeometryCollection

(geometries); } throw new IllegalStateException(String.format( "Programming error: Case of % d 0-Dim. en %d 1-Dim not properly handled", number0Dimensional, number1Dimensional)); } private CoordinateReferenceSystem

getCrs(){ return this.geometry.getCoordinateReferenceSystem(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy