Changeset 7459 in josm


Ignore:
Timestamp:
2014-08-29T02:59:24+02:00 (10 years ago)
Author:
Don-vip
Message:

fix #10419 - improved label placement inside areas (ex: addr:housenumber on buildings)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java

    r7448 r7459  
    433433        }
    434434
     435        drawAreaText(osm, text, area);
     436    }
     437
     438    private void drawAreaText(OsmPrimitive osm, TextElement text, Shape area) {
    435439        if (text != null && isShowNames()) {
    436440            // abort if we can't compose the label to be rendered
     
    449453            // Centroids are not optimal either, just imagine a U-shaped house.
    450454
    451             Rectangle centeredNBounds = new Rectangle(pb.x + (int)((pb.width - nb.getWidth())/2.0),
    452                     pb.y + (int)((pb.height - nb.getHeight())/2.0),
    453                     (int)nb.getWidth(),
    454                     (int)nb.getHeight());
    455 
    456             if ((pb.width >= nb.getWidth() && pb.height >= nb.getHeight()) && // quick check
    457                     area.contains(centeredNBounds) // slow but nice
    458             ) {
    459                 Font defaultFont = g.getFont();
    460                 int x = (int)(centeredNBounds.getMinX() - nb.getMinX());
    461                 int y = (int)(centeredNBounds.getMinY() - nb.getMinY());
    462                 displayText(null, name, x, y, osm.isDisabled(), text);
    463                 g.setFont(defaultFont);
     455            // quick check to see if label box is smaller than primitive box
     456            if (pb.width >= nb.getWidth() && pb.height >= nb.getHeight()) {
     457
     458                final double w = pb.width  - nb.getWidth();
     459                final double h = pb.height - nb.getHeight();
     460
     461                final int x2 = pb.x + (int)(w/2.0);
     462                final int y2 = pb.y + (int)(h/2.0);
     463
     464                final int nbw = (int) nb.getWidth();
     465                final int nbh = (int) nb.getHeight();
     466
     467                Rectangle centeredNBounds = new Rectangle(x2, y2, nbw, nbh);
     468
     469                // slower check to see if label is displayed inside primitive shape
     470                boolean labelOK = area.contains(centeredNBounds);
     471                if (!labelOK) {
     472                    // if center position (C) is not inside osm shape, try naively some other positions as follows:
     473                    final int x1 = pb.x + (int)(  w/4.0);
     474                    final int x3 = pb.x + (int)(3*w/4.0);
     475                    final int y1 = pb.y + (int)(  h/4.0);
     476                    final int y3 = pb.y + (int)(3*h/4.0);
     477                    // +-----------+
     478                    // |  5  1  6  |
     479                    // |  4  C  2  |
     480                    // |  8  3  7  |
     481                    // +-----------+
     482                    Rectangle[] candidates = new Rectangle[] {
     483                            new Rectangle(x2, y1, nbw, nbh),
     484                            new Rectangle(x3, y2, nbw, nbh),
     485                            new Rectangle(x2, y3, nbw, nbh),
     486                            new Rectangle(x1, y2, nbw, nbh),
     487                            new Rectangle(x1, y1, nbw, nbh),
     488                            new Rectangle(x3, y1, nbw, nbh),
     489                            new Rectangle(x3, y3, nbw, nbh),
     490                            new Rectangle(x1, y3, nbw, nbh)
     491                    };
     492                    // Dumb algorithm to find a better placement. We could surely find a smarter one but it should
     493                    // solve most of building issues with only few calculations (8 at most)
     494                    for (int i = 0; i < candidates.length && !labelOK; i++) {
     495                        centeredNBounds = candidates[i];
     496                        labelOK = area.contains(centeredNBounds);
     497                    }
     498                }
     499                if (labelOK) {
     500                    Font defaultFont = g.getFont();
     501                    int x = (int)(centeredNBounds.getMinX() - nb.getMinX());
     502                    int y = (int)(centeredNBounds.getMinY() - nb.getMinY());
     503                    displayText(null, name, x, y, osm.isDisabled(), text);
     504                    g.setFont(defaultFont);
     505                } else if (Main.isDebugEnabled()) {
     506                    Main.debug("Couldn't find a correct label placement for "+osm+" / "+name);
     507                }
    464508            }
    465509        }
Note: See TracChangeset for help on using the changeset viewer.