Statistics
| Revision:

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

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

    
26
import java.awt.Color;
27
import java.awt.Graphics2D;
28
import java.awt.Rectangle;
29
import java.awt.geom.AffineTransform;
30
import java.util.Objects;
31
import java.util.concurrent.Callable;
32
import java.util.logging.Level;
33
import org.gvsig.compat.print.PrintAttributes;
34
import org.gvsig.fmap.dal.feature.Feature;
35
import org.gvsig.fmap.geom.Geometry;
36
import org.gvsig.fmap.geom.GeometryLocator;
37
import org.gvsig.fmap.geom.GeometryManager;
38
import org.gvsig.fmap.geom.GeometryUtils;
39
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
40
import org.gvsig.fmap.geom.operation.GeometryOperationException;
41
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
42
import org.gvsig.fmap.geom.primitive.Envelope;
43
import org.gvsig.fmap.geom.primitive.Line;
44
import org.gvsig.fmap.geom.primitive.Point;
45
import org.gvsig.fmap.mapcontext.MapContext;
46
import org.gvsig.fmap.mapcontext.MapContextLocator;
47
import org.gvsig.fmap.mapcontext.ViewPort;
48
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
49
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol_v2;
50
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
51
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
52
import org.gvsig.legend.urbanhorizontalsignage.lib.api.UrbanHorizontalSignageData;
53
import static org.gvsig.legend.urbanhorizontalsignage.lib.api.UrbanHorizontalSignageData.CONTINUITY_MODE_CONT_DISC;
54
import static org.gvsig.legend.urbanhorizontalsignage.lib.api.UrbanHorizontalSignageData.CONTINUITY_MODE_DISC;
55
import static org.gvsig.legend.urbanhorizontalsignage.lib.api.UrbanHorizontalSignageData.CONTINUITY_MODE_DISC_CONT;
56
import static org.gvsig.legend.urbanhorizontalsignage.lib.api.UrbanHorizontalSignageData.CONTINUITY_MODE_DISC_DISC;
57
import org.gvsig.legend.urbanhorizontalsignage.lib.api.UrbanHorizontalSignageLocator;
58
import org.gvsig.legend.urbanhorizontalsignage.lib.api.UrbanHorizontalSignageManager;
59
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.AbstractSymbol;
60
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit;
61
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
62
import static org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl.AbstractLineSymbol.LINE_SYMBOL_PERSISTENCE_DEFINITION_NAME;
63
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl.SimpleLineSymbol;
64
import org.gvsig.tools.ToolsLocator;
65
import org.gvsig.tools.dynobject.DynStruct;
66
import org.gvsig.tools.persistence.PersistenceManager;
67
import org.gvsig.tools.persistence.PersistentState;
68
import org.gvsig.tools.persistence.exception.PersistenceException;
69
import org.gvsig.tools.task.Cancellable;
70
import org.slf4j.Logger;
71
import org.slf4j.LoggerFactory;
72
import org.gvsig.tools.swing.api.TransparencySupport;
73

    
74
public class UrbanHorizontalSignageSymbol extends AbstractSymbol implements ISymbol_v2, TransparencySupport {
75

    
76
    private static final Logger LOG = LoggerFactory.getLogger(UrbanHorizontalSignageSymbol.class);
77
    private static final String SYMBOL_NAME = "UrbanHorizontalSignageSymbol";
78
    private static final String URBAN_HORIZONTAL_SIGNAGE_SYMBOL_PERSISTENCE_DEFINITION_NAME = "UrbanHorizontalSignageSymbol";
79
    
80
    private static final String FIELD_WIDTH = "width";
81
    private static final String FIELD_CONTINUITY = "continuity";
82
    private static final String FIELD_SEGMENTS_COLOR = "segmentsColor";
83
    private static final String FIELD_SEGMENTS_LENGTH = "segmentsLength";
84
    private static final String FIELD_HOLES_COLOR = "holesColor";
85
    private static final String FIELD_HOLES_LENGTH = "holesLength";
86
    private static final String FIELD_PAINT_HOLES = "paintHoles";
87
    private static final String FIELD_GAP_WIDTH = "gapWidth";
88
    private static final String FIELD_ROUND_VERTEX = "roundVertex";
89
    private static final String FIELD_SEGMENTS_GEOMETRY = "segmentsGeometry";
90
    private static final String FIELD_HOLES_GEOMETRY = "holesGeometry";
91
    private static final String FIELD_TRANSPARENCY = "transparency";
92
    private static final String FIELD_MUST_DRAW_ORIGINAL_GEOMETRY = "mustDrawOriginalGeometry";
93
    private static final String FIELD_COLOR_FOR_ORIGINAL_GEOMETRY = "colorForOriginalGeometry";
94
    
95

    
96

    
97
//    private static final String FIELD_SYMBOL_FOR_SELECTION = "symbolForSelection";
98
    private UrbanHorizontalSignageData data;
99

    
100
    transient private UrbanHorizontalSignageSymbol symbolForSelection;
101
    
102
    private boolean mustDrawOriginalGeometry;
103
    private Color colorForOriginalGeometry;
104
    private double cartographicSize;
105
    private double transparency; //[0.0, 1.0]
106

    
107
    public UrbanHorizontalSignageSymbol() {
108
        super();
109
        this.mustDrawOriginalGeometry = false;
110
        this.transparency = 1.0;
111
    }
112

    
113
    public void setData(UrbanHorizontalSignageData data) {
114
        this.data = data;
115
    }
116

    
117
    public UrbanHorizontalSignageData getData() {
118
        return data;
119
    }
120

    
121
    /**
122
     * Sets the transparency for symbol. The valid values are in [0.0, 1.0]
123
     * 
124
     * @param transparency 
125
     */
126
    @Override
127
    public void setTransparency(double transparency) {
128
        if(transparency < 0 || transparency > 1.0){
129
            throw new IllegalArgumentException("Transparency value must be in [0.0, 1.0] ("+transparency+")");
130
        }
131
        this.transparency = transparency;
132
    }
133

    
134
    @Override
135
    public double getTransparency() {
136
        return transparency;
137
    }
138
    
139
    @Override
140
    public ISymbol getSymbolForSelection() {
141
        if (symbolForSelection == null) {
142
            symbolForSelection = (UrbanHorizontalSignageSymbol) cloneForSelection();
143
            symbolForSelection.mustDrawOriginalGeometry = true;
144
        } else {
145
            symbolForSelection.setColor(MapContext.getSelectionColor());
146
        }
147
        return symbolForSelection;
148
    }
149

    
150
    @Override
151
    public void draw(Graphics2D g, AffineTransform affineTransform,
152
            Geometry originalGeometry, Feature feature, Cancellable cancel) {
153
        
154
        if (true) {
155
            // Esto deberia ser para optimizar el pintado de 
156
            // geometrias grandes.
157
            try {
158
                Geometry env = originalGeometry.getEnvelope().getGeometry();
159
                env.transform(affineTransform);
160
                Envelope env2 = env.getEnvelope();
161
                if (env2.getLength(0) < 1.5 && env2.getLength(1) < 1.5) {
162
                    g.setColor(data.getSegmentsColor());
163
                    Point upperCorner = env2.getUpperCorner();
164
                    int x = (int) upperCorner.getX();
165
                    int y = (int) upperCorner.getY();
166
                    g.drawLine(x, y, x, y);
167
                    return;
168
                }
169
            } catch (Exception ex) {
170
                LOG.warn("Error optimizing the drawing of the geometry. Continues with normal drawing.", ex);
171
                // Do nothing, continue with the draw of the original geometry
172
            }
173
        }
174

    
175
        UrbanHorizontalSignageManager uhsManager = UrbanHorizontalSignageLocator.getUrbanHorizontalSignageManager();
176
        uhsManager.calculateGeometries(originalGeometry, data);
177
        
178
        MultiPolygon geom = data.getSegmentsGeometry();
179
        if (geom != null && geom.getPrimitivesNumber() > 0) {
180
            Color color = data.getSegmentsColor();
181
            Color transparentColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), (int)(255*transparency));
182
            g.setColor(transparentColor);
183
            g.fill(geom.getShape(affineTransform));
184
        }
