Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.symbology / org.gvsig.symbology.lib / org.gvsig.symbology.lib.impl / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / symbol / marker / impl / AbstractMarkerSymbol.java @ 45529

History | View | Annotate | Download (20.4 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl;
25

    
26
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol_v2;
27
import java.awt.Color;
28
import java.awt.Graphics2D;
29
import java.awt.Point;
30
import java.awt.Rectangle;
31
import java.awt.geom.AffineTransform;
32
import java.awt.geom.Point2D;
33
import org.apache.commons.lang3.StringUtils;
34
import org.gvsig.compat.print.PrintAttributes;
35
import org.gvsig.expressionevaluator.ExpressionUtils;
36
import org.gvsig.expressionevaluator.SymbolTable;
37
import org.gvsig.fmap.dal.DALLocator;
38
import org.gvsig.fmap.dal.expressionevaluator.FeatureSymbolTable;
39
import org.gvsig.fmap.dal.feature.Feature;
40
import org.gvsig.fmap.geom.Geometry;
41
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
42
import org.gvsig.fmap.geom.Geometry.TYPES;
43
import org.gvsig.fmap.geom.GeometryLocator;
44
import org.gvsig.fmap.geom.GeometryManager;
45
import org.gvsig.fmap.geom.exception.CreateGeometryException;
46
import org.gvsig.fmap.mapcontext.MapContextLocator;
47
import org.gvsig.fmap.mapcontext.ViewPort;
48
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
49
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.AbstractSymbol;
50
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit;
51
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.IMask;
52
import org.gvsig.tools.ToolsLocator;
53
import org.gvsig.tools.dynobject.DynStruct;
54
import org.gvsig.tools.persistence.PersistenceManager;
55
import org.gvsig.tools.persistence.PersistentState;
56
import org.gvsig.tools.persistence.exception.PersistenceException;
57
import org.gvsig.tools.util.Callable;
58

    
59
/**
60
 * Abstract class that any MARKER SYMBOL should extend.
61
 *
62
 * @author gvSIG team
63
 */
64
@SuppressWarnings("UseSpecificCatch")
65
public abstract class AbstractMarkerSymbol extends AbstractSymbol implements IMarkerSymbol_v2 {
66

    
67
    public static final String MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME = "MarkerSymbol";
68

    
69
    private static final String FIELD_COLOR = "color";
70
    private static final String FIELD_ROTATION = "rotation";
71
    private static final String FIELD_OFFSET = "offset";
72
    private static final String FIELD_SIZE = "size";
73
    private static final String FIELD_MASK = "mask";
74
    private static final String FIELD_LINETOOFFSETCOLOR = "lineToOffsetColor";
75
    private static final String FIELD_DRAWLINETOOFFSET = "drawLineToOffset";
76
    private static final String FIELD_SIZE_EXPRESSION = "sizeExpression";
77
    private static final String FIELD_OFFSETX_EXPRESSION = "offsetXExpression";
78
    private static final String FIELD_OFFSETY_EXPRESSION = "offsetYExpression";
79
    private static final String FIELD_ROTATION_EXPRESSION = "rotationExpression";
80
    private static final String FIELD_LINETOOFFSETCOLOR_EXPRESSION = "lineToOffsetColorExpression";
81

    
82
    private static final GeometryManager GEOMETRY_MANAGER = GeometryLocator.getGeometryManager();
83
    
84
    private Color color;
85
    private double rotation;
86
    private Point2D offset = new Point2D.Double();
87
    private double size = 4d;
88
    private IMask mask;
89

    
90
    private Color lineToOffsetColor;
91
    private boolean drawLineToOffset;
92

    
93
    private String sizeExpression;
94
    private String offsetXExpression;
95
    private String offsetYExpression;
96
    private String rotationExpression;
97
    private String lineToOffsetColorExpression;
98
    
99
    private transient org.gvsig.fmap.geom.primitive.Point point;
100
    private transient ViewPort viewPort;
101
    private transient double dpi;
102

    
103
    public AbstractMarkerSymbol() {
104
        super();
105
        color = MapContextLocator.getSymbolManager()
106
                .getSymbolPreferences()
107
                .getDefaultSymbolFillColor();
108
        this.lineToOffsetColor = Color.BLACK;
109
        try {
110
            this.point = GEOMETRY_MANAGER.createPoint(0, 0, SUBTYPES.GEOM2D);
111
        } catch (CreateGeometryException ex) {
112
            
113
        }
114
    }
115

    
116
    protected org.gvsig.fmap.geom.primitive.Point getPoint(double x, double y) {
117
        this.point.setX(x);
118
        this.point.setY(y);
119
        return this.point;
120
    }
121
    
122
    @Override
123
    public final int getSymbolType() {
124
        return Geometry.TYPES.POINT;
125
    }
126
    
127
    @Override
128
    public double getRotation() {
129
        return rotation;
130
    }
131

    
132
    @Override
133
    public void setRotation(double r) {
134
        this.rotation = r;
135
    }
136

    
137
    @Override
138
    public Point2D getOffset() {
139
        if (offset == null) {
140
            offset = new Point();
141
        }
142
        return offset;
143
    }
144

    
145
    @Override
146
    public void setOffset(Point2D offset) {
147
        this.offset = offset;
148
    }
149

    
150
    private FeatureSymbolTable symbolTable = null;
151
    
152
    protected SymbolTable getSymbolTable(Feature f) {
153
        if( symbolTable==null ) {
154
            this.symbolTable = DALLocator.getManager().createFeatureSymbolTable();
155
            this.symbolTable.addSymbolTable(ExpressionUtils.createSymbolTable());
156
        }
157
        symbolTable.setFeature(f);
158
        return symbolTable;
159
    }
160
        
161
    @Override
162
    public Color getLineToOffsetColor() {
163
        return this.lineToOffsetColor;
164
    }
165

    
166
    @Override
167
    public void setLineToOffsetColor(Color color) {
168
        this.lineToOffsetColor = color;
169
    }
170

    
171
    @Override
172
    public boolean isDrawLineToOffset() {
173
        return this.drawLineToOffset;
174
    }
175

    
176
    @Override
177
    public void setDrawLineToOffset(boolean drawLineToOffset) {
178
        this.drawLineToOffset = drawLineToOffset;
179
    }
180

    
181
    @Override
182
    public String getOffsetXExpression() {
183
        return offsetXExpression;
184
    }
185

    
186
    @Override
187
    public void setOffsetXExpression(String offsetXExpression) {
188
        this.offsetXExpression = StringUtils.trimToNull(offsetXExpression);
189
    }
190

    
191
    @Override
192
    public String getOffsetYExpression() {
193
        return offsetYExpression;
194
    }
195

    
196
    @Override
197
    public void setOffsetYExpression(String offsetYExpression) {
198
        this.offsetYExpression = StringUtils.trimToNull(offsetYExpression);
199
    }
200

    
201
    @Override
202
    public String getRotationExpression() {
203
        return rotationExpression;
204
    }
205

    
206
    @Override
207
    public void setRotationExpression(String rotationExpression) {
208
        this.rotationExpression = StringUtils.trimToNull(rotationExpression);
209
    }
210

    
211
    @Override
212
    public String getSizeExpression() {
213
        return sizeExpression;
214
    }
215

    
216
    @Override
217
    public void setSizeExpression(String sizeExpression) {
218
        this.sizeExpression = StringUtils.trimToNull(sizeExpression);
219
    }
220

    
221
    @Override
222
    public String getLineToOffsetColorExpression() {
223
        return this.lineToOffsetColorExpression;
224
    }
225

    
226
    @Override
227
    public void setLineToOffsetColorExpression(String lineToOffsetColorExpression) {
228
        this.lineToOffsetColorExpression = StringUtils.trimToNull(lineToOffsetColorExpression);
229
    }
230

    
231
    @Override
232
    public Point2D getEfectiveOffset(Feature f) {
233
        if( f == null ) {
234
            f = this.getFeature();
235
        }
236
        Point2D p;
237
        if( f==null || StringUtils.isBlank(this.offsetXExpression) || StringUtils.isBlank(this.offsetYExpression) ) {
238
            p = this.getOffset();
239
            p = new Point2D.Double(
240
                    toCartographicUnits(p.getX()), 
241
                    toCartographicUnits(p.getY())
242
            );
243
        } else {
244
            double offsetX = toCartographicUnits(ExpressionUtils.parseDouble(
245
                    this.getSymbolTable(f), 
246
                    offsetXExpression, 
247
                    (int) this.getOffset().getX()
248
            ));
249
            double offsetY = toCartographicUnits(ExpressionUtils.parseDouble(
250
                    this.getSymbolTable(f), 
251
                    offsetYExpression, 
252
                    (int) this.getOffset().getY()
253
            ));
254
            p = new Point2D.Double(offsetX, offsetY);
255
        }
256
        return p;
257
    }
258

    
259
    @Override
260
    public double getEfectiveRotationInDegres(Feature f) {
261
        // Por defecto vedra en grados.
262
        if( f == null ) {
263
            f = this.getFeature();
264
        }
265
        if( f==null || StringUtils.isBlank(this.rotationExpression) ) {
266
            return this.getRotation();
267
        }
268
        double r = ExpressionUtils.parseDouble(
269
                this.getSymbolTable(f), 
270
                rotationExpression, 
271
                this.getRotation()
272
        );
273
        return r;
274
    }
275

    
276
    @Override
277
    public double getEfectiveRotationInRadians(Feature f) {
278
        // Pillamos el valor por defecto que es en grados y lo transformamos a radianes.
279
        double r = this.getEfectiveRotationInDegres(f);
280
        if( r == 0 ) {
281
            return 0;
282
        }
283
        r = Math.toRadians(r);
284
        return r;
285
    }
286

    
287
    @Override
288
    public Color getEfectiveLineToOffsetColor(Feature f) {
289
        if( f == null ) {
290
            f = this.getFeature();
291
        }
292
        if( f==null || StringUtils.isBlank(this.lineToOffsetColorExpression) ) {
293
            return this.getLineToOffsetColor();
294
        }
295
        Color theColor = ExpressionUtils.parseColor(
296
                this.getSymbolTable(f), 
297
                this.lineToOffsetColorExpression, 
298
                this.getLineToOffsetColor()
299
        );
300
        return theColor;
301
    }
302

    
303
    @Override
304
    public double getEfectiveSize(Feature f) {
305
        if( f == null ) {
306
            f = this.getFeature();
307
        }
308
        if( f==null || StringUtils.isBlank(this.sizeExpression) ) {
309
            return this.getSize();
310
        }
311
        double sz = ExpressionUtils.parseDouble(
312
                this.getSymbolTable(f), 
313
                this.sizeExpression, 
314
                -1
315
        );
316
        if(sz<0){
317
            return this.getSize();
318
        }
319
        return toCartographicUnits(sz);
320
    }
321

    
322
    @Override
323
    public boolean isSuitableFor(Geometry geom) {
324
        return geom.getType() == Geometry.TYPES.POINT;
325
    }
326

    
327
    @Override
328
    public int getOnePointRgb() {
329
        return color.getRGB();
330
    }
331

    
332
    @Override
333
    public double getSize() {
334
        return size;
335
    }
336

    
337
    @Override
338
    public void setSize(double size) {
339
        this.size = size;
340
    }
341

    
342
    @Override
343
    public Color getColor() {
344
        return color;
345
    }
346

    
347
    @Override
348
    public void setColor(Color color) {
349
        this.color = color;
350
    }
351

    
352
    @Override
353
    public void setAlpha(int outlineAlpha) {
354
        Color theColor = getColor();
355
        setColor(new Color(theColor.getRed(), theColor.getGreen(), theColor.getBlue(),
356
                outlineAlpha));
357
    }
358

    
359
    @Override
360
    public void getPixExtentPlus(Geometry geom, float[] distances, ViewPort viewPort, int dpi) {
361
        float cs = (float) getCartographicSize(viewPort, dpi, geom);
362
        distances[0] = cs;
363
        distances[1] = cs;
364
    }
365

    
366
    @Override
367
    public void print(Graphics2D g, AffineTransform at, Geometry geom, PrintAttributes properties) {
368
        double originalSize = getEfectiveSize(getFeature());
369
        double theSize = originalSize;
370
        // scale it to size
371
        int pq = properties.getPrintQuality();
372
        switch (pq) {
373
            case PrintAttributes.PRINT_QUALITY_NORMAL:
374
                theSize *= (double) 300 / 72;
375
                break;
376
            case PrintAttributes.PRINT_QUALITY_HIGH:
377
                theSize *= (double) 600 / 72;
378
                break;
379
            case PrintAttributes.PRINT_QUALITY_DRAFT:
380
                // size *= 72/72; // (which is the same than doing nothing)
381
                break;
382
            default:
383
                break;
384
        }
385
//                setSize(theSize);
386
        draw(g, at, geom, getFeature(), null);
387
//                setSize(originalSize);
388
    }
389

    
390
    @Override
391
    public final IMask getMask() {
392
        return mask;
393
    }
394

    
395
    @Override
396
    public void drawInsideRectangle(Graphics2D g, AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
397
        try {
398
            if (properties == null) {
399
                draw(
400
                        g, 
401
                        scaleInstance, 
402
                        this.getPoint(r.getCenterX(), r.getCenterY()),
403
//                        GEOMETRY_MANAGER.createPoint(r.getCenterX(), r.getCenterY(), SUBTYPES.GEOM2D), 
404
                        this.getFeature(), 
405
                        null
406
                );
407
            } else {
408
                double originalSize = getEfectiveSize(getFeature());
409
                double theSize = originalSize;
410
                int pq = properties.getPrintQuality();
411
                switch (pq) {
412
                    case PrintAttributes.PRINT_QUALITY_NORMAL:
413
                        theSize *= (double) 300 / 72;
414
                        break;
415
                    case PrintAttributes.PRINT_QUALITY_HIGH:
416
                        theSize *= (double) 600 / 72;
417
                        break;
418
                    case PrintAttributes.PRINT_QUALITY_DRAFT:
419
                        // d *= 72/72; // (which is the same than doing nothing)
420
                        break;
421
                    default:
422
                        break;
423
                }
424
                setSize(theSize);
425
                print(
426
                        g, 
427
                        scaleInstance, 
428
                        this.getPoint(r.getCenterX(), r.getCenterY()),
429
//                        GEOMETRY_MANAGER.createPoint(r.getCenterX(), r.getCenterY(), SUBTYPES.GEOM2D), 
430
                        properties
431
                );
432
                setSize(originalSize);
433
            }
434

    
435
        } catch (Exception e) {
436
            SymbolDrawingException sde = new SymbolDrawingException(TYPES.POINT);
437
            sde.initCause(e);
438
            throw sde;
439
        }
440
    }
441

    
442
    @Override
443
    public final void setMask(IMask mask) {
444
        this.mask = mask;
445
    }
446

    
447
    @Override
448
    public void setCartographicSize(double cartographicSize, Geometry geom) {
449
        setSize(cartographicSize);
450
    }
451

    
452
    @Override
453
    public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
454
        this.viewPort = viewPort;
455
        this.dpi  = dpi;
456

    
457
        double oldSize = getSize();
458
        setCartographicSize(getCartographicSize(
459
                viewPort,
460
                dpi,
461
                geom),
462
                geom);
463
        return oldSize;
464
    }
465

    
466
    @Override
467
    public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
468
        return CartographicSupportToolkit.
469
                getCartographicLength(this,
470
                        getSize(),
471
                        viewPort,
472
                        dpi);
473
    }
