Statistics
| Revision:

root / org.gvsig.legend.urbanhorizontalsignage / trunk / org.gvsig.legend.urbanhorizontalsignage / org.gvsig.legend.urbanhorizontalsignage.lib / org.gvsig.legend.urbanhorizontalsignage.lib.impl / src / main / java / org / gvsig / legend / urbanhorizontalsignage / lib / impl / linelegend / UrbanHorizontalSignageSymbol.java @ 9513

History | View | Annotate | Download (16.2 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.legend.urbanhorizontalsignage.lib.impl.linelegend;
25

    
26
import java.awt.Color;
27
import java.awt.Graphics2D;
28
import java.awt.Rectangle;
29
import java.awt.Shape;
30
import java.awt.geom.AffineTransform;
31
import java.util.concurrent.Callable;
32
import org.gvsig.fmap.dal.feature.Feature;
33
import org.gvsig.fmap.geom.Geometry;
34
import org.gvsig.fmap.geom.GeometryUtils;
35
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
36
import org.gvsig.fmap.geom.primitive.Envelope;
37
import org.gvsig.fmap.geom.primitive.Line;
38
import org.gvsig.fmap.geom.primitive.Point;
39
import org.gvsig.fmap.mapcontext.MapContext;
40
import org.gvsig.fmap.mapcontext.MapContextLocator;
41
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
42
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol_v2;
43
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
44
import org.gvsig.legend.urbanhorizontalsignage.lib.api.UrbanHorizontalSignageLocator;
45
import org.gvsig.legend.urbanhorizontalsignage.lib.api.UrbanHorizontalSignageManager;
46
import org.gvsig.legend.urbanhorizontalsignage.lib.api.linelegend.UrbanHorizontalSignageData;
47
import static org.gvsig.legend.urbanhorizontalsignage.lib.api.linelegend.UrbanHorizontalSignageData.CONTINUITY_MODE_CONT_DISC;
48
import static org.gvsig.legend.urbanhorizontalsignage.lib.api.linelegend.UrbanHorizontalSignageData.CONTINUITY_MODE_DISC;
49
import static org.gvsig.legend.urbanhorizontalsignage.lib.api.linelegend.UrbanHorizontalSignageData.CONTINUITY_MODE_DISC_CONT;
50
import static org.gvsig.legend.urbanhorizontalsignage.lib.api.linelegend.UrbanHorizontalSignageData.CONTINUITY_MODE_DISC_DISC;
51
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.AbstractSymbol;
52
import org.gvsig.tools.persistence.PersistentState;
53
import org.gvsig.tools.persistence.exception.PersistenceException;
54
import org.gvsig.tools.swing.api.TransparencySupport;
55
import org.gvsig.tools.task.Cancellable;
56
import org.slf4j.Logger;
57
import org.slf4j.LoggerFactory;
58

    
59
public class UrbanHorizontalSignageSymbol extends AbstractSymbol implements ISymbol_v2, TransparencySupport {
60

    
61
    private static final Logger LOG = LoggerFactory.getLogger(UrbanHorizontalSignageSymbol.class);
62
    private static final String SYMBOL_NAME = "UrbanHorizontalSignageSymbol";
63
    private static final String URBAN_HORIZONTAL_SIGNAGE_SYMBOL_PERSISTENCE_DEFINITION_NAME = "UrbanHorizontalSignageSymbol";
64
    
65
    private static final String FIELD_WIDTH = "width";
66
    private static final String FIELD_CONTINUITY = "continuity";
67
    private static final String FIELD_SEGMENTS_COLOR = "segmentsColor";
68
    private static final String FIELD_SEGMENTS_LENGTH = "segmentsLength";
69
    private static final String FIELD_HOLES_COLOR = "holesColor";
70
    private static final String FIELD_HOLES_LENGTH = "holesLength";
71
    private static final String FIELD_PAINT_HOLES = "paintHoles";
72
    private static final String FIELD_GAP_WIDTH = "gapWidth";
73
    private static final String FIELD_ROUND_VERTEX = "roundVertex";
74
    private static final String FIELD_SEGMENTS_GEOMETRY = "segmentsGeometry";
75
    private static final String FIELD_HOLES_GEOMETRY = "holesGeometry";
76
    private static final String FIELD_TRANSPARENCY = "transparency";
77
    private static final String FIELD_MUST_DRAW_ORIGINAL_GEOMETRY = "mustDrawOriginalGeometry";
78
    private static final String FIELD_COLOR_FOR_ORIGINAL_GEOMETRY = "colorForOriginalGeometry";
79
    
80

    
81

    
82
//    private static final String FIELD_SYMBOL_FOR_SELECTION = "symbolForSelection";
83
    private UrbanHorizontalSignageData data;
84

    
85
    transient private UrbanHorizontalSignageSymbol symbolForSelection;
86
    
87
    private boolean mustDrawOriginalGeometry;
88
    private Color colorForOriginalGeometry;
89
    private double cartographicSize;
90
    private double transparency; //[0.0, 1.0]
91

    
92
    public UrbanHorizontalSignageSymbol() {
93
        super();
94
        this.mustDrawOriginalGeometry = false;
95
        this.transparency = 1.0;
96
    }
97

    
98
    public void setData(UrbanHorizontalSignageData data) {
99
        this.data = data;
100
    }
101

    
102
    public UrbanHorizontalSignageData getData() {
103
        return data;
104
    }
105

    
106
    /**
107
     * Sets the transparency for symbol. The valid values are in [0.0, 1.0]
108
     * 
109
     * @param transparency 
110
     */
111
    @Override
112
    public void setTransparency(double transparency) {
113
        if(transparency < 0 || transparency > 1.0){
114
            throw new IllegalArgumentException("Transparency value must be in [0.0, 1.0] ("+transparency+")");
115
        }
116
        this.transparency = transparency;
117
    }
118

    
119
    @Override
120
    public double getTransparency() {
121
        return transparency;
122
    }
123
    
124
    @Override
125
    public ISymbol getSymbolForSelection() {
126
        if (symbolForSelection == null) {
127
            symbolForSelection = (UrbanHorizontalSignageSymbol) cloneForSelection();
128
            symbolForSelection.mustDrawOriginalGeometry = true;
129
        } else {
130
            symbolForSelection.setColor(MapContext.getSelectionColor());
131
        }
132
        return symbolForSelection;
133
    }
134
    
135
    protected Geometry getSampleGeometry(Rectangle r) {
136
        final int hGap = (int) (r.getWidth() * 0.1); // the left and right margins
137
        final int vPos = 1;                                                  // the top and bottom margins
138
        final int splitCount = 3;                                          // number of lines
139
        final int splitHSize = (r.width - hGap - hGap) / splitCount;
140
        int hPos = hGap;
141
        boolean swap = false;
142

    
143
        Line geom = GeometryUtils.createLine(Geometry.SUBTYPES.GEOM2D);
144
        geom.addVertex(r.x + hPos, r.y + r.height - vPos);
145

    
146
        for (int i = 0; i < splitCount; i++) {
147
            swap = !swap;
148
            geom.addVertex(r.x + hPos + splitHSize, (swap ? vPos : r.height - vPos) + r.y);
149
            hPos += splitHSize;
150
        }
151
        return geom;
152
    }
153
    
154

    
155
    @Override
156
    public void draw(Graphics2D g, AffineTransform affineTransform,
157
            Geometry originalGeometry, Feature feature, Cancellable cancel, Rectangle r) {
158
        if(r != null){
159
            originalGeometry = getSampleGeometry(r);
160
        }
161
        if (true) {
162
            // Esto deberia ser para optimizar el pintado de 
163
            // geometrias grandes.
164
            try {
165
                Geometry env = originalGeometry.getEnvelope().getGeometry();
166
                env.transform(affineTransform);
167
                Envelope env2 = env.getEnvelope();
168
                if (env2.getLength(0) < 1.5 && env2.getLength(1) < 1.5) {
169
                    Color color = data.getSegmentsColor();
170
                    Color transparentColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), (int)(transparency*color.getAlpha()));
171
                    g.setColor(transparentColor);
172
                    Point upperCorner = env2.getUpperCorner();
173
                    int x = (int) upperCorner.getX();
174
                    int y = (int) upperCorner.getY();
175
                    g.drawLine(x, y, x, y);
176
                    return;
177
                }
178
            } catch (Exception ex) {
179
                LOG.warn("Error optimizing the drawing of the geometry. Continues with normal drawing.", ex);
180
                // Do nothing, continue with the draw of the original geometry
181
            }
182
        }
183

    
184
        UrbanHorizontalSignageManager uhsManager = UrbanHorizontalSignageLocator.getUrbanHorizontalSignageManager();
185
        uhsManager.calculateGeometries(originalGeometry, data);
186
        
187
        MultiPolygon geom = data.getSegmentsGeometry();
188
        if (geom != null && geom.getPrimitivesNumber() > 0) {
189
            Color color = data.getSegmentsColor();
190
            Shape shape = geom.getShape(affineTransform);
191
            Color transparentColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), (int)(transparency*color.getAlpha()));
