Example #1
0
  boolean layout(PointLabel label, LabelIndex labels) {
    String text = label.getText();
    Feature f = label.getFeature();
    Geometry g = label.getGeometry();

    Rule rule = label.getRule();

    // get center in screen space
    Coordinate centroid = g.getCentroid().getCoordinate();

    PointF anchor = tx.getWorldToCanvas().map(centroid);

    // apply offsets
    anchor.x += rule.number(f, TEXT_DX, 0f);
    anchor.y += rule.number(f, TEXT_DY, 0f);

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

    // compute bounds of this label
    Rect b = new Rect();
    p.getTextBounds(text, 0, text.length(), b);

    // padding
    float padding = rule.number(f, TEXT_MIN_PADDING, 0f);
    if (padding > 0f) {
      b = expand(b, padding);
    }

    // label.setAnchor(new Coordinate(center.x,center.y));
    // label.setBox(envelope(rectFromBottomLeft(center, b.width(), b.height())));

    RectF c = new RectF(b);
    tx.getCanvasToWorld().mapRect(c);

    centroid = tx.getCanvasToWorld().map(anchor);
    label.setAnchor(centroid);

    RectF box = null;
    switch (p.getTextAlign()) {
      case LEFT:
        box = rectFromBottomLeft(point(centroid), c.width(), c.height());
        break;
      case CENTER:
        box = rectFromBottomCenter(point(centroid), c.width(), c.height());
        break;
      case RIGHT:
        box = rectFromBottomRight(point(centroid), c.width(), c.height());
        break;
    }

    label.setBox(envelope(box));

    return labels.insert(label);
  }
Example #2
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);
  }