Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extSymbology / src / org / gvsig / symbology / fmap / labeling / GeneralLabelingStrategy.java @ 23918

History | View | Annotate | Download (20.4 KB)

1 20768 jdominguez
/* 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.symbology.fmap.labeling;
109
110
import java.awt.Graphics2D;
111 23367 vcaballero
import java.awt.geom.NoninvertibleTransformException;
112
import java.awt.geom.PathIterator;
113
import java.awt.geom.Point2D;
114 20768 jdominguez
import java.awt.geom.Rectangle2D;
115
import java.awt.image.BufferedImage;
116
import java.io.CharArrayReader;
117 22516 jvidal
import java.io.StringReader;
118 20768 jdominguez
import java.text.NumberFormat;
119
import java.util.ArrayList;
120 22187 jdominguez
import java.util.Hashtable;
121 20768 jdominguez
import java.util.TreeSet;
122
123
import javax.print.attribute.PrintRequestAttributeSet;
124
125
import org.apache.log4j.Logger;
126
import org.cresques.cts.ICoordTrans;
127
import org.gvsig.symbology.fmap.labeling.parse.LabelExpressionParser;
128
import org.gvsig.symbology.fmap.labeling.parse.ParseException;
129
import org.gvsig.symbology.fmap.labeling.placements.ILabelPlacement;
130 22082 vcaballero
import org.gvsig.symbology.fmap.labeling.placements.LinePlacementConstraints;
131
import org.gvsig.symbology.fmap.labeling.placements.MultiShapePlacementConstraints;
132
import org.gvsig.symbology.fmap.labeling.placements.PointPlacementConstraints;
133
import org.gvsig.symbology.fmap.labeling.placements.PolygonPlacementConstraints;
134 20768 jdominguez
import org.gvsig.symbology.fmap.labeling.placements.RemoveDuplicatesComparator;
135 22187 jdominguez
import org.gvsig.symbology.fmap.rendering.filter.operations.Expression;
136
import org.gvsig.symbology.fmap.rendering.filter.operations.ExpressionException;
137 23367 vcaballero
import org.gvsig.symbology.fmap.symbols.SmartTextSymbol;
138 20768 jdominguez
139
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
140
import com.hardcode.gdbms.engine.values.Value;
141
import com.iver.cit.gvsig.fmap.ViewPort;
142
import com.iver.cit.gvsig.fmap.core.FShape;
143 23367 vcaballero
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
144 20768 jdominguez
import com.iver.cit.gvsig.fmap.core.IFeature;
145
import com.iver.cit.gvsig.fmap.core.IGeometry;
146 23367 vcaballero
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
147
import com.iver.cit.gvsig.fmap.core.symbols.ITextSymbol;
148
import com.iver.cit.gvsig.fmap.core.v02.FConstant;
149 20768 jdominguez
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
150
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
151
import com.iver.cit.gvsig.fmap.layers.FLayer;
152
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
153
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.ILabelingMethod;
154
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.ILabelingStrategy;
155
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.IPlacementConstraints;
156
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.IZoomConstraints;
157
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.LabelClass;
158
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.LabelLocationMetrics;
159
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.LabelingFactory;
160
import com.iver.utiles.XMLEntity;
161
import com.iver.utiles.swing.threads.Cancellable;
162
163
/**
164 22516 jvidal
 *
165 20768 jdominguez
 * GeneralLabelingStrategy.java
166
 *
167 22516 jvidal
 *
168 20768 jdominguez
 * @author jaume dominguez faus - jaume.dominguez@iver.es Jan 4, 2008
169
 *
170
 */
