Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extSymbology / src / org / gvsig / symbology / fmap / symbols / PictureLineSymbol.java @ 25807

History | View | Annotate | Download (10.6 KB)

1 20768 jdominguez
/* 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 22644 vcaballero
import com.iver.cit.gvsig.fmap.core.symbols.SymbolDrawingException;
70 20768 jdominguez
import com.iver.utiles.XMLEntity;
71
import com.iver.utiles.swing.threads.Cancellable;
72
73
/**
74
 * PictureLineSymbol allows to use any symbol defined as an image (by an image file)
75
 * supported  by gvSIG.This symbol will be used as an initial object.The line will be
76
 * painted as a succession of puntual symbols through the path defined by it(the line).
77
 *
78
 * @author jaume dominguez faus - jaume.dominguez@iver.es
79
 */
80
public class PictureLineSymbol extends AbstractLineSymbol  {
81
//        transient private BufferedImage img;
82
//        transient private BufferedImage selImg;
83
        transient private PictureLineSymbol selectionSym;
84
        private String selImagePath;
85
        private double width;
86
        private String imagePath;
87
        private boolean selected;
88
        private double xScale = 1, csXScale = xScale;
89
        private double yScale = 1, csYScale = yScale;
90
91
        private BackgroundFileStyle bgImage;
92
        private BackgroundFileStyle bgSelImage;
93
        /**
94
         * Constructor method
95
         *
96
         */
97
        public PictureLineSymbol() {
98
                super();
99
        }
100
        /**
101
         * Constructor method
102
         * @param imageURL, URL of the normal image
103
         * @param selImageURL, URL of the image when it is selected in the map
104
         * @throws IOException
105
         */
106
107
        public PictureLineSymbol(URL imageURL, URL selImageURL) throws IOException {
108
                setImage(imageURL);
109
                if (selImageURL!=null)
110
                        setSelImage(selImageURL);
111
                else setSelImage(imageURL);
112
        }
113
        /**
114
         * Sets the URL for the image to be used as a picture line symbol
115
         * @param imageFile, File
116
         * @throws IOException
117
         */
118
        public void setImage(URL imageUrl) throws IOException{
119
120
                bgImage= BackgroundFileStyle.createStyleByURL(imageUrl);
121
                imagePath = imageUrl.toString();
122
        }
123
        /**
124
         * Sets the URL for the image to be used as a picture line symbol (when it is selected in the map)
125
         * @param imageFile, File
126
         * @throws IOException
127
         */
128
        public void setSelImage(URL selImageUrl) throws IOException{
129
130
                bgSelImage= BackgroundFileStyle.createStyleByURL(selImageUrl);
131
                selImagePath = selImageUrl.toString();
132
        }
133
134
135
        public void setLineWidth(double width) {
136
                this.width = width;
137
                getLineStyle().setLineWidth((float) width);
138
        }
139
140
        public double getLineWidth() {
141
                return width;
142
        }
143
144
        public ISymbol getSymbolForSelection() {
145
                if (selectionSym == null) {
146
                        selectionSym = (PictureLineSymbol) SymbologyFactory.createSymbolFromXML(getXMLEntity(), getDescription());
147
                        selectionSym.selected=true;
148
                        selectionSym.selectionSym = selectionSym; // avoid too much lazy creations
149
150
                }
151
                return selectionSym;
152
153
        }
154
155
        public void draw(Graphics2D g, AffineTransform affineTransform, FShape shp, Cancellable cancel) {
156
                float csWidth = getLineStyle().getLineWidth();
157
                g.setClip(new BasicStroke((float) csWidth, BasicStroke.CAP_ROUND,BasicStroke.CAP_ROUND).createStrokedShape(shp));
158
                BackgroundFileStyle bg = (!selected) ? bgImage : bgSelImage ;
159
160
                if (csXScale<=0 &&  csYScale<=0)
161
                        return;
162
163
                Rectangle bounds = bg.getBounds();
164
                final double imageWidth  = bounds.getWidth()  * csXScale;
165
                final double imageHeight = bounds.getHeight() * csYScale;
166
167
                if (imageWidth==0 || imageHeight==0) return;
168
                int height = (int) csWidth;
169
170
                PathLength pl = new PathLength(shp);
171
                PathIterator iterator = ((FPolyline2D) shp).getPathIterator(null, 0.8);
172
                double[] theData = new double[6];
173
                Point2D firstPoint = null, startPoint = null, endPoint = null;
174
                if (!iterator.isDone()) {
175
                        if ( iterator.currentSegment(theData) != PathIterator.SEG_CLOSE) {
176
                                firstPoint = new Point2D.Double(theData[0], theData[1]);
177
                        }
178
                }
179
                float currentPathLength = 1;
180
181
                Rectangle rect = new Rectangle();
182
183
                while ((cancel==null || !cancel.isCanceled()) && !iterator.isDone()) {
184
185
                        int theType = iterator.currentSegment(theData);
186
                        switch (theType) {
187
                        case PathIterator.SEG_MOVETO:
188
                                startPoint = new Point2D.Double(theData[0], theData[1]);
189
190
                                endPoint = null;
191
                                iterator.next();
192
193
                                continue;
194
195
                        case PathIterator.SEG_LINETO:
196
                        case PathIterator.SEG_QUADTO:
197
                        case PathIterator.SEG_CUBICTO:
198
                                endPoint = new Point2D.Double(theData[0], theData[1]);
199
200
                                break;
201
                        case PathIterator.SEG_CLOSE:
202
                                endPoint = startPoint;
203
                                startPoint = firstPoint;
204
                                break;
205
                        }
206
207
                        double a = endPoint.getX() - startPoint.getX();
208
                        double b = endPoint.getY() - startPoint.getY();
209
                        double theta = pl.angleAtLength(currentPathLength);
210
211
                        double x = startPoint.getX();
212
                        double y = startPoint.getY();
213
214
                        // Theorem of Pythagoras
215
                        float segmentLength = (float) Math.sqrt(a*a + b*b);
216
217
                        // compute how many times the image has to be drawn
218
                        // to completely cover this segment's length
219
                        int count = (int) Math.ceil(segmentLength/imageWidth);
220
221
                        for (int i = 0; (cancel==null || !cancel.isCanceled()) && i < count; i++) {
222
                                g.translate(x, y);
223
                                g.rotate(theta);
224
225
                                double xOffsetTranslation = imageWidth*i;
226
227
228
                                g.translate(xOffsetTranslation, -csWidth);
229
230
                                rect.setBounds(0, (int) Math.round(height*.5), (int) Math.ceil(imageWidth), height);
231 22644 vcaballero
                                try {
232
                                        bg.drawInsideRectangle(g, rect, false);
233
                                } catch (SymbolDrawingException e) {
234
                                        Logger.getLogger(getClass()).warn(Messages.getString("label_style_could_not_be_painted"), e);
235
                                }
236 20768 jdominguez
                                g.setColor(Color.red);
237
                                g.translate(-xOffsetTranslation, csWidth);
238
239
                                g.rotate(-theta);
240
                                g.translate(-x, -y);
241
                        }
242
243
                        startPoint = endPoint;
244
                        currentPathLength += segmentLength;
245
                        iterator.next();
246
                }
247
248
                g.setClip(null);
249
                g.setColor(Color.red);
250
251
        }
252
253
254
        public XMLEntity getXMLEntity() {
255
                XMLEntity xml = new XMLEntity();
256
                xml.putProperty("className", getClassName());
257
                xml.putProperty("isShapeVisible", isShapeVisible());
258
                xml.putProperty("desc", getDescription());
259
                xml.putProperty("imagePath", imagePath);
260
                xml.putProperty("selImagePath", selImagePath);
261
                xml.putProperty("lineWidth", getLineWidth());
262
                xml.putProperty("xScale", getXScale());
263
                xml.putProperty("yScale", getYScale());
264
265
                // measure unit
266
                xml.putProperty("unit", getUnit());
267
268
                // reference system
269
                xml.putProperty("referenceSystem", getReferenceSystem());
270
271
                return xml;
272
273
        }
274
275
        public void setXMLEntity(XMLEntity xml) {
276 20905 jdominguez
                System.out.println(this.getClass().getClassLoader());
277 20768 jdominguez
                setDescription(xml.getStringProperty("desc"));
278
                setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
279
                imagePath = xml.getStringProperty("imagePath");
280
                selImagePath = xml.getStringProperty("selImagePath");
281
                setLineWidth(xml.getDoubleProperty("lineWidth"));
282
                setXScale(xml.getDoubleProperty("xScale"));
283
                setYScale(xml.getDoubleProperty("yScale"));
284
                setReferenceSystem(xml.getIntProperty("referenceSystem"));
285
                setUnit(xml.getIntProperty("unit"));
286
287
288
                try {
289
                        setImage(new URL(imagePath));
290
                        setSelImage(new URL(selImagePath));
291
                } catch (MalformedURLException e) {
292
                        Logger.getLogger(getClass()).error(Messages.getString("invalid_url"));
293
                } catch (IOException e) {
294
                        Logger.getLogger(getClass()).error(Messages.getString("invalid_url"));
295
296
                }
297
298
        }
299
        /**
300
         * Sets the yscale for the picture line symbol
301
         * @param yScale
302
         */
303
        public void setYScale(double yScale) {
304
                this.yScale = yScale;
305
                this.csYScale = yScale;
306
        }
307
        /**
308
         * Sets the xscale for the picture line symbol
309
         * @param xScale
310
         */
311
        public void setXScale(double xScale) {
312
                this.xScale = xScale;
313
                this.csXScale = xScale;
314
        }
315
316
        public String getClassName() {
317
                return getClass().getName();
318
        }
319
320
        public void print(Graphics2D g, AffineTransform at, FShape shape,
321
                        PrintRequestAttributeSet properties) throws ReadDriverException {
322
                // TODO Implement it
323
                throw new Error("Not yet implemented!");
324
325
        }
326
        /**
327
         * Returns the path of the image that is used as a picture line symbol (when it
328
         * is selected in the map)
329
         * @return selimagePath,String
330
         */
331
        public String getSelImagePath() {
332
                return selImagePath;
333
        }
334
        /**
335
         * Returns the path of the image that is used as a picture line symbol
336
         * @return imagePath,String
337
         */
338
        public String getImagePath() {
339
                return imagePath;
340
        }
341
        /**
342
         * Returns the xscale for the picture line symbol
343
         * @param xScale
344
         */
345
        public double getXScale() {
346
                return xScale;
347
        }
348
        /**
349
         * Returns the yscale for the picture line symbol
350
         * @param yScale
351
         */
352
        public double getYScale() {
353
                return yScale;
354
        }
355
356
        @Override
357
        public void setCartographicSize(double cartographicSize, FShape shp) {
358
                getLineStyle().setLineWidth((float) cartographicSize);
359
                double scale = cartographicSize/width;
360
                csXScale = xScale * scale;
361
                csYScale = yScale * scale;
362
        }
363
364
        @Override
365
        public double toCartographicSize(ViewPort viewPort, double dpi, FShape shp) {
366
                double s = super.toCartographicSize(viewPort, dpi, shp);
367
                setCartographicSize(CartographicSupportToolkit.
368
                                getCartographicLength(this, width, viewPort, dpi), shp);
369
                return s;
370
        }
371
}