Statistics
| Revision:

root / trunk / extensions / extSymbology / src / org / gvsig / symbology / fmap / labeling / GeneralLabelingStrategy.java @ 24226

History | View | Annotate | Download (23.9 KB)

1
/* 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
import java.awt.geom.NoninvertibleTransformException;
112
import java.awt.geom.PathIterator;
113
import java.awt.geom.Point2D;
114
import java.awt.geom.Rectangle2D;
115
import java.awt.image.BufferedImage;
116
import java.io.CharArrayReader;
117
import java.io.StringReader;
118
import java.text.NumberFormat;
119
import java.util.ArrayList;
120
import java.util.Hashtable;
121
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.AbstractPlacementConstraints;
130
import org.gvsig.symbology.fmap.labeling.placements.ILabelPlacement;
131
import org.gvsig.symbology.fmap.labeling.placements.LinePlacementConstraints;
132
import org.gvsig.symbology.fmap.labeling.placements.MultiShapePlacementConstraints;
133
import org.gvsig.symbology.fmap.labeling.placements.PointPlacementConstraints;
134
import org.gvsig.symbology.fmap.labeling.placements.PolygonPlacementConstraints;
135
import org.gvsig.symbology.fmap.labeling.placements.PolygonPlacementOnCentroid;
136
import org.gvsig.symbology.fmap.labeling.placements.PolygonPlacementParallel;
137
import org.gvsig.symbology.fmap.labeling.placements.RemoveDuplicatesComparator;
138
import org.gvsig.symbology.fmap.rendering.filter.operations.Expression;
139
import org.gvsig.symbology.fmap.rendering.filter.operations.ExpressionException;
140
import org.gvsig.symbology.fmap.symbols.SmartTextSymbol;
141

    
142
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
143
import com.hardcode.gdbms.engine.values.Value;
144
import com.iver.andami.PluginServices;
145
import com.iver.cit.gvsig.fmap.MapContext;
146
import com.iver.cit.gvsig.fmap.ViewPort;
147
import com.iver.cit.gvsig.fmap.core.CartographicSupport;
148
import com.iver.cit.gvsig.fmap.core.CartographicSupportToolkit;
149
import com.iver.cit.gvsig.fmap.core.FShape;
150
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
151
import com.iver.cit.gvsig.fmap.core.IFeature;
152
import com.iver.cit.gvsig.fmap.core.IGeometry;
153
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
154
import com.iver.cit.gvsig.fmap.core.symbols.ITextSymbol;
155
import com.iver.cit.gvsig.fmap.core.v02.FConstant;
156
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
157
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
158
import com.iver.cit.gvsig.fmap.layers.FLayer;
159
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
160
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.ILabelingMethod;
161
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.ILabelingStrategy;
162
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.IPlacementConstraints;
163
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.IZoomConstraints;
164
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.LabelClass;
165
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.LabelLocationMetrics;
166
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.LabelingFactory;
167
import com.iver.utiles.XMLEntity;
168
import com.iver.utiles.swing.threads.Cancellable;
169

    
170
/**
171
 *
172
 * GeneralLabelingStrategy.java
173
 *
174
 *
175
 * @author jaume dominguez faus - jaume.dominguez@iver.es Jan 4, 2008
176
 *
177
 */
