Statistics
| Revision:

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

History | View | Annotate | Download (10.8 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.File;
51
import java.io.IOException;
52
import java.net.MalformedURLException;
53
import java.net.URL;
54

    
55
import javax.print.attribute.PrintRequestAttributeSet;
56

    
57
import org.apache.batik.ext.awt.geom.PathLength;
58
import org.apache.log4j.Logger;
59
import org.gvsig.symbology.fmap.styles.BackgroundFileStyle;
60
import org.gvsig.tools.file.PathGenerator;
61

    
62
import com.iver.cit.gvsig.fmap.Messages;
63
import com.iver.cit.gvsig.fmap.ViewPort;
64
import com.iver.cit.gvsig.fmap.core.CartographicSupportToolkit;
65
import com.iver.cit.gvsig.fmap.core.FPolyline2D;
66
import com.iver.cit.gvsig.fmap.core.FShape;
67
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
68
import com.iver.cit.gvsig.fmap.core.symbols.AbstractLineSymbol;
69
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
70
import com.iver.cit.gvsig.fmap.core.symbols.SymbolDrawingException;
71
import com.iver.utiles.XMLEntity;
72
import com.iver.utiles.swing.threads.Cancellable;
73

    
74
/**
75
 * PictureLineSymbol allows to use any symbol defined as an image (by an image file)
76
 * supported  by gvSIG.This symbol will be used as an initial object.The line will be
77
 * painted as a succession of puntual symbols through the path defined by it(the line).
78
 *
79
 * @author jaume dominguez faus - jaume.dominguez@iver.es
80
 */
81
public class PictureLineSymbol extends AbstractLineSymbol  {
82
//        transient private BufferedImage img;
83
//        transient private BufferedImage selImg;
84
        transient private PictureLineSymbol selectionSym;
85
        private String selImagePath;
86
        private double width;
87
        private String imagePath;
88
        private boolean selected;
89
        private double xScale = 1, csXScale = xScale;
90
        private double yScale = 1, csYScale = yScale;
91

    
92
        private BackgroundFileStyle bgImage;
93
        private BackgroundFileStyle bgSelImage;
94
        private PrintRequestAttributeSet properties;
95
        private PathGenerator pathGenerator=PathGenerator.getInstance();
96

    
97
        /**
98
         * Constructor method
99
         *
100
         */
101
        public PictureLineSymbol() {
102
                super();
103
        }
104
        /**
105
         * Constructor method
106
         * @param imageURL, URL of the normal image
107
         * @param selImageURL, URL of the image when it is selected in the map
108
         * @throws IOException
109
         */
110

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

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

    
134
                bgSelImage= BackgroundFileStyle.createStyleByURL(selImageUrl);
135
                selImagePath = selImageUrl.toString();
136
        }
137

    
138

    
139
        public void setLineWidth(double width) {
140
                this.width = width;
141
                getLineStyle().setLineWidth((float) width);
142
        }
143

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

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

    
154
                }
155
                return selectionSym;
156

    
157
        }
158

    
159
        public void draw(Graphics2D g, AffineTransform affineTransform, FShape shp, Cancellable cancel) {
160
                float csWidth = getLineStyle().getLineWidth();
161
                g.setClip(new BasicStroke((float) csWidth, BasicStroke.CAP_ROUND,BasicStroke.CAP_ROUND).createStrokedShape(shp));
162
                BackgroundFileStyle bg = (!selected) ? bgImage : bgSelImage ;
163

    
164
                if (csXScale<=0 &&  csYScale<=0)
165
                        return;
166

    
167
                Rectangle bounds = bg.getBounds();
168
                final double imageWidth  = bounds.getWidth()  * csXScale;
169
                final double imageHeight = bounds.getHeight() * csYScale;
170

    
171
                if (imageWidth==0 || imageHeight==0) return;
172
                int height = (int) csWidth;
173

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

    
185
                Rectangle rect = new Rectangle();
186

    
187
                while ((cancel==null || !cancel.isCanceled()) && !iterator.isDone()) {
188

    
189
                        int theType = iterator.currentSegment(theData);
190
                        switch (theType) {
191
                        case PathIterator.SEG_MOVETO:
192
                                startPoint = new Point2D.Double(theData[0], theData[1]);
193

    
194
                                endPoint = null;
195
                                iterator.next();
196

    
197
                                continue;
198

    
199
                        case PathIterator.SEG_LINETO:
200
                        case PathIterator.SEG_QUADTO:
201
                        case PathIterator.SEG_CUBICTO:
202
                                endPoint = new Point2D.Double(theData[0], theData[1]);
203

    
204
                                break;
205
                        case PathIterator.SEG_CLOSE:
206
                                endPoint = startPoint;
207
                                startPoint = firstPoint;
208
                                break;
209
                        }
210

    
211
                        double a = endPoint.getX() - startPoint.getX();
212
                        double b = endPoint.getY() - startPoint.getY();
213
                        double theta = pl.angleAtLength(currentPathLength);
214

    
215
                        double x = startPoint.getX();
216
                        double y = startPoint.getY();
217

    
218
                        // Theorem of Pythagoras
219
                        float segmentLength = (float) Math.sqrt(a*a + b*b);
220

    
221
                        // compute how many times the image has to be drawn
222
                        // to completely cover this segment's length
223
                        int count = (int) Math.ceil(segmentLength/imageWidth);
224

    
225
                        for (int i = 0; (cancel==null || !cancel.isCanceled()) && i < count; i++) {
226
                                g.translate(x, y);
227
                                g.rotate(theta);
228

    
229
                                double xOffsetTranslation = imageWidth*i;
230

    
231

    
232
                                g.translate(xOffsetTranslation, -csWidth);
233

    
234
                                rect.setBounds(0, (int) Math.round(height*.5), (int) Math.ceil(imageWidth), height);
235
                                try {
236
                                        bg.drawInsideRectangle(g, rect, false);
237
                                } catch (SymbolDrawingException e) {
238
                                        Logger.getLogger(getClass()).warn(Messages.getString("label_style_could_not_be_painted"), e);
239
                                }
240
                                g.setColor(Color.red);
241
                                g.translate(-xOffsetTranslation, csWidth);
242

    
243
                                g.rotate(-theta);
244
                                g.translate(-x, -y);
245
                        }
246

    
247
                        startPoint = endPoint;
248
                        currentPathLength += segmentLength;
249
                        iterator.next();
250
                }
251

    
252
                g.setClip(null);
253
                g.setColor(Color.red);
254

    
255
        }