171 20905 jdominguez
public class GeneralLabelingStrategy implements ILabelingStrategy, Cloneable {
172 22082 vcaballero
        public static IPlacementConstraints DefaultPointPlacementConstraints = new PointPlacementConstraints();
173
        public static IPlacementConstraints DefaultLinePlacementConstraints = new LinePlacementConstraints();
174
        public static IPlacementConstraints DefaultPolygonPlacementConstraints = new PolygonPlacementConstraints();
175 22216 jdominguez
        private static String[] NO_TEXT = new String[] { "text " };
176 22082 vcaballero
        private static MultiShapePlacementConstraints DefaultMultiShapePlacementConstratints = new MultiShapePlacementConstraints();
177 20768 jdominguez
        private ILabelingMethod method;
178
        private IPlacementConstraints placementConstraints;
179
        protected FLyrVect layer;
180
        private IZoomConstraints zoomConstraints;
181
        private boolean allowOverlapping;
182 22082 vcaballero
        private long parseTime;
183 22516 jvidal
184 20768 jdominguez
        public void setLayer(FLayer layer) throws ReadDriverException {
185
                FLyrVect l = (FLyrVect) layer;
186
                this.layer = l;
187
        }
188
189
        public ILabelingMethod getLabelingMethod() {
190
                return method;
191
        }
192
193
        public void setLabelingMethod(ILabelingMethod method) {
194
                this.method = method;
195
        }
196
197 22160 vcaballero
        public void draw(BufferedImage mapImage, Graphics2D mapGraphics,
198
        ViewPort viewPort,        Cancellable cancel, double dpi) throws ReadDriverException {
199
200
//                boolean bVisualFXEnabled = false; // if true, the user can see how the labeling is drawing up
201 20768 jdominguez
                TreeSet<?> placedLabels = null;
202 22082 vcaballero
                parseTime =0;
203 20768 jdominguez
                long t1 = System.currentTimeMillis();
204
                String[] usedFields = getUsedFields();
205 22516 jvidal
206 20768 jdominguez
                int notPlacedCount = 0;
207
                int placedCount = 0;
208 22516 jvidal
209 22160 vcaballero
                /*
210
                 * Get the label placement solvers according the user's settings
211
                 */
212 20768 jdominguez
                ILabelPlacement placement = PlacementManager.getPlacement(getPlacementConstraints(), layer.getShapeType());
213
214 22516 jvidal
                /*
215
                 * get an ordered set of the LabelClasses up on the
216 20768 jdominguez
                 * label priority
217
                 */
218
                LabelClass[] lcs = method.getLabelClasses();
219
                TreeSet<LabelClass> ts = new TreeSet<LabelClass>(new LabelClassComparatorByPriority());
220
221
                for (int i = 0; i < lcs.length; i++) ts.add(lcs[i]);
222 22516 jvidal
223 22160 vcaballero
                if (ts.size()==0) return;
224 22516 jvidal
225 22160 vcaballero
//                // -- visual FX stuff
226
//                BufferedImage visualFXim = null;
227
//                Graphics2D visualFXgr = null;
228
//                if (bVisualFXEnabled) {
229
//                        visualFXim = new BufferedImage(mapImage.getWidth(),
230
//                                        mapImage.getHeight(),
231
//                                        BufferedImage.TYPE_INT_ARGB);
232
//                        visualFXgr = visualFXim.createGraphics();
233
//                        visualFXgr.drawImage(mapImage, null, null);
234
//                }
235
//                int drawEach = 300; // (milliseconds)
236
//                long lastTime = System.currentTimeMillis();
237
//                // -- end visual FX stuff
238 22516 jvidal
239
                /*
240 20768 jdominguez
                 * now we have an ordered set, it is only need to give a pass
241
                 * for each label class to render by priorities.
242 22516 jvidal
                 *
243 20768 jdominguez
                 * If no priorities were defined, the following loop only executes
244
                 * once
245
                 */
246
                for (LabelClass lc : ts) {
247
                        IFeatureIterator it =  method.getFeatureIteratorByLabelClass(layer, lc, viewPort, usedFields);
248 22516 jvidal
249
                        // duplicates treatment stuff
250 22160 vcaballero
                        /* handle the duplicates mode */
251
                        int duplicateMode = getDuplicateLabelsMode();
252 20768 jdominguez
                        if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) {
253
                                // we need to register the labels already placed
254 22516 jvidal
                                if (placedLabels == null)
255 20768 jdominguez
                                        placedLabels = new TreeSet<String[]>(
256
                                                        new RemoveDuplicatesComparator());
257
                                else placedLabels.clear();
258
                        }
259 22516 jvidal
260
261 20905 jdominguez
                        boolean bLabelsReallocatable = !isAllowingOverlap();
262 22160 vcaballero
263
                        BufferedImage overlapDetectImage = null;
264
                        Graphics2D overlapDetectGraphics = null;
265 20768 jdominguez
                        if (bLabelsReallocatable) {
266 22160 vcaballero
                                overlapDetectImage = new BufferedImage(
267 22082 vcaballero
                                                mapImage.getWidth(),
268
                                                mapImage.getHeight(),
269 22160 vcaballero
                                                BufferedImage.TYPE_INT_ARGB
270
                                );
271
                                overlapDetectGraphics = overlapDetectImage.createGraphics();
272
                                overlapDetectGraphics.setRenderingHints(mapGraphics.getRenderingHints());
273 20768 jdominguez
                        }
274 22516 jvidal
275 20768 jdominguez
                        while ( !cancel.isCanceled() && it.hasNext()) {
276
                                IFeature feat = it.next();
277
                                IGeometry geom = feat.getGeometry();
278
279
                                if (!setupLabel(feat, lc, cancel, usedFields, viewPort, dpi, duplicateMode, placedLabels))
280
                                        continue;
281 22516 jvidal
282 20768 jdominguez
                                // Check if size is a pixel
283
                                if (isOnePoint(viewPort, geom)) {
284
                                        continue;
285
                                }
286 22516 jvidal
287 23367 vcaballero
288 20768 jdominguez
                                // Calculate the label possible places
289
                                ArrayList<LabelLocationMetrics> llm = placement.guess(
290 22516 jvidal
                                                lc,
291 20768 jdominguez
                                                FConverter.transformToInts(geom, viewPort.getAffineTransform()),
292
                                                getPlacementConstraints(),
293
                                                0,
294
                                                cancel);
295 22516 jvidal
296 23367 vcaballero
297 22160 vcaballero
                                BufferedImage targetBI;
298
                                Graphics2D targetGr;
299
                                if (bLabelsReallocatable) {
300
                                        targetBI = overlapDetectImage;
301
                                        targetGr = overlapDetectGraphics;
302
                                } else {
303
//                                        // -- visual FX stuff
304
//                                        if (bVisualFXEnabled) {
305
//                                                targetBI = visualFXim;
306
//                                                targetGr = visualFXgr;
307
//                                        } else {
308
//                                        // -- end visual FX stuff
309
                                                targetBI = mapImage;
310
                                                targetGr = mapGraphics;
311
//                                        }
312
                                }
313 20768 jdominguez
314 23367 vcaballero
315
316 22516 jvidal
                                /*
317 20768 jdominguez
                                 * search if there is room left by the previous and
318
                                 * with more priority labels, then check the current
319
                                 * level
320
                                 */
321 22516 jvidal
                                if (lookupAndPlaceLabel(targetBI, targetGr, llm,
322 22160 vcaballero
                                        placement, lc, geom, viewPort, cancel,        bLabelsReallocatable)) {
323 20768 jdominguez
                                        placedCount++;
324
                                } else {
325
                                        notPlacedCount++;
326
                                }
327 22516 jvidal
328 22160 vcaballero
//                                // -- visual FX stuff
329
//                                if (bVisualFXEnabled && System.currentTimeMillis() - lastTime > drawEach) {
330
//                                        lastTime = System.currentTimeMillis();
331
//                                        mapGraphics.drawImage(visualFXim, null, null);
332
//                                }
333
//                                // -- end visual FX stuff
334 20768 jdominguez
                        }
335 22516 jvidal
336 22160 vcaballero
                        if (bLabelsReallocatable) {
337
//                                // -- visual FX stuff
338 22516 jvidal
//                                if (bVisualFXEnabled)
339 22160 vcaballero
//                                        visualFXgr.drawImage(overlapDetectImage, null, null);
340 22516 jvidal
//                                else
341 22160 vcaballero
//                                // -- end visual FX stuff
342
                                        mapGraphics.drawImage(overlapDetectImage, null, null);
343
                        }
344 20768 jdominguez
                }
345 22516 jvidal
346 20768 jdominguez
                int total = placedCount+notPlacedCount;
347
348 22082 vcaballero
                double totalTime = (System.currentTimeMillis()-t1);
349 22516 jvidal
350 20905 jdominguez
                if (total>0)
351 22160 vcaballero
                        Logger.getLogger(getClass()).info("Labeled layer '"+layer.getName()+
352
                                        "' "+totalTime/1000D+" seconds. "+placedCount+"/"+total+
353
                                        " labels placed ("+NumberFormat.getInstance().
354
                                        format(100*placedCount/(double) total)+"%)");
355 20768 jdominguez
356 22082 vcaballero
                if (cancel.isCanceled()) {
357 22160 vcaballero
                        Logger.getLogger(getClass()).info("Layer labeling canceled: '"+
358
                                        layer.getName()+"'");
359 22082 vcaballero
                } else {
360 22160 vcaballero
                        Logger.getLogger(getClass()).info("Total labels parse time = "+
361
                                        parseTime+" ("+NumberFormat.getInstance().
362
                                        format(parseTime*100/totalTime)+"%)");
363 22082 vcaballero
                }
364 22516 jvidal
365 22160 vcaballero
//                // -- visual FX stuff
366
//                if (bVisualFXEnabled) {
367
//                        mapGraphics.drawImage(visualFXim, null, null);
368
//                }
369
//                // -- end visual FX stuff
370 20768 jdominguez
        }