474
    
475
    private double toCartographicUnits(double value){
476
        if(viewPort == null){
477
            return value;
478
        }
479
        return CartographicSupportToolkit.
480
                getCartographicLength(this,
481
                        value,
482
                        viewPort,
483
                        dpi);
484
    }
485

    
486
    @Override
487
    public Object clone() throws CloneNotSupportedException {
488
        AbstractMarkerSymbol copy = (AbstractMarkerSymbol) super.clone();
489

    
490
        // Clone the offset
491
        if (offset != null) {
492
            copy.offset = (Point2D) offset.clone();
493
        }
494

    
495
        // clone the mask
496
        if (mask != null) {
497
            copy.mask = (IMask) mask.clone();
498
        }
499
        return copy;
500
    }
501

    
502
    @Override
503
    public void loadFromState(PersistentState state)
504
            throws PersistenceException {
505
        // Set parent symbol properties
506
        super.loadFromState(state);
507
        // Set own properties
508
        setColor((Color) state.get(FIELD_COLOR));
509
        setMask((IMask) state.get(FIELD_MASK));
510
        setOffset((Point2D) state.get(FIELD_OFFSET));
511
        setRotation(state.getDouble(FIELD_ROTATION));
512
        setSize(state.getDouble(FIELD_SIZE));
513
        setDrawLineToOffset(state.getBoolean(FIELD_DRAWLINETOOFFSET, false));
514
        setLineToOffsetColor((Color) state.get(FIELD_LINETOOFFSETCOLOR));
515
        
516
        setSizeExpression(state.getString(FIELD_SIZE_EXPRESSION));
517
        setOffsetXExpression(state.getString(FIELD_OFFSETX_EXPRESSION));
518
        setOffsetYExpression(state.getString(FIELD_OFFSETY_EXPRESSION));
519
        setRotationExpression(state.getString(FIELD_ROTATION_EXPRESSION));
520
        setLineToOffsetColorExpression(state.getString(FIELD_LINETOOFFSETCOLOR_EXPRESSION));
521
    }