185

    
186
        switch (data.getContinuity()) {
187
            case CONTINUITY_MODE_CONT_DISC:
188
            case CONTINUITY_MODE_DISC_CONT:
189
            case CONTINUITY_MODE_DISC:
190
            case CONTINUITY_MODE_DISC_DISC:
191
                if (data.isPaintHoles()) {
192
                    geom = data.getHolesGeometry();
193
                    if (geom != null && geom.getPrimitivesNumber() > 0) {
194
                        Color color = data.getHolesColor();
195
                        Color transparentColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), (int)(255*transparency));
196
                        g.setColor(transparentColor);
197
                        g.fill(geom.getShape(affineTransform));
198
                    }
199
                }
200
        }
201

    
202
        //For debug purposse only
203
        if(mustDrawOriginalGeometry){
204
            g.setColor(getColor());
205
            g.draw(originalGeometry.getShape(affineTransform));
206
        }
207

    
208
    }
209

    
210
    @Override
211
    public int getOnePointRgb() {
212
        return data.getSegmentsColor().getRGB();
213
    }
214

    
215
    @Override
216
    public void drawInsideRectangle(Graphics2D g,
217
            AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
218
        
219
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
220
        
221
        final int hGap = (int) (r.getWidth() * 0.1); // the left and right margins
222
        final int vPos = 1;                                                  // the top and bottom margins
223
        final int splitCount = 3;                                          // number of lines
224
        final int splitHSize = (r.width - hGap - hGap) / splitCount;
225
        int hPos = hGap;
226
        boolean swap = false;
227

    
228
        Line geom = GeometryUtils.createLine(Geometry.SUBTYPES.GEOM2D);
229
        geom.addVertex(r.x + hPos, r.y + r.height - vPos);
230

    
231
        for (int i = 0; i < splitCount; i++) {
232
            swap = !swap;
233
            geom.addVertex(r.x + hPos + splitHSize, (swap ? vPos : r.height - vPos) + r.y);
234
            hPos += splitHSize;
235
        }
236

    
237
        try {
238
            if (properties == null) {
239
                draw(g, new AffineTransform(), geom, null, null);
240
            } else {
241
                print(g, new AffineTransform(), geom, properties);
242
            }
243
        } catch (Exception e) {
244
            throw new SymbolDrawingException(SymbolDrawingException.UNSUPPORTED_SET_OF_SETTINGS);
245
        }
246

    
247
    }
