Statistics
| Revision:

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 @ 44534

History | View | Annotate | Download (29.2 KB)

1 40911 jldominguez
package org.gvsig.labeling.label;
2
3
import java.awt.Graphics2D;
4
import java.awt.geom.Point2D;
5
import java.awt.image.BufferedImage;
6
import java.util.ArrayList;
7
import java.util.Iterator;
8 41227 jldominguez
import java.util.List;
9 40911 jldominguez
import java.util.TreeMap;
10
import java.util.TreeSet;
11 43510 jjdelcerro
import org.cresques.cts.ICoordTrans;
12 40911 jldominguez
13 42980 fdiaz
import org.slf4j.Logger;
14
import org.slf4j.LoggerFactory;
15
16 40911 jldominguez
import org.gvsig.compat.print.PrintAttributes;
17
import org.gvsig.fmap.dal.exception.DataException;
18
import org.gvsig.fmap.dal.exception.ReadException;
19
import org.gvsig.fmap.dal.feature.Feature;
20
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
21
import org.gvsig.fmap.dal.feature.FeatureSet;
22
import org.gvsig.fmap.geom.Geometry;
23
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
24
import org.gvsig.fmap.geom.Geometry.TYPES;
25
import org.gvsig.fmap.geom.GeometryException;
26
import org.gvsig.fmap.geom.GeometryLocator;
27
import org.gvsig.fmap.geom.GeometryManager;
28 41227 jldominguez
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
29 42555 fdiaz
import org.gvsig.fmap.geom.operation.GeometryOperationException;
30
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
31 40911 jldominguez
import org.gvsig.fmap.geom.primitive.Envelope;
32
import org.gvsig.fmap.geom.primitive.Point;
33
import org.gvsig.fmap.geom.type.GeometryType;
34
import org.gvsig.fmap.mapcontext.ViewPort;
35
import org.gvsig.fmap.mapcontext.layers.FLayer;
36
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
37
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelClass;
38
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingMethod;
39
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy;
40
import org.gvsig.fmap.mapcontext.rendering.legend.styling.IPlacementConstraints;
41
import org.gvsig.fmap.mapcontext.rendering.legend.styling.IZoomConstraints;
42
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
43
import org.gvsig.i18n.Messages;
44
import org.gvsig.labeling.lang.LabelClassUtils;
45
import org.gvsig.labeling.placements.ILabelPlacement;
46
import org.gvsig.labeling.placements.LinePlacementConstraints;
47
import org.gvsig.labeling.placements.MultiShapePlacementConstraints;
48
import org.gvsig.labeling.placements.PlacementManager;
49
import org.gvsig.labeling.placements.PointPlacementConstraints;
50
import org.gvsig.labeling.placements.PolygonPlacementConstraints;
51
import org.gvsig.labeling.placements.RemoveDuplicatesComparator;
52
import org.gvsig.labeling.symbol.SmartTextSymbol;
53
import org.gvsig.labeling.symbol.SymbolUtils;
54
import org.gvsig.symbology.SymbologyLocator;
55
import org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling.LabelLocationMetrics;
56
import org.gvsig.tools.ToolsLocator;
57
import org.gvsig.tools.dispose.DisposableIterator;
58
import org.gvsig.tools.dynobject.DynStruct;
59
import org.gvsig.tools.persistence.PersistenceManager;
60
import org.gvsig.tools.persistence.PersistentState;
61
import org.gvsig.tools.persistence.exception.PersistenceException;
62
import org.gvsig.tools.task.Cancellable;
63 42555 fdiaz
64 44534 omartinez
public class GeneralLabelingStrategy implements IGeneralLabelingStrategy {
65 41789 fdiaz
66
        private static final Logger logger = LoggerFactory
67
                        .getLogger(GeneralLabelingStrategy.class);
68
69
        public static final String GENERAL_LABEL_STRATEGY_PERSISTENCE_NAME = "GENERAL_LABEL_STRATEGY_PERSISTENCE_NAME";
70
71
        public static PointPlacementConstraints DefaultPointPlacementConstraints = new PointPlacementConstraints();
72
        public static LinePlacementConstraints DefaultLinePlacementConstraints = new LinePlacementConstraints();
73
        public static PolygonPlacementConstraints DefaultPolygonPlacementConstraints = new PolygonPlacementConstraints();
74
75 40911 jldominguez
        private static String[] NO_TEXT = { Messages.getText("text_field") };
76 41789 fdiaz
77
        private static MultiShapePlacementConstraints DefaultMultiShapePlacementConstratints = new MultiShapePlacementConstraints();
78
79 40911 jldominguez
        private ILabelingMethod method;
80
        private IPlacementConstraints placementConstraints;
81
        private IZoomConstraints zoomConstraints;
82 41789 fdiaz
83 40911 jldominguez
        private boolean allowOverlapping;
84 41789 fdiaz
85 40911 jldominguez
        protected FLyrVect layer;
86
87 41789 fdiaz
        // private long parseTime;
88 40911 jldominguez
        private int unit;
89
        private int referenceSystem;
90
        // private double sizeAfter;
91 41789 fdiaz
        private boolean printMode = false; /*
92
                                                                                 * indicate whether output is for a
93
                                                                                 * print product (PDF, PS, ...)
94
                                                                                 */
95
96 42980 fdiaz
        private List<Geometry> drawnGeometryLabels;
97
98 40911 jldominguez
        public GeneralLabelingStrategy() {
99 41789 fdiaz
                method = SymbologyLocator.getSymbologyManager()
100
                                .createDefaultLabelingMethod();
101 40911 jldominguez
        }
102
103
        public void setLayer(FLayer layer) {
104
                FLyrVect l = (FLyrVect) layer;
105
                this.layer = l;
106
        }
107
108
        public ILabelingMethod getLabelingMethod() {
109
                return method;
110
        }
111
112
        public void setLabelingMethod(ILabelingMethod method) {
113
                this.method = method;
114
        }
115
116 41789 fdiaz
        private class GeometryItem {
117 40911 jldominguez
                public Geometry geom = null;
118
                public int weigh = 0;
119
                public double savedPerimeter;
120
121 41789 fdiaz
                public GeometryItem(Geometry geom, int weigh) {
122 40911 jldominguez
                        this.geom = geom;
123
                        this.weigh = weigh;
124
                        this.savedPerimeter = 0;
125
                }
126
        }
127 41789 fdiaz
128 42980 fdiaz
    public void draw(BufferedImage mapImage, Graphics2D mapGraphics, double scale, ViewPort viewPort,
129
        Cancellable cancel, double dpi) throws ReadException {
130 40911 jldominguez
131 42980 fdiaz
        drawnGeometryLabels = new ArrayList<Geometry>(1000);
132 41789 fdiaz
133 42980 fdiaz
        int x = (int) viewPort.getOffset().getX();
134
        int y = (int) viewPort.getOffset().getY();
135 40911 jldominguez
136 42980 fdiaz
        // offsets for page generation (PDF, PS, direct printing)
137
        int print_offset_x = x;
138
        int print_offset_y = y;
139
        if (printMode) {
140
            // for printing, we never offset the labels themselves
141
            x = 0;
142
            y = 0;
143
            printMode = false;
144
        }
145 41789 fdiaz
146 42980 fdiaz
        TreeMap<String[], GeometryItem> labelsToPlace = null;
147 40911 jldominguez
148 42980 fdiaz
        String[] usedFields = getUsedFields();
149 40911 jldominguez
150 42980 fdiaz
        int notPlacedCount = 0;
151
        int placedCount = 0;
152 40911 jldominguez
153 42980 fdiaz
        /*
154
         * Get the label placement solvers according the user's settings
155
         */
156
        ILabelPlacement placement = PlacementManager.getPlacement(getPlacementConstraints(), layer.getShapeType());
157 40911 jldominguez
158 42980 fdiaz
        BufferedImage targetBI;
159
        Graphics2D targetGr;
160 40911 jldominguez
161 42980 fdiaz
        /*
162
         * get an ordered set of the LabelClasses up on the label priority
163
         */
164
        ILabelClass[] lcs = method.getLabelClasses();
165
        TreeSet<ILabelClass> ts = new TreeSet<ILabelClass>(new LabelClassComparatorByPriority());
166 40911 jldominguez
167 42980 fdiaz
        for (int i = 0; i < lcs.length; i++)
168
            ts.add(lcs[i]);
169 40911 jldominguez
170 42980 fdiaz
        if (ts.size() == 0)
171
            return;
172 41789 fdiaz
173 42980 fdiaz
        /*
174
         * now we have an ordered set, it is only need to give a pass for each
175
         * label class to render by priorities.
176
         *
177
         * If no priorities were defined, the following loop only executes once
178
         */
179
        for (ILabelClass lc : ts) {
180 41789 fdiaz
181 42980 fdiaz
            if (!lc.isVisible(scale)) {
182
                /*
183
                 * Avoid non-visible labels
184
                 */
185
                continue;
186
            }
187 40911 jldominguez
188 42980 fdiaz
            FeatureSet fset = null;
189
            DisposableIterator diter = null;
190
            try {
191 40911 jldominguez
192 42980 fdiaz
                try {
193
                    fset = method.getFeatureIteratorByLabelClass(layer, lc, viewPort, usedFields);
194
                } catch (DataException e) {
195
                    throw new ReadException(layer.getFeatureStore().getProviderName(), e);
196
                }
197 40911 jldominguez
198 42980 fdiaz
                // duplicates treatment stuff
199
                /* handle the duplicates mode */
200
                int duplicateMode = getDuplicateLabelsMode();
201
                if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) {
202
                    // we need to register the labels already placed
203 40911 jldominguez
204 42980 fdiaz
                    labelsToPlace = new TreeMap<String[], GeometryItem>(new RemoveDuplicatesComparator());
205
                }
206 40911 jldominguez
207 42980 fdiaz
                boolean bLabelsReallocatable = !isAllowingOverlap();
208 41790 fdiaz
209 42980 fdiaz
                BufferedImage overlapDetectImage = null;
210
                Graphics2D overlapDetectGraphics = null;
211
                if (bLabelsReallocatable) {
212
                    int width = viewPort.getImageWidth() + print_offset_x;
213 41790 fdiaz
214 42980 fdiaz
                    if (width < 0) {
215
                        width = 1;
216
                    }
217
                    int height = viewPort.getImageHeight() + print_offset_y;
218
                    if (height < 0) {
219
                        height = 1;
220
                    }
221
                    if (mapImage != null)
222
                        overlapDetectImage =
223
                            new BufferedImage(mapImage.getWidth() + print_offset_x, mapImage.getHeight()
224
                                + print_offset_y, BufferedImage.TYPE_INT_ARGB);
225
                    else
226
                        overlapDetectImage =
227
                            new BufferedImage(viewPort.getImageWidth() + print_offset_x, viewPort.getImageHeight()
228
                                + print_offset_y, BufferedImage.TYPE_INT_ARGB);
229 40911 jldominguez
230 42980 fdiaz
                    overlapDetectGraphics = overlapDetectImage.createGraphics();
231
                    overlapDetectGraphics.setRenderingHints(mapGraphics.getRenderingHints());
232
                }
233
                if (bLabelsReallocatable) {
234
                    targetBI = overlapDetectImage;
235
                    targetGr = overlapDetectGraphics;
236
                    targetGr.translate(-x, -y);
237
                } else {
238
                    targetBI = mapImage;
239
                    targetGr = mapGraphics;
240
                }
241 40911 jldominguez
242 42980 fdiaz
                try {
243
                    diter = fset.fastIterator();
244
                } catch (DataException e) {
245
                    throw new ReadException(layer.getFeatureStore().getProviderName(), e);
246
                }
247
                Feature featu = null;
248
                Geometry geome = null;
249 40911 jldominguez
250 42980 fdiaz
                while (!cancel.isCanceled() && diter.hasNext()) {
251 40911 jldominguez
252 43313 fdiaz
                    featu = ((Feature) diter.next()).getCopy();
253 42980 fdiaz
                    geome = featu.getDefaultGeometry();
254
                    if (geome == null || geome.getType() == Geometry.TYPES.NULL) {
255
                        continue;
256
                    }
257 43510 jjdelcerro
                    ICoordTrans ct = layer.getCoordTrans();
258
                    if( ct!=null ) {
259
                        geome.reProject(ct);
260
                    }
261 42980 fdiaz
                    if (!setupLabel(featu, lc, cancel, usedFields, viewPort, dpi, duplicateMode)) {
262
                        continue;
263
                    }
264 41789 fdiaz
265 42980 fdiaz
                    String[] texts = lc.getTexts();
266 41789 fdiaz
267 42980 fdiaz
                    if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) {
268
                        // check if this text (so label) is already present in
269
                        // the map
270 41789 fdiaz
271 42980 fdiaz
                        GeometryItem item = labelsToPlace.get(texts);
272
                        if (item == null) {
273
                            item = new GeometryItem(geome, 0);
274
                            labelsToPlace.put(texts, item);
275
                        }
276
                        if (item.geom != null) {
277 41789 fdiaz
278 42980 fdiaz
                            notPlacedCount++;
279
                            if (geome.getType() != Geometry.TYPES.POINT) {
280 41789 fdiaz
281 42980 fdiaz
                                Envelope auxBox = geome.getEnvelope();
282
                                double perimeterAux = 2 * (auxBox.getLength(0) + auxBox.getLength(1));
283
                                if (perimeterAux > item.savedPerimeter) {
284
                                    item.geom = geome; // FConverter.jts_to_igeometry(jtsGeom);
285
                                    item.savedPerimeter = perimeterAux;
286
                                }
287
                            } else {
288
                                int weigh = item.weigh;
289 41789 fdiaz
290 42980 fdiaz
                                try {
291
                                    Point pointFromLabel = item.geom.centroid();
292
                                    Point pointGeome = geome.centroid();
293
                                    item.geom =
294
                                        GeometryLocator.getGeometryManager().createPoint(
295
                                            (pointFromLabel.getX() * weigh + pointGeome.getX()) / (weigh + 1),
296
                                            (pointFromLabel.getY() * weigh + pointGeome.getY()) / (weigh + 1),
297
                                            Geometry.SUBTYPES.GEOM2D);
298
                                } catch (Exception ex) {
299
                                    throw new ReadException(layer.getFeatureStore().getProviderName(), ex);
300
                                }
301 40911 jldominguez
302 42980 fdiaz
                            }
303
                        } else {
304
                            item.geom = geome;
305
                        }
306
                        item.weigh++;
307
                    } else {
308
                        // Check if size is a pixel
309
                        if (isOnePoint(viewPort, geome)) {
310
                            continue;
311
                        }
312 41789 fdiaz
313 42980 fdiaz
                        List<Geometry> geome_parts = new ArrayList<Geometry>();
314
                        if (duplicateMode == IPlacementConstraints.ONE_LABEL_PER_FEATURE_PART) {
315
                            geome_parts = getGeometryParts(geome);
316
                        } else {
317
                            geome_parts.add(geome);
318
                        }
319 41789 fdiaz
320 42980 fdiaz
                        try {
321
                            int n = geome_parts.size();
322
                            for (int k = 0; k < n; k++) {
323
                                drawLabelInGeom(targetBI, targetGr, lc, placement, viewPort, geome_parts.get(k),
324
                                    cancel, dpi, bLabelsReallocatable);
325
                            }
326
                        } catch (GeometryException e) {
327
                            throw new ReadException(layer.getFeatureStore().getProviderName(), e);
328
                        }
329 41789 fdiaz
330 42980 fdiaz
                        placedCount++;
331
                    }
332
                }
333 41789 fdiaz
334 42980 fdiaz
                // ======= End iteration in feature set ====================
335 40911 jldominguez
336 42980 fdiaz
                if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) {
337
                    Iterator<String[]> textsIt = labelsToPlace.keySet().iterator();
338
                    while (!cancel.isCanceled() && textsIt.hasNext()) {
339
                        notPlacedCount++;
340
                        String[] texts = textsIt.next();
341 40911 jldominguez
342 42980 fdiaz
                        GeometryItem item = labelsToPlace.get(texts);
343
                        if (item != null) {
344
                            lc.setTexts(texts);
345
                            // Check if size is a pixel
346
                            if (isOnePoint(viewPort, item.geom)) {
347
                                continue;
348
                            }
349 40911 jldominguez
350 42980 fdiaz
                            try {
351
                                drawLabelInGeom(targetBI, targetGr, lc, placement, viewPort, item.geom, cancel, dpi,
352
                                    bLabelsReallocatable);
353
                            } catch (GeometryException e) {
354
                                throw new ReadException(layer.getFeatureStore().getProviderName(), e);
355
                            }
356
                        }
357
                    }
358
                }
359 41790 fdiaz
360 42980 fdiaz
                if (bLabelsReallocatable) {
361
                    targetGr.translate(x, y);
362
                    if (mapImage != null) {
363
                        mapGraphics.drawImage(overlapDetectImage, null, null);
364
                    } else {
365
                        mapGraphics.drawImage(overlapDetectImage, null, null);
366
                    }
367
                }
368 40911 jldominguez
369 42980 fdiaz
            } finally {
370
                if (diter != null) {
371
                    diter.dispose();
372
                }
373
                if (fset != null) {
374
                    fset.dispose();
375
                }
376
            }