178
public class GeneralLabelingStrategy implements ILabelingStrategy, Cloneable,CartographicSupport {
179
        public static IPlacementConstraints DefaultPointPlacementConstraints = new PointPlacementConstraints();
180
        public static IPlacementConstraints DefaultLinePlacementConstraints = new LinePlacementConstraints();
181
        public static IPlacementConstraints DefaultPolygonPlacementConstraints = new PolygonPlacementConstraints();
182
        private static String[] NO_TEXT = {PluginServices.getText(null, "text_field")};
183
        private static MultiShapePlacementConstraints DefaultMultiShapePlacementConstratints = new MultiShapePlacementConstraints();
184
        private ILabelingMethod method;
185
        private IPlacementConstraints placementConstraints;
186
        protected FLyrVect layer;
187
        private IZoomConstraints zoomConstraints;
188
        private boolean allowOverlapping;
189
        private long parseTime;
190
        private int unit;
191
        private int referenceSystem;
192

    
193
        public void setLayer(FLayer layer) throws ReadDriverException {
194
                FLyrVect l = (FLyrVect) layer;
195
                this.layer = l;
196
        }
197

    
198
        public ILabelingMethod getLabelingMethod() {
199
                return method;
200
        }
201

    
202
        public void setLabelingMethod(ILabelingMethod method) {
203
                this.method = method;
204
        }
205

    
206
        public void draw(BufferedImage mapImage, Graphics2D mapGraphics,
207
                        ViewPort viewPort,        Cancellable cancel, double dpi) throws ReadDriverException {
208

    
209
//                boolean bVisualFXEnabled = false; // if true, the user can see how the labeling is drawing up
210
                TreeSet<?> placedLabels = null;
211
                parseTime =0;
212
                long t1 = System.currentTimeMillis();
213
                String[] usedFields = getUsedFields();
214

    
215
                int notPlacedCount = 0;
216
                int placedCount = 0;
217

    
218
                /*
219
                 * Get the label placement solvers according the user's settings
220
                 */
221
                ILabelPlacement placement = PlacementManager.getPlacement(getPlacementConstraints(), layer.getShapeType());
222

    
223
                /*
224
                 * get an ordered set of the LabelClasses up on the
225
                 * label priority
226
                 */
227
                LabelClass[] lcs = method.getLabelClasses();
228
                TreeSet<LabelClass> ts = new TreeSet<LabelClass>(new LabelClassComparatorByPriority());
229

    
230
                for (int i = 0; i < lcs.length; i++) ts.add(lcs[i]);
231

    
232
                if (ts.size()==0) return;
233

    
234
//                // -- visual FX stuff
235
//                BufferedImage visualFXim = null;
236
//                Graphics2D visualFXgr = null;
237
//                if (bVisualFXEnabled) {
238
//                visualFXim = new BufferedImage(mapImage.getWidth(),
239
//                mapImage.getHeight(),
240
//                BufferedImage.TYPE_INT_ARGB);
241
//                visualFXgr = visualFXim.createGraphics();
242
//                visualFXgr.drawImage(mapImage, null, null);
243
//                }
244
//                int drawEach = 300; // (milliseconds)
245
//                long lastTime = System.currentTimeMillis();
246
//                // -- end visual FX stuff
247

    
248
                /*
249
                 * now we have an ordered set, it is only need to give a pass
250
                 * for each label class to render by priorities.
251
                 *
252
                 * If no priorities were defined, the following loop only executes
253
                 * once
254
                 */
255
                for (LabelClass lc : ts) {
256
                        IFeatureIterator it =  method.getFeatureIteratorByLabelClass(layer, lc, viewPort, usedFields);
257

    
258
                        // duplicates treatment stuff
259
                        /* handle the duplicates mode */
260
                        int duplicateMode = getDuplicateLabelsMode();
261
                        if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) {
262
                                // we need to register the labels already placed
263
                                if (placedLabels == null)
264
                                        placedLabels = new TreeSet<String[]>(
265
                                                        new RemoveDuplicatesComparator());
266
                                        else placedLabels.clear();
267
                        }
268

    
269

    
270
                        boolean bLabelsReallocatable = !isAllowingOverlap();
271

    
272
                        BufferedImage overlapDetectImage = null;
273
                        Graphics2D overlapDetectGraphics = null;
274
                        if (bLabelsReallocatable) {
275
                                overlapDetectImage = new BufferedImage(
276
                                                mapImage.getWidth()+(int)viewPort.getOffset().getX(),
277
                                                mapImage.getHeight()+(int)viewPort.getOffset().getY(),
278
                                                BufferedImage.TYPE_INT_ARGB
279
                                );
280
                                overlapDetectGraphics = overlapDetectImage.createGraphics();
281
                                overlapDetectGraphics.setRenderingHints(mapGraphics.getRenderingHints());
282
                        }
283

    
284
                        while ( !cancel.isCanceled() && it.hasNext()) {
285
                                IFeature feat = it.next();
286
                                IGeometry geom = feat.getGeometry();
287

    
288
                                if (!setupLabel(feat, lc, cancel, usedFields, viewPort, dpi, duplicateMode, placedLabels))
289
                                        continue;
290

    
291
                                // Check if size is a pixel
292
                                if (isOnePoint(viewPort, geom)) {
293
                                        continue;
294
                                }
295

    
296
                                ArrayList<LabelLocationMetrics> llm = null;
297
                                // Calculate the label possible places
298
//                                if (placement instanceof PolygonPlacementOnCentroid){
299
//                                llm = ((PolygonPlacementOnCentroid)placement).guess(
300
//                                lc,
301
//                                (FShape)geom.getInternalShape(),
302
//                                getPlacementConstraints(),
303
//                                0,
304
//                                cancel,viewPort);
305
//                                }else if(placement instanceof PolygonPlacementParallel){
306
//                                llm = ((PolygonPlacementParallel)placement).guess(
307
//                                lc,
308
//                                (FShape)geom.getInternalShape(),
309
//                                getPlacementConstraints(),
310
//                                0,
311
//                                cancel,viewPort);
312
//                                }else{
313
//                                llm = placement.guess(
314
//                                lc,
315
//                                FConverter.transformToInts(geom, viewPort.getAffineTransform()),
316
//                                getPlacementConstraints(),
317
//                                0,
318
//                                cancel);
319
//                                }
320

    
321

    
322

    
323

    
324

    
325
                                llm = placement.guess(
326
                                                lc,
327
                                                geom,
328
                                                getPlacementConstraints(),
329
                                                0,
330
                                                cancel,viewPort);
331

    
332
                                BufferedImage targetBI;
333
                                Graphics2D targetGr;
334
                                if (bLabelsReallocatable) {
335
                                        targetBI = overlapDetectImage;
336
                                        targetGr = overlapDetectGraphics;
337
                                } else {
338
//                                        // -- visual FX stuff
339
//                                        if (bVisualFXEnabled) {
340
//                                        targetBI = visualFXim;
341
//                                        targetGr = visualFXgr;
342
//                                        } else {
343
//                                        // -- end visual FX stuff
344
                                        targetBI = mapImage;
345
                                        targetGr = mapGraphics;
346
//                                        }
347
                                }
348

    
349

    
350

    
351
                                setReferenceSystem(lc.getReferenceSystem());
352
                                setUnit(lc.getUnit());
353

    
354
                                double sizeBefore = lc.getTextSymbol().getFont().getSize();
355

    
356

    
357
                                double sizeAfter = CartographicSupportToolkit.getCartographicLength(this,
358
                                                sizeBefore,
359
                                                viewPort,
360
                                                MapContext.getScreenDPI());
361

    
362
                                lc.getTextSymbol().setFontSize(sizeAfter * FConstant.FONT_HEIGHT_SCALE_FACTOR);
363

    
364

    
365
                                /*
366
                                 * search if there is room left by the previous and
367
                                 * with more priority labels, then check the current
368
                                 * level
369
                                 */
370
                                if (lookupAndPlaceLabel(targetBI, targetGr, llm,
371
                                                placement, lc, geom, viewPort, cancel,        bLabelsReallocatable)) {
372
                                        placedCount++;
373
                                } else {
374
                                        notPlacedCount++;
375
                                }
376

    
377
                                lc.getTextSymbol().setFontSize(sizeBefore);
378

    
379
//                                // -- visual FX stuff
380
//                                if (bVisualFXEnabled && System.currentTimeMillis() - lastTime > drawEach) {
381
//                                lastTime = System.currentTimeMillis();
382
//                                mapGraphics.drawImage(visualFXim, null, null);
383
//                                }
384
//                                // -- end visual FX stuff
385
                        }
386

    
387
                        if (bLabelsReallocatable) {
388
//                                // -- visual FX stuff
389
//                                if (bVisualFXEnabled)
390
//                                visualFXgr.drawImage(overlapDetectImage, null, null);
391
//                                else
392
//                                // -- end visual FX stuff
393
                                mapGraphics.drawImage(overlapDetectImage, null, null);
394
                        }
395
                }
396

    
397
                int total = placedCount+notPlacedCount;
398

    
399
                double totalTime = (System.currentTimeMillis()-t1);
400

    
401
                if (total>0)
402
                        Logger.getLogger(getClass()).info("Labeled layer '"+layer.getName()+
403
                                        "' "+totalTime/1000D+" seconds. "+placedCount+"/"+total+
404
                                        " labels placed ("+NumberFormat.getInstance().
405
                                        format(100*placedCount/(double) total)+"%)");
406

    
407
                if (cancel.isCanceled()) {
408
                        Logger.getLogger(getClass()).info("Layer labeling canceled: '"+
409
                                        layer.getName()+"'");
410
                } else {
411
                        Logger.getLogger(getClass()).info("Total labels parse time = "+
412
                                        parseTime+" ("+NumberFormat.getInstance().
413
                                        format(parseTime*100/totalTime)+"%)");
414
                }
415

    
416
//                // -- visual FX stuff
417
//                if (bVisualFXEnabled) {
418
//                mapGraphics.drawImage(visualFXim, null, null);
419
//                }
420
//                // -- end visual FX stuff
421
        }
