package org.osm2world.core.map_elevation.creation;
import java.util.List;
import org.openstreetmap.josm.plugins.graphview.core.data.TagGroup;
import org.osm2world.core.map_data.data.MapData;
import org.osm2world.core.map_data.data.MapNode;
import org.osm2world.core.map_data.data.MapSegment;
/**
* relies on tags that explicitly set elevation.
* Subclasses determine the tag(s) to be used for this purpose.
*/
public abstract class TagElevationCalculator implements ElevationCalculator {
Double terrainElevation;
boolean enableUnknownEleWarning;
/**
* @param terrainElevation elevation for the terrain
*/
public TagElevationCalculator(Double terrainElevation,
boolean enableUnknownEleWarning) {
this.terrainElevation = terrainElevation;
this.enableUnknownEleWarning = enableUnknownEleWarning;
}
public TagElevationCalculator() {
this(0.0, false);
}
@Override
public void calculateElevations(MapData mapData,
TerrainElevationData eleData) {
// //TODO replace old ElevationProfile stuff
//
// /* set nodes' elevation profiles */
//
// for (MapNode node : mapData.getMapNodes()) {
//
// Double ele = getEleForTags(node.getTags());
//
// if (ele == null) {
//
// /* use elevation information from nodes or areas containing
// * this node. If they have contradicting information, the
// * results will be unpredictable.
// */
//
// for (MapSegment segment : node.getConnectedSegments()) {
// if (ele == null) {
// TagGroup tags;
// if (segment instanceof MapWaySegment) {
// tags = ((MapWaySegment) segment).getTags();
// } else {
// tags = ((MapAreaSegment) segment).getArea().getTags();
// }
// ele = getEleForTags(tags);
// }
// }
//
// }
//
// if (ele != null) {
//
// NodeElevationProfile profile = new NodeElevationProfile(node);
// profile.setEle(ele);
// node.setElevationProfile(profile);
//
// }
//
// }
//
// /* set elevation profiles for nodes without elevation profiles,
// * attempt interpolation the two closest connected nodes with ele */
//
// for (MapNode node : mapData.getMapNodes()) {
//
// if (node.getElevationProfile() == null) {
//
// List<Connection> connections = new ArrayList<Connection>();
//
// for (MapSegment segment : node.getConnectedSegments()) {
//
// Connection connection =
// findConnectionToNodeWithEle(node, segment);
//
// if (connection != null) {
// connections.add(connection);
// }
//
// }
//
// // sort by length
// Collections.sort(connections, new Comparator<Connection>() {
// public int compare(Connection c1, Connection c2) {
// return Double.compare(c1.getLength(), c2.getLength());
// };
// });
//
// double ele = 0;
//
// if (connections.size() < 2) {
// if (enableUnknownEleWarning) {
// System.err.println("node without ele information: " + node);
// }
// } else {
//
// /* interpolate between 2 closest connected nodes */
//
// Connection cA = connections.get(0);
// Connection cB = connections.get(1);
// double eleA = cA.endNode.getElevationProfile().getEle();
// double eleB = cB.endNode.getElevationProfile().getEle();
//
// ele = ((eleA * cB.getLength()) + (eleB * cA.getLength()))
// / (cA.getLength() + cB.getLength());
//
// }
//
// NodeElevationProfile profile = new NodeElevationProfile(node);
// profile.setEle(ele);
// node.setElevationProfile(profile);
//
// }
//
// }
//
// /* set way segments' elevation profiles (based on nodes' elevations) */
//
// for (MapWaySegment segment : mapData.getMapWaySegments()) {
//
// if (segment.getPrimaryRepresentation() == null) continue;
//
// WaySegmentElevationProfile profile =
// new WaySegmentElevationProfile(segment);
//
// profile.addPointWithEle(
// segment.getStartNode().getElevationProfile().getPointWithEle());
// profile.addPointWithEle(
// segment.getEndNode().getElevationProfile().getPointWithEle());
//
// segment.setElevationProfile(profile);
//
// }
//
// /* set areas' elevation profiles (based on nodes' elevations) */
//
// for (MapArea area : mapData.getMapAreas()) {
//
// if (area.getPrimaryRepresentation() == null) continue;
//
// AreaElevationProfile profile =
// new AreaElevationProfile(area);
//
// for (MapNode node : area.getBoundaryNodes()) {
// profile.addPointWithEle(
// node.getElevationProfile().getPointWithEle());
// }
//
// for (List<MapNode> holeOutline : area.getHoles()) {
// for (MapNode node : holeOutline) {
// profile.addPointWithEle(
// node.getElevationProfile().getPointWithEle());
// }
// }
//
// area.setElevationProfile(profile);
//
// }
}
/**
* a sequence of {@link MapSegment}s
* that leads to a {@link MapNode} at the end
*/
private static class Connection {
public final List<MapSegment> segmentSequence;
public final MapNode endNode;
public Connection(List<MapSegment> segmentSequence, MapNode endNode) {
this.segmentSequence = segmentSequence;
this.endNode = endNode;
}
public double getLength() {
double distance = 0.0;
for (MapSegment s : segmentSequence) {
distance += s.getLineSegment().getLength();
}
return distance;
}
}
/**
* Tries to find the segment sequence to a node with elevation information.
* More precisely, this follows the sequence of segments started by
* the specified first segment until ... <ul>
* <li>... a node with elevation information is found and is returned.</li>
* <li>... the sequence segment branches, null is returned.</li>
* <li>... the sequence returns to the start, null is returned.</li>
* </ul>
*/
//TODO replace old ElevationProfile stuff
// private static final Connection findConnectionToNodeWithEle(
// MapNode node, MapSegment firstSegmentForSequence) {
//
// List<MapSegment> segmentSequence = new ArrayList<MapSegment>();
//
// MapNode currentNode = node;
// MapSegment currentSegment = firstSegmentForSequence;
//
// while (true) { //one of the return conditions will ultimately be true
//
// segmentSequence.add(currentSegment);
//
// currentNode = currentSegment.getOtherNode(currentNode);
//
// if (currentNode.getElevationProfile() != null) {
// return new Connection(segmentSequence, currentNode);
// } else if (currentNode == node) {
// return null;
// } else if (currentNode.getConnectedSegments().size() > 2) {
// return null;
// }
//
// // use the one connected segment that is not the current segment
// // as the next current segment
//
// for (MapSegment s : currentNode.getConnectedSegments()) {
// if (s != currentSegment) {
// currentSegment = s;
// break;
// }
// }
//
// }
//
// }
/**
* returns the elevation as set explicitly by the tags
*
* @return elevation; null if the tags don't define the elevation
*/
protected abstract Double getEleForTags(TagGroup tags);
}