248

    
249
    @Override
250
    public Object clone() throws CloneNotSupportedException {
251
        UrbanHorizontalSignageSymbol copy = (UrbanHorizontalSignageSymbol) super.clone();
252

    
253
        if (symbolForSelection != null) {
254
            copy.symbolForSelection = (UrbanHorizontalSignageSymbol) symbolForSelection
255
                    .clone();
256
        }
257

    
258
        return copy;
259
    }
260

    
261
    @Override
262
    public void loadFromState(PersistentState state) throws PersistenceException {
263
        // Set parent style properties
264
        super.loadFromState(state);
265
        
266
        UrbanHorizontalSignageData data = new DefaultUrbanHorizontalSignageData();
267
        data.setWidth(state.getDouble(FIELD_WIDTH, UrbanHorizontalSignageData.DEFAULT_WIDTH_VALUE));
268
        data.setContinuity(state.getInt(FIELD_CONTINUITY, UrbanHorizontalSignageData.DEFAULT_CONTINUITY_VALUE));
269
        
270
        Color color = (Color) state.get(FIELD_SEGMENTS_COLOR);
271
        data.setSegmentsColor(color != null ? color : UrbanHorizontalSignageData.DEFAULT_SEGMENT_COLOR_VALUE);
272
        
273
        data.setSegmentsLength(state.getDouble(FIELD_SEGMENTS_LENGTH, UrbanHorizontalSignageData.DEFAULT_SEGMENT_LENGTH_VALUE));
274
        
275
        color = (Color) state.get(FIELD_HOLES_COLOR);
276
        data.setHolesColor(color != null ? color : UrbanHorizontalSignageData.DEFAULT_HOLES_COLOR_VALUE);
277
        
278
        data.setHolesLength(state.getDouble(FIELD_HOLES_LENGTH, UrbanHorizontalSignageData.DEFAULT_HOLES_LENGTH_VALUE));
279
        data.setGapWidth(state.getDouble(FIELD_GAP_WIDTH, UrbanHorizontalSignageData.DEFAULT_GAP_WIDTH_VALUE));
280
        data.setRoundVertex(state.getBoolean(FIELD_ROUND_VERTEX, UrbanHorizontalSignageData.DEFAULT_ROUND_VERTEX_VALUE));
281
        
282
        this.transparency = state.getDouble(FIELD_TRANSPARENCY, 1.0);
283
        this.mustDrawOriginalGeometry = state.getBoolean(FIELD_MUST_DRAW_ORIGINAL_GEOMETRY, false);
284
        color = (Color) state.get(FIELD_COLOR_FOR_ORIGINAL_GEOMETRY);
285
        this.colorForOriginalGeometry = color != null ? color : MapContext.getSelectionColor();
286
        this.data = data;
287

    
288
    }