377
        } // big iteration
378 41789 fdiaz
379 42980 fdiaz
    }
380
381 41227 jldominguez
        private List<Geometry> getGeometryParts(Geometry ge) {
382
383 41789 fdiaz
                List<Geometry> resp = new ArrayList<Geometry>();
384
                if (ge != null) {
385
                        if (ge instanceof MultiPrimitive) {
386
                                MultiPrimitive mp = (MultiPrimitive) ge;
387
                                int n = mp.getPrimitivesNumber();
388
                                for (int i = 0; i < n; i++) {
389
                                        resp.add(mp.getPrimitiveAt(i));
390
                                }
391
                        } else {
392
                                resp.add(ge);
393
                        }
394
                }
395
                return resp;
396
        }
397 40911 jldominguez
398 41789 fdiaz
        private void drawLabelInGeom(BufferedImage targetBI, Graphics2D targetGr,
399
                        ILabelClass lc, ILabelPlacement placement, ViewPort viewPort,
400
                        Geometry geom, Cancellable cancel, double dpi,
401
                        boolean bLabelsReallocatable) throws GeometryException {
402
403 40911 jldominguez
                lc.toCartographicSize(viewPort, dpi, null);
404
                ArrayList<LabelLocationMetrics> llm = null;
405 41789 fdiaz
                llm = placement.guess(lc, geom, getPlacementConstraints(), 0, cancel,
406
                                viewPort);
407 40911 jldominguez
408
                setReferenceSystem(lc.getReferenceSystem());
409
                setUnit(lc.getUnit());
410
411
                /*
412 41789 fdiaz
                 * search if there is room left by the previous and with more priority
413
                 * labels, then check the current level
414 40911 jldominguez
                 */
415 41789 fdiaz
                lookupAndPlaceLabel(targetBI, targetGr, llm, placement, lc, geom,
416
                                viewPort, cancel, bLabelsReallocatable);
417 40911 jldominguez
418
        }
