static Geometry densify(Geometry geom, CoordinateReferenceSystem crs, double maxAreaError)
      throws FactoryException, TransformException {
    // basic checks
    if (maxAreaError <= 0) {
      throw new IllegalArgumentException("maxAreaError must be greater than 0");
    }
    if (!(geom instanceof Polygon) && !(geom instanceof MultiPolygon)) {
      throw new IllegalArgumentException("Geom must be poligonal");
    }
    if (crs == null) {
      throw new IllegalArgumentException("CRS cannot be set to null");
    }
    double previousArea = 0.0;
    CoordinateReferenceSystem targetCRS = CRS.parseWKT(ECKERT_IV_WKT);
    MathTransform firstTransform = CRS.findMathTransform(crs, targetCRS);
    GeometryFactory geomFactory = new GeometryFactory();
    int ngeom = geom.getNumGeometries();
    Geometry densifiedGeometry = geom;
    double areaError = 1.0d;
    int maxIterate = 0;
    do {
      double max = 0;
      maxIterate++;
      // check the maximum side length of the densifiedGeometry
      for (int j = 0; j < ngeom; j++) {
        Geometry geometry = densifiedGeometry.getGeometryN(j);
        Coordinate[] coordinates = geometry.getCoordinates();
        int n = coordinates.length;
        for (int i = 0; i < (n - 1); i++) {
          Coordinate[] coords = new Coordinate[2];
          coords[0] = coordinates[i];
          coords[1] = coordinates[i + 1];
          LineString lineString = geomFactory.createLineString(coords);
          if (lineString.getLength() > max) max = lineString.getLength();
        }
      }

      // calculate the denified geometry
      densifiedGeometry = Densifier.densify(densifiedGeometry, max / 2);

      // reproject densifiedGeometry to Eckert IV
      Geometry targetGeometry = JTS.transform(densifiedGeometry, firstTransform);
      double nextArea = targetGeometry.getArea();

      // evaluate the current error
      areaError = Math.abs(previousArea - nextArea) / nextArea;
      //      logger3.info("AREA ERROR"+areaError);
      previousArea = nextArea;
      // check whether the current error is greater than the maximum allowed
    } while (areaError > maxAreaError && maxIterate < 10);
    return densifiedGeometry;
  }
 /**
  * Creates a circle shape, using the JTS buffer algorithm. The method is used when there is no
  * street found within the given traveltime, e.g. when the pointer is placed on a field or in the
  * woods.<br>
  * TODO: Note it is actually not correct to do buffer calculation in Euclidian 2D, since the
  * resulting shape will be elliptical when projected.
  *
  * @param dropPoint the location given by the user
  * @param pathToStreet the path from the dropPoint to the street, used to retrieve the buffer
  *     distance
  * @return a Circle
  */
 private Geometry createCirle(Coordinate dropPoint, LineString pathToStreet) {
   double length = pathToStreet.getLength();
   GeometryFactory gf = new GeometryFactory();
   Point dp = gf.createPoint(dropPoint);
   Geometry buffer = dp.buffer(length);
   return buffer;
 }
  public void findClosestPoint(String wktA, String wktB) {
    System.out.println("-------------------------------------");
    try {
      Geometry A = wktRdr.read(wktA);
      Geometry B = wktRdr.read(wktB);
      System.out.println("Geometry A: " + A);
      System.out.println("Geometry B: " + B);
      DistanceOp distOp = new DistanceOp(A, B);

      double distance = distOp.distance();
      System.out.println("Distance = " + distance);

      Coordinate[] closestPt = distOp.nearestPoints();
      LineString closestPtLine = fact.createLineString(closestPt);
      System.out.println(
          "Closest points: " + closestPtLine + " (distance = " + closestPtLine.getLength() + ")");
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
  /** Splits the input geometry into two LineStrings at a fraction of the distance covered. */
  public static P2<LineString> splitGeometryAtFraction(Geometry geometry, double fraction) {
    LineString empty = new LineString(null, gf);
    Coordinate[] coordinates = geometry.getCoordinates();
    CoordinateSequence sequence = gf.getCoordinateSequenceFactory().create(coordinates);
    LineString total = new LineString(sequence, gf);

    if (coordinates.length < 2) return new P2<LineString>(empty, empty);
    if (fraction <= 0) return new P2<LineString>(empty, total);
    if (fraction >= 1) return new P2<LineString>(total, empty);

    double totalDistance = total.getLength();
    double requestedDistance = totalDistance * fraction;

    // An index in JTS can actually refer to any point along the line. It is NOT an array index.
    LocationIndexedLine line = new LocationIndexedLine(geometry);
    LinearLocation l = LengthLocationMap.getLocation(geometry, requestedDistance);

    LineString beginning = (LineString) line.extractLine(line.getStartIndex(), l);
    LineString ending = (LineString) line.extractLine(l, line.getEndIndex());

    return new P2<LineString>(beginning, ending);
  }
 /**
  * Extraction of a sub-LineString from an existing line, starting from 0;
  *
  * @param ls the line from which we extract the sub LineString ()
  * @param fraction [0..1], the length until where we want the substring to go
  * @return the sub-LineString
  */
 LineString getSubLineString(LineString ls, double fraction) {
   if (fraction >= 1) return ls;
   LengthIndexedLine linRefLine = new LengthIndexedLine(ls);
   LineString subLine = (LineString) linRefLine.extractLine(0, fraction * ls.getLength());
   return subLine;
 }
Beispiel #6
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);
  }