371 22516 jvidal
372 20768 jdominguez
        private int getDuplicateLabelsMode() {
373
                if (getPlacementConstraints() == null) {
374
                        return IPlacementConstraints.DefaultDuplicateLabelsMode;
375
                }
376
                return getPlacementConstraints().getDuplicateLabelsMode();
377
        }
378
379 22516 jvidal
        private boolean lookupAndPlaceLabel(BufferedImage bi, Graphics2D g,
380 22082 vcaballero
                        ArrayList<LabelLocationMetrics> llm, ILabelPlacement placement,
381
                        LabelClass lc, IGeometry geom,        ViewPort viewPort,
382
                        Cancellable cancel, boolean bLabelsReallocatable) {
383 20768 jdominguez
                int i;
384
                for (i = 0; !cancel.isCanceled() && i < llm.size(); i++) {
385
                        LabelLocationMetrics labelMetrics = llm.get(i);
386
387
                        if (bLabelsReallocatable) {
388 23367 vcaballero
                                 if (!isOverlapping(bi, lc.getShape(labelMetrics))) {
389
                                        if(!getPlacementConstraints().isFollowingLine()){
390
                                                lc.draw(g, labelMetrics, (FShape) geom.getInternalShape());
391
                                        }
392
                                        else{
393
                                                SmartTextSymbolLabelClass smsLc = new SmartTextSymbolLabelClass();
394
                                                SmartTextSymbol sms = new SmartTextSymbol(lc.getTextSymbol(),getPlacementConstraints());
395
                                                smsLc.setTextSymbol(sms);
396
                                                geom.transform(viewPort.getAffineTransform());
397
                                                smsLc.draw(g, null, (FShape) geom.getInternalShape());
398
399
                                        }
400 22187 jdominguez
                                        return true;
401 22516 jvidal
                                }
402 20768 jdominguez
                        } else {
403 23367 vcaballero
                                if(!getPlacementConstraints().isFollowingLine())
404
                                        lc.draw(g, labelMetrics, null);
405
                                else{
406
                                                SmartTextSymbolLabelClass smsLc = new SmartTextSymbolLabelClass();
407
                                                SmartTextSymbol sms = new SmartTextSymbol(lc.getTextSymbol(),getPlacementConstraints());
408
                                                smsLc.setTextSymbol(sms);
409
                                                geom.transform(viewPort.getAffineTransform());
410
                                                smsLc.draw(g, null, (FShape) geom.getInternalShape());
411
                                        }
412 20768 jdominguez
                                return true;
413
                        }
414 22516 jvidal
                }
415 20768 jdominguez
                return false;
416
        }