419
420
        private int getDuplicateLabelsMode() {
421
                if (getPlacementConstraints() == null) {
422
                        return IPlacementConstraints.DefaultDuplicateLabelsMode;
423
                }
424
                return getPlacementConstraints().getDuplicateLabelsMode();
425
        }
426
427
        private boolean lookupAndPlaceLabel(BufferedImage bi, Graphics2D g,
428
                        ArrayList<LabelLocationMetrics> llm, ILabelPlacement placement,
429 41789 fdiaz
                        ILabelClass lc, Geometry geom, ViewPort viewPort,
430 40911 jldominguez
                        Cancellable cancel, boolean bLabelsReallocatable)
431 41789 fdiaz
                        throws GeometryException {
432
433 42980 fdiaz
            GeometryManager gm = GeometryLocator.getGeometryManager();
434 40911 jldominguez
                int i;
435
                for (i = 0; !cancel.isCanceled() && i < llm.size(); i++) {
436
                        LabelLocationMetrics labelMetrics = llm.get(i);
437
438
                        IPlacementConstraints pc = getPlacementConstraints();
439 41789 fdiaz
                        if (pc instanceof MultiShapePlacementConstraints) {
440
                                MultiShapePlacementConstraints mpc = (MultiShapePlacementConstraints) pc;
441
442 40911 jldominguez
                                GeometryType geom_gt = null;
443 41789 fdiaz
444 40911 jldominguez
                                geom_gt = gm.getGeometryType(geom.getType(), SUBTYPES.GEOM2D);
445
446 41789 fdiaz
                                if (geom_gt.getType() == TYPES.POINT
447
                                                || geom_gt.getType() == TYPES.MULTIPOINT) {
448 40911 jldominguez
                                        pc = mpc.getPointConstraints();
449
                                } else {
450 41789 fdiaz
                                        if (geom_gt.isTypeOf(TYPES.CURVE)
451
                                                        || geom_gt.getType() == TYPES.MULTICURVE) {
452 40911 jldominguez
                                                pc = mpc.getLineConstraints();
453
                                        } else {
454 41789 fdiaz
                                                if (geom_gt.isTypeOf(TYPES.SURFACE)
455
                                                                || geom_gt.getType() == TYPES.MULTISURFACE) {
456 40911 jldominguez
                                                        pc = mpc.getPolygonConstraints();
457
                                                }
458
                                        }
459
                                }
460
                        }
461
462
                        /*
463
                         * Ver comentario en el metodo drawLabelInGeom
464
                         */
465
                        if (bLabelsReallocatable) {
466 41789 fdiaz
467 40911 jldominguez
                                Geometry aux_geom = null;
468
                                aux_geom = lc.getShape(labelMetrics);
469 41789 fdiaz
470 40911 jldominguez
                                if (!isOverlapping(bi, aux_geom)) {
471
472 41789 fdiaz
                                        if (!pc.isFollowingLine()) {
473 40911 jldominguez
                                                lc.draw(g, labelMetrics, geom);
474
                                        } else {
475 41789 fdiaz
476 41131 jldominguez
                                                ILabelClass smsLc = new SmartTextSymbolLabelClass();
477 41789 fdiaz
                                                SmartTextSymbol sms = new SmartTextSymbol(
478
                                                                lc.getTextSymbol(), pc);
479 40911 jldominguez
480 41789 fdiaz
                                                double sizeBefore = lc.getTextSymbol().getFont()
481
                                                                .getSize();
482
                                                double sizeAfter = SymbolUtils.getCartographicLength(
483
                                                                this, sizeBefore, viewPort, viewPort.getDPI());
484 40911 jldominguez
                                                sms.setFontSize(sizeAfter);
485
486
                                                smsLc.setTextSymbol(sms);
487
                                                geom.transform(viewPort.getAffineTransform());
488
                                                smsLc.draw(g, null, geom);
489
                                                sms.setFontSize(sizeBefore);
490
491
                                        }
492
                                        return true;
493
                                }
494
                        } else {
495 41789 fdiaz
                                if (!pc.isFollowingLine()) {
496 40911 jldominguez
                                        lc.draw(g, labelMetrics, null);
497 41789 fdiaz
                                } else {
498
                                        ILabelClass smsLc = new SmartTextSymbolLabelClass();
499
                                        SmartTextSymbol sms = new SmartTextSymbol(
500
                                                        lc.getTextSymbol(), pc);
501 40911 jldominguez
502
                                        double sizeBefore = lc.getTextSymbol().getFont().getSize();
503
                                        double sizeAfter = SymbolUtils.getCartographicLength(this,
504 41789 fdiaz
                                                        sizeBefore, viewPort, viewPort.getDPI());
505 40911 jldominguez
                                        sms.setFontSize(sizeAfter);
506
507
                                        smsLc.setTextSymbol(sms);
508
                                        geom.transform(viewPort.getAffineTransform());
509
                                        smsLc.draw(g, null, geom);
510
511
                                        sms.setFontSize(sizeBefore);
512
                                }
513
                                return true;
514
                        }
515
                }
516
                return false;
517
        }
