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

History | View | Annotate | Download (16.1 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 java.awt.Color;
27
import java.awt.Graphics2D;
28
import java.awt.Point;
29
import java.awt.Rectangle;
30
import java.awt.geom.AffineTransform;
31
import java.awt.geom.Point2D;
32
import org.apache.commons.lang3.StringUtils;
33

    
34
import org.gvsig.compat.print.PrintAttributes;
35
import org.gvsig.expressionevaluator.ExpressionBuilder;
36
import org.gvsig.expressionevaluator.ExpressionUtils;
37
import org.gvsig.expressionevaluator.SymbolTable;
38
import org.gvsig.fmap.dal.DALLocator;
39
import org.gvsig.fmap.dal.expressionevaluator.FeatureSymbolTable;
40
import org.gvsig.fmap.dal.feature.Feature;
41
import org.gvsig.fmap.geom.Geometry;
42
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
43
import org.gvsig.fmap.geom.Geometry.TYPES;
44
import org.gvsig.fmap.geom.GeometryLocator;
45
import org.gvsig.fmap.geom.GeometryManager;
46
import org.gvsig.fmap.geom.exception.CreateGeometryException;
47
import org.gvsig.fmap.mapcontext.MapContextLocator;
48
import org.gvsig.fmap.mapcontext.ViewPort;
49
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
50
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.AbstractSymbol;
51
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit;
52
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
53
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.IMask;
54
import org.gvsig.tools.ToolsLocator;
55
import org.gvsig.tools.dynobject.DynStruct;
56
import org.gvsig.tools.persistence.PersistenceManager;
57
import org.gvsig.tools.persistence.PersistentState;
58
import org.gvsig.tools.persistence.exception.PersistenceException;
59
import org.gvsig.tools.util.Callable;
60

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

    
69
    public static final String MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME = "MarkerSymbol";
70

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

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

    
89
    private boolean drawLineToOffset;
90

    
91
    private String offsetXExpression;
92
    private String offsetYExpression;
93
    private String rotationExpression;
94
    private String lineToOffsetColorExpression;
95

    
96
    public AbstractMarkerSymbol() {
97
        super();
98
        color = MapContextLocator.getSymbolManager()
99
                .getSymbolPreferences()
100
                .getDefaultSymbolFillColor();
101
    }
102

    
103
    @Override
104
    public final int getSymbolType() {
105
        return Geometry.TYPES.POINT;
106
    }
107

    
108
    @Override
109
    public double getRotation() {
110
        return rotation;
111
    }
112

    
113
    @Override
114
    public void setRotation(double r) {
115
        this.rotation = r;
116
    }
117

    
118
    @Override
119
    public Point2D getOffset() {
120
        if (offset == null) {
121
            offset = new Point();
122
        }
123
        return offset;
124
    }
125

    
126
    @Override
127
    public void setOffset(Point2D offset) {
128
        this.offset = offset;
129
    }
130

    
131
    private FeatureSymbolTable symbolTable = null;
132
    
133
    private SymbolTable getSymbolTable(Feature f) {
134
        if( symbolTable==null ) {
135
            this.symbolTable = DALLocator.getManager().createFeatureSymbolTable();
136
        }
137
        symbolTable.setFeature(f);
138
        return symbolTable;
139
    }
140
        
141
    public String getOffsetXExpression() {
142
        return offsetXExpression;
143
    }
144

    
145
    public void setOffsetXExpression(String offsetXExpression) {
146
        this.offsetXExpression = StringUtils.trimToNull(offsetXExpression);
147
    }
148

    
149
    public String getOffsetYExpression() {
150
        return offsetYExpression;
151
    }
152

    
153
    public void setOffsetYExpression(String offsetYExpression) {
154
        this.offsetYExpression = StringUtils.trimToNull(offsetYExpression);
155
    }
156

    
157
    public String getRotationExpression() {
158
        return rotationExpression;
159
    }
160

    
161
    public void setRotationExpression(String rotationExpression) {
162
        this.rotationExpression = StringUtils.trimToNull(rotationExpression);
163
    }
164

    
165
    public Color getLineToOffsetColor() {
166
        return this.getLineToOffsetColor(null);
167
    }
168

    
169
    public Color getLineToOffsetColor(Feature f) {
170
        return ExpressionUtils.parseColor(this.getSymbolTable(f), this.lineToOffsetColorExpression, Color.BLACK);
171
    }
172

    
173
    public String getLineToOffsetColorExpression() {
174
        return this.lineToOffsetColorExpression;
175
    }
176

    
177
    public void setLineToOffsetColorExpression(String lineToOffsetColorExpression) {
178
        this.lineToOffsetColorExpression = StringUtils.trimToNull(lineToOffsetColorExpression);
179
    }
180

    
181
    public void setLineToOffsetColor(Color lineToOffsetColor) {
182
        ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
183
        this.lineToOffsetColorExpression = StringUtils.trimToNull(builder.color(color).toString());
184
    }
185

    
186
    public boolean isDrawLineToOffset() {
187
        return this.isDrawLineToOffset(null);
188
    }
189

    
190
    public boolean isDrawLineToOffset(Feature f) {
191
        return this.drawLineToOffset;
192
    }
193

    
194
    public void setDrawLineToOffset(boolean drawLineToOffset) {
195
        this.drawLineToOffset = drawLineToOffset;
196
    }
197

    
198
    public Point2D getEfectiveOffset(Feature f) {
199
        if( f==null || StringUtils.isBlank(this.offsetXExpression) || StringUtils.isBlank(this.offsetYExpression) ) {
200
            return this.getOffset();
201
        }
202
        int offsetX = ExpressionUtils.parseInt(this.getSymbolTable(f), offsetXExpression, (int) this.getOffset().getX());
203
        int offsetY = ExpressionUtils.parseInt(this.getSymbolTable(f), offsetYExpression, (int) this.getOffset().getY());
204
        Point p = new Point(offsetX, offsetY);
205
        return p;
206
    }
207

    
208
    public double getEfectiveRotation(Feature f) {
209
        if( f==null || StringUtils.isBlank(this.rotationExpression) ) {
210
            return this.getRotation();
211
        }
212
        double r = ExpressionUtils.parseDouble(this.getSymbolTable(f), rotationExpression, this.getRotation());
213
        return r;
214
    }
215

    
216
    @Override
217
    public boolean isSuitableFor(Geometry geom) {
218
        return geom.getType() == Geometry.TYPES.POINT;
219
    }
220

    
221
    @Override
222
    public int getOnePointRgb() {
223
        return color.getRGB();
224
    }
225

    
226
    @Override
227
    public double getSize() {
228
        return size;
229
    }
230

    
231
    @Override
232
    public void setSize(double size) {
233
        this.size = size;
234
    }
235

    
236
    @Override
237
    public Color getColor() {
238
        return color;
239
    }
240

    
241
    @Override
242
    public void setColor(Color color) {
243
        this.color = color;
244
    }
245

    
246
    @Override
247
    public void setAlpha(int outlineAlpha) {
248
        Color theColor = getColor();
249
        setColor(new Color(theColor.getRed(), theColor.getGreen(), theColor.getBlue(),
250
                outlineAlpha));
251
    }
252

    
253
    @Override
254
    public void getPixExtentPlus(Geometry geom, float[] distances, ViewPort viewPort, int dpi) {
255
        float cs = (float) getCartographicSize(viewPort, dpi, geom);
256
        distances[0] = cs;
257
        distances[1] = cs;
258
    }
259

    
260
    @Override
261
    public void print(Graphics2D g, AffineTransform at, Geometry geom, PrintAttributes properties) {
262
        double originalSize = getSize();
263
        double theSize = originalSize;
264
        // scale it to size
265
        int pq = properties.getPrintQuality();
266
        switch (pq) {
267
            case PrintAttributes.PRINT_QUALITY_NORMAL:
268
                theSize *= (double) 300 / 72;
269
                break;
270
            case PrintAttributes.PRINT_QUALITY_HIGH:
271
                theSize *= (double) 600 / 72;
272
                break;
273
            case PrintAttributes.PRINT_QUALITY_DRAFT:
274
                // size *= 72/72; // (which is the same than doing nothing)
275
                break;
276
            default:
277
                break;
278
        }
279
//                setSize(theSize);
280
        draw(g, at, geom, null, null);
281
//                setSize(originalSize);
282
    }
283

    
284
    @Override
285
    public final IMask getMask() {
286
        return mask;
287
    }
288

    
289
    @Override
290
    public void drawInsideRectangle(Graphics2D g, AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
291
        try {
292
            if (properties == null) {
293
                draw(g, scaleInstance, GEOMETRY_MANAGER.createPoint(r.getCenterX(), r.getCenterY(), SUBTYPES.GEOM2D), null, null);
294
            } else {
295
                double originalSize = getSize();
296
                double theSize = originalSize;
297
                int pq = properties.getPrintQuality();
298
                switch (pq) {
299
                    case PrintAttributes.PRINT_QUALITY_NORMAL:
300
                        theSize *= (double) 300 / 72;
301
                        break;
302
                    case PrintAttributes.PRINT_QUALITY_HIGH:
303
                        theSize *= (double) 600 / 72;
304
                        break;
305
                    case PrintAttributes.PRINT_QUALITY_DRAFT:
306
                        // d *= 72/72; // (which is the same than doing nothing)
307
                        break;
308
                    default:
309
                        break;
310
                }
311
                setSize(theSize);
312
                print(g, scaleInstance, GEOMETRY_MANAGER.createPoint(r.getCenterX(), r.getCenterY(), SUBTYPES.GEOM2D), properties);
313
                setSize(originalSize);
314
            }
315

    
316
        } catch (CreateGeometryException e) {
317
            throw new SymbolDrawingException(TYPES.POINT);
318
        }
319
    }
320

    
321
    @Override
322
    public final void setMask(IMask mask) {
323
        this.mask = mask;
324
    }
325

    
326
    @Override
327
    public void setCartographicSize(double cartographicSize, Geometry geom) {
328
        setSize(cartographicSize);
329
    }
330

    
331
    @Override
332
    public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
333
        double oldSize = getSize();
334
        setCartographicSize(getCartographicSize(
335
                viewPort,
336
                dpi,
337
                geom),
338
                geom);
339
        return oldSize;
340
    }