417 22516 jvidal
418 20768 jdominguez
        @SuppressWarnings("unchecked")
419 22516 jvidal
        private boolean setupLabel(IFeature feat, LabelClass lc,
420 20768 jdominguez
        Cancellable cancel, String[] usedFields, ViewPort viewPort,
421
        double dpi, int duplicateMode, TreeSet<?> placedLabels) {
422
423
                Value[] vv = feat.getAttributes();
424
                String expr = lc.getLabelExpression();
425 22516 jvidal
426 22187 jdominguez
                long pt1 = System.currentTimeMillis();
427 22216 jdominguez
                String[] texts = NO_TEXT;
428 22187 jdominguez
                try {
429
430 22082 vcaballero
                        for (int i = 0; !cancel.isCanceled() && i < usedFields.length; i++) {
431 22187 jdominguez
                                symbol_table.put(usedFields[i], vv[i]);
432 20768 jdominguez
                        }
433 22516 jvidal
434 22216 jdominguez
                        if (expr != null) {
435 22952 vcaballero
436
                                if(expr.equals(";"))
437
                                        expr = texts[0];
438
439 22216 jdominguez
                                // parse (if it hasn't been parsed yet) and evaluate the expression
440 22516 jvidal
                                Object labelContents = getEvaluator(expr).evaluate();
441 22216 jdominguez
                                if (String[].class.equals(labelContents.getClass())) {
442
                                        texts = (String[]) labelContents;
443
                                } else {
444
                                        texts = new String[] { labelContents.toString() };
445
                                }
446
                                parseTime += System.currentTimeMillis()-pt1;
447 22187 jdominguez
                        }
448
                        if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) {
449
                                // check if this text (so label) is already present in the map
450 22516 jvidal
                                if (placedLabels.contains(texts))
451 22187 jdominguez
                                        // the label has already placed before
452
                                        return false;
453 20768 jdominguez
454 22187 jdominguez
                                /*
455
                                 *  the text is not present, it will be registered for next to
456
                                 *  be avoided
457
                                 */
458
                                ((TreeSet<String[]>) placedLabels).add(texts);
459
                        }
460
                        lc.setTexts(texts);
461
                } catch (ExpressionException e) {
462
                        e.printStackTrace();
463
                        return false;
464 22516 jvidal
                }