289

    
290
    @Override
291
    public void saveToState(PersistentState state) throws PersistenceException {
292
        // Save parent fill symbol properties
293
        super.saveToState(state);
294

    
295
        // Save own properties
296
        
297
        if(data != null){
298
            state.set(FIELD_WIDTH, data.getWidth());
299
            state.set(FIELD_CONTINUITY, data.getContinuity());
300
            state.set(FIELD_SEGMENTS_COLOR, data.getSegmentsColor());
301
            state.set(FIELD_SEGMENTS_LENGTH, data.getSegmentsLength());
302
            state.set(FIELD_HOLES_COLOR, data.getHolesColor());
303
            state.set(FIELD_HOLES_LENGTH, data.getHolesLength());
304
            state.set(FIELD_PAINT_HOLES, data.isPaintHoles());
305
            state.set(FIELD_GAP_WIDTH, data.getGapWidth());
306
            state.set(FIELD_ROUND_VERTEX, data.isRoundVertex());
307
        }
308
        state.set(FIELD_MUST_DRAW_ORIGINAL_GEOMETRY, mustDrawOriginalGeometry);
309
        state.set(FIELD_COLOR_FOR_ORIGINAL_GEOMETRY, colorForOriginalGeometry);
310
        state.set(FIELD_TRANSPARENCY, this.getTransparency());
311
    }
312

    
313
    @Override
314
    public void getPixExtentPlus(Geometry geom, float[] distances, ViewPort viewPort, int dpi) {
315
        float cs = (float) getCartographicSize(viewPort, dpi, geom);
316
        // TODO and add the line offset
317
        distances[0] = cs;
318
        distances[1] = cs;
319
    }
320

    
321
    @Override
322
    public int getSymbolType() {
323
        return Geometry.TYPES.CURVE;
324
    }
325

    
326
    @Override
327
    public boolean isSuitableFor(Geometry geom) {
328
        return geom.getGeometryType().isTypeOf(Geometry.TYPES.CURVE);
329
    }
330

    
331
    @Override
332
    public Color getColor() {
333
        return this.colorForOriginalGeometry;
334
    }
335

    
336
    @Override
337
    public void setColor(Color color) {
338
        this.colorForOriginalGeometry = color;
339
    }
340

    
341
    @Override
342
    public void print(Graphics2D g, AffineTransform at, Geometry shape, PrintAttributes properties) {
343
        draw(g, at, shape, null, null);
344
//                double originalSize = getLineWidth();
345
//                double size=originalSize;
346
//                // scale it to size
347
//                int pq = properties.getPrintQuality();
348
//                if (pq == PrintAttributes.PRINT_QUALITY_NORMAL){
349
//                        size *= (double) 300/72;
350
//                }else if (pq == PrintAttributes.PRINT_QUALITY_HIGH){
351
//                        size *= (double) 600/72;
352
//                }else if (pq == PrintAttributes.PRINT_QUALITY_DRAFT){
353
//                        // size *= 72/72; // (which is the same than doing nothing)
354
//                }
355
//                setLineWidth(size);
356
//                draw(g,at,geom,null, null);
357
//                setLineWidth(originalSize);
358
    }
359

    
360
    @Override
361
    public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
