001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/graphics/optimizers/LabelChoice.java $
002 /*----------------------------------------------------------------------------
003 This file is part of deegree, http://deegree.org/
004 Copyright (C) 2001-2009 by:
005 Department of Geography, University of Bonn
006 and
007 lat/lon GmbH
008
009 This library is free software; you can redistribute it and/or modify it under
010 the terms of the GNU Lesser General Public License as published by the Free
011 Software Foundation; either version 2.1 of the License, or (at your option)
012 any later version.
013 This library is distributed in the hope that it will be useful, but WITHOUT
014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016 details.
017 You should have received a copy of the GNU Lesser General Public License
018 along with this library; if not, write to the Free Software Foundation, Inc.,
019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020
021 Contact information:
022
023 lat/lon GmbH
024 Aennchenstr. 19, 53177 Bonn
025 Germany
026 http://lat-lon.de/
027
028 Department of Geography, University of Bonn
029 Prof. Dr. Klaus Greve
030 Postfach 1147, 53001 Bonn
031 Germany
032 http://www.geographie.uni-bonn.de/deegree/
033
034 e-mail: info@deegree.org
035 ----------------------------------------------------------------------------*/
036 package org.deegree.graphics.optimizers;
037
038 import org.deegree.graphics.displayelements.Label;
039 import org.deegree.graphics.displayelements.LabelDisplayElement;
040
041 /**
042 * Represents different possibilities (candidates) to draw a {@link LabelDisplayElement}.
043 * <p>
044 * A {@link LabelChoice} has several {@link Label} candidates, one of this candidates is selected and represents the
045 * best choice.
046 *
047 * @author <a href="mailto:mschneider@lat-lon.de">Andreas Poth</a>
048 * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider</a>
049 * @author last edited by: $Author: mschneider $
050 *
051 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
052 */
053 public class LabelChoice {
054
055 // associated LabelDisplayElement
056 private LabelDisplayElement element;
057
058 // currently selected Label (in candidates array)
059 private int selected;
060
061 // candidate Label objects
062 private Label[] candidates;
063
064 // quality of each Label
065 private float[] qualities;
066
067 // boundingbox of all contained labels
068 private int maxX;
069
070 // boundingbox of all contained labels
071 private int maxY;
072
073 // boundingbox of all contained labels
074 private int minX;
075
076 // boundingbox of all contained labels
077 private int minY;
078
079 /**
080 * Creates a new instance of {@link LabelChoice}.
081 *
082 * @param element
083 * @param candidates
084 * @param qualities
085 * @param selected
086 * @param maxX
087 * @param maxY
088 * @param minX
089 * @param minY
090 */
091 public LabelChoice( LabelDisplayElement element, Label[] candidates, float[] qualities, int selected, int maxX,
092 int maxY, int minX, int minY ) {
093 this.element = element;
094 this.candidates = candidates;
095 this.qualities = qualities;
096 this.selected = selected;
097 this.maxX = maxX;
098 this.maxY = maxY;
099 this.minX = minX;
100 this.minY = minY;
101 }
102
103 /**
104 * Selects one of the contained {@link Label} candidates randomly.
105 */
106 public void selectLabelRandomly() {
107 selected = (int) ( Math.random() * ( candidates.length - 1 ) + 0.5 );
108 }
109
110 /**
111 * Sets the selected {@link Label} candidate.
112 *
113 * @param selected
114 * the index of the {@link Label} to be selected
115 */
116 public void setSelected( int selected ) {
117 this.selected = selected;
118 }
119
120 /**
121 * Returns the index of the currently selected {@link Label}.
122 *
123 * @return the index of the currently selected {@link Label}
124 */
125 public int getSelected() {
126 return selected;
127 }
128
129 /**
130 * Returns the quality measure of the currently selected {@link Label}
131 *
132 * @return the quality of the currently selected {@link Label}
133 */
134 public float getQuality() {
135 return qualities[selected];
136 }
137
138 /**
139 * Returns the currently selected {@link Label} (which is the best choice of the candidates).
140 *
141 * @return the currently selected {@link Label}
142 */
143 public Label getSelectedLabel() {
144 return candidates[selected];
145 }
146
147 /**
148 * Returns the associated {@link LabelDisplayElement}.
149 *
150 * @return the associated {@link LabelDisplayElement}
151 */
152 public LabelDisplayElement getElement() {
153 return element;
154 }
155
156 /**
157 * Returns the max x value of the bounding box of all {@link Label} candidates.
158 *
159 * @return max x value of the bounding box
160 */
161 public int getMaxX() {
162 return maxX;
163 }
164
165 /**
166 * Returns the max y value of the bounding box of all {@link Label} candidates.
167 *
168 * @return max y value of the bounding box
169 */
170 public int getMaxY() {
171 return maxY;
172 }
173
174 /**
175 * Returns the min x value of the bounding box of all {@link Label} candidates.
176 *
177 * @return min x value of the bounding box
178 */
179 public int getMinX() {
180 return minX;
181 }
182
183 /**
184 * Returns the min y value of the bounding box of all {@link Label} candidates.
185 *
186 * @return min y value of the bounding box
187 */
188 public int getMinY() {
189 return minY;
190 }
191
192 /**
193 * Determines if this {@link LabelChoice} can intersect with another {@link LabelChoice} by any chance, i.e. whether
194 * there are at least two {@link Label} candidates from each choice that intersect.
195 *
196 * @param that
197 * {@link LabelChoice} to be tested against this {@link LabelChoice}
198 * @return true if the two {@link LabelChoice}s can intersect
199 */
200 public boolean intersects( LabelChoice that ) {
201
202 int west1 = getMinX();
203 int south1 = getMinY();
204 int east1 = getMaxX();
205 int north1 = getMaxY();
206
207 int west2 = that.getMinX();
208 int south2 = that.getMinY();
209 int east2 = that.getMaxX();
210 int north2 = that.getMaxY();
211
212 // special cases: one box lays completly inside the other one
213 if ( ( west1 <= west2 ) && ( south1 <= south2 ) && ( east1 >= east2 ) && ( north1 >= north2 ) ) {
214 return true;
215 }
216 if ( ( west1 >= west2 ) && ( south1 >= south2 ) && ( east1 <= east2 ) && ( north1 <= north2 ) ) {
217 return true;
218 }
219 // in any other case of intersection, at least one line of the BBOX has
220 // to cross a line of the other BBOX
221 // check western boundary of box 1
222 // "touching" boxes must not intersect
223 if ( ( west1 >= west2 ) && ( west1 < east2 ) ) {
224 if ( ( south1 <= south2 ) && ( north1 > south2 ) ) {
225 return true;
226 }
227
228 if ( ( south1 < north2 ) && ( north1 >= north2 ) ) {
229 return true;
230 }
231 }
232 // check eastern boundary of box 1
233 // "touching" boxes must not intersect
234 if ( ( east1 > west2 ) && ( east1 <= east2 ) ) {
235 if ( ( south1 <= south2 ) && ( north1 > south2 ) ) {
236 return true;
237 }
238
239 if ( ( south1 < north2 ) && ( north1 >= north2 ) ) {
240 return true;
241 }
242 }
243 // check southern boundary of box 1
244 // "touching" boxes must not intersect
245 if ( ( south1 >= south2 ) && ( south1 < north2 ) ) {
246 if ( ( west1 <= west2 ) && ( east1 > west2 ) ) {
247 return true;
248 }
249
250 if ( ( west1 < east2 ) && ( east1 >= east2 ) ) {
251 return true;
252 }
253 }
254 // check northern boundary of box 1
255 // "touching" boxes must not intersect
256 if ( ( north1 > south2 ) && ( north1 <= north2 ) ) {
257 if ( ( west1 <= west2 ) && ( east1 > west2 ) ) {
258 return true;
259 }
260
261 if ( ( west1 < east2 ) && ( east1 >= east2 ) ) {
262 return true;
263 }
264 }
265 return false;
266 }
267
268 @Override
269 public String toString() {
270 if ( candidates.length > 0 ) {
271 return candidates[0].toString();
272 }
273 return "empty";
274 }
275 }