예제 #1
0
  /** Add a ring to a builder */
  private void addRing(LineString r, Geobuf.Data.Geometry.Builder builder) {
    // skip last point, same as first
    builder.addLengths(r.getNumPoints() - 1);

    long x, y, prevX = 0, prevY = 0;

    // last point is same as first, skip
    for (int i = 0; i < r.getNumPoints() - 1; i++) {
      // delta code
      Coordinate coord = r.getCoordinateN(i);
      // note that roundoff errors do not accumulate
      x = (long) (coord.x * precisionMultiplier);
      y = (long) (coord.y * precisionMultiplier);
      builder.addCoords(x - prevX);
      builder.addCoords(y - prevY);
      prevX = x;
      prevY = y;
    }
  }
예제 #2
0
  /** Moves the iterator ahead to the next vertex and (possibly) linear component. */
  public void next() {
    if (!hasNext()) return;

    vertexIndex++;
    if (vertexIndex >= currentLine.getNumPoints()) {
      componentIndex++;
      loadCurrentLine();
      vertexIndex = 0;
    }
  }
  /** calculate the length of this street segement from its geometry */
  protected void calculateLengthFromGeometry() {
    double accumulatedMeters = 0;

    LineString geom = getGeometry();

    for (int i = 1; i < geom.getNumPoints(); i++) {
      accumulatedMeters +=
          SphericalDistanceLibrary.distance(geom.getCoordinateN(i - 1), geom.getCoordinateN(i));
    }

    length_mm = (int) (accumulatedMeters * 1000);
  }
예제 #4
0
  private boolean testForUshape(
      Edge edge,
      long maxTime,
      long fromTime,
      long toTime,
      double angleLimit,
      double distanceTolerance,
      double userSpeed,
      boolean hasCar,
      boolean performSpeedTest) {

    LineString ls = (LineString) edge.getGeometry();
    if (ls.getNumPoints() <= 3) { // first filter since u-shapes need at least 4 pts
      // this is the normal case
      return false;
    } else {
      // try to identify u-shapes by checking if the angle EndPoint-StartPoint-StartPoint+1
      // is about 90 degrees (using Azimuths on the sphere)
      double diffTo90Azimuths = 360;
      if (edge instanceof PlainStreetEdge) {
        double firstSegmentAngle = DirectionUtils.getFirstAngle(edge.getGeometry());
        if (firstSegmentAngle < 0) firstSegmentAngle = firstSegmentAngle + Math.PI;
        double firstToLastSegmentAngle = getFirstToLastSegmentAngle(edge.getGeometry());
        if (firstToLastSegmentAngle < 0)
          firstToLastSegmentAngle = firstToLastSegmentAngle + Math.PI;
        double diffAzimuths = Math.abs(firstToLastSegmentAngle - firstSegmentAngle);
        diffTo90Azimuths = Math.abs(diffAzimuths - (Math.PI / 2.0));
      } else {
        // this will happen in particular for transit routes
        // LOG.debug("Edge is not a PlainStreetEdge");
      }
      if (diffTo90Azimuths < angleLimit) {
        // no need to test further if we know its a u-shape
        // System.out.println("u-shape found, (spherical) angle: " + diffTo90Azimuths* 180/Math.PI);
        return true;
      } else {
        if (performSpeedTest) {
          // Use also a distance based criteria since the angle criteria may fail.
          // However a distance based one may fail as well for steep terrain.
          long dt = Math.abs(toTime - fromTime);
          double lineDist = edge.getDistance();
          double distanceToWalkInTimeMissing =
              distanceToMoveInRemainingTime(maxTime, fromTime, dt, userSpeed, edge, hasCar, false);
          double approxWalkableDistanceInTime = distanceToWalkInTimeMissing * distanceTolerance;
          if ((approxWalkableDistanceInTime < lineDist)) {
            return true;
          }
        }
        return false;
      }
    }
  }
예제 #5
0
 /**
  * Make sure the network doesn't have any problems
  *
  * @param n - the network to be tested
  */
 static void testNetworkForIssues(Network n) {
   System.out.println("testing");
   for (Object o : n.allNodes) {
     GeoNode node = (GeoNode) o;
     for (Object p : n.getEdgesOut(node)) {
       sim.field.network.Edge e = (sim.field.network.Edge) p;
       LineString ls = (LineString) ((MasonGeometry) e.info).geometry;
       Coordinate c1 = ls.getCoordinateN(0);
       Coordinate c2 = ls.getCoordinateN(ls.getNumPoints() - 1);
       GeoNode g1 = (GeoNode) e.getFrom();
       GeoNode g2 = (GeoNode) e.getTo();
       if (c1.distance(g1.geometry.getCoordinate()) > 1) System.out.println("found you");
       if (c2.distance(g2.geometry.getCoordinate()) > 1) System.out.println("found you");
     }
   }
 }
