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

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