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

Last change on this file since 12082 was 12082, checked in by bastiK, 7 years ago

minor fixes to ensure unmodifiable StyleElement classes

File size: 3.7 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 protected CompletelyInsideAreaStrategy() {
25 }
26
27 @Override
28 public MapViewPositionAndRotation findLabelPlacement(MapViewPath path, Rectangle2D nb) {
29 // Using the Centroid is Nicer for buildings like: +--------+
30 // but this needs to be fast. As most houses are | 42 |
31 // boxes anyway, the center of the bounding box +---++---+
32 // will have to do. ++
33 // Centroids are not optimal either, just imagine a U-shaped house.
34
35 Rectangle pb = path.getBounds();
36
37 // quick check to see if label box is smaller than primitive box
38 if (pb.width < nb.getWidth() || pb.height < nb.getHeight()) {
39 return null;
40 }
41
42 final double w = pb.width - nb.getWidth();
43 final double h = pb.height - nb.getHeight();
44
45 final int x2 = pb.x + (int) (w / 2.0);
46 final int y2 = pb.y + (int) (h / 2.0);
47
48 final int nbw = (int) nb.getWidth();
49 final int nbh = (int) nb.getHeight();
50
51 Rectangle centeredNBounds = new Rectangle(x2, y2, nbw, nbh);
52
53 // slower check to see if label is displayed inside primitive shape
54 if (path.contains(centeredNBounds)) {
55 return centerOf(path.getMapViewState(), centeredNBounds);
56 }
57
58 // if center position (C) is not inside osm shape, try naively some other positions as follows:
59 final int x1 = pb.x + (int) (.25 * w);
60 final int x3 = pb.x + (int) (.75 * w);
61 final int y1 = pb.y + (int) (.25 * h);
62 final int y3 = pb.y + (int) (.75 * h);
63 // +-----------+
64 // | 5 1 6 |
65 // | 4 C 2 |
66 // | 8 3 7 |
67 // +-----------+
68 Rectangle[] candidates = new Rectangle[] {
69 new Rectangle(x2, y1, nbw, nbh),
70 new Rectangle(x3, y2, nbw, nbh),
71 new Rectangle(x2, y3, nbw, nbh),
72 new Rectangle(x1, y2, nbw, nbh),
73 new Rectangle(x1, y1, nbw, nbh),
74 new Rectangle(x3, y1, nbw, nbh),
75 new Rectangle(x3, y3, nbw, nbh),
76 new Rectangle(x1, y3, nbw, nbh)
77 };
78 // Dumb algorithm to find a better placement. We could surely find a smarter one but it should
79 // solve most of building issues with only few calculations (8 at most)
80 for (int i = 0; i < candidates.length; i++) {
81 centeredNBounds = candidates[i];
82 if (path.contains(centeredNBounds)) {
83 return centerOf(path.getMapViewState(), centeredNBounds);
84 }
85 }
86
87 // none found
88 return null;
89 }
90
91 private static MapViewPositionAndRotation centerOf(MapViewState mapViewState, Rectangle centeredNBounds) {
92 return new MapViewPositionAndRotation(
93 mapViewState.getForView(centeredNBounds.getCenterX(), centeredNBounds.getCenterY()), 0);
94 }
95
96 @Override
97 public boolean supportsGlyphVector() {
98 return false;
99 }
100}
Note: See TracBrowser for help on using the repository browser.