Statistics
| Revision:

root / branches / Mobile_Compatible_Hito_1 / libFMap / src / es / prodevelop / gvsig / mobile / fmap / util / graph2d / RotationUtils.java @ 21606

History | View | Annotate | Download (9.82 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 Prodevelop 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
 *   http://www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   Prodevelop Integraci?n de Tecnolog?as SL
34
 *   Conde Salvatierra de ?lava , 34-10
35
 *   46004 Valencia
36
 *   Spain
37
 *
38
 *   +34 963 510 612
39
 *   +34 963 510 968
40
 *   gis@prodevelop.es
41
 *   http://www.prodevelop.es
42
 *
43
 *    or
44
 *
45
 *   Instituto de Rob?tica
46
 *   Apartado de correos 2085
47
 *   46071 Valencia
48
 *   (Spain)
49
 *   
50
 *   +34 963 543 577
51
 *   jjordan@robotica.uv.es
52
 *   http://robotica.uv.es
53
 *   
54
 */
55

    
56
package es.prodevelop.gvsig.mobile.fmap.util.graph2d;
57

    
58
import java.awt.Color;
59
import java.awt.Graphics;
60
import java.awt.Graphics2D;
61
import java.awt.Image;
62
import java.awt.Toolkit;
63
import java.awt.geom.AffineTransform;
64
import java.awt.image.BufferedImage;
65
import java.awt.image.FilteredImageSource;
66

    
67
import megamek.client.ui.AWT.util.RotateFilter;
68

    
69
import org.apache.log4j.Logger;
70

    
71
import es.prodevelop.gvsig.mobile.fmap.driver.raster.ecw.EcwReader;
72
import es.prodevelop.gvsig.mobile.fmap.util.Utils;
73

    
74
/**
75
 * Utility class to perform graphic rotations. Currently not used.
76
 * 
77
 * @see java.awt.geom.AffineTransform
78
 * 
79
 * @author jcarras
80
 * @author jldominguez
81
 *
82
 */
83
public class RotationUtils {
84
        private static Logger logger = Logger.getLogger(RotationUtils.class.getName());
85
        
86
        public static void drawRotatedText(
87
                        Graphics2D g,
88
                        String text,
89
                        Color c,
90
                        int x,
91
                        int y,
92
                        double alpha_degrees) {
93
                
94
                if (alpha_degrees > Math.PI/2 && alpha_degrees <-Math.PI/2){
95
                        logger.error("Angle not as spected");
96
                        //Try to handle with this
97
                        while(alpha_degrees>Math.PI/2)
98
                                alpha_degrees -= Math.PI;
99
                        while(alpha_degrees<-Math.PI/2)
100
                                alpha_degrees += Math.PI;
101
                }
102
                
103
                int w = g.getFontMetrics().stringWidth(text);
104
                int h = g.getFontMetrics().getHeight();
105
                if (Utils.USING_PDA)
106
                        h-= 4;
107
                
108
                Image img = Utils.createBufferedImage(w+h*2, w+h*2);
109
                Graphics g2 = img.getGraphics();
110
                g2.setColor(Color.black);
111
                g2.fillRect(0,0,w+2*h, w+2*h);
112
                g2.setColor(Color.WHITE);
113
                if (Utils.USING_PDA){
114
                        g2.drawString(text, h, w/2 );
115
                        //g2.drawLine(0,w/2,h+w+h,w/2);
116
                } else {
117
                        g2.drawString(text, h, w/2+h );
118
                        //g2.drawLine(0,w/2+h,h+w+h,w/2+h);
119
                }
120
                
121
                RotateFilter filt = new RotateFilter(alpha_degrees,c);
122
                Image img2 = Toolkit.getDefaultToolkit().createImage(
123
                                new FilteredImageSource(img.getSource(),filt));
124
                
125
                /*
126
                g.drawImage(img2,
127
                                (int)(x-(w/2+h-Math.cos(alpha_degrees))),
128
                                (int)(y-(w/2+h+h/2+Math.sin(alpha_degrees))),
129
                                null);*/
130
                int x1 = (int)(x-(w/2+h-(w/2)*Math.cos(alpha_degrees)));
131
                if (alpha_degrees>=0)
132
                        x1 = (int)(x-(w/2+h-(w/2)*Math.cos(alpha_degrees)));
133
                
134
                int y1= (int)(y-(w/2+h+(w/2)*Math.sin(alpha_degrees)));
135
                
136
                if (alpha_degrees>=0)
137
                        y1= (int)(y-(w/2+h+(w/2)*Math.sin(alpha_degrees)));
138
                g.drawImage(img2,
139
                                x1,
140
                                y1,
141
                                null);
142
                
143
                
144
        }
145
        public static void drawRotatedText2(
146
                        Graphics2D g,
147
                        String text,
148
                        Color c,
149
                        int x,
150
                        int y,
151
                        double alpha_degrees) {
152
                
153
                if (alpha_degrees > Math.PI/2 && alpha_degrees <-Math.PI/2){
154
                        logger.error("Angle not as spected");
155
                        //Try to handle with this
156
                        while(alpha_degrees>Math.PI/2)
157
                                alpha_degrees -= Math.PI;
158
                        while(alpha_degrees<-Math.PI/2)
159
                                alpha_degrees += Math.PI;
160
                }
161
                
162
                int w = g.getFontMetrics().stringWidth(text);
163
                int h = g.getFontMetrics().getHeight();
164
                
165
                Image img = Utils.createBufferedImage(w*2+h*2, w*2+h*2);
166
                Graphics g2 = img.getGraphics();
167
                g2.setColor(Color.black);
168
                g2.fillRect(0,0,w*2+h, w*2+h);
169
                g2.setColor(Color.WHITE);
170
                if (Utils.USING_PDA)
171
                        g2.drawString(text, w+h, w);
172
                else
173
                        g2.drawString(text, w+h, w+h);
174
                RotateFilter filt = new RotateFilter(alpha_degrees,c);
175
                Image img2 = Toolkit.getDefaultToolkit().createImage(
176
                                new FilteredImageSource(img.getSource(),filt));
177
                g.drawImage(img2,x-w-h,y-w-h,null);
178
                
179
                
180
                
181
        }
182
        
183
        public static void drawRotatedText3(
184
                        Graphics2D g,
185
                        String text,
186
                        Color c,
187
                        int x,
188
                        int y,
189
                        double alpha_degrees) {
190
                
191
                int w = g.getFontMetrics().stringWidth(text);
192
                int h = g.getFontMetrics().getHeight();
193
                BufferedImage img = Utils.createBufferedImage(w, h);
194
                Graphics g2 = img.getGraphics();
195
                // g2.setColor(Color.BLACK);
196
                // g2.fillRect(0, 0, w, h);
197
                g2.setColor(Color.WHITE);
198
                g2.drawString(text, 0, h - 1);
199
                
200
                int[] input_raster = img.getRGB(0, 0, w, h, null, 0, w);
201
                
202
                int red = c.getRed();
203
                int green = c.getGreen();
204
                int blue = c.getBlue();
205
                
206
                double alpha_radians = alpha_degrees * Math.PI / 180.0;
207
                double inc_alpha = Math.atan((1.0 * h) / (1.0 * w));
208

    
209
                int x_offset = getRotatedImageXOffset(w, h, alpha_radians);
210
                int y_offset = getRotatedImageYOffset(w, h, alpha_radians, inc_alpha);
211
                
212
                Image rotated_img = null;
213
                
214
                if (Utils.USING_PDA) {
215

    
216
                        byte[] rotated_png = getRotatedPngBytes(
217
                                input_raster,
218
                                w, h,
219
                                alpha_radians,
220
                                inc_alpha,
221
                                red, green, blue,
222
                                x_offset);
223
                        
224
                        rotated_img = Toolkit.getDefaultToolkit().createImage(rotated_png);
225
                        
226
                } else {
227
                        
228
                        rotated_img = getRotatedImage(
229
                                        input_raster,
230
                                        w, h,
231
                                        alpha_radians,
232
                                        inc_alpha,
233
                                        red, green, blue,
234
                                        x_offset);
235
                }
236

    
237
                g.drawImage(rotated_img, x + x_offset, y + y_offset, null);
238
        }
239

    
240
        private static byte[] getRotatedPngBytes(
241
                        int[] input_raster,
242
                        int w, int h,
243
                        double r,
244
                        double inc_r,
245
                        int red, int green, int blue,
246
                        int x_off) {
247
                
248
                int out_w = (int) Math.round(w * Math.cos(r) + h * Math.sin(r));
249
                double m = Math.sqrt(w * w + h * h);
250
                int out_h = (int) Math.round(m * Math.sin(r + inc_r));
251
                
252
                int[] out_raster = rotate(
253
                                input_raster, w, h, r, inc_r, out_w, out_h, red, green, blue, x_off);
254
                
255
                return EcwReader.paintArray(out_raster, out_w, out_h, 0, false);
256
        }
257
        
258
        private static Image getRotatedImage(
259
                        int[] input_raster,
260
                        int w, int h,
261
                        double r,
262
                        double inc_r,
263
                        int red, int green, int blue,
264
                        int x_off) {
265
                
266
                int out_w = (int) Math.round(w * Math.cos(r) + h * Math.sin(r));
267
                double m = Math.sqrt(w * w + h * h);
268
                int out_h = (int) Math.round(m * Math.sin(r + inc_r));
269
                
270
                int[] out_raster = rotate(
271
                                input_raster, w, h, r, inc_r, out_w, out_h, red, green, blue, x_off);
272
                
273
                BufferedImage resp = new BufferedImage(out_w, out_h, 1);
274
                resp.setRGB(0, 0, out_w, out_h, out_raster, 0, out_w);
275
                return resp;                
276
        }
277
        
278
        
279
        private static int getBitmapBlueValue(int[] bit_map, int w, int h, int x, int y) {
280
                
281
                if (x >= w) return 0; 
282
                if (x < 0) return 0; 
283
                if (y >= h) return 0; 
284
                if (y < 0) return 0;
285
                
286
                return bit_map[w * y + x] & 0xff;
287
        }
288
        
289
    private static int rotatePixel(
290
                    int x, int y,
291
                    int[] in_raster,
292
                    int in_w, int in_h,
293
                    double m00, double m01, double m10, double m11,
294
                    int red, int green, int blue,
295
                    int x_off) {
296
            
297
        double rx = (x + x_off) * m00 - y * m10;
298
        double ry = (x + x_off) * m01 + y * m11;
299
        
300
        return pixelBilinear(rx, ry, in_raster, in_w, in_h, red, green, blue);
301
    }
302

    
303
        private static int pixelBilinear(
304
                        double rx,
305
                        double ry,
306
                        int[] in_raster,
307
                        int in_w, int in_h,
308
                        int red, int green, int blue) {
309
                
310
                int fx = (int) Math.floor(rx);
311
                int fy = (int) Math.floor(ry);
312
                
313
                int b0 = getBitmapBlueValue(in_raster, in_w, in_h, fx    , fy    );
314
                int b1 = getBitmapBlueValue(in_raster, in_w, in_h, fx + 1, fy    );
315
                int b2 = getBitmapBlueValue(in_raster, in_w, in_h, fx    , fy + 1);
316
                int b3 = getBitmapBlueValue(in_raster, in_w, in_h, fx + 1, fy + 1);
317
                
318
                if ((b0 == 0) && (b1 == 0) && (b2 == 0) && (b3 == 0)) return 0;  
319
                
320
                double xv = rx - fx;
321
                double yv = ry - fy;
322

    
323
                double mul0 = (1.0 - xv) * (1.0 - yv);
324
                double mul1 = xv * (1.0 - yv);
325
                double mul2 = (1.0 - xv) * yv;
326
                double mul3 = xv * yv;        
327

    
328
                int transp = (int) Math.round(
329
                                mul0 * b0
330
                                + mul1 * b1
331
                                + mul2 * b2
332
                                + mul3 * b3);
333
                
334
                return transp * 16777216 + red * 65536 + green * 256 + blue;
335
        }
336
        
337
        private static int[] rotate(
338
                        int[] input_raster,
339
                        int w, int h,
340
                        double r, double inc_r,
341
                        int out_w, int out_h,
342
                        int red, int green, int blue,
343
                        int x_off) {
344
                
345
                AffineTransform at = AffineTransform.getRotateInstance(-r);
346
                double m00 = at.getScaleX();
347
                double m01 = at.getShearX();
348
                double m10 = at.getShearY();
349
                double m11 = at.getScaleY();
350
                
351
                // double the_sin = 
352
                int[] resp = new int[out_w * out_h];
353
                int inv_j = 0;
354
                
355
                for (int j=0; j<out_h; j++) {
356
                
357
                        inv_j = out_h - 1 - j; 
358
                        for (int i=0; i<out_w; i++) {
359
                                resp[out_w * inv_j + i] = rotatePixel(
360
                                                i, inv_j,
361
                                                input_raster,
362
                                                w, h,
363
                                                m00, m01, m10, m11,
364
                                                red, green, blue,
365
                                                x_off);
366
                        }
367
                }
368
                
369
                return resp;
370
        }
371

    
372
        private static int getRotatedImageXOffset(int w, int h, double alpha_rad) {
373

    
374
                return -(int) Math.round(h * Math.sin(alpha_rad));
375
        }
376

    
377
        private static int getRotatedImageYOffset(
378
                        int w, int h,
379
                        double alpha_rad,
380
                        double inc_alpha) {
381

    
382
                double hipot = Math.sqrt(w * w + h * h);
383
                return -(int) Math.round(hipot * Math.sin(alpha_rad + inc_alpha));
384
        }
385
}