422

    
423
        private int getDuplicateLabelsMode() {
424
                if (getPlacementConstraints() == null) {
425
                        return IPlacementConstraints.DefaultDuplicateLabelsMode;
426
                }
427
                return getPlacementConstraints().getDuplicateLabelsMode();
428
        }
429

    
430
        private boolean lookupAndPlaceLabel(BufferedImage bi, Graphics2D g,
431
                        ArrayList<LabelLocationMetrics> llm, ILabelPlacement placement,
432
                        LabelClass lc, IGeometry geom,        ViewPort viewPort,
433
                        Cancellable cancel, boolean bLabelsReallocatable) {
434
                int i;
435

    
436
                for (i = 0; !cancel.isCanceled() && i < llm.size(); i++) {
437
                        LabelLocationMetrics labelMetrics = llm.get(i);
438

    
439
                        if (bLabelsReallocatable) {
440
                                if (!isOverlapping(bi, lc.getShape(labelMetrics))) {
441
                                        if(!getPlacementConstraints().isFollowingLine()){
442
                                                lc.draw(g, labelMetrics, (FShape) geom.getInternalShape());
443
                                        }
444
                                        else{
445
                                                SmartTextSymbolLabelClass smsLc = new SmartTextSymbolLabelClass();
446
                                                SmartTextSymbol sms = new SmartTextSymbol(lc.getTextSymbol(),getPlacementConstraints());
447
                                                smsLc.setTextSymbol(sms);
448
                                                geom.transform(viewPort.getAffineTransform());
449
                                                smsLc.draw(g, null, (FShape) geom.getInternalShape());
450

    
451
                                        }
452
                                        return true;
453
                                }
454
                        } else {
455
                                if(!getPlacementConstraints().isFollowingLine())
456
                                        lc.draw(g, labelMetrics, null);
457
                                else{
458
                                        SmartTextSymbolLabelClass smsLc = new SmartTextSymbolLabelClass();
459
                                        SmartTextSymbol sms = new SmartTextSymbol(lc.getTextSymbol(),getPlacementConstraints());
460
                                        smsLc.setTextSymbol(sms);
461
                                        geom.transform(viewPort.getAffineTransform());
462
                                        smsLc.draw(g, null, (FShape) geom.getInternalShape());
463
                                }
464
                                return true;
465
                        }
466
                }
467
                return false;
468
        }