465 22082 vcaballero
466 20768 jdominguez
                lc.toCartographicSize(viewPort, dpi, null);
467
                return true;
468
        }
469 22187 jdominguez
        private Hashtable<String, Value> symbol_table = new Hashtable<String, Value>();
470
        private Hashtable<String, Expression> evaluators = new Hashtable<String, Expression>();
471 22516 jvidal
472 22187 jdominguez
        private Expression getEvaluator(String strExpr) {
473
                Expression expr = evaluators.get(strExpr);
474
                if (expr == null) {
475
                        LabelExpressionParser p = new LabelExpressionParser(
476 22516 jvidal
                                        new StringReader(strExpr),symbol_table);
477
478 22187 jdominguez
                        try {
479
                                p.LabelExpression();
480
                        } catch (ParseException e) {
481
                                e.printStackTrace();
482
                        }
483
                        expr = (Expression) p.getStack().pop();
484
                        evaluators.put(strExpr, expr);
485
                }
486
                return expr;
487
        }
488 22516 jvidal
489 20768 jdominguez
        private boolean isOverlapping(BufferedImage bi, FShape labelShape) {
490 22516 jvidal
491 20768 jdominguez
                Rectangle2D rPixels = labelShape.getBounds2D();
492
            for (int i= (int) rPixels.getX(); i<rPixels.getMaxX(); i++){
493
                for (int j= (int) rPixels.getY(); j<rPixels.getMaxY(); j++){
494
                        if (!labelShape.contains(i, j)) {
495
                                continue;
496
                        }
497 22516 jvidal
498 20768 jdominguez
                        if (i<0 || j<0) {
499
                                continue;
500
                        }
501 22516 jvidal
502 20768 jdominguez
                        if (bi.getWidth()<i+1 || bi.getHeight()<j+1) {
503
                                continue;
504
                        }
505 22516 jvidal
506 20768 jdominguez
                    if (bi.getRGB(i,j)!=0){
507
                                return true;
508
                    }
509
                }
510
            }
511
            return false;
512
        }
