svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.labeling.app / org.gvsig.labeling.app.mainplugin / src / main / java / org / gvsig / labeling / label / GeneralLabelingStrategy.java @ 41676
History | View | Annotate | Download (32.2 KB)
1 | 40911 | jldominguez | /* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
---|---|---|---|
2 | *
|
||
3 | * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
|
||
4 | *
|
||
5 | * This program is free software; you can redistribute it and/or
|
||
6 | * modify it under the terms of the GNU General Public License
|
||
7 | * as published by the Free Software Foundation; either version 2
|
||
8 | * of the License, or (at your option) any later version.
|
||
9 | *
|
||
10 | * This program is distributed in the hope that it will be useful,
|
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
13 | * GNU General Public License for more details.
|
||
14 | *
|
||
15 | * You should have received a copy of the GNU General Public License
|
||
16 | * along with this program; if not, write to the Free Software
|
||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
||
18 | *
|
||
19 | * For more information, contact:
|
||
20 | *
|
||
21 | * Generalitat Valenciana
|
||
22 | * Conselleria d'Infraestructures i Transport
|
||
23 | * Av. Blasco Ib??ez, 50
|
||
24 | * 46010 VALENCIA
|
||
25 | * SPAIN
|
||
26 | *
|
||
27 | * +34 963862235
|
||
28 | * gvsig@gva.es
|
||
29 | * www.gvsig.gva.es
|
||
30 | *
|
||
31 | * or
|
||
32 | *
|
||
33 | * IVER T.I. S.A
|
||
34 | * Salamanca 50
|
||
35 | * 46005 Valencia
|
||
36 | * Spain
|
||
37 | *
|
||
38 | * +34 963163400
|
||
39 | * dac@iver.es
|
||
40 | */
|
||
41 | |||
42 | /* CVS MESSAGES:
|
||
43 | *
|
||
44 | * $Id: GeneralLabelingStrategy.java 13749 2007-09-17 14:16:11Z jaume $
|
||
45 | * $Log$
|
||
46 | * Revision 1.2 2007-09-17 14:16:11 jaume
|
||
47 | * multilayer symbols sizing bug fixed
|
||
48 | *
|
||
49 | * Revision 1.1 2007/05/22 12:17:41 jaume
|
||
50 | * *** empty log message ***
|
||
51 | *
|
||
52 | * Revision 1.1 2007/05/22 10:05:31 jaume
|
||
53 | * *** empty log message ***
|
||
54 | *
|
||
55 | * Revision 1.10 2007/05/17 09:32:06 jaume
|
||
56 | * *** empty log message ***
|
||
57 | *
|
||
58 | * Revision 1.9 2007/05/09 11:04:58 jaume
|
||
59 | * refactored legend hierarchy
|
||
60 | *
|
||
61 | * Revision 1.8 2007/04/13 11:59:30 jaume
|
||
62 | * *** empty log message ***
|
||
63 | *
|
||
64 | * Revision 1.7 2007/04/12 14:28:43 jaume
|
||
65 | * basic labeling support for lines
|
||
66 | *
|
||
67 | * Revision 1.6 2007/04/11 16:01:08 jaume
|
||
68 | * maybe a label placer refactor
|
||
69 | *
|
||
70 | * Revision 1.5 2007/04/10 16:34:01 jaume
|
||
71 | * towards a styled labeling
|
||
72 | *
|
||
73 | * Revision 1.4 2007/04/02 16:34:56 jaume
|
||
74 | * Styled labeling (start commiting)
|
||
75 | *
|
||
76 | * Revision 1.3 2007/03/28 16:48:01 jaume
|
||
77 | * *** empty log message ***
|
||
78 | *
|
||
79 | * Revision 1.2 2007/03/26 14:40:38 jaume
|
||
80 | * added print method (BUT UNIMPLEMENTED)
|
||
81 | *
|
||
82 | * Revision 1.1 2007/03/20 16:16:20 jaume
|
||
83 | * refactored to use ISymbol instead of FSymbol
|
||
84 | *
|
||
85 | * Revision 1.2 2007/03/09 11:20:57 jaume
|
||
86 | * Advanced symbology (start committing)
|
||
87 | *
|
||
88 | * Revision 1.1 2007/03/09 08:33:43 jaume
|
||
89 | * *** empty log message ***
|
||
90 | *
|
||
91 | * Revision 1.1.2.5 2007/02/21 07:34:08 jaume
|
||
92 | * labeling starts working
|
||
93 | *
|
||
94 | * Revision 1.1.2.4 2007/02/15 16:23:44 jaume
|
||
95 | * *** empty log message ***
|
||
96 | *
|
||
97 | * Revision 1.1.2.3 2007/02/09 07:47:05 jaume
|
||
98 | * Isymbol moved
|
||
99 | *
|
||
100 | * Revision 1.1.2.2 2007/02/02 16:21:24 jaume
|
||
101 | * start commiting labeling stuff
|
||
102 | *
|
||
103 | * Revision 1.1.2.1 2007/02/01 17:46:49 jaume
|
||
104 | * *** empty log message ***
|
||
105 | *
|
||
106 | *
|
||
107 | */
|
||
108 | package org.gvsig.labeling.label; |
||
109 | |||
110 | import java.awt.Graphics2D; |
||
111 | import java.awt.geom.Point2D; |
||
112 | import java.awt.image.BufferedImage; |
||
113 | import java.util.ArrayList; |
||
114 | 41421 | jjdelcerro | import java.util.HashMap; |
115 | 40911 | jldominguez | import java.util.Iterator; |
116 | 41227 | jldominguez | import java.util.List; |
117 | 41421 | jjdelcerro | import java.util.Map; |
118 | 40911 | jldominguez | import java.util.TreeMap; |
119 | import java.util.TreeSet; |
||
120 | |||
121 | import org.gvsig.compat.print.PrintAttributes; |
||
122 | import org.gvsig.fmap.dal.exception.DataException; |
||
123 | import org.gvsig.fmap.dal.exception.ReadException; |
||
124 | import org.gvsig.fmap.dal.feature.Feature; |
||
125 | import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
||
126 | import org.gvsig.fmap.dal.feature.FeatureSet; |
||
127 | import org.gvsig.fmap.geom.Geometry; |
||
128 | import org.gvsig.fmap.geom.Geometry.SUBTYPES; |
||
129 | import org.gvsig.fmap.geom.Geometry.TYPES; |
||
130 | import org.gvsig.fmap.geom.GeometryException; |
||
131 | import org.gvsig.fmap.geom.GeometryLocator; |
||
132 | import org.gvsig.fmap.geom.GeometryManager; |
||
133 | 41227 | jldominguez | import org.gvsig.fmap.geom.aggregate.MultiPrimitive; |
134 | 40911 | jldominguez | import org.gvsig.fmap.geom.primitive.Envelope; |
135 | import org.gvsig.fmap.geom.primitive.Point; |
||
136 | import org.gvsig.fmap.geom.type.GeometryType; |
||
137 | import org.gvsig.fmap.mapcontext.ViewPort; |
||
138 | import org.gvsig.fmap.mapcontext.layers.FLayer; |
||
139 | import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect; |
||
140 | import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelClass; |
||
141 | import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingMethod; |
||
142 | import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy; |
||
143 | import org.gvsig.fmap.mapcontext.rendering.legend.styling.IPlacementConstraints; |
||
144 | import org.gvsig.fmap.mapcontext.rendering.legend.styling.IZoomConstraints; |
||
145 | import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport; |
||
146 | import org.gvsig.i18n.Messages; |
||
147 | import org.gvsig.labeling.lang.LabelClassUtils; |
||
148 | import org.gvsig.labeling.placements.ILabelPlacement; |
||
149 | import org.gvsig.labeling.placements.LinePlacementConstraints; |
||
150 | import org.gvsig.labeling.placements.MultiShapePlacementConstraints; |
||
151 | import org.gvsig.labeling.placements.PlacementManager; |
||
152 | import org.gvsig.labeling.placements.PointPlacementConstraints; |
||
153 | import org.gvsig.labeling.placements.PolygonPlacementConstraints; |
||
154 | import org.gvsig.labeling.placements.RemoveDuplicatesComparator; |
||
155 | import org.gvsig.labeling.symbol.SmartTextSymbol; |
||
156 | import org.gvsig.labeling.symbol.SymbolUtils; |
||
157 | import org.gvsig.symbology.SymbologyLocator; |
||
158 | import org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling.LabelLocationMetrics; |
||
159 | import org.gvsig.tools.ToolsLocator; |
||
160 | import org.gvsig.tools.dispose.DisposableIterator; |
||
161 | import org.gvsig.tools.dynobject.DynStruct; |
||
162 | import org.gvsig.tools.persistence.PersistenceManager; |
||
163 | import org.gvsig.tools.persistence.PersistentState; |
||
164 | import org.gvsig.tools.persistence.exception.PersistenceException; |
||
165 | import org.gvsig.tools.task.Cancellable; |
||
166 | import org.slf4j.Logger; |
||
167 | import org.slf4j.LoggerFactory; |
||
168 | |||
169 | /**
|
||
170 | *
|
||
171 | * GeneralLabelingStrategy.java
|
||
172 | *
|
||
173 | *
|
||
174 | * @author jaume dominguez faus - jaume.dominguez@iver.es Jan 4, 2008
|
||
175 | *
|
||
176 | */
|
||
177 | public class GeneralLabelingStrategy implements |
||
178 | ILabelingStrategy, Cloneable, CartographicSupport {
|
||
179 | |||
180 | private static final Logger logger = LoggerFactory.getLogger( |
||
181 | GeneralLabelingStrategy.class); |
||
182 | |||
183 | public static final String GENERAL_LABEL_STRATEGY_PERSISTENCE_NAME = |
||
184 | "GENERAL_LABEL_STRATEGY_PERSISTENCE_NAME";
|
||
185 | |||
186 | public static PointPlacementConstraints DefaultPointPlacementConstraints = |
||
187 | new PointPlacementConstraints();
|
||
188 | public static LinePlacementConstraints DefaultLinePlacementConstraints = |
||
189 | new LinePlacementConstraints();
|
||
190 | public static PolygonPlacementConstraints DefaultPolygonPlacementConstraints = |
||
191 | new PolygonPlacementConstraints();
|
||
192 | |||
193 | private static String[] NO_TEXT = { Messages.getText("text_field") }; |
||
194 | |||
195 | private static MultiShapePlacementConstraints DefaultMultiShapePlacementConstratints = |
||
196 | new MultiShapePlacementConstraints();
|
||
197 | |||
198 | private ILabelingMethod method;
|
||
199 | private IPlacementConstraints placementConstraints;
|
||
200 | private IZoomConstraints zoomConstraints;
|
||
201 | |||
202 | private boolean allowOverlapping; |
||
203 | |||
204 | protected FLyrVect layer;
|
||
205 | |||
206 | |||
207 | 41421 | jjdelcerro | // private long parseTime;
|
208 | 40911 | jldominguez | private int unit; |
209 | private int referenceSystem; |
||
210 | // private double sizeAfter;
|
||
211 | private boolean printMode = false; /* indicate whether output is for a print product (PDF, PS, ...) */ |
||
212 | |||
213 | public GeneralLabelingStrategy() {
|
||
214 | method = |
||
215 | SymbologyLocator.getSymbologyManager().createDefaultLabelingMethod(); |
||
216 | } |
||
217 | |||
218 | public void setLayer(FLayer layer) { |
||
219 | FLyrVect l = (FLyrVect) layer; |
||
220 | this.layer = l;
|
||
221 | } |
||
222 | |||
223 | public ILabelingMethod getLabelingMethod() {
|
||
224 | return method;
|
||
225 | } |
||
226 | |||
227 | public void setLabelingMethod(ILabelingMethod method) { |
||
228 | this.method = method;
|
||
229 | } |
||
230 | |||
231 | private class GeometryItem{ |
||
232 | public Geometry geom = null; |
||
233 | public int weigh = 0; |
||
234 | public double savedPerimeter; |
||
235 | |||
236 | public GeometryItem(Geometry geom, int weigh){ |
||
237 | this.geom = geom;
|
||
238 | this.weigh = weigh;
|
||
239 | this.savedPerimeter = 0; |
||
240 | } |
||
241 | } |
||
242 | public void draw(BufferedImage mapImage, Graphics2D mapGraphics, |
||
243 | 41676 | jjdelcerro | double scale, ViewPort viewPort,
|
244 | 40911 | jldominguez | Cancellable cancel, |
245 | double dpi) throws ReadException { |
||
246 | |||
247 | int x = (int)viewPort.getOffset().getX(); |
||
248 | int y = (int)viewPort.getOffset().getY(); |
||
249 | // boolean bVisualFXEnabled = false; // if true, the user can see how the labeling is drawing up
|
||
250 | |||
251 | //offsets for page generation (PDF, PS, direct printing)
|
||
252 | int print_offset_x = x;
|
||
253 | int print_offset_y = y;
|
||
254 | if (printMode) {
|
||
255 | //for printing, we never offset the labels themselves
|
||
256 | x = 0;
|
||
257 | y = 0;
|
||
258 | printMode = false;
|
||
259 | } |
||
260 | |||
261 | TreeMap<String[], GeometryItem> labelsToPlace = null; |
||
262 | 41421 | jjdelcerro | // parseTime =0;
|
263 | 40911 | jldominguez | // long t1 = System.currentTimeMillis();
|
264 | |||
265 | String[] usedFields = getUsedFields(); |
||
266 | |||
267 | int notPlacedCount = 0; |
||
268 | int placedCount = 0; |
||
269 | |||
270 | /*
|
||
271 | * Get the label placement solvers according the user's settings
|
||
272 | */
|
||
273 | ILabelPlacement placement = PlacementManager.getPlacement( |
||
274 | getPlacementConstraints(), layer.getShapeType()); |
||
275 | |||
276 | |||
277 | BufferedImage targetBI;
|
||
278 | Graphics2D targetGr;
|
||
279 | |||
280 | |||
281 | /*
|
||
282 | * get an ordered set of the LabelClasses up on the
|
||
283 | * label priority
|
||
284 | */
|
||
285 | ILabelClass[] lcs = method.getLabelClasses();
|
||
286 | TreeSet<ILabelClass> ts = new TreeSet<ILabelClass>( |
||
287 | new LabelClassComparatorByPriority());
|
||
288 | |||
289 | for (int i = 0; i < lcs.length; i++) ts.add(lcs[i]); |
||
290 | |||
291 | if (ts.size()==0) return; |
||
292 | |||
293 | /*
|
||
294 | * now we have an ordered set, it is only need to give a pass
|
||
295 | * for each label class to render by priorities.
|
||
296 | *
|
||
297 | * If no priorities were defined, the following loop only executes
|
||
298 | * once
|
||
299 | */
|
||
300 | for (ILabelClass lc : ts) {
|
||
301 | |||
302 | 41676 | jjdelcerro | if (!lc.isVisible(scale)) {
|
303 | 41194 | jldominguez | /*
|
304 | * Avoid non-visible labels
|
||
305 | */
|
||
306 | continue;
|
||
307 | } |
||
308 | |||
309 | 40911 | jldominguez | FeatureSet fset = null;
|
310 | |||
311 | try {
|
||
312 | fset = method.getFeatureIteratorByLabelClass( |
||
313 | layer, lc, viewPort, usedFields); |
||
314 | } catch (DataException e) {
|
||
315 | throw new ReadException(layer.getFeatureStore().getProviderName(), e); |
||
316 | } |
||
317 | |||
318 | // duplicates treatment stuff
|
||
319 | /* handle the duplicates mode */
|
||
320 | int duplicateMode = getDuplicateLabelsMode();
|
||
321 | if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) {
|
||
322 | // we need to register the labels already placed
|
||
323 | |||
324 | labelsToPlace = new TreeMap<String[], GeometryItem>( |
||
325 | new RemoveDuplicatesComparator());
|
||
326 | } |
||
327 | |||
328 | boolean bLabelsReallocatable = !isAllowingOverlap();
|
||
329 | |||
330 | BufferedImage overlapDetectImage = null; |
||
331 | Graphics2D overlapDetectGraphics = null; |
||
332 | if (bLabelsReallocatable) {
|
||
333 | int width = viewPort.getImageWidth() + print_offset_x;
|
||
334 | |||
335 | if(width<0){ |
||
336 | width = 1;
|
||
337 | } |
||
338 | int height = viewPort.getImageHeight() + print_offset_y;
|
||
339 | if(height<0){ |
||
340 | height = 1;
|
||
341 | } |
||
342 | if (mapImage!=null) |
||
343 | overlapDetectImage = new BufferedImage( |
||
344 | mapImage.getWidth() + print_offset_x, |
||
345 | mapImage.getHeight() + print_offset_y, |
||
346 | BufferedImage.TYPE_INT_ARGB
|
||
347 | ); |
||
348 | else
|
||
349 | overlapDetectImage = new BufferedImage( |
||
350 | viewPort.getImageWidth() + print_offset_x, |
||
351 | viewPort.getImageHeight() + print_offset_y, |
||
352 | BufferedImage.TYPE_INT_ARGB
|
||
353 | ); |
||
354 | |||
355 | overlapDetectGraphics = overlapDetectImage.createGraphics(); |
||
356 | overlapDetectGraphics.setRenderingHints(mapGraphics.getRenderingHints()); |
||
357 | } |
||
358 | if (bLabelsReallocatable) {
|
||
359 | targetBI = overlapDetectImage; |
||
360 | targetGr = overlapDetectGraphics; |
||
361 | targetGr.translate(-x, -y); |
||
362 | } else {
|
||
363 | targetBI = mapImage; |
||
364 | targetGr = mapGraphics; |
||
365 | } |
||
366 | |||
367 | DisposableIterator diter = null;
|
||
368 | try {
|
||
369 | diter = fset.fastIterator(); |
||
370 | } catch (DataException e) {
|
||
371 | throw new ReadException(layer.getFeatureStore().getProviderName(), e); |
||
372 | } |
||
373 | Feature featu = null;
|
||
374 | Geometry geome = null;
|
||
375 | while ( !cancel.isCanceled() && diter.hasNext()) {
|
||
376 | |||
377 | featu = (Feature) diter.next(); |
||
378 | geome = featu.getDefaultGeometry(); |
||
379 | if (geome == null || geome.getType() == Geometry.TYPES.NULL) { |
||
380 | continue;
|
||
381 | } |
||
382 | |||
383 | |||
384 | if (!setupLabel(featu, lc, cancel,
|
||
385 | usedFields, viewPort, dpi, duplicateMode)) { |
||
386 | continue;
|
||
387 | } |
||
388 | |||
389 | String[] texts = lc.getTexts(); |
||
390 | |||
391 | if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) {
|
||
392 | // check if this text (so label) is already present in the map
|
||
393 | |||
394 | GeometryItem item = labelsToPlace.get(texts); |
||
395 | if (item == null){ |
||
396 | item = new GeometryItem(geome, 0); |
||
397 | labelsToPlace.put(texts, item); |
||
398 | } |
||
399 | if (item.geom != null) { |
||
400 | |||
401 | notPlacedCount++; |
||
402 | if (geome.getType() != Geometry.TYPES.POINT) {
|
||
403 | // FJP: Cambiamos la uni?n por una comprobaci?n de longitud, por ejemplo.
|
||
404 | // La geometr?a con mayor longitud del bounding box ser? la que etiquetamos.
|
||
405 | // Ser? inexacto, pero m?s r?pido. Solo lo queremos para saber qu? entidad etiquetamos
|
||
406 | // El problema con la uni?n es que para l?neas va muy mal (no sabes lo que te va
|
||
407 | // a etiquetar, y para pol?gonos ser? muy lenta. De todas formas, habr?a que evitar
|
||
408 | // la conversi?n al JTS.
|
||
409 | // Geometry jtsGeom = item.geom.toJTSGeometry().union(geom.toJTSGeometry());
|
||
410 | // if (jtsGeom instanceof LineString) {
|
||
411 | // CoordinateSequence cs = ((LineString) (jtsGeom)).getCoordinateSequence();
|
||
412 | // CoordinateSequences.reverse(cs);
|
||
413 | // jtsGeom = new LineString(cs, null);
|
||
414 | // }
|
||
415 | // item.geom = FConverter.jts_to_igeometry(jtsGeom);
|
||
416 | |||
417 | Envelope auxBox = geome.getEnvelope(); |
||
418 | double perimeterAux = 2 * (auxBox.getLength(0)+auxBox.getLength(1)); |
||
419 | if (perimeterAux > item.savedPerimeter) {
|
||
420 | item.geom = geome; //FConverter.jts_to_igeometry(jtsGeom);
|
||
421 | item.savedPerimeter = perimeterAux; |
||
422 | } |
||
423 | } else {
|
||
424 | int weigh = item.weigh;
|
||
425 | |||
426 | try {
|
||
427 | Point pointFromLabel = item.geom.centroid();
|
||
428 | Point pointGeome = geome.centroid();
|
||
429 | item.geom = GeometryLocator.getGeometryManager().createPoint( |
||
430 | (pointFromLabel.getX()*weigh + pointGeome.getX())/(weigh+1),
|
||
431 | (pointFromLabel.getY()*weigh + pointGeome.getY())/(weigh+1),
|
||
432 | Geometry.SUBTYPES.GEOM2D); |
||
433 | } catch (Exception ex) { |
||
434 | throw new ReadException(layer.getFeatureStore().getProviderName(), ex); |
||
435 | } |
||
436 | |||
437 | } |
||
438 | } else {
|
||
439 | item.geom = geome; |
||
440 | } |
||
441 | item.weigh++; |
||
442 | } else {
|
||
443 | // Check if size is a pixel
|
||
444 | if (isOnePoint(viewPort, geome)) {
|
||
445 | continue;
|
||
446 | } |
||
447 | 41227 | jldominguez | |
448 | List<Geometry> geome_parts = new ArrayList<Geometry>(); |
||
449 | if (duplicateMode == IPlacementConstraints.ONE_LABEL_PER_FEATURE_PART) {
|
||
450 | geome_parts = getGeometryParts(geome); |
||
451 | } else {
|
||
452 | geome_parts.add(geome); |
||
453 | } |
||
454 | 40911 | jldominguez | |
455 | try {
|
||
456 | 41227 | jldominguez | int n = geome_parts.size();
|
457 | for (int k=0; k<n; k++) { |
||
458 | drawLabelInGeom( |
||
459 | targetBI, targetGr, |
||
460 | lc, placement, |
||
461 | viewPort, geome_parts.get(k), |
||
462 | cancel, dpi, |
||
463 | bLabelsReallocatable); |
||
464 | } |
||
465 | 40911 | jldominguez | } catch (GeometryException e) {
|
466 | throw new ReadException( |
||
467 | layer.getFeatureStore().getProviderName(), e); |
||
468 | } |
||
469 | 41227 | jldominguez | |
470 | |||
471 | 40911 | jldominguez | placedCount++; |
472 | } |
||
473 | } |
||
474 | |||
475 | // ======= End iteration in feature set ====================
|
||
476 | |||
477 | if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) {
|
||
478 | Iterator<String[]> textsIt = labelsToPlace.keySet().iterator(); |
||
479 | while ( !cancel.isCanceled() && textsIt.hasNext()) {
|
||
480 | notPlacedCount++; |
||
481 | String[] texts = textsIt.next(); |
||
482 | |||
483 | GeometryItem item = labelsToPlace.get(texts); |
||
484 | if(item != null){ |
||
485 | lc.setTexts(texts); |
||
486 | // Check if size is a pixel
|
||
487 | if (isOnePoint(viewPort, item.geom)) {
|
||
488 | continue;
|
||
489 | } |
||
490 | |||
491 | // lc.toCartographicSize(viewPort, dpi, null);
|
||
492 | try {
|
||
493 | drawLabelInGeom(targetBI, targetGr, |
||
494 | lc, placement, viewPort, item.geom, |
||
495 | cancel, dpi, bLabelsReallocatable); |
||
496 | } catch (GeometryException e) {
|
||
497 | throw new ReadException( |
||
498 | layer.getFeatureStore().getProviderName(), e); |
||
499 | } |
||
500 | } |
||
501 | } |
||
502 | } |
||
503 | |||
504 | if (bLabelsReallocatable) {
|
||
505 | targetGr.translate(x, y); |
||
506 | if (mapImage!=null) { |
||
507 | // Graphics2D aux = (Graphics2D) mapImage.getGraphics();
|
||
508 | mapGraphics.drawImage(overlapDetectImage, null, null); |
||
509 | } else {
|
||
510 | mapGraphics.drawImage(overlapDetectImage, null, null); |
||
511 | } |
||
512 | } |
||
513 | |||
514 | |||
515 | } // big iteration
|
||
516 | // double totalTime = (System.currentTimeMillis()-t1);
|
||
517 | //
|
||
518 | // int total = placedCount+notPlacedCount;
|
||
519 | //
|
||
520 | // if (total>0)
|
||
521 | // Logger.getLogger(getClass()).info("Labeled layer '"+layer.getName()+
|
||
522 | // "' "+totalTime/1000D+" seconds. "+placedCount+"/"+total+
|
||
523 | // " labels placed ("+NumberFormat.getInstance().
|
||
524 | // format(100*placedCount/(double) total)+"%)");
|
||
525 | //
|
||
526 | // if (cancel.isCanceled()) {
|
||
527 | // Logger.getLogger(getClass()).info("Layer labeling canceled: '"+
|
||
528 | // layer.getName()+"'");
|
||
529 | // } else {
|
||
530 | // Logger.getLogger(getClass()).info("Total labels parse time = "+
|
||
531 | // parseTime+" ("+NumberFormat.getInstance().
|
||
532 | // format(parseTime*100/totalTime)+"%)");
|
||
533 | // }
|
||
534 | |||
535 | } |
||
536 | |||
537 | |||
538 | 41227 | jldominguez | private List<Geometry> getGeometryParts(Geometry ge) { |
539 | |||
540 | List<Geometry> resp = new ArrayList<Geometry>(); |
||
541 | if (ge != null) { |
||
542 | if (ge instanceof MultiPrimitive) { |
||
543 | MultiPrimitive mp = (MultiPrimitive) ge; |
||
544 | int n = mp.getPrimitivesNumber();
|
||
545 | for (int i=0; i<n; i++) { |
||
546 | resp.add(mp.getPrimitiveAt(i)); |
||
547 | } |
||
548 | } else {
|
||
549 | resp.add(ge); |
||
550 | } |
||
551 | } |
||
552 | return resp;
|
||
553 | } |
||
554 | |||
555 | private void drawLabelInGeom( |
||
556 | 40911 | jldominguez | BufferedImage targetBI, Graphics2D targetGr, ILabelClass lc, |
557 | ILabelPlacement placement, ViewPort viewPort, Geometry geom, |
||
558 | Cancellable cancel, |
||
559 | double dpi, boolean bLabelsReallocatable) throws GeometryException { |
||
560 | |||
561 | lc.toCartographicSize(viewPort, dpi, null);
|
||
562 | ArrayList<LabelLocationMetrics> llm = null; |
||
563 | llm = placement.guess( |
||
564 | lc, |
||
565 | geom, |
||
566 | getPlacementConstraints(), |
||
567 | 0,
|
||
568 | cancel,viewPort); |
||
569 | |||
570 | setReferenceSystem(lc.getReferenceSystem()); |
||
571 | setUnit(lc.getUnit()); |
||
572 | |||
573 | /*
|
||
574 | * search if there is room left by the previous and
|
||
575 | * with more priority labels, then check the current
|
||
576 | * level
|
||
577 | */
|
||
578 | // if (
|
||
579 | lookupAndPlaceLabel(targetBI, targetGr, llm, |
||
580 | placement, lc, geom, viewPort, cancel, bLabelsReallocatable); //{
|
||
581 | |||
582 | // lc.getTextSymbol().setFontSize(sizeBefore);
|
||
583 | // }
|
||
584 | // lc.toCartographicSize(viewPort, dpi, null);
|
||
585 | |||
586 | } |
||
587 | |||
588 | private int getDuplicateLabelsMode() { |
||
589 | if (getPlacementConstraints() == null) { |
||
590 | return IPlacementConstraints.DefaultDuplicateLabelsMode;
|
||
591 | } |
||
592 | return getPlacementConstraints().getDuplicateLabelsMode();
|
||
593 | } |
||
594 | |||
595 | private boolean lookupAndPlaceLabel(BufferedImage bi, Graphics2D g, |
||
596 | ArrayList<LabelLocationMetrics> llm, ILabelPlacement placement,
|
||
597 | ILabelClass lc, Geometry geom, ViewPort viewPort, |
||
598 | Cancellable cancel, boolean bLabelsReallocatable)
|
||
599 | throws GeometryException {
|
||
600 | |||
601 | int i;
|
||
602 | for (i = 0; !cancel.isCanceled() && i < llm.size(); i++) { |
||
603 | LabelLocationMetrics labelMetrics = llm.get(i); |
||
604 | |||
605 | IPlacementConstraints pc = getPlacementConstraints(); |
||
606 | if(pc instanceof MultiShapePlacementConstraints) { |
||
607 | MultiShapePlacementConstraints mpc = (MultiShapePlacementConstraints)pc; |
||
608 | |||
609 | GeometryManager gm = GeometryLocator.getGeometryManager(); |
||
610 | GeometryType line_gt = null;
|
||
611 | GeometryType polyg_gt = null;
|
||
612 | GeometryType geom_gt = null;
|
||
613 | |||
614 | line_gt = gm.getGeometryType(TYPES.CURVE, SUBTYPES.GEOM2D); |
||
615 | polyg_gt = gm.getGeometryType(TYPES.SURFACE, SUBTYPES.GEOM2D); |
||
616 | geom_gt = gm.getGeometryType(geom.getType(), SUBTYPES.GEOM2D); |
||
617 | |||
618 | if (geom_gt.getType() == TYPES.POINT ||
|
||
619 | geom_gt.getType() == TYPES.MULTIPOINT) { |
||
620 | pc = mpc.getPointConstraints(); |
||
621 | } else {
|
||
622 | if (geom_gt.isTypeOf(TYPES.CURVE) ||
|
||
623 | geom_gt.getType() == TYPES.MULTICURVE) { |
||
624 | pc = mpc.getLineConstraints(); |
||
625 | } else {
|
||
626 | if (geom_gt.isTypeOf(TYPES.SURFACE) ||
|
||
627 | geom_gt.getType() == TYPES.MULTISURFACE) { |
||
628 | pc = mpc.getPolygonConstraints(); |
||
629 | } |
||
630 | } |
||
631 | } |
||
632 | } |
||
633 | |||
634 | /*
|
||
635 | * Ver comentario en el metodo drawLabelInGeom
|
||
636 | */
|
||
637 | // lc.getTextSymbol().setFontSize(sizeAfter);// * FConstant.FONT_HEIGHT_SCALE_FACTOR);
|
||
638 | if (bLabelsReallocatable) {
|
||
639 | |||
640 | Geometry aux_geom = null;
|
||
641 | aux_geom = lc.getShape(labelMetrics); |
||
642 | |||
643 | if (!isOverlapping(bi, aux_geom)) {
|
||
644 | |||
645 | if(!pc.isFollowingLine()){
|
||
646 | lc.draw(g, labelMetrics, geom); |
||
647 | } else {
|
||
648 | |||
649 | 41131 | jldominguez | ILabelClass smsLc = new SmartTextSymbolLabelClass();
|
650 | 40911 | jldominguez | SmartTextSymbol sms = new SmartTextSymbol(lc.getTextSymbol(), pc);
|
651 | |||
652 | double sizeBefore = lc.getTextSymbol().getFont().getSize();
|
||
653 | double sizeAfter = SymbolUtils.getCartographicLength(this, |
||
654 | sizeBefore, |
||
655 | viewPort, |
||
656 | 41419 | jjdelcerro | viewPort.getDPI()); |
657 | 40911 | jldominguez | sms.setFontSize(sizeAfter); |
658 | |||
659 | smsLc.setTextSymbol(sms); |
||
660 | geom.transform(viewPort.getAffineTransform()); |
||
661 | smsLc.draw(g, null, geom);
|
||
662 | sms.setFontSize(sizeBefore); |
||
663 | |||
664 | } |
||
665 | return true; |
||
666 | } |
||
667 | } else {
|
||
668 | if(!pc.isFollowingLine()){
|
||
669 | lc.draw(g, labelMetrics, null);
|
||
670 | } |
||
671 | else{
|
||
672 | 41131 | jldominguez | ILabelClass smsLc = new SmartTextSymbolLabelClass();
|
673 | 40911 | jldominguez | SmartTextSymbol sms = new SmartTextSymbol(lc.getTextSymbol(),pc);
|
674 | |||
675 | double sizeBefore = lc.getTextSymbol().getFont().getSize();
|
||
676 | double sizeAfter = SymbolUtils.getCartographicLength(this, |
||
677 | sizeBefore, |
||
678 | viewPort, |
||
679 | 41419 | jjdelcerro | viewPort.getDPI()); |
680 | 40911 | jldominguez | sms.setFontSize(sizeAfter); |
681 | |||
682 | smsLc.setTextSymbol(sms); |
||
683 | geom.transform(viewPort.getAffineTransform()); |
||
684 | smsLc.draw(g, null, geom);
|
||
685 | |||
686 | sms.setFontSize(sizeBefore); |
||
687 | } |
||
688 | return true; |
||
689 | } |
||
690 | } |
||
691 | return false; |
||
692 | } |
||
693 | |||
694 | /**
|
||
695 | * Divide una cadena de caracteres por el caracter dos puntos
|
||
696 | * siempre que no est? entre comillas.
|
||
697 | *
|
||
698 | * @param str
|
||
699 | * Cadena de caracteres
|
||
700 | *
|
||
701 | * @return String[]
|
||
702 | *
|
||
703 | */
|
||
704 | private String[] divideExpression(String str){ |
||
705 | ArrayList<String> r = new ArrayList<String>(); |
||
706 | boolean inQuotationMarks = false; |
||
707 | int lastIndex = 0; |
||
708 | for(int i=0; i<str.length(); i++){ |
||
709 | if(str.substring(i, i+1).compareTo("\"")==0){ |
||
710 | inQuotationMarks = !inQuotationMarks; |
||
711 | continue;
|
||
712 | } |
||
713 | if(str.substring(i, i+1).compareTo(":")==0 && !inQuotationMarks){ |
||
714 | if(lastIndex < i){
|
||
715 | r.add(str.substring(lastIndex, i)); |
||
716 | } |
||
717 | lastIndex = i+1;
|
||
718 | } |
||
719 | } |
||
720 | if(lastIndex < str.length()-1){ |
||
721 | r.add(str.substring(lastIndex)); |
||
722 | } |
||
723 | String[] result = new String[r.size()]; |
||
724 | r.toArray(result); |
||
725 | return result;
|
||
726 | } |
||
727 | |||
728 | /**
|
||
729 | * Compute the texts to show in the label and store them in LabelClass.
|
||
730 | */
|
||
731 | @SuppressWarnings("unchecked") |
||
732 | private boolean setupLabel(Feature featu, ILabelClass lc, |
||
733 | Cancellable cancel, String[] usedFields, ViewPort viewPort, |
||
734 | 41421 | jjdelcerro | double dpi, int duplicateMode){ |
735 | 40911 | jldominguez | |
736 | String expr = lc.getStringLabelExpression();
|
||
737 | |||
738 | long pt1 = System.currentTimeMillis(); |
||
739 | String[] texts = NO_TEXT; |
||
740 | 41421 | jjdelcerro | List<String> preTexts = new ArrayList<String>(); |
741 | 40911 | jldominguez | try {
|
742 | if (expr != null) { |
||
743 | |||
744 | if (expr.equals("")) { |
||
745 | expr = texts[0];
|
||
746 | } |
||
747 | |||
748 | String[] multiexpr = divideExpression(expr); |
||
749 | for (int i=0; i<multiexpr.length; i++) { |
||
750 | |||
751 | expr = multiexpr[i]; |
||
752 | Object res = LabelClassUtils.evaluate(expr, featu.getEvaluatorData());
|
||
753 | if (res != null) { |
||
754 | preTexts.add(res.toString()); |
||
755 | } else {
|
||
756 | 41421 | jjdelcerro | preTexts.add("");
|
757 | 40911 | jldominguez | } |
758 | } |
||
759 | texts = new String[preTexts.size()]; |
||
760 | preTexts.toArray(texts); |
||
761 | 41421 | jjdelcerro | // parseTime += System.currentTimeMillis()-pt1;
|
762 | 40911 | jldominguez | } |
763 | lc.setTexts(texts); |
||
764 | |||
765 | } catch (Exception e) { |
||
766 | 41421 | jjdelcerro | logger.warn("While setting up label", e);
|
767 | 40911 | jldominguez | return false; |
768 | } |
||
769 | return true; |
||
770 | } |
||
771 | |||
772 | private boolean isOverlapping(BufferedImage bi, Geometry lblgeom) { |
||
773 | |||
774 | if (lblgeom==null || lblgeom.getType() == TYPES.NULL) { |
||
775 | return false; |
||
776 | } |
||
777 | |||
778 | Envelope rPixels = lblgeom.getEnvelope(); |
||
779 | int minx = (int) rPixels.getMinimum(0); |
||
780 | int miny = (int) rPixels.getMinimum(1); |
||
781 | int maxx = (int) rPixels.getMaximum(0); |
||
782 | int maxy = (int) rPixels.getMaximum(1); |
||
783 | |||
784 | for (int i = minx; i <= maxx; i++) { |
||
785 | for (int j = miny; j <= maxy; j++) { |
||
786 | |||
787 | if (!lblgeom.contains(i, j)
|
||
788 | // contains seems to don't detect points
|
||
789 | // placed in the rectangle boundaries
|
||
790 | && !lblgeom.intersects(i, j, i, j)) { |
||
791 | continue;
|
||
792 | } |
||
793 | |||
794 | if (i<0 || j<0) { |
||
795 | continue;
|
||
796 | } |
||
797 | |||
798 | if (bi.getWidth()<i+1 || bi.getHeight()<j+1) { |
||
799 | continue;
|
||
800 | } |
||
801 | |||
802 | if (bi.getRGB(i,j)!=0){ |
||
803 | return true; |
||
804 | } |
||
805 | } |
||
806 | } |
||
807 | return false; |
||
808 | } |
||
809 | |||
810 | private boolean isOnePoint(ViewPort viewPort, Geometry geom) { |
||
811 | |||
812 | boolean onePoint = false; |
||
813 | int shapeType = geom.getType();
|
||
814 | |||
815 | if (shapeType != TYPES.POINT && shapeType != TYPES.MULTIPOINT) {
|
||
816 | |||
817 | Envelope env = geom.getEnvelope(); |
||
818 | double dist1Pixel = viewPort.getDist1pixel();
|
||
819 | onePoint = (env.getLength(0) <= dist1Pixel
|
||
820 | && env.getLength(1) <= dist1Pixel);
|
||
821 | } |
||
822 | return onePoint;
|
||
823 | } |
||
824 | |||
825 | |||
826 | public boolean isAllowingOverlap() { |
||
827 | return allowOverlapping;
|
||
828 | } |
||
829 | |||
830 | public void setAllowOverlapping(boolean allowOverlapping) { |
||
831 | this.allowOverlapping = allowOverlapping;
|
||
832 | } |
||
833 | |||
834 | public IPlacementConstraints getPlacementConstraints() {
|
||
835 | if (placementConstraints != null) |
||
836 | return placementConstraints;
|
||
837 | |||
838 | GeometryType gt = null;
|
||
839 | |||
840 | try {
|
||
841 | gt = layer.getGeometryType(); |
||
842 | // force 2d for comparison
|
||
843 | gt = GeometryLocator.getGeometryManager().getGeometryType( |
||
844 | gt.getType(), SUBTYPES.GEOM2D); |
||
845 | } catch (Exception e) { |
||
846 | logger.error("While getting placements constraints.", e);
|
||
847 | return null; |
||
848 | } |
||
849 | |||
850 | if (gt.isTypeOf(TYPES.POINT)
|
||
851 | || gt.isTypeOf(TYPES.MULTIPOINT)) { |
||
852 | return DefaultPointPlacementConstraints;
|
||
853 | } else {
|
||
854 | if (gt.isTypeOf(TYPES.CURVE)
|
||
855 | || gt.isTypeOf(TYPES.MULTICURVE)) { |
||
856 | return DefaultLinePlacementConstraints;
|
||
857 | } else {
|
||
858 | if (gt.isTypeOf(TYPES.SURFACE)
|
||
859 | || gt.isTypeOf(TYPES.MULTISURFACE)) { |
||
860 | return DefaultPolygonPlacementConstraints;
|
||
861 | } else {
|
||
862 | if (gt.isTypeOf(TYPES.AGGREGATE) ||
|
||
863 | gt.isTypeOf(TYPES.GEOMETRY)) { |
||
864 | DefaultMultiShapePlacementConstratints.setPointConstraints(DefaultPointPlacementConstraints); |
||
865 | DefaultMultiShapePlacementConstratints.setLineConstraints(DefaultLinePlacementConstraints); |
||
866 | DefaultMultiShapePlacementConstratints.setPolygonConstraints(DefaultPolygonPlacementConstraints); |
||
867 | return DefaultMultiShapePlacementConstratints;
|
||
868 | } |
||
869 | } |
||
870 | } |
||
871 | } |
||
872 | return null; |
||
873 | } |
||
874 | |||
875 | public void setPlacementConstraints(IPlacementConstraints constraints) { |
||
876 | this.placementConstraints = constraints;
|
||
877 | } |
||
878 | |||
879 | public IZoomConstraints getZoomConstraints() {
|
||
880 | return zoomConstraints;
|
||
881 | } |
||
882 | |||
883 | public void setZoomConstraints(IZoomConstraints constraints) { |
||
884 | this.zoomConstraints = constraints;
|
||
885 | } |
||
886 | |||
887 | public void print( |
||
888 | 41676 | jjdelcerro | Graphics2D g, double scale, ViewPort viewPort, |
889 | 40911 | jldominguez | Cancellable cancel, PrintAttributes properties) |
890 | throws ReadException {
|
||
891 | |||
892 | double dpi = 100; |
||
893 | int pq = properties.getPrintQuality();
|
||
894 | if (pq == PrintAttributes.PRINT_QUALITY_NORMAL){
|
||
895 | dpi = 300;
|
||
896 | } else if (pq == PrintAttributes.PRINT_QUALITY_HIGH){ |
||
897 | dpi = 600;
|
||
898 | } else if (pq == PrintAttributes.PRINT_QUALITY_DRAFT){ |
||
899 | dpi = 72;
|
||
900 | } |
||
901 | |||
902 | viewPort.setOffset(new Point2D.Double(0,0)); |
||
903 | |||
904 | /* signal printing output */
|
||
905 | printMode = true;
|
||
906 | |||
907 | 41676 | jjdelcerro | draw(null,g,scale, viewPort,cancel,dpi);
|
908 | 40911 | jldominguez | } |
909 | |||
910 | public String[] getUsedFields() { |
||
911 | |||
912 | /*
|
||
913 | * TODO Solve the problem with the [ and ].
|
||
914 | * Currently SQLJEP evaluator cannot tell which
|
||
915 | * fields are being used. Options: allow [] and remove them or
|
||
916 | * maybe while parsing the SQLJEP evaluator can inform with events like
|
||
917 | * "I have found a field"
|
||
918 | *
|
||
919 | */
|
||
920 | |||
921 | FeatureAttributeDescriptor[] atts = null; |
||
922 | try {
|
||
923 | atts = layer.getFeatureStore().getDefaultFeatureType().getAttributeDescriptors(); |
||
924 | } catch (DataException e) {
|
||
925 | logger.error("While getting atributes.", e);
|
||
926 | } |
||
927 | |||
928 | int n = atts.length;
|
||
929 | String[] resp = new String[n]; |
||
930 | for (int i=0; i<n; i++) { |
||
931 | resp[i] = atts[i].getName(); |
||
932 | } |
||
933 | return resp;
|
||
934 | |||
935 | /*
|
||
936 | ILabelClass[] lcs = method.getLabelClasses();
|
||
937 | ArrayList<String> fieldNames = new ArrayList<String>();
|
||
938 | for (int i = 0; i < lcs.length; i++) {
|
||
939 | if(lcs[i].getLabelExpressions() != null){
|
||
940 | for (int j = 0; j < lcs[i].getLabelExpressions().length; j++) {
|
||
941 | String expr = lcs[i].getLabelExpressions()[j];
|
||
942 | int start;
|
||
943 | while (expr != null &&
|
||
944 | (start = expr.indexOf("[")) != -1) {
|
||
945 | int end = expr.indexOf("]");
|
||
946 | String field = expr.substring(start+1, end).trim();
|
||
947 | if (!fieldNames.contains(field))
|
||
948 | fieldNames.add(field);
|
||
949 | expr = expr.substring(end+1, expr.length());
|
||
950 | }
|
||
951 | }
|
||
952 | }
|
||
953 | }
|
||
954 | return fieldNames.toArray(new String[fieldNames.size()]);
|
||
955 | */
|
||
956 | } |
||
957 | |||
958 | |||
959 | public boolean shouldDrawLabels(double scale) { |
||
960 | double minScaleView = -1; |
||
961 | double maxScaleView = -1; |
||
962 | |||
963 | if (zoomConstraints != null) { |
||
964 | minScaleView = zoomConstraints.getMinScale(); |
||
965 | maxScaleView = zoomConstraints.getMaxScale(); |
||
966 | } |
||
967 | |||
968 | if (minScaleView == -1 && maxScaleView == -1) { |
||
969 | // parameters not set, so the layer decides.
|
||
970 | return layer.isWithinScale(scale);
|
||
971 | } |
||
972 | |||
973 | if (minScaleView >= scale) {
|
||
974 | return (maxScaleView != -1) ? maxScaleView <= scale : true; |
||
975 | } |
||
976 | |||
977 | return false; |
||
978 | } |
||
979 | |||
980 | public void setUnit(int unitIndex) { |
||
981 | unit = unitIndex; |
||
982 | |||
983 | } |
||
984 | |||
985 | public int getUnit() { |
||
986 | return unit;
|
||
987 | } |
||
988 | |||
989 | public int getReferenceSystem() { |
||
990 | return referenceSystem;
|
||
991 | } |
||
992 | |||
993 | public void setReferenceSystem(int referenceSystem) { |
||
994 | this.referenceSystem = referenceSystem;
|
||
995 | } |
||
996 | |||
997 | public static void registerPersistent() { |
||
998 | |||
999 | PersistenceManager manager = ToolsLocator.getPersistenceManager(); |
||
1000 | if (manager.getDefinition(GENERAL_LABEL_STRATEGY_PERSISTENCE_NAME) == null) { |
||
1001 | DynStruct definition = manager.addDefinition( |
||
1002 | GeneralLabelingStrategy.class, |
||
1003 | GENERAL_LABEL_STRATEGY_PERSISTENCE_NAME, |
||
1004 | GENERAL_LABEL_STRATEGY_PERSISTENCE_NAME+" Persistence definition",
|
||
1005 | null,
|
||
1006 | null);
|
||
1007 | definition.addDynFieldObject("labelingMethod")
|
||
1008 | .setClassOfValue(ILabelingMethod.class).setMandatory(true);
|
||
1009 | definition.addDynFieldObject("placementConstraints")
|
||
1010 | .setClassOfValue(IPlacementConstraints.class).setMandatory(false);
|
||
1011 | definition.addDynFieldObject("zoomConstraints")
|
||
1012 | .setClassOfValue(IZoomConstraints.class).setMandatory(false);
|
||
1013 | |||
1014 | definition.addDynFieldBoolean("allowOverlapping").setMandatory(true); |
||
1015 | definition.addDynFieldInt("unit").setMandatory(true); |
||
1016 | definition.addDynFieldInt("referenceSystem").setMandatory(true); |
||
1017 | } |
||
1018 | } |
||
1019 | |||
1020 | |||
1021 | public void loadFromState(PersistentState state) throws PersistenceException { |
||
1022 | |||
1023 | method = (ILabelingMethod) state.get("labelingMethod");
|
||
1024 | |||
1025 | if (state.hasValue("placementConstraints")) { |
||
1026 | placementConstraints = |
||
1027 | (IPlacementConstraints) state.get("placementConstraints");
|
||
1028 | } |
||
1029 | |||
1030 | if (state.hasValue("zoomConstraints")) { |
||
1031 | zoomConstraints = (IZoomConstraints) state.get("zoomConstraints");
|
||
1032 | } |
||
1033 | |||
1034 | this.allowOverlapping = state.getBoolean("allowOverlapping"); |
||
1035 | this.unit = state.getInt("unit"); |
||
1036 | this.referenceSystem = state.getInt("referenceSystem"); |
||
1037 | } |
||
1038 | |||
1039 | public void saveToState(PersistentState state) throws PersistenceException { |
||
1040 | |||
1041 | state.set("labelingMethod", method);
|
||
1042 | |||
1043 | if (placementConstraints != null) { |
||
1044 | state.set("placementConstraints", placementConstraints);
|
||
1045 | } |
||
1046 | |||
1047 | if (zoomConstraints != null) { |
||
1048 | state.set("zoomConstraints", zoomConstraints);
|
||
1049 | } |
||
1050 | |||
1051 | state.set("allowOverlapping", allowOverlapping);
|
||
1052 | state.set("unit", unit);
|
||
1053 | state.set("referenceSystem", referenceSystem);
|
||
1054 | |||
1055 | } |
||
1056 | |||
1057 | public double toCartographicSize(ViewPort vp, double dpi, Geometry geom) { |
||
1058 | /*
|
||
1059 | * This method is not used but we must implement CartographicSupport
|
||
1060 | */
|
||
1061 | return 0; |
||
1062 | } |
||
1063 | |||
1064 | public void setCartographicSize(double cartographicSize, Geometry geom) { |
||
1065 | /*
|
||
1066 | * This method is not used but we must implement CartographicSupport
|
||
1067 | */
|
||
1068 | } |
||
1069 | |||
1070 | public double getCartographicSize(ViewPort vp, double dpi, Geometry geom) { |
||
1071 | /*
|
||
1072 | * This method is not used but we must implement CartographicSupport
|
||
1073 | */
|
||
1074 | return 0; |
||
1075 | } |
||
1076 | |||
1077 | public Object clone() throws CloneNotSupportedException { |
||
1078 | return LabelClassUtils.clone(this); |
||
1079 | } |
||
1080 | |||
1081 | |||
1082 | } |