522

    
523
    @Override
524
    public void saveToState(PersistentState state) throws PersistenceException {
525
        // Save parent symbol properties
526
        super.saveToState(state);
527
        // Save own properties
528
        state.set(FIELD_COLOR, getColor());
529
        state.set(FIELD_MASK, getMask());
530
        state.set(FIELD_OFFSET, getOffset());
531
        state.set(FIELD_ROTATION, getRotation());
532
        state.set(FIELD_SIZE, getSize());
533
        state.set(FIELD_LINETOOFFSETCOLOR, getLineToOffsetColor());
534
        state.set(FIELD_DRAWLINETOOFFSET, isDrawLineToOffset());
535

    
536
        state.set(FIELD_OFFSETX_EXPRESSION, getOffsetXExpression());
537
        state.set(FIELD_OFFSETY_EXPRESSION, getOffsetYExpression());
538
        state.set(FIELD_SIZE_EXPRESSION, getSizeExpression());
539
        state.set(FIELD_ROTATION_EXPRESSION, getRotationExpression());
540
        state.set(FIELD_LINETOOFFSETCOLOR_EXPRESSION, getLineToOffsetColorExpression());
541
    }
542

    
543
    public static class RegisterPersistence implements Callable {
544

    
545
        @Override
546
        public Object call() throws Exception {
547
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
548
            if (manager.getDefinition(MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME) == null) {
549
                DynStruct definition = manager.addDefinition(
550
                        AbstractMarkerSymbol.class,
551
                        MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME,
552
                        MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME + " Persistence definition",
553
                        null,
554
                        null
555
                );
556

    
557
                // Extend the Symbol base definition
558
                definition.extend(manager.getDefinition(SYMBOL_PERSISTENCE_DEFINITION_NAME));
559

    
560
                // Color
561
                definition.addDynFieldObject(FIELD_COLOR).setMandatory(false).setClassOfValue(Color.class);
562
                // Mask
563
                definition.addDynFieldObject(FIELD_MASK).setMandatory(false).setClassOfValue(IMask.class);
564

    
565
                // Offset
566
                definition.addDynFieldObject(FIELD_OFFSET).setMandatory(false).setClassOfValue(Point2D.class);
567

    
568
                // Rotation
569
                definition.addDynFieldDouble(FIELD_ROTATION).setMandatory(false);
570

    
571
                // Size
572
                definition.addDynFieldDouble(FIELD_SIZE).setMandatory(false);
573

    
574

    
575
                definition.addDynFieldBoolean(FIELD_DRAWLINETOOFFSET).setMandatory(false);
576
                definition.addDynFieldObject(FIELD_LINETOOFFSETCOLOR).setClassOfValue(Color.class).setMandatory(false);
577
                
578
                definition.addDynFieldString(FIELD_OFFSETX_EXPRESSION).setMandatory(false);
579
                definition.addDynFieldString(FIELD_OFFSETY_EXPRESSION).setMandatory(false);
580
                definition.addDynFieldString(FIELD_LINETOOFFSETCOLOR_EXPRESSION).setMandatory(false);
581
                definition.addDynFieldString(FIELD_ROTATION_EXPRESSION).setMandatory(false);
582
                definition.addDynFieldString(FIELD_SIZE_EXPRESSION).setMandatory(false);
583
            }
584
            return true;
585
        }
586

    
587
    }
588

    
589
}