protected void calcAndStore(final GeodeticCalculator calc, final Point locA, final Point locB) { // get the output dataset Length_M target = (Length_M) getOutputs().get(0); // now find the range between them calc.setStartingGeographicPoint( locA.getCentroid().getOrdinate(0), locA.getCentroid().getOrdinate(1)); calc.setDestinationGeographicPoint( locB.getCentroid().getOrdinate(0), locB.getCentroid().getOrdinate(1)); double thisDist = calc.getOrthodromicDistance(); target.add(Measure.valueOf(thisDist, target.getUnits())); }
/** * Computes the angle from the first point to the last point of a LineString or MultiLineString. * TODO: put this method into org.opentripplanner.common.geometry.DirectionUtils * * @param geometry a LineString or a MultiLineString * @return */ public synchronized double getFirstToLastSegmentAngle(Geometry geometry) { LineString line; if (geometry instanceof MultiLineString) { line = (LineString) geometry.getGeometryN(geometry.getNumGeometries() - 1); } else { assert geometry instanceof LineString; line = (LineString) geometry; } int numPoints = line.getNumPoints(); Coordinate coord0 = line.getCoordinateN(0); Coordinate coord1 = line.getCoordinateN(numPoints - 1); int i = numPoints - 3; while (distanceLibrary.fastDistance(coord0, coord1) < 10 && i >= 0) { coord1 = line.getCoordinateN(i--); } geodeticCalculator.setStartingGeographicPoint(coord0.x, coord0.y); geodeticCalculator.setDestinationGeographicPoint(coord1.x, coord1.y); return geodeticCalculator.getAzimuth() * Math.PI / 180; }
/** * wrap the actual operation. We're doing this since we need to separate it from the core * "execute" operation in order to support dynamic updates * * @param unit * @param outputs */ private void performCalc(List<IStoreItem> outputs) { // and the bounding period TimePeriod period = getBoundingTime(data.values()); // check it's valid if (period.invalid()) { System.err.println("Insufficient coverage for datasets"); return; } // ok, let's start by finding our time sync IBaseTemporalCollection times = getOptimalTimes(period, data.values()); // check we were able to find some times if (times == null) { System.err.println("Unable to find time source dataset"); return; } // get the output dataset final Temporal.Frequency_Hz output = (Frequency_Hz) outputs.iterator().next(); final GeodeticCalculator calc = GeoSupport.getCalculator(); // and now we can start looping through Iterator<Long> tIter = times.getTimes().iterator(); while (tIter.hasNext()) { long thisTime = (long) tIter.next(); if ((thisTime >= period.startTime) && (thisTime <= period.endTime)) { // ok, now collate our data Geometry txLoc = locationFor(data.get(TX + "LOC"), thisTime); Geometry rxLoc = locationFor(data.get(RX + "LOC"), thisTime); double txCourseRads = valueAt(data.get(TX + "COURSE"), thisTime, SI.RADIAN); double rxCourseRads = valueAt(data.get(RX + "COURSE"), thisTime, SI.RADIAN); double txSpeedMSec = valueAt(data.get(TX + "SPEED"), thisTime, SI.METERS_PER_SECOND); double rxSpeedMSec = valueAt(data.get(RX + "SPEED"), thisTime, SI.METERS_PER_SECOND); double freq = valueAt(data.get(TX + "FREQ"), thisTime, SI.HERTZ); double soundSpeed = valueAt(data.get("SOUND_SPEED"), thisTime, SI.METERS_PER_SECOND); // now find the bearing between them calc.setStartingGeographicPoint( txLoc.getCentroid().getOrdinate(0), txLoc.getCentroid().getOrdinate(1)); calc.setDestinationGeographicPoint( rxLoc.getCentroid().getOrdinate(0), rxLoc.getCentroid().getOrdinate(1)); double angleDegs = calc.getAzimuth(); if (angleDegs < 0) angleDegs += 360; double angleRads = Math.toRadians(angleDegs); // ok, and the calculation double shifted = calcPredictedFreqSI( soundSpeed, txCourseRads, rxCourseRads, txSpeedMSec, rxSpeedMSec, angleRads, freq); output.add(thisTime, shifted); } } }