source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/placement/CompletelyInsideAreaStrategy.java@ 11748

Last change on this file since 11748 was 11748, checked in by michael2402, 7 years ago

Move label / icon placement code to new package. Unify the handling of text label positioning (path / center)

File size: 3.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint.styleelement.placement;
3
4import java.awt.Rectangle;
5import java.awt.geom.Rectangle2D;
6
7import org.openstreetmap.josm.gui.MapViewState;
8import org.openstreetmap.josm.gui.draw.MapViewPath;
9import org.openstreetmap.josm.gui.draw.MapViewPositionAndRotation;
10
11/**
12 * Places the label / icon so that it is completely inside the area.
13 *
14 * @author Michael Zangl
15 * @since 11722
16 * @since 11748 moved to own file
17 */
18public class CompletelyInsideAreaStrategy implements PositionForAreaStrategy {
19 /**
20 * An instance of this class.
21 */
22 public static final CompletelyInsideAreaStrategy INSTANCE = new CompletelyInsideAreaStrategy();
23
24 @Override
25 public MapViewPositionAndRotation findLabelPlacement(MapViewPath path, Rectangle2D nb) {
26 // Using the Centroid is Nicer for buildings like: +--------+
27 // but this needs to be fast. As most houses are | 42 |
28 // boxes anyway, the center of the bounding box +---++---+
29 // will have to do. ++
30 // Centroids are not optimal either, just imagine a U-shaped house.
31
32 Rectangle pb = path.getBounds();
33
34 // quick check to see if label box is smaller than primitive box
35 if (pb.width < nb.getWidth() || pb.height < nb.getHeight()) {
36 return null;
37 }
38
39 final double w = pb.width - nb.getWidth();
40 final double h = pb.height - nb.getHeight();
41
42 final int x2 = pb.x + (int) (w / 2.0);
43 final int y2 = pb.y + (int) (h / 2.0);
44
45 final int nbw = (int) nb.getWidth();
46 final int nbh = (int) nb.getHeight();
47
48 Rectangle centeredNBounds = new Rectangle(x2, y2, nbw, nbh);
49
50 // slower check to see if label is displayed inside primitive shape
51 if (path.contains(centeredNBounds)) {
52 return centerOf(path.getMapViewState(), centeredNBounds);
53 }
54
55 // if center position (C) is not inside osm shape, try naively some other positions as follows:
56 final int x1 = pb.x + (int) (.25 * w);
57 final int x3 = pb.x + (int) (.75 * w);
58 final int y1 = pb.y + (int) (.25 * h);
59 final int y3 = pb.y + (int) (.75 * h);
60 // +-----------+
61 // | 5 1 6 |
62 // | 4 C 2 |
63 // | 8 3 7 |
64 // +-----------+
65 Rectangle[] candidates = new Rectangle[] {
66 new Rectangle(x2, y1, nbw, nbh),
67 new Rectangle(x3, y2, nbw, nbh),
68 new Rectangle(x2, y3, nbw, nbh),
69 new Rectangle(x1, y2, nbw, nbh),
70 new Rectangle(x1, y1, nbw, nbh),
71 new Rectangle(x3, y1, nbw, nbh),
72 new Rectangle(x3, y3, nbw, nbh),
73 new Rectangle(x1, y3, nbw, nbh)
74 };
75 // Dumb algorithm to find a better placement. We could surely find a smarter one but it should
76 // solve most of building issues with only few calculations (8 at most)
77 for (int i = 0; i < candidates.length; i++) {
78 centeredNBounds = candidates[i];
79 if (path.contains(centeredNBounds)) {
80 return centerOf(path.getMapViewState(), centeredNBounds);
81 }
82 }
83
84 // none found
85 return null;
86 }
87
88 private MapViewPositionAndRotation centerOf(MapViewState mapViewState, Rectangle centeredNBounds) {
89 return new MapViewPositionAndRotation(
90 mapViewState.getForView(centeredNBounds.getCenterX(), centeredNBounds.getCenterY()), 0);
91 }
92
93 @Override
94 public boolean supportsGlyphVector() {
95 return false;
96 }
97}
Note: See TracBrowser for help on using the repository browser.