469

    
470
        @SuppressWarnings("unchecked")
471
        private boolean setupLabel(IFeature feat, LabelClass lc,
472
                        Cancellable cancel, String[] usedFields, ViewPort viewPort,
473
                        double dpi, int duplicateMode, TreeSet<?> placedLabels) {
474

    
475
                Value[] vv = feat.getAttributes();
476
                String expr = lc.getStringLabelExpression();
477

    
478
                long pt1 = System.currentTimeMillis();
479
                String[] texts = NO_TEXT;
480
//                String[] texts = {PluginServices.getText(this, "text_field")};
481
                try {
482

    
483
                        for (int i = 0; !cancel.isCanceled() && i < usedFields.length; i++) {
484
                                try {
485
                                        int index = layer.getSource().getRecordset().getFieldIndexByName(usedFields[i]);
486
                                        if(index != -1)
487
                                                symbol_table.put(usedFields[i], feat.getAttribute(index));
488
                                } catch (ReadDriverException e) {
489
                                        // TODO Auto-generated catch block
490
                                        e.printStackTrace();
491
                                }
492
                        }
493

    
494
                        if (expr != null) {
495

    
496
                                if(expr.equals("") || expr.equals(LabelExpressionParser.tokenFor(LabelExpressionParser.EOEXPR)))
497
                                        expr = texts[0];
498

    
499
                                // parse (if it hasn't been parsed yet) and evaluate the expression
500
                                Object labelContents = getEvaluator(expr).evaluate();
501
                                if (String[].class.equals(labelContents.getClass())) {
502
                                        texts = (String[]) labelContents;
503
                                } else {
504
                                        texts = new String[] { labelContents.toString() };
505
                                }
506
                                parseTime += System.currentTimeMillis()-pt1;
507
                        }
508
                        if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) {
509
                                // check if this text (so label) is already present in the map
510
                                if (placedLabels.contains(texts))
511
                                        // the label has already placed before
512
                                        return false;
513

    
514
                                /*
515
                                 *  the text is not present, it will be registered for next to
516
                                 *  be avoided
517
                                 */
518
                                ((TreeSet<String[]>) placedLabels).add(texts);
519
                        }
520
                        lc.setTexts(texts);
521

    
522
                } catch (ExpressionException e) {
523
                        e.printStackTrace();
524
                        return false;
525
                }
