Statistics
| Revision:

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

History | View | Annotate | Download (10.3 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 com.iver.cit.gvsig.fmap.core.symbols;
42

    
43
import java.awt.BasicStroke;
44
import java.awt.Color;
45
import java.awt.Graphics2D;
46
import java.awt.Shape;
47
import java.awt.geom.AffineTransform;
48
import java.awt.geom.PathIterator;
49
import java.awt.geom.Point2D;
50
import java.awt.image.BufferedImage;
51
import java.io.File;
52
import java.io.IOException;
53
import java.net.URL;
54
import java.util.Random;
55

    
56
import javax.imageio.ImageIO;
57
import javax.print.attribute.PrintRequestAttributeSet;
58

    
59
import org.apache.batik.ext.awt.geom.PathLength;
60
import org.apache.log4j.Logger;
61

    
62
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
63
import com.iver.cit.gvsig.fmap.Messages;
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.utiles.XMLEntity;
68

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

    
100
        public PictureLineSymbol(URL imageURL, URL selImageURL) throws IOException {
101
                this(new File(imageURL.getFile()), selImageURL !=null ? new File(selImageURL.getFile()) : null);
102
        }
103
        /**
104
         * Constructor method
105
         * @param imageFile, File of the normal image
106
         * @param selImageFile, File of the image when it is selected in the map
107
         * @throws IOException
108
         */
109
        public PictureLineSymbol(File imageFile, File selImageFile) throws IOException {
110
                setImage(imageFile);
111
                if (selImageFile!=null)
112
                        setSelImage(selImageFile);
113
        }
114
        /**
115
         * Sets the file for the image to be used as a picture line symbol
116
         * @param imageFile, File
117
         * @throws IOException
118
         */
119
        public void setImage(File imageFile) throws IOException{
120
                img = ImageIO.read(imageFile);
121
                imagePath = imageFile.getAbsolutePath();
122
//                imageOutline = null;
123
        }
124
        /**
125
         * Sets the file for the image to be used as a picture line symbol (when it is selected in the map)
126
         * @param imageFile, File
127
         * @throws IOException
128
         */
129
        public void setSelImage(File imageFile) throws IOException{
130
                if (imageFile!=null && imageFile.exists()) {
131
                        selImg = ImageIO.read(imageFile);
132
                        selImagePath = imageFile.getAbsolutePath();
133
                } else {
134
                        selImg = img;
135
                        selImagePath = imagePath;
136
                }
137

    
138
//                imageOutline = null;
139
        }
140

    
141
        public void setLineWidth(double width) {
142
                this.width = width;
143

    
144
        }
145

    
146
        public double getLineWidth() {
147
                return width;
148
        }
149

    
150
        public ISymbol getSymbolForSelection() {
151
                if (selectionSym == null) {
152
                        selectionSym = (PictureLineSymbol) SymbologyFactory.createSymbolFromXML(getXMLEntity(), getDescription());
153
                        selectionSym.selected=true;
154
                        selectionSym.selectionSym = selectionSym; // avoid too much lazy creations
155

    
156
                }
157
                return selectionSym;
158

    
159
        }
160
        /**
161
         * Returns the image that will substitute the picture line symbol when it is selected
162
         * in the map
163
         * @return img, BufferedImage
164
         * @throws IOException
165
         */
166
        private BufferedImage getImg() throws IOException {
167
                if (img == null) {
168
                        img = ImageIO.read(new File(imagePath));
169
                }
170
                return img;
171
        }
172
        /**
173
         * Returns the image that will substitute the picture line symbol when it is selected
174
         * in the map
175
         * @return selImg, BufferedImage
176
         * @throws IOException
177
         */
178
        private BufferedImage getSelImg() throws IOException {
179
                if (selImg == null) {
180
                        if (selImagePath!= null) {
181
                                selImg = ImageIO.read(new File(selImagePath));
182
                        } else return getImg();
183
                }
184
                return selImg;
185
        }
186

    
187
        public void draw(Graphics2D g, AffineTransform affineTransform, FShape shp) {
188
                g.setClip(new BasicStroke((float) width, BasicStroke.CAP_ROUND,BasicStroke.CAP_ROUND).createStrokedShape(shp));
189

    
190
                try{
191
                        BufferedImage img = selected ? getSelImg() : getImg();
192
                        if (xScale<=0 &&  yScale<=0)
193
                                return;
194
                        AffineTransform scaleInstance = AffineTransform.getScaleInstance(xScale, yScale);
195

    
196
                        final double imageWidth  = img.getWidth()  * xScale;
197
                        final double imageHeight = img.getHeight() * yScale;
198

    
199
                        if (imageWidth==0 || imageHeight==0) return;
200
                        double halfImageHeight = imageHeight*.5;
201

    
202
                        PathLength pl = new PathLength(shp);
203
                        PathIterator iterator = ((FPolyline2D) shp).getPathIterator(null, 0.8);
204
                        double[] theData = new double[6];
205
                        Point2D firstPoint = null, startPoint = null, endPoint = null;
206
                        if (!iterator.isDone()) {
207
                                if ( iterator.currentSegment(theData) != PathIterator.SEG_CLOSE) {
208
                                        firstPoint = new Point2D.Double(theData[0], theData[1]);
209
                                }
210
                        }
211
                        float currentPathLength = 1;
212

    
213
                        while (!iterator.isDone()) {
214

    
215
                                int theType = iterator.currentSegment(theData);
216
                                switch (theType) {
217
                                case PathIterator.SEG_MOVETO:
218
                                        startPoint = new Point2D.Double(theData[0], theData[1]);
219

    
220
                                        endPoint = null;
221
                                        iterator.next();
222

    
223
                                        continue;
224

    
225
                                case PathIterator.SEG_LINETO:
226
                                case PathIterator.SEG_QUADTO:
227
                                case PathIterator.SEG_CUBICTO:
228
                                        endPoint = new Point2D.Double(theData[0], theData[1]);
229

    
230
                                        break;
231
                                case PathIterator.SEG_CLOSE:
232
                                        endPoint = startPoint;
233
                                        startPoint = firstPoint;
234
                                        break;
235
                                }
236

    
237
                                double a = endPoint.getX() - startPoint.getX();
238
                                double b = endPoint.getY() - startPoint.getY();
239
                                double theta = pl.angleAtLength(currentPathLength);
240

    
241
                                double x = startPoint.getX();
242
                                double y = startPoint.getY();
243

    
244
                                // Theorem of Pythagoras
245
                                float segmentLength = (float) Math.sqrt(a*a + b*b);
246

    
247
                                // compute how many times the image has to be drawn
248
                                // to completely cover this segment's length
249
                                int count = (int) Math.ceil(segmentLength/imageWidth);
250

    
251
                                for (int i = 0; i < count; i++) {
252
                                        g.translate(x, y);
253
                                        g.rotate(theta);
254

    
255
                                        double xOffsetTranslation = imageWidth*i;
256

    
257
                                                g.translate(xOffsetTranslation, -halfImageHeight);
258
                                                g.drawImage(img, scaleInstance, null);
259
                                                g.translate(-xOffsetTranslation, halfImageHeight);
260

    
261
                                        g.rotate(-theta);
262
                                        g.translate(-x, -y);
263
                                }
264

    
265
                                startPoint = endPoint;
266
                                currentPathLength += segmentLength;
267
                                iterator.next();
268
                        }
269

    
270
                } catch (IOException e) {
271
                        Logger.getLogger(this.getClass()).error(Messages.getString("failed_to_read_image_file"), e);
272
                }
273
                g.setClip(null);
274
        }
275

    
276
        public int getPixExtentPlus(Graphics2D g, AffineTransform affineTransform,
277
                        Shape shp) {
278
                // TODO Implement it
279
                throw new Error("Not yet implemented!");
280

    
281
        }
282

    
283
        public XMLEntity getXMLEntity() {
284
                XMLEntity xml = new XMLEntity();
285
                xml.putProperty("className", getClassName());
286
                xml.putProperty("isShapeVisible", isShapeVisible());
287
                xml.putProperty("desc", getDescription());
288
                xml.putProperty("imagePath", imagePath);
289
                xml.putProperty("selImagePath", selImagePath);
290
                xml.putProperty("lineWidth", getLineWidth());
291
                xml.putProperty("xScale", getXScale());
292
                xml.putProperty("yScale", getYScale());
293

    
294
                // measure unit
295
                xml.putProperty("unit", getUnit());
296

    
297
                // reference system
298
                xml.putProperty("referenceSystem", getReferenceSystem());
299

    
300
                return xml;
301

    
302
        }
303

    
304
        public void setXMLEntity(XMLEntity xml) {
305
                setDescription(xml.getStringProperty("desc"));
306
                setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
307
                imagePath = xml.getStringProperty("imagePath");
308
                selImagePath = xml.getStringProperty("selImagePath");
309
                setLineWidth(xml.getDoubleProperty("lineWidth"));
310
                setXScale(xml.getDoubleProperty("xScale"));
311
                setYScale(xml.getDoubleProperty("yScale"));
312
                setReferenceSystem(xml.getIntProperty("referenceSystem"));
313
                setUnit(xml.getIntProperty("unit"));
314

    
315
        }
316
        /**
317
         * Sets the yscale for the picture line symbol
318
         * @param yScale
319
         */
320
        public void setYScale(double yScale) {
321
                this.yScale = yScale;
322

    
323
        }
324
        /**
325
         * Sets the xscale for the picture line symbol
326
         * @param xScale
327
         */
328
        public void setXScale(double xScale) {
329
                this.xScale = xScale;
330
        }
331

    
332
        public String getClassName() {
333
                return getClass().getName();
334
        }
335

    
336
        public void print(Graphics2D g, AffineTransform at, FShape shape,
337
                        PrintRequestAttributeSet properties) throws ReadDriverException {
338
                // TODO Implement it
339
                throw new Error("Not yet implemented!");
340

    
341
        }
342
        /**
343
         * Returns the path of the image that is used as a picture line symbol (when it
344
         * is selected in the map)
345
         * @return selimagePath,String
346
         */
347
        public String getSelImagePath() {
348
                return selImagePath;
349
        }
350
        /**
351
         * Returns the path of the image that is used as a picture line symbol
352
         * @return imagePath,String
353
         */
354
        public String getImagePath() {
355
                return imagePath;
356
        }
357
        /**
358
         * Returns the xscale for the picture line symbol
359
         * @param xScale
360
         */
361
        public double getXScale() {
362
                return xScale;
363
        }
364
        /**
365
         * Returns the yscale for the picture line symbol
366
         * @param yScale
367
         */
368
        public double getYScale() {
369
                return yScale;
370
        }
371

    
372
}