192
            g.setColor(transparentColor);
193
            g.fill(shape);
194
            g.setColor(color.darker());
195
            g.draw(shape);
196
        }
197

    
198
        switch (data.getContinuity()) {
199
            case CONTINUITY_MODE_CONT_DISC:
200
            case CONTINUITY_MODE_DISC_CONT:
201
            case CONTINUITY_MODE_DISC:
202
            case CONTINUITY_MODE_DISC_DISC:
203
                if (data.isPaintHoles()) {
204
                    geom = data.getHolesGeometry();
205
                    if (geom != null && geom.getPrimitivesNumber() > 0) {
206
                        Color color = data.getHolesColor();
207
                        Color transparentColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), (int)(transparency*color.getAlpha()));
208
                        g.setColor(transparentColor);
209
                        g.fill(geom.getShape(affineTransform));
210
                    }
211
                }
212
        }
213

    
214
        //For debug purposse only
215
        if(mustDrawOriginalGeometry){
216
            g.setColor(getColor());
217
            g.draw(originalGeometry.getShape(affineTransform));
218
        }
219

    
220
    }
221

    
222
    @Override
223
    public Object clone() throws CloneNotSupportedException {
224
        UrbanHorizontalSignageSymbol copy = (UrbanHorizontalSignageSymbol) super.clone();
225

    
226
        if (symbolForSelection != null) {
227
            copy.symbolForSelection = (UrbanHorizontalSignageSymbol) symbolForSelection
228
                    .clone();
229
        }
230

    
231
        return copy;
232
    }