526

    
527
                lc.toCartographicSize(viewPort, dpi, null);
528
                return true;
529
        }
530
        private Hashtable<String, Value> symbol_table = new Hashtable<String, Value>();
531
        private Hashtable<String, Expression> evaluators = new Hashtable<String, Expression>();
532

    
533
        private Expression getEvaluator(String strExpr) {
534
                Expression expr = evaluators.get(strExpr);
535
                if (expr == null) {
536
                        LabelExpressionParser p = new LabelExpressionParser(
537
                                        new StringReader(strExpr),symbol_table);
538

    
539
                        try {
540
                                p.LabelExpression();
541
                        } catch (ParseException e) {
542
                                e.printStackTrace();
543
                        }
544
                        expr = (Expression) p.getStack().pop();
545
                        evaluators.put(strExpr, expr);
546
                }
547
                return expr;
548
        }
549

    
550
        private boolean isOverlapping(BufferedImage bi, FShape labelShape) {
551

    
552
                Rectangle2D rPixels = labelShape.getBounds2D();
553
                for (int i= (int) rPixels.getX(); i<rPixels.getMaxX(); i++){
554
                        for (int j= (int) rPixels.getY(); j<rPixels.getMaxY(); j++){
555
                                if (!labelShape.contains(i, j)) {
556
                                        continue;
557
                                }
558

    
559
                                if (i<0 || j<0) {
560
                                        continue;
561
                                }
562

    
563
                                if (bi.getWidth()<i+1 || bi.getHeight()<j+1) {
564
                                        continue;
565
                                }
566

    
567
                                if (bi.getRGB(i,j)!=0){
568
                                        return true;
569
                                }
570
                        }
571
                }
572
                return false;
573
        }