518
519
        /**
520 41789 fdiaz
         * Divide una cadena de caracteres por el caracter dos puntos siempre que no
521
         * est? entre comillas.
522 40911 jldominguez
         *
523
         * @param str
524
         *            Cadena de caracteres
525
         *
526
         * @return String[]
527
         *
528
         */
529 41789 fdiaz
        private String[] divideExpression(String str) {
530 40911 jldominguez
                ArrayList<String> r = new ArrayList<String>();
531
                boolean inQuotationMarks = false;
532
                int lastIndex = 0;
533 41789 fdiaz
                for (int i = 0; i < str.length(); i++) {
534 42171 jbadia
                        String currentChar = str.substring(i, i + 1);
535
                        if (currentChar.compareTo("\"") == 0 ) {
536 40911 jldominguez
                                inQuotationMarks = !inQuotationMarks;
537 42171 jbadia
                                // Si es el cierre de las comillas
538
                                if(!inQuotationMarks){
539
                                        r.add(str.substring(lastIndex, i + 1).replace("\"", "'"));
540
                                        lastIndex = i + 1;
541
                                }
542 40911 jldominguez
                        }
543 42171 jbadia
                        if (currentChar.compareTo(":") == 0
544 41789 fdiaz
                                        && !inQuotationMarks) {
545
                                if (lastIndex < i) {
546 40911 jldominguez
                                        r.add(str.substring(lastIndex, i));
547
                                }
548 41789 fdiaz
                                lastIndex = i + 1;
549 40911 jldominguez
                        }
550
                }
551 41789 fdiaz
                if (lastIndex < str.length() - 1) {
552 40911 jldominguez
                        r.add(str.substring(lastIndex));
553
                }
554
                String[] result = new String[r.size()];
555
                r.toArray(result);
556
                return result;
557
        }