256

    
257

    
258
        public XMLEntity getXMLEntity() {
259
                XMLEntity xml = new XMLEntity();
260
                xml.putProperty("className", getClassName());
261
                xml.putProperty("isShapeVisible", isShapeVisible());
262
                xml.putProperty("desc", getDescription());
263
                xml.putProperty("imagePath", pathGenerator.getPath(imagePath));
264
                xml.putProperty("selImagePath", pathGenerator.getPath(selImagePath));
265
                xml.putProperty("lineWidth", getLineWidth());
266
                xml.putProperty("xScale", getXScale());
267
                xml.putProperty("yScale", getYScale());
268

    
269
                // measure unit
270
                xml.putProperty("unit", getUnit());
271

    
272
                // reference system
273
                xml.putProperty("referenceSystem", getReferenceSystem());
274

    
275
                return xml;
276

    
277
        }
278

    
279
        public void setXMLEntity(XMLEntity xml) {
280
                System.out.println(this.getClass().getClassLoader());
281
                setDescription(xml.getStringProperty("desc"));
282
                setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
283
                imagePath = pathGenerator.getAbsolutePath(xml.getStringProperty("imagePath"));
284
                selImagePath = pathGenerator.getAbsolutePath(xml.getStringProperty("selImagePath"));
285
                setLineWidth(xml.getDoubleProperty("lineWidth"));
286
                setXScale(xml.getDoubleProperty("xScale"));
287
                setYScale(xml.getDoubleProperty("yScale"));
288
                setReferenceSystem(xml.getIntProperty("referenceSystem"));
289
                setUnit(xml.getIntProperty("unit"));
290

    
291

    
292
                try {
293
                        setImage(new URL(imagePath));
294
                        setSelImage(new URL(selImagePath));
295
                } catch (MalformedURLException e) {
296
                        Logger.getLogger(getClass()).error(Messages.getString("invalid_url"));
297
                } catch (IOException e) {
298
                        Logger.getLogger(getClass()).error(Messages.getString("invalid_url"));
299

    
300
                }
301

    
302
        }
303
        /**
304
         * Sets the yscale for the picture line symbol
305
         * @param yScale
306
         */
307
        public void setYScale(double yScale) {
308
                this.yScale = yScale;
309
                this.csYScale = yScale;
310
        }
311
        /**
312
         * Sets the xscale for the picture line symbol
313
         * @param xScale
314
         */
315
        public void setXScale(double xScale) {
316
                this.xScale = xScale;
317
                this.csXScale = xScale;
318
        }
319

    
320
        public String getClassName() {
321
                return getClass().getName();
322
        }
323

    
324
        public void print(Graphics2D g, AffineTransform at, FShape shape,
325
                        PrintRequestAttributeSet properties) {
326
                this.properties=properties;
327
        draw(g, at, shape, null);
328
        this.properties=null;
329

    
330
        }
331
        /**
332
         * Returns the path of the image that is used as a picture line symbol (when it
333
         * is selected in the map)
334
         * @return selimagePath,String
335
         */
336
        public String getSelImagePath() {
337
                return selImagePath;
338
        }
339
        /**
340
         * Returns the path of the image that is used as a picture line symbol
341
         * @return imagePath,String
342
         */
343
        public String getImagePath() {
344
                return imagePath;
345
        }
346
        /**
347
         * Returns the xscale for the picture line symbol
348
         * @param xScale
349
         */
350
        public double getXScale() {
351
                return xScale;
352
        }
353
        /**
354
         * Returns the yscale for the picture line symbol
355
         * @param yScale
356
         */
357
        public double getYScale() {
358
                return yScale;
359
        }
360

    
361
        @Override
362
        public void setCartographicSize(double cartographicSize, FShape shp) {
363
                getLineStyle().setLineWidth((float) cartographicSize);
364
                double scale = cartographicSize/width;
365
                csXScale = xScale * scale;
366
                csYScale = yScale * scale;
367
        }
368

    
369
        @Override
370
        public double toCartographicSize(ViewPort viewPort, double dpi, FShape shp) {
371
                double s = super.toCartographicSize(viewPort, dpi, shp);
372
                setCartographicSize(CartographicSupportToolkit.
373
                                getCartographicLength(this, width, viewPort, dpi), shp);
374
                return s;
375
        }
376
}