예제 #6
0
  /**
   * 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;
  }
 private void writeLineString(LineString geom, ValueSetter dest) {
   dest.setInt(geom.getNumPoints());
   writeCoordinates(geom.getCoordinateSequence(), getCoordDim(geom), dest);
 }
예제 #8
0
  boolean layout(LineLabel label, LabelIndex labels) {
    String txt = label.getText();
    Rule rule = label.getRule();
    Feature f = label.getFeature();
    Geometry g = label.getGeometry();

    LineString line = null;
    if (g instanceof MultiLineString) {
      // TODO: handle multiple lines
      if (g.getNumGeometries() == 1) {
        line = (LineString) g.getGeometryN(0);
      }
    } else {
      line = (LineString) g;
    }
    if (line == null) {
      return false;
    }

    Paint p = label.get(Paint.class, Paint.class);

    // compute the bounds of the label with no rotation
    Rect r = new Rect();
    p.getTextBounds(txt, 0, txt.length(), r);

    // map it to world coordinates
    RectF bounds = new RectF(r);
    tx.getCanvasToWorld().mapRect(bounds);

    // ignore label if its too long for the line

    if (line.getLength() < bounds.width()) {
      // ignore this label
      return false;
    }

    // reverse
    if (line.getPointN(0).getX() > line.getPointN(line.getNumPoints() - 1).getX()) {
      line = (LineString) line.reverse();
    }

    // compute width of individual letters
    float[] widths = new float[txt.length()];
    p.getTextWidths(txt, widths);

    // map the widths to world space
    float sum = 0;
    for (int i = 0; i < widths.length; i++) {
      RectF s = new RectF(0, 0, widths[i], 1);
      tx.getCanvasToWorld().mapRect(s);

      widths[i] = s.width();
      sum += s.width();
    }

    // TODO: properly figure out spacing between letters
    float space = tx.getCanvasToWorld().mapRadius(1);

    // allowable angle change in consecutive characters
    double maxAngleDelta = rule.number(f, TEXT_MAX_CHAR_ANGLE_DELTA, DEFAULT_MAX_ANGLE_CHAR_DELTA);

    //
    // sample points along the line for letters
    //
    List<LineSegment> path = new ArrayList<LineSegment>();

    LineSampler sampler = new LineSampler(line.getCoordinates());

    for (int i = 0; i < txt.length(); i++) {
      // get next point
      Coordinate c1 = sampler.sample();

      // advance by width of letter
      sampler.advance(widths[i]);

      // get point for end of letter
      Coordinate c2 = sampler.sample();

      if (c1 == null || c2 == null) {
        // ran out of room
        return false;
      }

      LineSegment seg = new LineSegment(c1, c2);

      // check angle made with previous segment
      if (i > 0) {
        LineSegment prev = path.get(i - 1);
        if (Math.abs(angle(seg) - angle(prev)) > maxAngleDelta) {
          return false;
        }
      }

      path.add(seg);
      sampler.advance(space);
    }

    label.setPath(path);
    label.setShape(toShape(path, bounds.height()));
    return labels.insert(label);
  }
예제 #9
0
 /**
  * Tests whether there are any vertices left to iterator over. Specifically, hasNext() return
  * <tt>true</tt> if the current state of the iterator represents a valid location on the linear
  * geometry.
  *
  * @return <code>true</code> if there are more vertices to scan
  */
 public boolean hasNext() {
   if (componentIndex >= numLines) return false;
   if (componentIndex == numLines - 1 && vertexIndex >= currentLine.getNumPoints()) return false;
   return true;
 }
예제 #10
0
 /**
  * Checks whether the iterator cursor is pointing to the
  * endpoint of a component {@link LineString}.
  *
  * @return <code>true</true> if the iterator is at an endpoint
  */
 public boolean isEndOfLine() {
   if (componentIndex >= numLines) return false;
   // LineString currentLine = (LineString) linear.getGeometryN(componentIndex);
   if (vertexIndex < currentLine.getNumPoints() - 1) return false;
   return true;
 }