558
559
        /**
560
         * Compute the texts to show in the label and store them in LabelClass.
561
         */
562
        @SuppressWarnings("unchecked")
563
        private boolean setupLabel(Feature featu, ILabelClass lc,
564
                        Cancellable cancel, String[] usedFields, ViewPort viewPort,
565 41789 fdiaz
                        double dpi, int duplicateMode) {
566 40911 jldominguez
567
                String expr = lc.getStringLabelExpression();
568
569
                long pt1 = System.currentTimeMillis();
570
                String[] texts = NO_TEXT;
571 41421 jjdelcerro
                List<String> preTexts = new ArrayList<String>();
572 40911 jldominguez
                try {
573
                        if (expr != null) {
574
575
                                if (expr.equals("")) {
576
                                        expr = texts[0];
577
                                }
578
579
                                String[] multiexpr = divideExpression(expr);
580 41789 fdiaz
                                for (int i = 0; i < multiexpr.length; i++) {
581
582 40911 jldominguez
                                        expr = multiexpr[i];
583 41789 fdiaz
                                        Object res = LabelClassUtils.evaluate(expr,
584
                                                        featu.getEvaluatorData());
585 40911 jldominguez
                                        if (res != null) {
586
                                                preTexts.add(res.toString());
587
                                        } else {
588 41421 jjdelcerro
                                                preTexts.add("");
589 40911 jldominguez
                                        }
590
                                }
591
                                texts = new String[preTexts.size()];
592
                                preTexts.toArray(texts);
593 41789 fdiaz
                                // parseTime += System.currentTimeMillis()-pt1;
594 40911 jldominguez
                        }
595
                        lc.setTexts(texts);
596
597
                } catch (Exception e) {
598 41421 jjdelcerro
                        logger.warn("While setting up label", e);
599 40911 jldominguez
                        return false;
600
                }
601
                return true;
602
        }
