Package org.osm2world.core.map_elevation.data

Source Code of org.osm2world.core.map_elevation.data.WaySegmentElevationProfile

package org.osm2world.core.map_elevation.data;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.osm2world.core.map_data.data.MapElement;
import org.osm2world.core.map_data.data.MapWaySegment;
import org.osm2world.core.map_elevation.creation.ElevationCalculator;
import org.osm2world.core.math.VectorXYZ;
import org.osm2world.core.math.VectorXZ;

/**
* elevation profile for a {@link MapWaySegment}
*/
public class WaySegmentElevationProfile extends ElevationProfile {

  private final MapWaySegment line;

  private List<VectorXYZ> pointsWithEle = null;

  public WaySegmentElevationProfile(MapWaySegment line) {
    this.line = line;
  }

  @Override
  protected MapElement getElement() {
    return line;
  }
 
  //TODO: is this needed?
  /** sort pointsWithEle by ascending (squared) distance from startPos */
  private void sortPointsWithEle() {
    Collections.sort(pointsWithEle, new Comparator<VectorXYZ>() {
      final VectorXZ startPos = line.getPrimaryRepresentation().getStartPosition();
      @Override
      public int compare(VectorXYZ v1, VectorXYZ v2) {
        return Double.compare(v1.xz().subtract(startPos)
            .lengthSquared(), v2.xz().subtract(startPos)
            .lengthSquared());
      }
    });
  }
 
  /*
   * methods providing access to the results
   */

  /**
   * returns all points along the line where elevation values exist. This will
   * at least include the starting and end point of the line. Other elements
   * in between are ordered along the line. Must not be used before calculation
   * results have been set using {@link #addPointWithEle(VectorXYZ)}
   */
  @Override
  public List<VectorXYZ> getPointsWithEle() {
   
    if (pointsWithEle == null) {
      throw new IllegalStateException("elevations have not been calculated yet");
    } else if (pointsWithEle.size() < 2) {
      throw new IllegalStateException("a line must have at least two points with elevation");
    }
   
    return pointsWithEle;
  }

  @Override
  public double getEleAt(VectorXZ pos) {

    if (pointsWithEle == null) {
      throw new IllegalStateException("elevations have not been calculated yet");
    } else if (pointsWithEle.size() < 2) {
      throw new IllegalStateException("a line must have at least two points with elevation");
    }
   
    //TODO: start pos isn't identical with first pointWithEle! can this cause problems?
   
    VectorXZ startPos = line.getPrimaryRepresentation().getStartPosition();
   
    final double posDistance = pos.subtract(startPos).length();

    // find points with known elevation directly before and after pos

    VectorXYZ before = null;
    VectorXYZ after = null;

    double beforeDistance = 0;
    double afterDistance = 0;

    for (VectorXYZ v : pointsWithEle) {
      double vFraction = v.xz().subtract(startPos).length();
      if (vFraction < posDistance) {
        before = v;
        beforeDistance = vFraction;
      } else if (vFraction == posDistance) {
        return v.y;
      } else {
        after = v;
        afterDistance = vFraction;
        break; // pointsWithEle are ordered
      }
    }

    // handle pos outside [startPos; endPos]

    if (before == null) {
      return after.y;
    } else if (after == null) {
      return before.y;
    }

    // interpolate between points before and after
   
    double influenceOfAfter = (posDistance - beforeDistance)
        / (afterDistance - beforeDistance);

    double ele = before.y * (1-influenceOfAfter) + after.y * influenceOfAfter;

    return ele;

  }
 
  /**
   * adds a result of {@link ElevationCalculator}.
   * Must be called at least twice (start and end node)
   */
  public void addPointWithEle(VectorXYZ pointWithEle) {
   
    if (pointsWithEle == null) {
      pointsWithEle = new ArrayList<VectorXYZ>();
    }
   
    this.pointsWithEle.add(pointWithEle);
   
    sortPointsWithEle(); //TODO: (performance) don't do this every time; insert in the right place instead
  }

  @Override
  public double getMaxEle() {
    if (pointsWithEle == null) {
      throw new IllegalStateException("elevations have not been calculated yet");
    }
    double maxEle = Double.MIN_VALUE;
    for (VectorXYZ pointWithEle : pointsWithEle) {
      maxEle = Math.max(maxEle, pointWithEle.y);
    }
    return maxEle;
  }

  @Override
  public double getMinEle() {
    if (pointsWithEle == null) {
      throw new IllegalStateException("elevations have not been calculated yet");
    }
    double minEle = Double.MAX_VALUE;
    for (VectorXYZ pointWithEle : pointsWithEle) {
      minEle = Math.min(minEle, pointWithEle.y);
    }
    return minEle;
  }
 
}
TOP

Related Classes of org.osm2world.core.map_elevation.data.WaySegmentElevationProfile

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.