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 |
} |