233

    
234
    @Override
235
    public void loadFromState(PersistentState state) throws PersistenceException {
236
        // Set parent style properties
237
        super.loadFromState(state);
238
        
239
        UrbanHorizontalSignageData theData = new DefaultUrbanHorizontalSignageData();
240
        theData.setWidth(state.getDouble(FIELD_WIDTH, UrbanHorizontalSignageData.DEFAULT_WIDTH_VALUE));
241
        theData.setContinuity(state.getInt(FIELD_CONTINUITY, UrbanHorizontalSignageData.DEFAULT_CONTINUITY_VALUE));
242
        
243
        Color color = (Color) state.get(FIELD_SEGMENTS_COLOR);
244
        theData.setSegmentsColor(color != null ? color : UrbanHorizontalSignageData.DEFAULT_SEGMENT_COLOR_VALUE);
245
        
246
        theData.setSegmentsLength(state.getDouble(FIELD_SEGMENTS_LENGTH, UrbanHorizontalSignageData.DEFAULT_SEGMENT_LENGTH_VALUE));
247
        
248
        color = (Color) state.get(FIELD_HOLES_COLOR);
249
        theData.setHolesColor(color != null ? color : UrbanHorizontalSignageData.DEFAULT_HOLES_COLOR_VALUE);
250
        
251
        theData.setHolesLength(state.getDouble(FIELD_HOLES_LENGTH, UrbanHorizontalSignageData.DEFAULT_HOLES_LENGTH_VALUE));
252
        theData.setGapWidth(state.getDouble(FIELD_GAP_WIDTH, UrbanHorizontalSignageData.DEFAULT_GAP_WIDTH_VALUE));
253
        theData.setRoundVertex(state.getBoolean(FIELD_ROUND_VERTEX, UrbanHorizontalSignageData.DEFAULT_ROUND_VERTEX_VALUE));
254
        
255
        this.transparency = state.getDouble(FIELD_TRANSPARENCY, 1.0);
256
        this.mustDrawOriginalGeometry = state.getBoolean(FIELD_MUST_DRAW_ORIGINAL_GEOMETRY, false);
257
        color = (Color) state.get(FIELD_COLOR_FOR_ORIGINAL_GEOMETRY);
258
        this.colorForOriginalGeometry = color != null ? color : MapContext.getSelectionColor();
259
        this.data = theData;
260

    
261
    }
262

    
263
    @Override
264
    public void saveToState(PersistentState state) throws PersistenceException {
265
        // Save parent fill symbol properties
266
        super.saveToState(state);
267

    
268
        // Save own properties
269
        
270
        if(data != null){
271
            state.set(FIELD_WIDTH, data.getWidth());
272
            state.set(FIELD_CONTINUITY, data.getContinuity());
273
            state.set(FIELD_SEGMENTS_COLOR, data.getSegmentsColor());
274
            state.set(FIELD_SEGMENTS_LENGTH, data.getSegmentsLength());
275
            state.set(FIELD_HOLES_COLOR, data.getHolesColor());
276
            state.set(FIELD_HOLES_LENGTH, data.getHolesLength());
277
            state.set(FIELD_PAINT_HOLES, data.isPaintHoles());
278
            state.set(FIELD_GAP_WIDTH, data.getGapWidth());
279
            state.set(FIELD_ROUND_VERTEX, data.isRoundVertex());
280
        }
281
        state.set(FIELD_MUST_DRAW_ORIGINAL_GEOMETRY, mustDrawOriginalGeometry);
282
        state.set(FIELD_COLOR_FOR_ORIGINAL_GEOMETRY, colorForOriginalGeometry);
283
        state.set(FIELD_TRANSPARENCY, this.getTransparency());
284
    }