603 41789 fdiaz
604 42980 fdiaz
    private boolean isOverlapping(BufferedImage bi, Geometry lblgeom) {
605 41789 fdiaz
606 42980 fdiaz
        for (Iterator iterator = drawnGeometryLabels.iterator(); iterator.hasNext();) {
607
            Geometry drawnGeometry = (Geometry) iterator.next();
608
            try {
609
                if (drawnGeometry.intersects(lblgeom)) {
610 42555 fdiaz
                    return true;
611
                }
612 42980 fdiaz
            } catch (GeometryOperationNotSupportedException | GeometryOperationException e) {
613
                logger.warn("Can't check overlapping geometry");
614 42555 fdiaz
            }
615
        }
616 42980 fdiaz
        drawnGeometryLabels.add(lblgeom);
617
        return false;
618 40911 jldominguez
619 42980 fdiaz
    }
620
621 40911 jldominguez
        private boolean isOnePoint(ViewPort viewPort, Geometry geom) {
622 41789 fdiaz
623 40911 jldominguez
                boolean onePoint = false;
624
                int shapeType = geom.getType();
625 41789 fdiaz
626 40911 jldominguez
                if (shapeType != TYPES.POINT && shapeType != TYPES.MULTIPOINT) {
627
628
                        Envelope env = geom.getEnvelope();
629
                        double dist1Pixel = viewPort.getDist1pixel();
630 41789 fdiaz
                        onePoint = (env.getLength(0) <= dist1Pixel && env.getLength(1) <= dist1Pixel);
631 40911 jldominguez
                }
632
                return onePoint;
633
        }