341

    
342
    @Override
343
    public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
344
        return CartographicSupportToolkit.
345
                getCartographicLength(this,
346
                        getSize(),
347
                        viewPort,
348
                        dpi);
349
    }
350

    
351
    @Override
352
    public Object clone() throws CloneNotSupportedException {
353
        AbstractMarkerSymbol copy = (AbstractMarkerSymbol) super.clone();
354

    
355
        // Clone the offset
356
        if (offset != null) {
357
            copy.offset = (Point2D) offset.clone();
358
        }
359

    
360
        // clone the mask
361
        if (mask != null) {
362
            copy.mask = (IMask) mask.clone();
363
        }
364
        return copy;
365
    }
366

    
367
    @Override
368
    public void loadFromState(PersistentState state)
369
            throws PersistenceException {
370
        // Set parent symbol properties
371
        super.loadFromState(state);
372
        // Set own properties
373
        setColor((Color) state.get(FIELD_COLOR));
374
        setMask((IMask) state.get(FIELD_MASK));
375
        setOffset((Point2D) state.get(FIELD_OFFSET));
376
        setRotation(state.getDouble(FIELD_ROTATION));
377
        setSize(state.getDouble(FIELD_SIZE));
378

    
379
        setDrawLineToOffset(state.getBoolean(FIELD_DRAWLINETOOFFSET));
380
        setOffsetXExpression(state.getString(FIELD_OFFSETX_EXPRESSION));
381
        setOffsetYExpression(state.getString(FIELD_OFFSETY_EXPRESSION));
382
        setRotationExpression(state.getString(FIELD_ROTATION_EXPRESSION));
383
        setLineToOffsetColorExpression(state.getString(FIELD_LINETOOFFSETCOLOR_EXPRESSION));
384
    }