574

    
575
        private boolean isOnePoint(ViewPort viewPort, IGeometry geom) {
576
                boolean onePoint = false;
577
                int shapeType = geom.getGeometryType();
578
                if (shapeType!=FShape.POINT && shapeType!=FShape.MULTIPOINT) {
579

    
580
                        Rectangle2D geomBounds = geom.getBounds2D();
581
                        ICoordTrans ct = layer.getCoordTrans();
582

    
583
                        if (ct!=null) {
584
                                geomBounds = ct.convert(geomBounds);
585
                        }
586

    
587
                        double dist1Pixel = viewPort.getDist1pixel();
588
                        onePoint = (geomBounds.getWidth() <= dist1Pixel
589
                                        && geomBounds.getHeight() <= dist1Pixel);
590
                }
591
                return onePoint;
592
        }
593

    
594
        public String getClassName() {
595
                return getClass().getName();
596
        }
597

    
598
        public XMLEntity getXMLEntity() {
599
                XMLEntity xml = new XMLEntity();
600
                xml.putProperty("className", getClassName());
601
                xml.putProperty("allowsOverlapping", allowOverlapping);
602
//                xml.putProperty("minScaleView", minScaleView);
603
//                xml.putProperty("maxScaleView", maxScaleView);
604

    
605
                if (method!=null) {
606
                        XMLEntity methodEntity = method.getXMLEntity();
607
                        methodEntity.putProperty("id", "LabelingMethod");
608
                        xml.addChild(methodEntity);
609
                }
610

    
611
                if (placementConstraints != null) {
612
                        XMLEntity pcEntity = placementConstraints.getXMLEntity();
613
                        pcEntity.putProperty("id", "PlacementConstraints");
614
                        xml.addChild(pcEntity);
615
                }
616

    
617
                if (zoomConstraints != null) {
618
                        XMLEntity zcEntity = zoomConstraints.getXMLEntity();
619
                        zcEntity.putProperty("id", "ZoomConstraints");
620
                        xml.addChild(zcEntity);
621
                }
622
                return xml;
623
        }
624

    
625
        public void setXMLEntity(XMLEntity xml) {
626
                XMLEntity aux = xml.firstChild("id", "LabelingMethod");
627

    
628
                // overlapping mode
629
                if (xml.contains("allowsOverlapping")) {
630
                        allowOverlapping = xml.getBooleanProperty("allowsOverlapping");
631
                }
632

    
633

    
634
                if (aux != null) {
635
                        method = LabelingFactory.createMethodFromXML(aux);
636
                }
637

    
638
                aux = xml.firstChild("id", "PlacementConstraints");
639
                if (aux != null) {
640
                        placementConstraints = LabelingFactory.createPlacementConstraintsFromXML(aux);
641
                }
642

    
643
                aux = xml.firstChild("id", "ZoomConstraints");
644
                if (aux != null) {
645
                        zoomConstraints = LabelingFactory.createZoomConstraintsFromXML(aux);
646
                }
647
        }
648

    
649
        public boolean isAllowingOverlap() {
650
                return allowOverlapping;
651
        }
652

    
653
        public void setAllowOverlapping(boolean allowOverlapping) {
654
                this.allowOverlapping = allowOverlapping;
655
        }