634
635
        public boolean isAllowingOverlap() {
636
                return allowOverlapping;
637
        }
638
639
        public void setAllowOverlapping(boolean allowOverlapping) {
640
                this.allowOverlapping = allowOverlapping;
641
        }
642
643
        public IPlacementConstraints getPlacementConstraints() {
644
                if (placementConstraints != null)
645
                        return placementConstraints;
646
647
                GeometryType gt = null;
648 41789 fdiaz
649 40911 jldominguez
                try {
650
                        gt = layer.getGeometryType();
651
                        // force 2d for comparison
652
                        gt = GeometryLocator.getGeometryManager().getGeometryType(
653
                                        gt.getType(), SUBTYPES.GEOM2D);
654
                } catch (Exception e) {
655
                        logger.error("While getting placements constraints.", e);
656
                        return null;
657
                }
658 41789 fdiaz
659
                if (gt.isTypeOf(TYPES.POINT) || gt.isTypeOf(TYPES.MULTIPOINT)) {
660 40911 jldominguez
                        return DefaultPointPlacementConstraints;
661
                } else {
662 41789 fdiaz
                        if (gt.isTypeOf(TYPES.CURVE) || gt.isTypeOf(TYPES.MULTICURVE)) {
663 40911 jldominguez
                                return DefaultLinePlacementConstraints;
664
                        } else {
665
                                if (gt.isTypeOf(TYPES.SURFACE)
666
                                                || gt.isTypeOf(TYPES.MULTISURFACE)) {
667
                                        return DefaultPolygonPlacementConstraints;
668
                                } else {
669 41789 fdiaz
                                        if (gt.isTypeOf(TYPES.AGGREGATE)
670
                                                        || gt.isTypeOf(TYPES.GEOMETRY)) {
671
                                                DefaultMultiShapePlacementConstratints
672
                                                                .setPointConstraints(DefaultPointPlacementConstraints);
673
                                                DefaultMultiShapePlacementConstratints
674
                                                                .setLineConstraints(DefaultLinePlacementConstraints);
675
                                                DefaultMultiShapePlacementConstratints
676
                                                                .setPolygonConstraints(DefaultPolygonPlacementConstraints);
677 40911 jldominguez
                                                return DefaultMultiShapePlacementConstratints;
678
                                        }
679
                                }
680
                        }
681
                }
682
                return null;
683
        }
684
685
        public void setPlacementConstraints(IPlacementConstraints constraints) {
686
                this.placementConstraints = constraints;
687
        }
688
689
        public IZoomConstraints getZoomConstraints() {
690
                return zoomConstraints;
691
        }
692
693
        public void setZoomConstraints(IZoomConstraints constraints) {
694
                this.zoomConstraints = constraints;
695
        }
696
697 41789 fdiaz
        public void print(Graphics2D g, double scale, ViewPort viewPort,
698 40911 jldominguez
                        Cancellable cancel, PrintAttributes properties)
699
                        throws ReadException {
700 41789 fdiaz
701 40911 jldominguez
                double dpi = 100;
702
                int pq = properties.getPrintQuality();
703 41789 fdiaz
                if (pq == PrintAttributes.PRINT_QUALITY_NORMAL) {
704 40911 jldominguez
                        dpi = 300;
705 41789 fdiaz
                } else if (pq == PrintAttributes.PRINT_QUALITY_HIGH) {
706 40911 jldominguez
                        dpi = 600;
707 41789 fdiaz
                } else if (pq == PrintAttributes.PRINT_QUALITY_DRAFT) {
708 40911 jldominguez
                        dpi = 72;
709
                }
710
711 41789 fdiaz
                viewPort.setOffset(new Point2D.Double(0, 0));
712
713 40911 jldominguez
                /* signal printing output */
714
                printMode = true;
715
716 41789 fdiaz
                draw(null, g, scale, viewPort, cancel, dpi);
717 40911 jldominguez
        }
718
719
        public String[] getUsedFields() {
720
721
                /*
722 41789 fdiaz
                 * TODO Solve the problem with the [ and ]. Currently SQLJEP evaluator
723
                 * cannot tell which fields are being used. Options: allow [] and remove
724
                 * them or maybe while parsing the SQLJEP evaluator can inform with
725
                 * events like "I have found a field"
726 40911 jldominguez
                 */
727 41789 fdiaz
728 40911 jldominguez
                FeatureAttributeDescriptor[] atts = null;
729
                try {
730 41789 fdiaz
                        atts = layer.getFeatureStore().getDefaultFeatureType()
731
                                        .getAttributeDescriptors();
732 40911 jldominguez
                } catch (DataException e) {
733
                        logger.error("While getting atributes.", e);
734
                }
735 41789 fdiaz
736 40911 jldominguez
                int n = atts.length;
737
                String[] resp = new String[n];
738 41789 fdiaz
                for (int i = 0; i < n; i++) {
739 40911 jldominguez
                        resp[i] = atts[i].getName();
740
                }
741
                return resp;
742
743
        }
