/******************************************************************************* * Copyright 2016 Geoscience Australia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package au.gov.ga.earthsci.worldwind.common.layers.borehole; import gov.nasa.worldwind.geom.LatLon; import gov.nasa.worldwind.geom.Position; import java.util.Map.Entry; import java.util.NavigableMap; import java.util.SortedMap; import java.util.TreeMap; /** * Basic implementation of {@link BoreholePath}. * * @author Michael de Hoog */ public class BoreholePathImpl implements BoreholePath { private final Borehole borehole; private final NavigableMap<Double, Position> positions = new TreeMap<Double, Position>(); public BoreholePathImpl(Borehole borehole) { this.borehole = borehole; } @Override public Borehole getBorehole() { return borehole; } @Override public SortedMap<Double, Position> getPositions() { return positions; } @Override public void addPosition(double measuredDepth, Position position) { positions.put(measuredDepth, position); } @Override public Position getPosition(double measuredDepth) { if (positions.isEmpty()) { Position boreholePosition = borehole.getPosition(); return new Position(boreholePosition, boreholePosition.elevation - measuredDepth); } if (positions.size() == 1) { //only one position, so extrapolate out Entry<Double, Position> firstEntry = positions.firstEntry(); Position position = firstEntry.getValue(); double elevationDelta = firstEntry.getKey() - measuredDepth; return new Position(position, position.elevation + elevationDelta); } Entry<Double, Position> floor = positions.floorEntry(measuredDepth); Entry<Double, Position> ceiling = positions.ceilingEntry(measuredDepth); if (floor == null) { floor = ceiling; ceiling = positions.higherEntry(floor.getKey()); } if (ceiling == null) { ceiling = floor; floor = positions.lowerEntry(ceiling.getKey()); } if (floor.getKey() == ceiling.getKey()) { //exact match, so don't interpolate return floor.getValue(); } double amount = (measuredDepth - floor.getKey()) / (ceiling.getKey() - floor.getKey()); Position floorPosition = floor.getValue(); Position ceilingPosition = ceiling.getValue(); //can't use Position.interpolate, because amount is clamped when interpolating elevation LatLon latlon = LatLon.interpolate(amount, floorPosition, ceilingPosition); double elevation = floorPosition.elevation + amount * (ceilingPosition.elevation - floorPosition.elevation); return new Position(latlon, elevation); } }