Statistics
| Revision:

root / trunk / extensions / extSymbology / src / org / gvsig / symbology / fmap / symbols / PictureLineSymbol.java @ 20905

History | View | Annotate | Download (10.4 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
package org.gvsig.symbology.fmap.symbols;
42

    
43
import java.awt.BasicStroke;
44
import java.awt.Color;
45
import java.awt.Graphics2D;
46
import java.awt.Rectangle;
47
import java.awt.geom.AffineTransform;
48
import java.awt.geom.PathIterator;
49
import java.awt.geom.Point2D;
50
import java.io.IOException;
51
import java.net.MalformedURLException;
52
import java.net.URL;
53

    
54
import javax.print.attribute.PrintRequestAttributeSet;
55

    
56
import org.apache.batik.ext.awt.geom.PathLength;
57
import org.apache.log4j.Logger;
58
import org.gvsig.symbology.fmap.styles.BackgroundFileStyle;
59

    
60
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
61
import com.iver.cit.gvsig.fmap.Messages;
62
import com.iver.cit.gvsig.fmap.ViewPort;
63
import com.iver.cit.gvsig.fmap.core.CartographicSupportToolkit;
64
import com.iver.cit.gvsig.fmap.core.FPolyline2D;
65
import com.iver.cit.gvsig.fmap.core.FShape;
66
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
67
import com.iver.cit.gvsig.fmap.core.symbols.AbstractLineSymbol;
68
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
69
import com.iver.utiles.XMLEntity;
70
import com.iver.utiles.swing.threads.Cancellable;
71

    
72
/**
73
 * PictureLineSymbol allows to use any symbol defined as an image (by an image file)
74
 * supported  by gvSIG.This symbol will be used as an initial object.The line will be
75
 * painted as a succession of puntual symbols through the path defined by it(the line).
76
 *
77
 * @author jaume dominguez faus - jaume.dominguez@iver.es
78
 */
79
public class PictureLineSymbol extends AbstractLineSymbol  {
80
//        transient private BufferedImage img;
81
//        transient private BufferedImage selImg;
82
        transient private PictureLineSymbol selectionSym;
83
        private String selImagePath;
84
        private double width;
85
        private String imagePath;
86
        private boolean selected;
87
        private double xScale = 1, csXScale = xScale;
88
        private double yScale = 1, csYScale = yScale;
89
        
90
        private BackgroundFileStyle bgImage;
91
        private BackgroundFileStyle bgSelImage;
92
        /**
93
         * Constructor method
94
         *
95
         */
96
        public PictureLineSymbol() {
97
                super();
98
        }
99
        /**
100
         * Constructor method
101
         * @param imageURL, URL of the normal image
102
         * @param selImageURL, URL of the image when it is selected in the map
103
         * @throws IOException
104
         */
105

    
106
        public PictureLineSymbol(URL imageURL, URL selImageURL) throws IOException {
107
                setImage(imageURL);
108
                if (selImageURL!=null)
109
                        setSelImage(selImageURL);
110
                else setSelImage(imageURL);
111
        }
112
        /**
113
         * Sets the URL for the image to be used as a picture line symbol
114
         * @param imageFile, File
115
         * @throws IOException
116
         */
117
        public void setImage(URL imageUrl) throws IOException{
118

    
119
                bgImage= BackgroundFileStyle.createStyleByURL(imageUrl);
120
                imagePath = imageUrl.toString();
121
        }
122
        /**
123
         * Sets the URL for the image to be used as a picture line symbol (when it is selected in the map)
124
         * @param imageFile, File
125
         * @throws IOException
126
         */
127
        public void setSelImage(URL selImageUrl) throws IOException{
128

    
129
                bgSelImage= BackgroundFileStyle.createStyleByURL(selImageUrl);
130
                selImagePath = selImageUrl.toString();
131
        }
132

    
133

    
134
        public void setLineWidth(double width) {
135
                this.width = width;
136
                getLineStyle().setLineWidth((float) width);
137
        }
138

    
139
        public double getLineWidth() {
140
                return width;
141
        }
142

    
143
        public ISymbol getSymbolForSelection() {
144
                if (selectionSym == null) {
145
                        selectionSym = (PictureLineSymbol) SymbologyFactory.createSymbolFromXML(getXMLEntity(), getDescription());
146
                        selectionSym.selected=true;
147
                        selectionSym.selectionSym = selectionSym; // avoid too much lazy creations
148

    
149
                }
150
                return selectionSym;
151

    
152
        }
153
        
154
        public void draw(Graphics2D g, AffineTransform affineTransform, FShape shp, Cancellable cancel) {
155
                float csWidth = getLineStyle().getLineWidth();
156
                g.setClip(new BasicStroke((float) csWidth, BasicStroke.CAP_ROUND,BasicStroke.CAP_ROUND).createStrokedShape(shp));
157
                BackgroundFileStyle bg = (!selected) ? bgImage : bgSelImage ;
158

    
159
                if (csXScale<=0 &&  csYScale<=0)
160
                        return;
161

    
162
                Rectangle bounds = bg.getBounds();
163
                final double imageWidth  = bounds.getWidth()  * csXScale;
164
                final double imageHeight = bounds.getHeight() * csYScale;
165

    
166
                if (imageWidth==0 || imageHeight==0) return;
167
                int height = (int) csWidth;
168

    
169
                PathLength pl = new PathLength(shp);
170
                PathIterator iterator = ((FPolyline2D) shp).getPathIterator(null, 0.8);
171
                double[] theData = new double[6];
172
                Point2D firstPoint = null, startPoint = null, endPoint = null;
173
                if (!iterator.isDone()) {
174
                        if ( iterator.currentSegment(theData) != PathIterator.SEG_CLOSE) {
175
                                firstPoint = new Point2D.Double(theData[0], theData[1]);
176
                        }
177
                }
178
                float currentPathLength = 1;
179

    
180
                Rectangle rect = new Rectangle();
181

    
182
                while ((cancel==null || !cancel.isCanceled()) && !iterator.isDone()) {
183

    
184
                        int theType = iterator.currentSegment(theData);
185
                        switch (theType) {
186
                        case PathIterator.SEG_MOVETO:
187
                                startPoint = new Point2D.Double(theData[0], theData[1]);
188

    
189
                                endPoint = null;
190
                                iterator.next();
191

    
192
                                continue;
193

    
194
                        case PathIterator.SEG_LINETO:
195
                        case PathIterator.SEG_QUADTO:
196
                        case PathIterator.SEG_CUBICTO:
197
                                endPoint = new Point2D.Double(theData[0], theData[1]);
198

    
199
                                break;
200
                        case PathIterator.SEG_CLOSE:
201
                                endPoint = startPoint;
202
                                startPoint = firstPoint;
203
                                break;
204
                        }
205

    
206
                        double a = endPoint.getX() - startPoint.getX();
207
                        double b = endPoint.getY() - startPoint.getY();
208
                        double theta = pl.angleAtLength(currentPathLength);
209

    
210
                        double x = startPoint.getX();
211
                        double y = startPoint.getY();
212

    
213
                        // Theorem of Pythagoras
214
                        float segmentLength = (float) Math.sqrt(a*a + b*b);
215

    
216
                        // compute how many times the image has to be drawn
217
                        // to completely cover this segment's length
218
                        int count = (int) Math.ceil(segmentLength/imageWidth);
219

    
220
                        for (int i = 0; (cancel==null || !cancel.isCanceled()) && i < count; i++) {
221
                                g.translate(x, y);
222
                                g.rotate(theta);
223

    
224
                                double xOffsetTranslation = imageWidth*i;
225

    
226
                                
227
                                g.translate(xOffsetTranslation, -csWidth);
228
                                
229
                                rect.setBounds(0, (int) Math.round(height*.5), (int) Math.ceil(imageWidth), height);
230
                                bg.drawInsideRectangle(g, rect, false);
231
                                g.setColor(Color.red);
232
                                g.translate(-xOffsetTranslation, csWidth);
233

    
234
                                g.rotate(-theta);
235
                                g.translate(-x, -y);
236
                        }
237

    
238
                        startPoint = endPoint;
239
                        currentPathLength += segmentLength;
240
                        iterator.next();
241
                }
242

    
243
                g.setClip(null);
244
                g.setColor(Color.red);
245
                
246
        }
247
        
248
        
249
        public XMLEntity getXMLEntity() {
250
                XMLEntity xml = new XMLEntity();
251
                xml.putProperty("className", getClassName());
252
                xml.putProperty("isShapeVisible", isShapeVisible());
253
                xml.putProperty("desc", getDescription());
254
                xml.putProperty("imagePath", imagePath);
255
                xml.putProperty("selImagePath", selImagePath);
256
                xml.putProperty("lineWidth", getLineWidth());
257
                xml.putProperty("xScale", getXScale());
258
                xml.putProperty("yScale", getYScale());
259

    
260
                // measure unit
261
                xml.putProperty("unit", getUnit());
262

    
263
                // reference system
264
                xml.putProperty("referenceSystem", getReferenceSystem());
265

    
266
                return xml;
267

    
268
        }
269

    
270
        public void setXMLEntity(XMLEntity xml) {
271
                System.out.println(this.getClass().getClassLoader());
272
                setDescription(xml.getStringProperty("desc"));
273
                setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
274
                imagePath = xml.getStringProperty("imagePath");
275
                selImagePath = xml.getStringProperty("selImagePath");
276
                setLineWidth(xml.getDoubleProperty("lineWidth"));
277
                setXScale(xml.getDoubleProperty("xScale"));
278
                setYScale(xml.getDoubleProperty("yScale"));
279
                setReferenceSystem(xml.getIntProperty("referenceSystem"));
280
                setUnit(xml.getIntProperty("unit"));
281
                
282

    
283
                try {
284
                        setImage(new URL(imagePath));
285
                        setSelImage(new URL(selImagePath));
286
                } catch (MalformedURLException e) {
287
                        Logger.getLogger(getClass()).error(Messages.getString("invalid_url"));
288
                } catch (IOException e) {
289
                        Logger.getLogger(getClass()).error(Messages.getString("invalid_url"));
290
                                        
291
                }
292

    
293
        }
294
        /**
295
         * Sets the yscale for the picture line symbol
296
         * @param yScale
297
         */
298
        public void setYScale(double yScale) {
299
                this.yScale = yScale;
300
                this.csYScale = yScale;
301
        }
302
        /**
303
         * Sets the xscale for the picture line symbol
304
         * @param xScale
305
         */
306
        public void setXScale(double xScale) {
307
                this.xScale = xScale;
308
                this.csXScale = xScale;
309
        }
310

    
311
        public String getClassName() {
312
                return getClass().getName();
313
        }
314

    
315
        public void print(Graphics2D g, AffineTransform at, FShape shape,
316
                        PrintRequestAttributeSet properties) throws ReadDriverException {
317
                // TODO Implement it
318
                throw new Error("Not yet implemented!");
319

    
320
        }
321
        /**
322
         * Returns the path of the image that is used as a picture line symbol (when it
323
         * is selected in the map)
324
         * @return selimagePath,String
325
         */
326
        public String getSelImagePath() {
327
                return selImagePath;
328
        }
329
        /**
330
         * Returns the path of the image that is used as a picture line symbol
331
         * @return imagePath,String
332
         */
333
        public String getImagePath() {
334
                return imagePath;
335
        }
336
        /**
337
         * Returns the xscale for the picture line symbol
338
         * @param xScale
339
         */
340
        public double getXScale() {
341
                return xScale;
342
        }
343
        /**
344
         * Returns the yscale for the picture line symbol
345
         * @param yScale
346
         */
347
        public double getYScale() {
348
                return yScale;
349
        }
350
        
351
        @Override
352
        public void setCartographicSize(double cartographicSize, FShape shp) {
353
                getLineStyle().setLineWidth((float) cartographicSize);
354
                double scale = cartographicSize/width;
355
                csXScale = xScale * scale;
356
                csYScale = yScale * scale;
357
        }
358
        
359
        @Override
360
        public double toCartographicSize(ViewPort viewPort, double dpi, FShape shp) {
361
                double s = super.toCartographicSize(viewPort, dpi, shp);
362
                setCartographicSize(CartographicSupportToolkit.
363
                                getCartographicLength(this, width, viewPort, dpi), shp);
364
                return s;
365
        }
366
}