362
        double oldSize = getData().getWidth();
363
        setCartographicSize(getCartographicSize(
364
                viewPort,
365
                dpi,
366
                geom),
367
                geom);
368
        return oldSize;
369

    
370
//        return 0;
371
    }
372

    
373
    @Override
374
    public void setCartographicSize(double cartographicSize, Geometry geom) {
375
        //DO NOTHING
376
        this.getData().setWidth(cartographicSize);
377
    }
378

    
379
    @Override
380
    public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
381
        return CartographicSupportToolkit.getCartographicLength(
382
                this,
383
                getData().getWidth(),
384
                viewPort,
385
                dpi
386
        );
387

    
388
//        return 0;
389
    }
390

    
391
//    public static class RegisterPersistence implements Callable {
392
//
393
//        @Override
394
//        public Object call() throws Exception {
395
//            PersistenceManager manager = ToolsLocator.getPersistenceManager();
396
//            if (manager.getDefinition(URBAN_HORIZONTAL_SIGNAGE_SYMBOL_PERSISTENCE_DEFINITION_NAME) == null) {
397
//                DynStruct definition = manager.addDefinition(
398
//                        UrbanHorizontalSignageSymbol.class,
399
//                        URBAN_HORIZONTAL_SIGNAGE_SYMBOL_PERSISTENCE_DEFINITION_NAME,
400
//                        URBAN_HORIZONTAL_SIGNAGE_SYMBOL_PERSISTENCE_DEFINITION_NAME + " Persistence definition",
401
//                        null,
402
//                        null
403
//                );
404
//                // Extend the LineSymbol base definition
405
//                definition.extend(manager.getDefinition(AbstractSymbol.SYMBOL_PERSISTENCE_DEFINITION_NAME));
406
//                
407
//                definition.addDynFieldDouble(FIELD_WIDTH).setMandatory(false);
408
//                definition.addDynFieldInt(FIELD_CONTINUITY).setMandatory(false);
409
//                definition.addDynFieldObject(FIELD_SEGMENTS_COLOR).setClassOfValue(Color.class).setMandatory(false);
410
//                definition.addDynFieldDouble(FIELD_SEGMENTS_LENGTH).setMandatory(false);
411
//                definition.addDynFieldObject(FIELD_HOLES_COLOR).setClassOfValue(Color.class).setMandatory(false);
412
//                definition.addDynFieldDouble(FIELD_HOLES_LENGTH).setMandatory(false);
413
//                definition.addDynFieldBoolean(FIELD_PAINT_HOLES).setMandatory(false);
414
//                definition.addDynFieldDouble(FIELD_GAP_WIDTH).setMandatory(false);
415
//                definition.addDynFieldBoolean(FIELD_ROUND_VERTEX).setMandatory(false);
416
//                definition.addDynFieldDouble(FIELD_TRANSPARENCY).setMandatory(false);
417
//                definition.addDynFieldBoolean(FIELD_MUST_DRAW_ORIGINAL_GEOMETRY).setMandatory(false);
418
//                definition.addDynFieldObject(FIELD_COLOR_FOR_ORIGINAL_GEOMETRY).setClassOfValue(Color.class).setMandatory(false);
419
//            }
420
//            return Boolean.TRUE;
421
//        }
422
//
423
//    }
424

    
425
    public static class RegisterSymbol implements Callable {
426

    
427
        @Override
428
        public Object call() throws Exception {
429
            int[] shapeTypes;
430
            SymbolManager manager = MapContextLocator.getSymbolManager();
431

    
432
            shapeTypes = new int[]{Geometry.TYPES.CURVE, Geometry.TYPES.ARC,
433
                Geometry.TYPES.MULTICURVE, Geometry.TYPES.CIRCUMFERENCE,
434
                Geometry.TYPES.PERIELLIPSE, Geometry.TYPES.SPLINE,
435
                Geometry.TYPES.LINE, Geometry.TYPES.MULTILINE};
436
            manager.registerSymbol(SYMBOL_NAME,
437
                    shapeTypes,
438
                    UrbanHorizontalSignageSymbol.class);
439

    
440
            return Boolean.TRUE;
441
        }
442

    
443
    }
444

    
445
}