385

    
386
    @Override
387
    public void saveToState(PersistentState state) throws PersistenceException {
388
        // Save parent symbol properties
389
        super.saveToState(state);
390
        // Save own properties
391
        state.set(FIELD_COLOR, getColor());
392
        state.set(FIELD_MASK, getMask());
393
        state.set(FIELD_OFFSET, getOffset());
394
        state.set(FIELD_ROTATION, getRotation());
395
        state.set(FIELD_SIZE, getSize());
396

    
397
        state.set(FIELD_OFFSETX_EXPRESSION, getOffsetXExpression());
398
        state.set(FIELD_OFFSETY_EXPRESSION, getOffsetYExpression());
399
        state.set(FIELD_ROTATION_EXPRESSION, getRotationExpression());
400
        state.set(FIELD_DRAWLINETOOFFSET, isDrawLineToOffset());
401
        state.set(FIELD_LINETOOFFSETCOLOR_EXPRESSION, getLineToOffsetColorExpression());
402
    }
403

    
404
    public static class RegisterPersistence implements Callable {
405

    
406
        @Override
407
        public Object call() throws Exception {
408
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
409
            if (manager.getDefinition(MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME) == null) {
410
                DynStruct definition = manager.addDefinition(
411
                        AbstractMarkerSymbol.class,
412
                        MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME,
413
                        MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME + " Persistence definition",
414
                        null,
415
                        null
416
                );
417

    
418
                // Extend the Symbol base definition
419
                definition.extend(manager.getDefinition(SYMBOL_PERSISTENCE_DEFINITION_NAME));
420

    
421
                // Color
422
                definition.addDynFieldObject(FIELD_COLOR).setMandatory(false).setClassOfValue(Color.class);
423
                // Mask
424
                definition.addDynFieldObject(FIELD_MASK).setMandatory(false).setClassOfValue(IMask.class);
425

    
426
                // Offset
427
                definition.addDynFieldObject(FIELD_OFFSET).setMandatory(false).setClassOfValue(Point2D.class);
428

    
429
                // Rotation
430
                definition.addDynFieldDouble(FIELD_ROTATION).setMandatory(true);
431

    
432
                // Size
433
                definition.addDynFieldDouble(FIELD_SIZE).setMandatory(true);
434

    
435

    
436
                definition.addDynFieldBoolean(FIELD_DRAWLINETOOFFSET).setMandatory(false);
437
                definition.addDynFieldString(FIELD_OFFSETX_EXPRESSION).setMandatory(false);
438
                definition.addDynFieldString(FIELD_OFFSETY_EXPRESSION).setMandatory(false);
439
                definition.addDynFieldString(FIELD_LINETOOFFSETCOLOR_EXPRESSION).setMandatory(false);
440
                definition.addDynFieldString(FIELD_ROTATION_EXPRESSION).setMandatory(false);
441
            }
442
            return true;
443
        }
444

    
445
    }
446

    
447
}