513 22516 jvidal
514 20768 jdominguez
        private boolean isOnePoint(ViewPort viewPort, IGeometry geom) {
515
                boolean onePoint = false;
516
                int shapeType = geom.getGeometryType();
517
                if (shapeType!=FShape.POINT && shapeType!=FShape.MULTIPOINT) {
518
519
                        Rectangle2D geomBounds = geom.getBounds2D();
520
                        ICoordTrans ct = layer.getCoordTrans();
521
522
                        if (ct!=null) {
523
                                geomBounds = ct.convert(geomBounds);
524
                        }
525
526
                        double dist1Pixel = viewPort.getDist1pixel();
527
                        onePoint = (geomBounds.getWidth() <= dist1Pixel
528
                                        && geomBounds.getHeight() <= dist1Pixel);
529
                }
530
                return onePoint;
531
        }
532
533
        public String getClassName() {
534
                return getClass().getName();
535
        }
536
537
        public XMLEntity getXMLEntity() {
538
                XMLEntity xml = new XMLEntity();
539
                xml.putProperty("className", getClassName());
540 22082 vcaballero
                xml.putProperty("allowsOverlapping", allowOverlapping);
541
//                xml.putProperty("minScaleView", minScaleView);
542
//                xml.putProperty("maxScaleView", maxScaleView);
543 22516 jvidal
544 20768 jdominguez
                if (method!=null) {
545
                        XMLEntity methodEntity = method.getXMLEntity();
546
                        methodEntity.putProperty("id", "LabelingMethod");
547
                        xml.addChild(methodEntity);
548
                }
549 22516 jvidal
550 20768 jdominguez
                if (placementConstraints != null) {
551
                        XMLEntity pcEntity = placementConstraints.getXMLEntity();
552
                        pcEntity.putProperty("id", "PlacementConstraints");
553
                        xml.addChild(pcEntity);
554
                }
555 22516 jvidal
556 20768 jdominguez
                if (zoomConstraints != null) {
557
                        XMLEntity zcEntity = zoomConstraints.getXMLEntity();
558
                        zcEntity.putProperty("id", "ZoomConstraints");
559
                        xml.addChild(zcEntity);
560
                }
561
                return xml;
562
        }
563
564
        public void setXMLEntity(XMLEntity xml) {
565
                XMLEntity aux = xml.firstChild("id", "LabelingMethod");
566
567
                // overlapping mode
568
                if (xml.contains("allowsOverlapping")) {
569
                        allowOverlapping = xml.getBooleanProperty("allowsOverlapping");
570
                }
571 22516 jvidal
572
573 20768 jdominguez
                if (aux != null) {
574
                        method = LabelingFactory.createMethodFromXML(aux);
575
                }
576 22516 jvidal
577 20768 jdominguez
                aux = xml.firstChild("id", "PlacementConstraints");
578
                if (aux != null) {
579
                        placementConstraints = LabelingFactory.createPlacementConstraintsFromXML(aux);
580
                }
581 22516 jvidal
582 20768 jdominguez
                aux = xml.firstChild("id", "ZoomConstraints");
583
                if (aux != null) {
584
                        zoomConstraints = LabelingFactory.createZoomConstraintsFromXML(aux);
585
                }
586
        }
