- Timestamp:
- 2017-03-13T14:19:07+01:00 (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
r11716 r11719 403 403 Shape area = path.createTransformedShape(mapState.getAffineTransform()); 404 404 405 if (!isOutlineOnly) { 405 if (color.getAlpha() == 0) { 406 // skip drawing 407 } else if (!isOutlineOnly) { 406 408 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); 407 409 if (fillImage == null) { … … 459 461 if (name == null || name.isEmpty()) return; 460 462 461 Rectangle pb = area.getBounds();462 463 FontMetrics fontMetrics = g.getFontMetrics(orderFont); // if slow, use cache 463 464 Rectangle2D nb = fontMetrics.getStringBounds(name, g); // if slow, approximate by strlen()*maxcharbounds(font) 464 465 465 // Using the Centroid is Nicer for buildings like: +--------+ 466 // but this needs to be fast. As most houses are | 42 | 467 // boxes anyway, the center of the bounding box +---++---+ 468 // will have to do. ++ 469 // Centroids are not optimal either, just imagine a U-shaped house. 470 471 // quick check to see if label box is smaller than primitive box 472 if (pb.width >= nb.getWidth() && pb.height >= nb.getHeight()) { 473 474 final double w = pb.width - nb.getWidth(); 475 final double h = pb.height - nb.getHeight(); 476 477 final int x2 = pb.x + (int) (w/2.0); 478 final int y2 = pb.y + (int) (h/2.0); 479 480 final int nbw = (int) nb.getWidth(); 481 final int nbh = (int) nb.getHeight(); 482 483 Rectangle centeredNBounds = new Rectangle(x2, y2, nbw, nbh); 484 485 // slower check to see if label is displayed inside primitive shape 486 boolean labelOK = area.contains(centeredNBounds); 487 if (!labelOK) { 488 // if center position (C) is not inside osm shape, try naively some other positions as follows: 489 // CHECKSTYLE.OFF: SingleSpaceSeparator 490 final int x1 = pb.x + (int) (w/4.0); 491 final int x3 = pb.x + (int) (3*w/4.0); 492 final int y1 = pb.y + (int) (h/4.0); 493 final int y3 = pb.y + (int) (3*h/4.0); 494 // CHECKSTYLE.ON: SingleSpaceSeparator 495 // +-----------+ 496 // | 5 1 6 | 497 // | 4 C 2 | 498 // | 8 3 7 | 499 // +-----------+ 500 Rectangle[] candidates = new Rectangle[] { 501 new Rectangle(x2, y1, nbw, nbh), 502 new Rectangle(x3, y2, nbw, nbh), 503 new Rectangle(x2, y3, nbw, nbh), 504 new Rectangle(x1, y2, nbw, nbh), 505 new Rectangle(x1, y1, nbw, nbh), 506 new Rectangle(x3, y1, nbw, nbh), 507 new Rectangle(x3, y3, nbw, nbh), 508 new Rectangle(x1, y3, nbw, nbh) 509 }; 510 // Dumb algorithm to find a better placement. We could surely find a smarter one but it should 511 // solve most of building issues with only few calculations (8 at most) 512 for (int i = 0; i < candidates.length && !labelOK; i++) { 513 centeredNBounds = candidates[i]; 514 labelOK = area.contains(centeredNBounds); 515 } 516 } 517 if (labelOK) { 518 Font defaultFont = g.getFont(); 519 int x = (int) (centeredNBounds.getMinX() - nb.getMinX()); 520 int y = (int) (centeredNBounds.getMinY() - nb.getMinY()); 521 displayText(null, name, x, y, osm.isDisabled(), text); 522 g.setFont(defaultFont); 523 } else if (Main.isTraceEnabled()) { 524 Main.trace("Couldn't find a correct label placement for "+osm+" / "+name); 525 } 526 } 527 } 466 Rectangle centeredNBounds = findLabelPlacement(area, nb); 467 if (centeredNBounds != null) { 468 Font defaultFont = g.getFont(); 469 int x = (int) (centeredNBounds.getMinX() - nb.getMinX()); 470 int y = (int) (centeredNBounds.getMinY() - nb.getMinY()); 471 displayText(null, name, x, y, osm.isDisabled(), text); 472 g.setFont(defaultFont); 473 } else if (Main.isTraceEnabled()) { 474 Main.trace("Couldn't find a correct label placement for "+osm+" / "+name); 475 } 476 } 477 } 478 479 /** 480 * Finds the correct position of a label / icon inside the area. 481 * @param area The area to search in 482 * @param nb The bounding box of the thing we are searching a place for. 483 * @return The position as rectangle with the same dimension as nb. <code>null</code> if none was found. 484 */ 485 private Rectangle findLabelPlacement(Shape area, Rectangle2D nb) { 486 // Using the Centroid is Nicer for buildings like: +--------+ 487 // but this needs to be fast. As most houses are | 42 | 488 // boxes anyway, the center of the bounding box +---++---+ 489 // will have to do. ++ 490 // Centroids are not optimal either, just imagine a U-shaped house. 491 492 Rectangle pb = area.getBounds(); 493 494 // quick check to see if label box is smaller than primitive box 495 if (pb.width < nb.getWidth() || pb.height < nb.getHeight()) { 496 return null; 497 } 498 499 final double w = pb.width - nb.getWidth(); 500 final double h = pb.height - nb.getHeight(); 501 502 final int x2 = pb.x + (int) (w/2.0); 503 final int y2 = pb.y + (int) (h/2.0); 504 505 final int nbw = (int) nb.getWidth(); 506 final int nbh = (int) nb.getHeight(); 507 508 Rectangle centeredNBounds = new Rectangle(x2, y2, nbw, nbh); 509 510 // slower check to see if label is displayed inside primitive shape 511 if (area.contains(centeredNBounds)) { 512 return centeredNBounds; 513 } 514 515 // if center position (C) is not inside osm shape, try naively some other positions as follows: 516 // CHECKSTYLE.OFF: SingleSpaceSeparator 517 final int x1 = pb.x + (int) (w/4.0); 518 final int x3 = pb.x + (int) (3*w/4.0); 519 final int y1 = pb.y + (int) (h/4.0); 520 final int y3 = pb.y + (int) (3*h/4.0); 521 // CHECKSTYLE.ON: SingleSpaceSeparator 522 // +-----------+ 523 // | 5 1 6 | 524 // | 4 C 2 | 525 // | 8 3 7 | 526 // +-----------+ 527 Rectangle[] candidates = new Rectangle[] { 528 new Rectangle(x2, y1, nbw, nbh), 529 new Rectangle(x3, y2, nbw, nbh), 530 new Rectangle(x2, y3, nbw, nbh), 531 new Rectangle(x1, y2, nbw, nbh), 532 new Rectangle(x1, y1, nbw, nbh), 533 new Rectangle(x3, y1, nbw, nbh), 534 new Rectangle(x3, y3, nbw, nbh), 535 new Rectangle(x1, y3, nbw, nbh) 536 }; 537 // Dumb algorithm to find a better placement. We could surely find a smarter one but it should 538 // solve most of building issues with only few calculations (8 at most) 539 for (int i = 0; i < candidates.length; i++) { 540 centeredNBounds = candidates[i]; 541 if (area.contains(centeredNBounds)) { 542 return centeredNBounds; 543 } 544 } 545 546 // none found 547 return null; 528 548 } 529 549
Note:
See TracChangeset
for help on using the changeset viewer.