Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / core / symbols / MultiLayerLineSymbol.java @ 13749

History | View | Annotate | Download (10.7 KB)

1
/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib��ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41

    
42
/* CVS MESSAGES:
43
*
44
* $Id: MultiLayerLineSymbol.java 13749 2007-09-17 14:16:11Z jaume $
45
* $Log$
46
* Revision 1.14  2007-09-17 14:16:11  jaume
47
* multilayer symbols sizing bug fixed
48
*
49
* Revision 1.13  2007/09/17 09:33:47  jaume
50
* some multishapedsymbol bugs fixed
51
*
52
* Revision 1.12  2007/08/09 08:04:48  jvidal
53
* javadoc
54
*
55
* Revision 1.11  2007/07/23 06:52:55  jaume
56
* Added support for arrow line decorator (start commiting)
57
*
58
* Revision 1.10  2007/07/18 06:54:34  jaume
59
* continuing with cartographic support
60
*
61
* Revision 1.9  2007/07/03 10:58:29  jaume
62
* first refactor on CartographicSupport
63
*
64
* Revision 1.8  2007/06/29 13:07:01  jaume
65
* +PictureLineSymbol
66
*
67
* Revision 1.7  2007/05/17 09:32:06  jaume
68
* *** empty log message ***
69
*
70
* Revision 1.6  2007/05/08 08:47:40  jaume
71
* *** empty log message ***
72
*
73
* Revision 1.5  2007/04/17 07:01:53  bsanchez
74
* - Corregido fallo de Double.MIN_VALUE por Double.NEGATIVE_INFINITY comentado por Victor Olaya.
75
*
76
* Revision 1.4  2007/03/26 14:26:02  jaume
77
* implemented Print
78
*
79
* Revision 1.3  2007/03/20 16:01:21  jaume
80
* *** empty log message ***
81
*
82
* Revision 1.2  2007/03/09 11:20:56  jaume
83
* Advanced symbology (start committing)
84
*
85
* Revision 1.1.2.3  2007/02/21 16:09:02  jaume
86
* *** empty log message ***
87
*
88
* Revision 1.1.2.2  2007/02/21 07:34:09  jaume
89
* labeling starts working
90
*
91
* Revision 1.1.2.1  2007/02/16 10:54:12  jaume
92
* multilayer splitted to multilayerline, multilayermarker,and  multilayerfill
93
*
94
*
95
*/
96
package com.iver.cit.gvsig.fmap.core.symbols;
97

    
98
import java.awt.Color;
99
import java.awt.Graphics2D;
100
import java.awt.Rectangle;
101
import java.awt.Shape;
102
import java.awt.geom.AffineTransform;
103
import java.util.ArrayList;
104

    
105
import javax.print.attribute.PrintRequestAttributeSet;
106

    
107
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
108
import com.iver.cit.gvsig.fmap.MapContext;
109
import com.iver.cit.gvsig.fmap.ViewPort;
110
import com.iver.cit.gvsig.fmap.core.FShape;
111
import com.iver.cit.gvsig.fmap.core.IGeometry;
112
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
113
import com.iver.cit.gvsig.fmap.core.styles.ILineStyle;
114
import com.iver.cit.gvsig.fmap.core.v02.FSymbol;
115
import com.iver.utiles.XMLEntity;
116
/**
117
 * MultiLayerLineSymbol allows to create new symbols using a composition of several lineal
118
 * symbols (xxxLineSymbol implementing ILineSymbol)and be treated as an only one symbol.
119
 *
120
 * @author  jaume dominguez faus - jaume.dominguez@iver.es
121
 */