587
588 20905 jdominguez
        public boolean isAllowingOverlap() {
589 20768 jdominguez
                return allowOverlapping;
590
        }
591 22516 jvidal
592 20768 jdominguez
        public void setAllowOverlapping(boolean allowOverlapping) {
593
                this.allowOverlapping = allowOverlapping;
594
        }
595 22516 jvidal
596 20768 jdominguez
        public IPlacementConstraints getPlacementConstraints() {
597 22082 vcaballero
                if (placementConstraints != null)
598
                        return placementConstraints;
599 22516 jvidal
600 22082 vcaballero
                try {
601
                        switch (layer.getShapeType()) {
602
                        case FShape.POINT:
603 22494 fpenarrubia
                        case FShape.MULTIPOINT:
604 22082 vcaballero
                                return DefaultPointPlacementConstraints;
605
                        case FShape.LINE:
606
                                return DefaultLinePlacementConstraints;
607
                        case FShape.POLYGON:
608
                                return DefaultPolygonPlacementConstraints;
609
                        case FShape.MULTI:
610
                                DefaultMultiShapePlacementConstratints.setPointConstraints(DefaultPointPlacementConstraints);
611
                                DefaultMultiShapePlacementConstratints.setLineConstraints(DefaultLinePlacementConstraints);
612
                                DefaultMultiShapePlacementConstratints.setPolygonConstraints(DefaultPolygonPlacementConstraints);
613
                                return DefaultMultiShapePlacementConstratints;
614
                        }
615
616
                } catch (ReadDriverException e) {
617 22516 jvidal
618 22082 vcaballero
                }
619
                return null;
620 20768 jdominguez
        }
621
622
        public void setPlacementConstraints(IPlacementConstraints constraints) {
623
                this.placementConstraints = constraints;
624
        }
625
626
        public IZoomConstraints getZoomConstraints() {
627
                return zoomConstraints;
628
        }
629
630
        public void setZoomConstraints(IZoomConstraints constraints) {
631
                this.zoomConstraints = constraints;
632
        }
633
634
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel, PrintRequestAttributeSet properties) throws ReadDriverException {
635
636
        }
637 22516 jvidal
638 20768 jdominguez
        public String[] getUsedFields() {
639
                LabelClass[] lcs = method.getLabelClasses();
640 22516 jvidal
                ArrayList<String> fieldNames = new ArrayList<String>();
641 20768 jdominguez
                for (int i = 0; i < lcs.length; i++) {
642
                        String expr = lcs[i].getLabelExpression();
643
                        int start;
644 22516 jvidal
                        while (expr != null &&
645 22187 jdominguez
                                  (start = expr.indexOf("[")) != -1) {
646 22516 jvidal
                                int end = expr.indexOf("]");
647 20768 jdominguez
                                String field = expr.substring(start+1, end).trim();
648
                                if (!fieldNames.contains(field))
649
                                        fieldNames.add(field);
650
                                expr = expr.substring(end+1, expr.length());
651
                        }
652
653
                }
654
                return fieldNames.toArray(new String[fieldNames.size()]);
655
        }
656 22516 jvidal
657 20768 jdominguez
        public boolean shouldDrawLabels(double scale) {
658 22082 vcaballero
                double minScaleView = -1;
659
                double maxScaleView = -1;
660 22516 jvidal
661 22082 vcaballero
                if (zoomConstraints != null) {
662
                        minScaleView = zoomConstraints.getMinScale();
663
                        maxScaleView = zoomConstraints.getMaxScale();
664
                }
665 22516 jvidal
666 20768 jdominguez
                if (minScaleView == -1 && maxScaleView == -1) {
667
                        // parameters not set, so the layer decides.
668
                        return layer.isWithinScale(scale);
669
                }
670 22516 jvidal
671 20768 jdominguez
                if (minScaleView <= scale) {
672
                        return (maxScaleView != -1) ? maxScaleView >= scale : true;
673
                }
674 22516 jvidal
675 20768 jdominguez
                return false;
676
        }
677
678
}