656

    
657
        public IPlacementConstraints getPlacementConstraints() {
658
                if (placementConstraints != null)
659
                        return placementConstraints;
660

    
661
                try {
662
                        switch (layer.getShapeType()) {
663
                        case FShape.POINT:
664
                        case FShape.MULTIPOINT:
665
                                return DefaultPointPlacementConstraints;
666
                        case FShape.LINE:
667
                                return DefaultLinePlacementConstraints;
668
                        case FShape.POLYGON:
669
                                return DefaultPolygonPlacementConstraints;
670
                        case FShape.MULTI:
671
                                DefaultMultiShapePlacementConstratints.setPointConstraints(DefaultPointPlacementConstraints);
672
                                DefaultMultiShapePlacementConstratints.setLineConstraints(DefaultLinePlacementConstraints);
673
                                DefaultMultiShapePlacementConstratints.setPolygonConstraints(DefaultPolygonPlacementConstraints);
674
                                return DefaultMultiShapePlacementConstratints;
675
                        }
676

    
677
                } catch (ReadDriverException e) {
678

    
679
                }
680
                return null;
681
        }
682

    
683
        public void setPlacementConstraints(IPlacementConstraints constraints) {
684
                this.placementConstraints = constraints;
685
        }
686

    
687
        public IZoomConstraints getZoomConstraints() {
688
                return zoomConstraints;
689
        }
690

    
691
        public void setZoomConstraints(IZoomConstraints constraints) {
692
                this.zoomConstraints = constraints;
693
        }
694

    
695
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel, PrintRequestAttributeSet properties) throws ReadDriverException {
696

    
697
        }
698

    
699
        public String[] getUsedFields() {
700
                LabelClass[] lcs = method.getLabelClasses();
701
                ArrayList<String> fieldNames = new ArrayList<String>();
702
                for (int i = 0; i < lcs.length; i++) {
703
                        if(lcs[i].getLabelExpressions() != null){
704
                                for (int j = 0; j < lcs[i].getLabelExpressions().length; j++) {
705
                                        String expr = lcs[i].getLabelExpressions()[j];
706
                                        int start;
707
                                        while (expr != null &&
708
                                                        (start = expr.indexOf("[")) != -1) {
709
                                                int end = expr.indexOf("]");
710
                                                String field = expr.substring(start+1, end).trim();
711
                                                if (!fieldNames.contains(field))
712
                                                        fieldNames.add(field);
713
                                                expr = expr.substring(end+1, expr.length());
714
                                        }
715
                                }
716
                        }
717
                }
718
                return fieldNames.toArray(new String[fieldNames.size()]);
719
        }
720

    
721

    
722
        public boolean shouldDrawLabels(double scale) {
723
                double minScaleView = -1;
724
                double maxScaleView = -1;
725

    
726
                if (zoomConstraints != null) {
727
                        minScaleView = zoomConstraints.getMinScale();
728
                        maxScaleView = zoomConstraints.getMaxScale();
729
                }
730

    
731
                if (minScaleView == -1 && maxScaleView == -1) {
732
                        // parameters not set, so the layer decides.
733
                        return layer.isWithinScale(scale);
734
                }
735

    
736
                if (minScaleView <= scale) {
737
                        return (maxScaleView != -1) ? maxScaleView >= scale : true;
738
                }
739

    
740
                return false;
741
        }
742

    
743
        public void setUnit(int unitIndex) {
744
                unit = unitIndex;
745

    
746
        }
747

    
748
        public int getUnit() {
749
                return unit;
750
        }
751

    
752
        public int getReferenceSystem() {
753
                return referenceSystem;
754
        }
755

    
756
        public void setReferenceSystem(int referenceSystem) {
757
                this.referenceSystem = referenceSystem;
758
        }
759

    
760
        public double toCartographicSize(ViewPort viewPort, double dpi, FShape shp) {
761
                // TODO Auto-generated method stub
762
                return 0;
763
        }
764

    
765
        public void setCartographicSize(double cartographicSize, FShape shp) {
766
                // TODO Auto-generated method stub
767

    
768
        }
769

    
770
        public double getCartographicSize(ViewPort viewPort, double dpi, FShape shp) {
771
                // TODO Auto-generated method stub
772
                return 0;
773
        }
774

    
775
}