744
745
        public boolean shouldDrawLabels(double scale) {
746
                double minScaleView = -1;
747
                double maxScaleView = -1;
748
749
                if (zoomConstraints != null) {
750
                        minScaleView = zoomConstraints.getMinScale();
751
                        maxScaleView = zoomConstraints.getMaxScale();
752
                }
753
754
                if (minScaleView == -1 && maxScaleView == -1) {
755
                        // parameters not set, so the layer decides.
756
                        return layer.isWithinScale(scale);
757
                }
758
759
                if (minScaleView >= scale) {
760
                        return (maxScaleView != -1) ? maxScaleView <= scale : true;
761
                }
762
763
                return false;
764
        }
765
766
        public void setUnit(int unitIndex) {
767
                unit = unitIndex;
768
769
        }
770
771
        public int getUnit() {
772
                return unit;
773
        }
774
775
        public int getReferenceSystem() {
776
                return referenceSystem;
777
        }
778
779
        public void setReferenceSystem(int referenceSystem) {
780
                this.referenceSystem = referenceSystem;
781
        }
782 41789 fdiaz
783 40911 jldominguez
        public static void registerPersistent() {
784 41789 fdiaz
785
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
786
                if (manager.getDefinition(GENERAL_LABEL_STRATEGY_PERSISTENCE_NAME) == null) {
787
                        DynStruct definition = manager.addDefinition(
788
                                        GeneralLabelingStrategy.class,
789
                                        GENERAL_LABEL_STRATEGY_PERSISTENCE_NAME,
790
                                        GENERAL_LABEL_STRATEGY_PERSISTENCE_NAME
791
                                                        + " Persistence definition", null, null);
792
                        definition.addDynFieldObject("labelingMethod")
793
                                        .setClassOfValue(ILabelingMethod.class).setMandatory(true);
794
                        definition.addDynFieldObject("placementConstraints")
795
                                        .setClassOfValue(IPlacementConstraints.class)
796
                                        .setMandatory(false);
797
                        definition.addDynFieldObject("zoomConstraints")
798
                                        .setClassOfValue(IZoomConstraints.class)
799
                                        .setMandatory(false);
800
801
                        definition.addDynFieldBoolean("allowOverlapping")
802
                                        .setMandatory(true);
803
                        definition.addDynFieldInt("unit").setMandatory(true);
804
                        definition.addDynFieldInt("referenceSystem").setMandatory(true);
805
                }
806 40911 jldominguez
        }
807 41789 fdiaz
808
        public void loadFromState(PersistentState state)
809
                        throws PersistenceException {
810
811 40911 jldominguez
                method = (ILabelingMethod) state.get("labelingMethod");
812 41789 fdiaz
813 40911 jldominguez
                if (state.hasValue("placementConstraints")) {
814 41789 fdiaz
                        placementConstraints = (IPlacementConstraints) state
815
                                        .get("placementConstraints");
816 40911 jldominguez
                }
817 41789 fdiaz
818 40911 jldominguez
                if (state.hasValue("zoomConstraints")) {
819
                        zoomConstraints = (IZoomConstraints) state.get("zoomConstraints");
820
                }
821
822
                this.allowOverlapping = state.getBoolean("allowOverlapping");
823
                this.unit = state.getInt("unit");
824
                this.referenceSystem = state.getInt("referenceSystem");
825
        }
826
827
        public void saveToState(PersistentState state) throws PersistenceException {
828 41789 fdiaz
829 40911 jldominguez
                state.set("labelingMethod", method);
830 41789 fdiaz
831 40911 jldominguez
                if (placementConstraints != null) {
832
                        state.set("placementConstraints", placementConstraints);
833
                }
834
835
                if (zoomConstraints != null) {
836
                        state.set("zoomConstraints", zoomConstraints);
837
                }
838
839
                state.set("allowOverlapping", allowOverlapping);
840
                state.set("unit", unit);
841
                state.set("referenceSystem", referenceSystem);
842
843
        }
844
845
        public double toCartographicSize(ViewPort vp, double dpi, Geometry geom) {
846
                /*
847
                 * This method is not used but we must implement CartographicSupport
848
                 */
849
                return 0;
850
        }
851
852
        public void setCartographicSize(double cartographicSize, Geometry geom) {
853
                /*
854
                 * This method is not used but we must implement CartographicSupport
855
                 */
856
        }
857
858
        public double getCartographicSize(ViewPort vp, double dpi, Geometry geom) {
859
                /*
860
                 * This method is not used but we must implement CartographicSupport
861
                 */
862
                return 0;
863
        }
864 41789 fdiaz
865 40911 jldominguez
        public Object clone() throws CloneNotSupportedException {
866
                return LabelClassUtils.clone(this);
867
        }
868
869
}