122
public class MultiLayerLineSymbol extends AbstractLineSymbol implements
123
                ILineSymbol, IMultiLayerSymbol {
124
        private ILineSymbol[] layers = new ILineSymbol[0];
125
        private ILineSymbol selectionSymbol;
126
        private double width;
127

    
128
        public Color getColor() {
129
                /*
130
                 * a multilayer symbol does not define any color, the color
131
                 * of each layer is defined by the layer itself
132
                 */
133
                return null;
134
        }
135

    
136
        public ILineStyle getLineStyle() {
137
                /*
138
                 * a multilayer symbol does not define any style, the style
139
                 * of each layer is defined by the layer itself
140
                 */
141
                return null;
142
        }
143

    
144
        public double getLineWidth() {
145
                return width;
146
        }
147

    
148
        public void setLineColor(Color color) {
149
                /*
150
                 * will apply the color to each layer
151
                 */
152
                for (int i = 0; i < layers.length; i++) {
153
                        layers[i].setLineColor(color);
154
                }
155
        }
156

    
157
        public void setLineStyle(ILineStyle lineStyle) {
158
                /*
159
                 * will apply the same patter to each layer
160
                 */
161
                for (int i = 0; i < layers.length; i++) {
162
                        layers[i].setLineStyle(lineStyle);
163
                }
164
        }
165

    
166
        public void setLineWidth(double width) {
167
                /* take the biggest width of the layer set and
168
                 * extract a factor scale that will be applied
169
                 * to each layer.
170
                 */
171
                if (width > 0) {
172
                        double scaleFactor = width / getLineWidth();        
173
                        this.width = width;
174
                        for (int i = 0; i < layers.length; i++) {
175
                                layers[i].setLineWidth(layers[i].getLineWidth()*scaleFactor);
176
                        }
177
                }
178
        }
179

    
180
        public void draw(Graphics2D g, AffineTransform affineTransform, FShape shp) {
181
                for (int i = 0; i < layers.length; i++) {
182
                        layers[i].draw(g, affineTransform, shp);
183
                }
184
        }
185

    
186
        public void drawInsideRectangle(Graphics2D g, AffineTransform scaleInstance, Rectangle r) {
187
                for (int i = 0; i < layers.length; i++) {
188
                        layers[i].drawInsideRectangle(g, scaleInstance, r);
189
                }
190
        }
191

    
192
        public int getOnePointRgb() {
193
                // will paint only the last layer pixel
194
                return layers[layers.length-1].getOnePointRgb();
195
        }
196

    
197
        public int getPixExtentPlus(Graphics2D g, AffineTransform affineTransform,
198
                        Shape shp) {
199
                // TODO Implement it
200
                throw new Error("Not yet implemented!");
201

    
202
        }
203

    
204
        public ISymbol getSymbolForSelection() {
205
                if (selectionSymbol == null) {
206
                        selectionSymbol = new SimpleLineSymbol();
207
                        selectionSymbol.setDescription(getDescription());
208
                        selectionSymbol.setLineWidth(getLineWidth());
209
                        selectionSymbol.setLineColor(MapContext.getSelectionColor());
210
                }
211
                return selectionSymbol;
212
        }
213

    
214

    
215
        public XMLEntity getXMLEntity() {
216
                XMLEntity xml = new XMLEntity();
217
                xml.putProperty("className", getClass().getName());
218
                xml.putProperty("isShapeVisible", isShapeVisible());
219
                xml.putProperty("desc", getDescription());
220
                xml.putProperty("lineWidth", getLineWidth());
221
                xml.putProperty("unit", getUnit());
222
                xml.putProperty("referenceSystem", getReferenceSystem());
223
                for (int i = 0; i < layers.length; i++) {
224
                        xml.addChild(layers[i].getXMLEntity());
225
                }
226
                return xml;
227
        }
228

    
229
        public boolean isSuitableFor(IGeometry geom) {
230
                return geom.getGeometryType() == FShape.LINE;
231
        }
232

    
233
        public String getClassName() {
234
                return getClass().getName();
235
        }
236

    
237
        public void setXMLEntity(XMLEntity xml) {
238
                setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
239
                setDescription(xml.getStringProperty("desc"));
240
                setLineWidth(xml.getDoubleProperty("lineWidth"));
241
                setUnit(xml.getIntProperty("unit"));
242
                setReferenceSystem(xml.getIntProperty("referenceSystem"));
243
                layers = new ILineSymbol[xml.getChildrenCount()];
244
                for (int i = 0; i < layers.length; i++) {
245
                        layers[i] = (ILineSymbol) SymbologyFactory.createSymbolFromXML(xml.getChild(i), "layer" + i);
246
                }
247
        }
248

    
249
        public void print(Graphics2D g, AffineTransform at, FShape shape, PrintRequestAttributeSet properties)
250
                        throws ReadDriverException {
251
                for (int i = 0; i < layers.length; i++) {
252
                        layers[i].print(g, at, shape, properties);
253
                }
254

    
255
        }
256

    
257
        public void setLayer(int index, ISymbol layer) throws IndexOutOfBoundsException {
258
                layers[index] = (ILineSymbol) layer;
259
        }
260

    
261
        public void swapLayers(int index1, int index2) {
262
                ISymbol aux1 = getLayer(index1), aux2 = getLayer(index2);
263
                layers[index2] = (ILineSymbol) aux1;
264
                layers[index1] = (ILineSymbol) aux2;
265
        }
266

    
267
        public ISymbol getLayer(int layerIndex) {
268
                return layers[layerIndex];
269
        }
270

    
271
        public int getLayerCount() {
272
                return layers.length;
273
        }
274

    
275
        public void addLayer(ISymbol newLayer) {
276
                if (newLayer == null) return;
277

    
278
                selectionSymbol = null; /* forces the selection symbol to be re-created
279
                                                                 * next time it is required
280
                                                                 */
281
                int size = layers.length+1;
282
                ILineSymbol[] newLayers = new ILineSymbol[size];
283
                for (int i = 0; i < newLayers.length-1; i++) {
284
                        newLayers[i] = layers[i];
285
                }
286
                newLayers[size-1] = (ILineSymbol) newLayer;
287
                layers = newLayers;
288
        }
289

    
290
        public void addLayer(ISymbol newLayer, int layerIndex) throws IndexOutOfBoundsException {
291
                if (newLayer == null) return; // null are not allowed
292

    
293
                selectionSymbol = null; /* forces the selection symbol to be re-created
294
                                                                  * next time it is required
295
                                                                  */
296
                if (layerIndex < 0 || layers.length < layerIndex)
297
                        throw new IndexOutOfBoundsException(layerIndex+" < 0 or "+layerIndex+" > "+layers.length);
298
                ArrayList newLayers = new ArrayList();
299
                for (int i = 0; i < layers.length; i++) {
300
                        newLayers.add(layers[i]);
301
                }
302
                newLayers.add(layerIndex, newLayer);
303
                layers = (ILineSymbol[]) newLayers.toArray(new ILineSymbol[0]);
304
        }
305

    
306
        public boolean removeLayer(ISymbol layer) {
307

    
308
                int capacity = 0;
309
                capacity = layers.length;
310
                ArrayList lst = new ArrayList(capacity);
311
                for (int i = 0; i < capacity; i++) {
312
                        lst.add(layers[i]);
313
                }
314
                boolean contains = lst.remove(layer);
315
                layers = (ILineSymbol[])lst.toArray(new ILineSymbol[0]);
316
                return contains;
317
        }
318

    
319
        public int getAlpha() {
320
                // will compute the acumulated opacity
321
                double myAlpha = 0;
322
                for (int i = 0; i < layers.length; i++) {
323
                        double layerAlpha = layers[i].getAlpha()/255D;
324
                        myAlpha += (1-myAlpha)*layerAlpha;
325
                }
326
                int result = (int) Math.round(myAlpha * 255);
327
                return (result>255) ? 255 : result;
328
        }
329

    
330
        public void setAlpha(int outlineAlpha) {
331
                // first, get the biggest alpha in the layers and the index if such layer
332
                int maxAlpha = Integer.MIN_VALUE;
333
                int maxAlphaLayerIndex = 0;
334
                for (int i = 0; i < layers.length; i++) {
335
                        if (layers[i].getAlpha() > maxAlpha) {
336
                                maxAlpha = layers[i].getAlpha();
337
                                maxAlphaLayerIndex = i;
338
                        }
339
                }
340

    
341
                // now, max alpha takes the value of the desired alpha and the rest
342
                // will take a scaled (to biggest alpha) alpha value
343
                for (int i = 0; i < layers.length; i++) {
344
                        if (i!=maxAlphaLayerIndex) {
345
                                double scaledAlpha = (double) layers[i].getAlpha()/maxAlpha;
346
                                layers[i].setAlpha((int) (outlineAlpha*scaledAlpha));
347
                        } else {
348
                                layers[i].setAlpha(outlineAlpha);
349
                        }
350
                }
351

    
352
        }
353

    
354
        public int getUnit() {
355
                return layers[0].getUnit();
356
        }
357

    
358
        public void setUnit(int unitIndex) {
359
                for (int i = 0; i < layers.length; i++) {
360
                        layers[i].setUnit(unitIndex);
361
                }
362
        }
363
        
364
        
365
//        public double computeCartographicSize(ViewPort viewPort, double dpi, FShape shp) {
366
//                double dpiScale = dpi/MapContext.getScreenDPI();
367
//                int unit = getUnit();
368
//                double widthInPixel;
369
//                if (unit==-1) {
370
//                        widthInPixel = getLineWidth();
371
//                } else {
372
//                        double dist1Pixel = viewPort.getDist1pixel()*MapContext.CHANGEM[viewPort.getMapUnits()];
373
//                        double lineWidth = getLineWidth()*MapContext.CHANGEM[unit];
374
//                        widthInPixel = lineWidth/dist1Pixel;
375
//                }
376
//                return new double[] {
377
//                                getLineWidth(),
378
//                                (widthInPixel*dpiScale)
379
//                                };
380
//        }
381

    
382

    
383
}