285

    
286
    @Override
287
    public int getSymbolType() {
288
        return Geometry.TYPES.CURVE;
289
    }
290

    
291
    @Override
292
    public boolean isSuitableFor(Geometry geom) {
293
        return geom.getGeometryType().isTypeOf(Geometry.TYPES.CURVE);
294
    }
295

    
296
    @Override
297
    public Color getColor() {
298
        return this.colorForOriginalGeometry;
299
    }
300

    
301
    @Override
302
    public void setColor(Color color) {
303
        this.colorForOriginalGeometry = color;
304
    }
305

    
306
//    public static class RegisterPersistence implements Callable {
307
//
308
//        @Override
309
//        public Object call() throws Exception {
310
//            PersistenceManager manager = ToolsLocator.getPersistenceManager();
311
//            if (manager.getDefinition(URBAN_HORIZONTAL_SIGNAGE_SYMBOL_PERSISTENCE_DEFINITION_NAME) == null) {
312
//                DynStruct definition = manager.addDefinition(
313
//                        UrbanHorizontalSignageSymbol.class,
314
//                        URBAN_HORIZONTAL_SIGNAGE_SYMBOL_PERSISTENCE_DEFINITION_NAME,
315
//                        URBAN_HORIZONTAL_SIGNAGE_SYMBOL_PERSISTENCE_DEFINITION_NAME + " Persistence definition",
316
//                        null,
317
//                        null
318
//                );
319
//                // Extend the LineSymbol base definition
320
//                definition.extend(manager.getDefinition(AbstractSymbol.SYMBOL_PERSISTENCE_DEFINITION_NAME));
321
//                
322
//                definition.addDynFieldDouble(FIELD_WIDTH).setMandatory(false);
323
//                definition.addDynFieldInt(FIELD_CONTINUITY).setMandatory(false);
324
//                definition.addDynFieldObject(FIELD_SEGMENTS_COLOR).setClassOfValue(Color.class).setMandatory(false);
325
//                definition.addDynFieldDouble(FIELD_SEGMENTS_LENGTH).setMandatory(false);
326
//                definition.addDynFieldObject(FIELD_HOLES_COLOR).setClassOfValue(Color.class).setMandatory(false);
327
//                definition.addDynFieldDouble(FIELD_HOLES_LENGTH).setMandatory(false);
328
//                definition.addDynFieldBoolean(FIELD_PAINT_HOLES).setMandatory(false);
329
//                definition.addDynFieldDouble(FIELD_GAP_WIDTH).setMandatory(false);
330
//                definition.addDynFieldBoolean(FIELD_ROUND_VERTEX).setMandatory(false);
331
//                definition.addDynFieldDouble(FIELD_TRANSPARENCY).setMandatory(false);
332
//                definition.addDynFieldBoolean(FIELD_MUST_DRAW_ORIGINAL_GEOMETRY).setMandatory(false);
333
//                definition.addDynFieldObject(FIELD_COLOR_FOR_ORIGINAL_GEOMETRY).setClassOfValue(Color.class).setMandatory(false);
334
//            }
335
//            return Boolean.TRUE;
336
//        }
337
//
338
//    }
339

    
340
    public static class RegisterSymbol implements Callable {
341

    
342
        @Override
343
        public Object call() throws Exception {
344
            int[] shapeTypes;
345
            SymbolManager manager = MapContextLocator.getSymbolManager();
346

    
347
            shapeTypes = new int[]{Geometry.TYPES.CURVE, Geometry.TYPES.ARC,
348
                Geometry.TYPES.MULTICURVE, Geometry.TYPES.CIRCUMFERENCE,
349
                Geometry.TYPES.PERIELLIPSE, Geometry.TYPES.SPLINE,
350
                Geometry.TYPES.LINE, Geometry.TYPES.MULTILINE};
351
            manager.registerSymbol(SYMBOL_NAME,
352
                    shapeTypes,
353
                    UrbanHorizontalSignageSymbol.class);
354

    
355
            return Boolean.TRUE;
356
        }
357

    
358
    }
359

    
360
}