Statistics
| Revision:

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

History | View | Annotate | Download (24.9 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.Graphics2D;
60
import java.awt.Point;
61
import java.awt.Shape;
62
import java.awt.Toolkit;
63
import java.awt.geom.AffineTransform;
64
import java.awt.geom.GeneralPath;
65
import java.awt.geom.PathIterator;
66
import java.awt.geom.Rectangle2D;
67
import java.awt.image.BufferedImage;
68
import java.util.ArrayList;
69

    
70
import org.apache.log4j.Logger;
71

    
72
import com.vividsolutions.jts.algorithm.CGAlgorithms;
73
import com.vividsolutions.jts.geom.Coordinate;
74
import com.vividsolutions.jts.geom.CoordinateList;
75

    
76
import es.prodevelop.geodetic.utils.conversion.GeoUtils;
77
import es.prodevelop.gvsig.mobile.fmap.core.FDot;
78
import es.prodevelop.gvsig.mobile.fmap.core.FMultiPoint2D;
79
import es.prodevelop.gvsig.mobile.fmap.core.FPoint2D;
80
import es.prodevelop.gvsig.mobile.fmap.core.FPolygon2D;
81
import es.prodevelop.gvsig.mobile.fmap.core.FPolyline2D;
82
import es.prodevelop.gvsig.mobile.fmap.driver.raster.ecw.EcwReader;
83
import es.prodevelop.gvsig.mobile.fmap.symbol.FSymbol;
84
import es.prodevelop.gvsig.mobile.fmap.util.Utils;
85

    
86
/**
87
 * Utility class for graphic purposes.
88
 * 
89
 * @see java.awt.geom.GeneralPath
90
 * @see java.awt.geom.AffineTransform
91
 * @see java.awt.geom.PathIterator
92
 * @see es.prodevelop.gvsig.mobile.fmap.symbol.FSymbol
93
 * 
94
 * @author jldominguez
95
 *
96
 */
97
public class Graph2DUtilities {
98

    
99
        private static Logger logger = Logger.getLogger(Graph2DUtilities.class.getName());
100
        private static final boolean PAINT_HOLES_PROPERLY = false;
101
        
102

    
103
        /**
104
         * Draws the general path on the graphics object with the given affine transformation
105
         * @param g the graphics object
106
         * @param gp the general path
107
         * @param at the affine transformation
108
         */
109
        public static void drawGeneralPath(Graphics2D g, GeneralPath gp, AffineTransform at) {
110
                
111
                ArrayList x = new ArrayList();
112
                ArrayList y = new ArrayList();
113
                float[] current = new float[6];
114
                
115
                PathIterator piter = gp.getPathIterator(at);
116
                
117
                while (!piter.isDone()) {
118
                        piter.currentSegment(current);
119
                        x.add(new Integer((int) current[0]));
120
                        y.add(new Integer((int) current[1]));
121
                }
122
                
123
                int[] gx = integerArrayListToIntArray(x);
124
                int[] gy = integerArrayListToIntArray(y);
125

    
126
                g.drawPolyline(gx, gy, gx.length);
127
        }
128
        
129
        
130
        /**
131
         * Converts array list of Integer objects into array of int
132
         * @param l
133
         * @return array of int
134
         */
135
        public static int[] integerArrayListToIntArray(ArrayList l) {
136

    
137
                int size = l.size();
138
                int[] resp = new int[size];
139
                for (int i=0; i<size; i++) {
140
                        resp[i] = ((Integer) l.get(i)).intValue();
141
                }
142
                return resp;
143
        }
144
        
145
        /**
146
         * Tries to simplify an array of x and y coordinates.
147
         * @param xs
148
         * @param ys
149
         */
150
        public static void simplifyArrayList(ArrayList xs, ArrayList ys) {
151
                /*
152
                Integer x = (Integer)xs.get(xs.size()-1);
153
                Integer y = (Integer)ys.get(xs.size()-1);
154
                for (int i=xs.size()-2; i> 0; i--){
155
                        Integer x1 = (Integer)xs.get(i);
156
                        Integer y1 = (Integer)ys.get(i);
157
                        //int diff = Math.abs(x1.intValue()-x.intValue())+Math.abs(y1.intValue()-y.intValue());
158
                        //if (diff>1){
159
                        if(x1.equals(x) && y1.equals(y)){
160
                                xs.remove(i);
161
                                ys.remove(i);
162
                        } else {
163
                                x=x1;
164
                                y=y1;
165
                        }
166
                }*/
167
        }
168
        
169
        /*
170
        public static void drawGeneralPath(Graphics2D g, GeneralPath gp) {
171
                
172
                ArrayList x = new ArrayList();
173
                ArrayList y = new ArrayList();
174
                float[] current = new float[6];
175
                
176
                PathIterator piter = gp.getPathIterator(null);
177
                
178
                while (!piter.isDone()) {
179
                        piter.currentSegment(current);
180
                        x.add(new Integer((int) current[0]));
181
                        y.add(new Integer((int) current[1]));
182
                }
183
                
184
                int[] gx = integerArrayListToIntArray(x);
185
                int[] gy = integerArrayListToIntArray(y);
186

187
                g.drawPolyline(gx, gy, gx.length);
188
        }
189
        */
190

    
191
        /**
192
         * Computes the affine transform needed to go from one rectangle to another
193
         * 
194
         * @param srcRegion source rectangle
195
         * @param dstRegion destination rectangle
196
         * @return the affine transform
197
         */
198
        public static AffineTransform createAffineTransform(
199
                        Rectangle2D srcRegion, Rectangle2D dstRegion) {
200
                
201
                double[][] matrix = new double[3][3];
202

    
203
                double scale     = dstRegion.getWidth() / srcRegion.getWidth();
204
                double translate = dstRegion.getMinX() - srcRegion.getMinX() * scale;
205
                matrix[0][0] = scale;
206
                matrix[0][2] = translate;
207

    
208
                scale     = - dstRegion.getHeight() / srcRegion.getHeight();
209
                translate = dstRegion.getMinY() - srcRegion.getMaxY() * scale;
210
                matrix[1][1] = scale;
211
                matrix[1][2] = translate;
212

    
213
                matrix[2][2] = 1;
214
                
215
                return new AffineTransform(
216
                                matrix[0][0],
217
                                matrix[1][0],
218
                                matrix[0][1],
219
                                matrix[1][1],
220
                                matrix[0][2],
221
                                matrix[1][2]
222
                                );
223

    
224
        }
225

    
226
        /**
227
         * Draws a shape on the graphics object with the given affine transform
228
         * @param g2d
229
         * @param shp
230
         * @param symbol
231
         */
232
        public static void drawShape(Graphics2D g2d, Shape shp, FSymbol symbol) {
233

    
234
                
235
                if (shp instanceof FDot) {
236
                        drawDot(g2d, (FDot) shp);
237
                        return;
238
                }
239
                
240
                
241
                if (shp instanceof FPolygon2D) {
242
                        drawPolygon(g2d, (FPolygon2D) shp, symbol);
243
                        return;
244
                }
245

    
246
                if (shp instanceof FPolyline2D) {
247
                        drawPolyLine(g2d, (FPolyline2D) shp);
248
                        return;
249
                }
250

    
251
                if (shp instanceof FPoint2D) {
252
                        drawPoint(g2d, (FPoint2D) shp);
253
                        return;
254
                }
255
                
256
                if (shp instanceof FMultiPoint2D) {
257
                        drawMultiPoint(g2d, (FMultiPoint2D) shp);
258
                        return;
259
                }
260
                
261
                logger.error("Did not draw shape of class: " + shp.getClass().getName());
262
        }
263
        
264
        /**
265
         * Draws a multipoint  on the graphics object 
266
         * @param g2d
267
         * @param mp
268
         */
269
        public static void drawMultiPoint(Graphics2D g2d, FMultiPoint2D mp) {
270
                
271
                int count = mp.getNumPoints();
272
                for (int i=0; i<count; i++) {
273
                        drawPoint(g2d, mp.getPoint(i));
274
                }
275
        }
276

    
277
        private static void drawShapeBorder(Graphics2D g2d, Shape shp) {
278

    
279
                
280
                if (shp instanceof FDot) {
281
                        drawDot(g2d, (FDot) shp);
282
                        return;
283
                }
284
                
285
                
286
                if (shp instanceof FPolygon2D) {
287
                        drawPolygonBorder(g2d, (FPolygon2D) shp);
288
                        return;
289
                }
290

    
291
                if (shp instanceof FPolyline2D) {
292
                        drawPolyLine(g2d, (FPolyline2D) shp);
293
                        return;
294
                }
295

    
296
                if (shp instanceof FPoint2D) {
297
                        drawPoint(g2d, (FPoint2D) shp);
298
                        return;
299
                }
300
                
301
                logger.error("Did not draw shape of class: " + shp.getClass().getName());
302
        }
303
        
304
        
305
        private static void drawShapeFill(Graphics2D g2d, Shape shp) {
306

    
307
                drawPolygonFill(g2d, (FPolygon2D) shp);
308
                
309
        }
310

    
311
        /**
312
         * Draws a point  on the graphics object 
313
         * @param g2d
314
         * @param point2D
315
         */
316
        public static void drawPoint(Graphics2D g2d, FPoint2D point2D) {
317
                int x = Math.round((float) point2D.getX()) - 1;
318
                int y = Math.round((float) point2D.getY()) - 1;
319
                g2d.drawRect(x, y, 3, 3);
320
        }
321

    
322
        
323
        /**
324
         * Draws a dot on the graphics object 
325
         * @param g2d
326
         * @param dot
327
         */
328
        public static void drawDot(Graphics2D g2d, FDot dot) {
329
                int x = Math.round((float) dot.getX());
330
                int y = Math.round((float) dot.getY());
331
                //TODO: Improve me please
332
                g2d.drawLine(x, y, x, y);
333
        }
334
        
335
        
336
        /**
337
         * Draws a polygon on the graphics object with the given symbol
338
         * @param g2d
339
         * @param polygon2D
340
         * @param symbol
341
         */
342
        public static void drawPolygon(Graphics2D g2d, FPolygon2D polygon2D, FSymbol symbol) {
343
                
344
                PathIterator piter = polygon2D.getPathIterator(null);
345
                
346
                if (symbol.isFilled() ) {
347
                        
348
                        if (PAINT_HOLES_PROPERLY) {
349
                                paintFilledWithHoles(g2d, piter, symbol);
350
                        } else {
351
                                fillMultiPolygonIterator(g2d, piter, symbol);                        
352
                        }
353
                        
354
                } else {
355
                        drawMultiPolygonIterator(g2d, piter);                        
356
                }
357
        }
358
        
359
        private static void drawPolygonBorder(Graphics2D g2d, FPolygon2D polygon2D) {
360
                
361
                PathIterator piter = polygon2D.getPathIterator(null);
362
                
363
                drawMultiPolygonIterator(g2d, piter);                        
364
        }
365
        
366
        private static void drawPolygonFill(Graphics2D g2d, FPolygon2D polygon2D) {
367
                
368
                PathIterator piter = polygon2D.getPathIterator(null);
369
                
370
                fillMultiPolygonIteratorFill(g2d, piter);                        
371

    
372
                        
373
        }        
374

    
375
        /**
376
         * Draws a polyline on the graphics object
377
         * 
378
         * @param g2d
379
         * @param polyline2D
380
         */
381
        public static void drawPolyLine(Graphics2D g2d, FPolyline2D polyline2D) {
382
                PathIterator piter = polyline2D.getPathIterator(null);
383
                drawMultiLineIterator(g2d, piter);
384
        }
385

    
386
        private static void drawMultiPolygonIterator(
387
                        Graphics2D g,
388
                        PathIterator piter
389
                        ) {
390
                
391
                ArrayList x = new ArrayList();
392
                ArrayList y = new ArrayList();
393
                
394
                Point last_pt = null;
395

    
396
                float[] current = new float[6];
397

    
398
                while (!piter.isDone()) {
399

    
400
                        if (piter.currentSegment(current) == PathIterator.SEG_MOVETO) {
401
                                if (x.size() > 0) {
402
                                        int[] gx = integerArrayListToIntArray(x);
403
                                        int[] gy = integerArrayListToIntArray(y);
404
                                        g.drawPolygon(gx, gy, gx.length);
405
                                }
406
                                x = new ArrayList();
407
                                y = new ArrayList();
408
                                last_pt = null; 
409
                        }
410
                        
411
                        if ((last_pt == null)
412
                                        || (last_pt.x != ((int) current[0]))
413
                                        || (last_pt.y != ((int) current[1]))) {
414
                                
415
                                last_pt = new Point((int) current[0], (int) current[1]);
416
                                x.add(new Integer(last_pt.x));
417
                                y.add(new Integer(last_pt.y));
418
                        }
419
                        
420
                        piter.next();
421
                }
422
                ArrayList x1 = new ArrayList(),y1=new ArrayList();
423
                simplifyArrayList(x,y);
424
                int[] gx = integerArrayListToIntArray(x);
425
                int[] gy = integerArrayListToIntArray(y);
426
                g.drawPolygon(gx, gy, gx.length);
427
        }
428
        
429

    
430
        
431
        private static void fillMultiPolygonIterator(
432
                        Graphics2D g,
433
                        PathIterator piter,
434
                        FSymbol sym
435
                        ) {
436
                
437
                ArrayList x = new ArrayList();
438
                ArrayList y = new ArrayList();
439
                
440
                Point last_pt = null;
441

    
442
                float[] current = new float[6];
443

    
444
                while (!piter.isDone()) {
445

    
446
                        if (piter.currentSegment(current) == PathIterator.SEG_MOVETO) {
447
                                if (x.size() > 0) {
448
                                        int[] gx = integerArrayListToIntArray(x);
449
                                        int[] gy = integerArrayListToIntArray(y);
450
                                        g.setColor(sym.getFillColor());
451
                                        g.fillPolygon(gx, gy, gx.length);
452
                                        g.setColor(sym.getBorderColor());
453
                                        g.drawPolyline(gx, gy, gx.length);
454
                                }
455
                                x = new ArrayList();
456
                                y = new ArrayList();
457
                                last_pt = null; 
458
                        }
459
                        
460
                        if ((last_pt == null)
461
                                        || (last_pt.x != ((int) current[0]))
462
                                        || (last_pt.y != ((int) current[1]))) {
463
                                
464
                                last_pt = new Point((int) current[0], (int) current[1]);
465
                                x.add(new Integer(last_pt.x));
466
                                y.add(new Integer(last_pt.y));
467
                        }
468
                        
469
                        piter.next();
470
                }
471
                
472
                int[] gx = integerArrayListToIntArray(x);
473
                int[] gy = integerArrayListToIntArray(y);
474
                g.setColor(sym.getFillColor());
475
                g.fillPolygon(gx, gy, gx.length);
476
                g.setColor(sym.getBorderColor());
477
                g.drawPolyline(gx, gy, gx.length);
478
        }
479
        
480
        private static void fillMultiPolygonIteratorFill(
481
                        Graphics2D g,
482
                        PathIterator piter
483
                        ) {
484
                
485
                ArrayList x = new ArrayList();
486
                ArrayList y = new ArrayList();
487
                
488
                Point last_pt = null;
489

    
490
                float[] current = new float[6];
491

    
492
                while (!piter.isDone()) {
493

    
494
                        if (piter.currentSegment(current) == PathIterator.SEG_MOVETO) {
495
                                if (x.size() > 0) {
496
                                        int[] gx = integerArrayListToIntArray(x);
497
                                        int[] gy = integerArrayListToIntArray(y);
498
                                        //g.setColor(sym.getFillColor());
499
                                        g.fillPolygon(gx, gy, gx.length);
500
                                        /*g.setColor(sym.getBorderColor());
501
                                        g.drawPolyline(gx, gy, gx.length);*/
502
                                }
503
                                x = new ArrayList();
504
                                y = new ArrayList();
505
                                last_pt = null; 
506
                        }
507
                        
508
                        if ((last_pt == null)
509
                                        || (last_pt.x != ((int) current[0]))
510
                                        || (last_pt.y != ((int) current[1]))) {
511
                                
512
                                last_pt = new Point((int) current[0], (int) current[1]);
513
                                x.add(new Integer(last_pt.x));
514
                                y.add(new Integer(last_pt.y));
515
                        }
516
                        
517
                        piter.next();
518
                }
519
                ArrayList x1 = new ArrayList(),y1=new ArrayList();
520
                simplifyArrayList(x,y);
521
                int[] gx = integerArrayListToIntArray(x);
522
                int[] gy = integerArrayListToIntArray(y);
523
                //g.setColor(sym.getFillColor());
524
                g.fillPolygon(gx, gy, gx.length);
525
                /*g.setColor(sym.getBorderColor());
526
                g.drawPolyline(gx, gy, gx.length);*/
527
        }
528

    
529
        private static void drawMultiLineIterator(
530
                        Graphics2D g,
531
                        PathIterator piter
532
                        ) {
533
                
534
                ArrayList x = new ArrayList();
535
                ArrayList y = new ArrayList();
536
                
537
                Point last_pt = null;
538

    
539
                float[] current = new float[6];
540

    
541
                while (!piter.isDone()) {
542

    
543
                        if (piter.currentSegment(current) == PathIterator.SEG_MOVETO) {
544
                                if (x.size() > 0) {
545
                                        int[] gx = integerArrayListToIntArray(x);
546
                                        int[] gy = integerArrayListToIntArray(y);
547
                                        g.drawPolyline(gx, gy, gx.length);
548
                                }
549
                                x = new ArrayList();
550
                                y = new ArrayList();
551
                                last_pt = null; 
552
                        }
553
                        
554
                        if ((last_pt == null)
555
                                        || (last_pt.x != ((int) current[0]))
556
                                        || (last_pt.y != ((int) current[1]))) {
557
                                
558
                                last_pt = new Point((int) current[0], (int) current[1]);
559
                                x.add(new Integer(last_pt.x));
560
                                y.add(new Integer(last_pt.y));
561
                        }
562
                        
563
                        piter.next();
564
                }
565
                
566
                int[] gx = integerArrayListToIntArray(x);
567
                int[] gy = integerArrayListToIntArray(y);
568
                g.drawPolyline(gx, gy, gx.length);
569
        }
570
        
571
        
572
        
573
        private static PathIterator getPathIterator(Shape shp) {
574
                
575
                if (shp instanceof FPolyline2D) {
576
                        return ((FPolyline2D) shp).getPathIterator(null);
577
                }
578
                
579
                if (shp instanceof FPolygon2D) {
580
                        return ((FPolygon2D) shp).getPathIterator(null);
581
                }
582
                
583
                if (shp instanceof FPoint2D) {
584
                        return ((FPoint2D) shp).getPathIterator(null);
585
                }
586
                
587
                logger.error("Did not get a path iterator: null"); 
588
                return null; // new PointIterator(new Point(0, 0), AffineTransform.getTranslateInstance(0, 0));
589
                
590
        }
591
        
592
        private static void printCoordList(CoordinateList list) {
593
                for (int i=0; i<list.size(); i++) {
594
                        logger.debug("coordenadas [" + i + "]: " + ((Coordinate) list.get(i)).x + ", " + ((Coordinate) list.get(i)).y + ", ");
595
                }
596
        }
597
        
598
        /**
599
         * Gets the area of the path iterator
600
         * @param piter the path iterator
601
         * @return the area of the path iterator
602
         */
603
        public static double getPathIteratorArea(PathIterator piter) {
604
                
605
                if (piter == null) {
606
                        return 0;
607
                }
608

    
609
                double resp = 0;
610

    
611
                double[] theData = new double[6];
612
                Coordinate c1 = null;
613
                Coordinate firstc = null;
614
                CoordinateList coordList = null;
615

    
616
                while (!piter.isDone()) {
617

    
618
                        int type = piter.currentSegment(theData);
619
                        
620
                        if (type == PathIterator.SEG_MOVETO) {
621
                                if (coordList != null) {
622
                                        coordList.add(firstc, true);
623
                                        // printCoordList(coordList);
624
                                        resp = resp + CGAlgorithms.signedArea(coordList.toCoordinateArray());
625
                                }
626
                                firstc = new Coordinate(theData[0], theData[1]);
627
                                coordList = new CoordinateList();
628
                        }
629
                        c1 = new Coordinate(theData[0], theData[1]);
630
                        coordList.add(c1, true);
631
                        piter.next();
632
                }
633
                
634
                if (coordList != null) {
635
                        coordList.add(firstc, true);
636
                        // printCoordList(coordList);
637
                        // resp = resp + Math.abs(CGAlgorithms.signedArea(coordList.toCoordinateArray()));
638
                        resp = resp + CGAlgorithms.signedArea(coordList.toCoordinateArray());
639
                }
640
                return Math.abs(resp);
641
        }
642
        
643
        /**
644
         * Gets the area of a given spherical path iterator
645
         * 
646
         * @param piter 
647
         * @return the area
648
         */
649
        public static double getSphericalPathIteratorArea(PathIterator piter) {
650
                
651
                if (piter == null) {
652
                        return 0;
653
                }
654

    
655
                double resp = 0;
656

    
657
                double[] theData = new double[6];
658
                Coordinate c1 = null;
659
                Coordinate firstc = null;
660
                CoordinateList coordList = null;
661

    
662
                while (!piter.isDone()) {
663

    
664
                        int type = piter.currentSegment(theData);
665
                        
666
                        if (type == PathIterator.SEG_MOVETO) {
667
                                if (coordList != null) {
668
                                        coordList.add(firstc, true);
669
                                        // printCoordList(coordList);
670
                                        resp = resp + GeoUtils.sphericalAreaFromCoordinatesArray(coordList.toCoordinateArray());
671
                                }
672
                                firstc = new Coordinate(theData[0], theData[1]);
673
                                coordList = new CoordinateList();
674
                        }
675
                        c1 = new Coordinate(theData[0], theData[1]);
676
                        coordList.add(c1, true);
677
                        piter.next();
678
                }
679
                
680
                if (coordList != null) {
681
                        coordList.add(firstc, true);
682
                        // printCoordList(coordList);
683
                        // resp = resp + Math.abs(CGAlgorithms.signedArea(coordList.toCoordinateArray()));
684
                        resp = resp + GeoUtils.sphericalAreaFromCoordinatesArray(coordList.toCoordinateArray());
685
                }
686
                return Math.abs(resp);
687
        }
688
        
689
        
690
        private static void paintFilledWithHoles(Graphics2D g, PathIterator piter, FSymbol sym) {
691
                
692
                ArrayList _split = split(piter);
693
                int[] indices = getShellIndicesAndHoleCount(_split);
694
                Object[] shellXYAndHolesList = groupParts(_split, indices);
695
                int nofshells = shellXYAndHolesList.length / 3;
696

    
697
                int[] shellx, shelly;
698
                ArrayList holesXY;
699

    
700
                for (int i=0; i<nofshells; i++) {
701
                        
702
                        shellx = (int[]) shellXYAndHolesList[3 * i];
703
                        shelly = (int[]) shellXYAndHolesList[3 * i + 1];
704
                        holesXY = (ArrayList) shellXYAndHolesList[3 * i + 2];
705

    
706
                        if (holesXY == null) {
707
                                
708
                                g.setColor(sym.getFillColor());
709
                                g.fillPolygon(shellx, shelly, shellx.length);
710
                                
711
                                g.setColor(sym.getBorderColor());
712
                                g.drawPolyline(shellx, shelly, shellx.length);
713

    
714
                        } else {
715
                                
716
                                        // --- not properly: shell: fill + border, holes: border
717
                                        g.setColor(sym.getFillColor());
718
                                        g.fillPolygon(shellx, shelly, shellx.length);
719
                                        
720
                                        g.setColor(sym.getBorderColor());
721
                                        g.drawPolyline(shellx, shelly, shellx.length);
722
                                        
723
                                        int[] hx, hy;
724
                                        int nh = holesXY.size() / 2;
725
                                        for (int h=0; h<nh; h++) {
726
                                                hx = (int[]) holesXY.get(2 * h);
727
                                                hy = (int[]) holesXY.get(2 * h + 1);
728
                                                g.drawPolyline(hx, hy, hx.length);
729
                                        }
730
                                        
731
                                        // ------- TODO ----------
732
                                        /*
733
                                        Object[] img_coords = getPaintedPolygonWithHoles(shellx, shelly, holesXY, sym);
734
                                        Image img = (Image) img_coords[0];
735
                                        int x = ((Integer) img_coords[1]).intValue();
736
                                        int y = ((Integer) img_coords[2]).intValue();
737
                                        g.drawImage(img, x, y, null);
738
                                        */
739
                        }
740

    
741
                }
742
        }
743

    
744
        private static Object[] getPaintedPolygonWithHoles(
745
                        int[] shellx,
746
                        int[] shelly,
747
                        ArrayList holesXYlist,
748
//                        int[] holex,
749
//                        int[] holey
750
                        FSymbol sym
751
                        ) {
752
                
753
                int minx = shellx[0];
754
                int maxx = shellx[0];
755
                int miny = shelly[0];
756
                int maxy = shelly[0];
757
                
758
                int nofp = shellx.length;
759
                int auxx, auxy;
760
                
761
                for (int i=0; i<nofp; i++) {
762
                        auxx = shellx[i];
763
                        auxy = shelly[i];
764
                        if (auxx > maxx) maxx = auxx;
765
                        if (auxx < minx) minx = auxx;
766
                        if (auxy > maxy) maxy = auxy;
767
                        if (auxy < miny) miny = auxy;
768
                }
769
                
770
                int w = maxx - minx + 1;
771
                int h = maxy - miny + 1;
772
                
773
                BufferedImage resp_img = Utils.createBufferedImage(w, h);
774
                Graphics2D g = (Graphics2D) resp_img.getGraphics();
775
                
776
                g.setColor(Color.BLACK);
777
                g.fillRect(0, 0, w, h);
778
                
779
                g.translate(-minx, -miny);
780

    
781
                g.setColor(Color.WHITE);
782
                g.fillPolygon(shellx, shelly, nofp);
783
                
784
                g.setColor(Color.BLACK);
785
                int nofholes = holesXYlist.size() / 2;
786
                
787
                int[] holex, holey;
788
                for (int i=0; i<nofholes; i++) {
789
                        holex = (int[]) holesXYlist.get(2 * i);
790
                        holey = (int[]) holesXYlist.get(2 * i + 1);
791
                        g.fillPolygon(holex, holey, holex.length);
792
                }
793

    
794
                int[] pixels = new int[w*h];
795
                pixels = resp_img.getRGB(0, 0, w, h, null, 0, w);
796

    
797
                byte[] alpha = getRedBand(pixels);
798

    
799
                g.setColor(sym.getFillColor());
800
                g.fillPolygon(shellx, shelly, nofp);
801

    
802
                pixels = resp_img.getRGB(0, 0, w, h, null, 0, w);
803
                
804

    
805
                pixels = setAlphaBand(pixels, alpha);
806
                byte[] png = EcwReader.paintArray(pixels, w, h, 0, true);
807
                
808
                Object[] resp = new Object[3];
809
                resp[0] = Toolkit.getDefaultToolkit().createImage(png);
810
                resp[1] = new Integer(minx);
811
                resp[2] = new Integer(miny);
812
                return resp; 
813
        }
814
        
815
        private static int[] setAlphaBand(int[] _p, byte[] _a) {
816
                int size = _p.length;
817
                int[] resp = new int[size];
818
                for (int i=0; i<size; i++) {
819
                        resp[i] = (_p[i] & 0x00ffffff) + (_a[i] << 24);
820
                }
821
                return resp;
822
        }
823

    
824
        private static byte[] getRedBand(int[] _p) {
825
                
826
                int size = _p.length;
827
                byte[] resp = new byte[size];
828
                
829
                for (int i=0; i<size; i++) {
830
                        resp[i] = (byte) ((_p[i] >> 16) & 0xff);
831
                }
832
                return resp;
833
        }
834

    
835
        private static String getFourBands(int p) {
836
                
837
                return
838
                "" + ((p & 0xff000000) >> 24) +
839
                ", " + ((p & 0x00ff0000) >> 16) +
840
                ", " + ((p & 0x0000ff00) >> 8) +
841
                ", " + (p & 0x000000ff);
842
                
843
        }
844
        
845
        private static boolean isShell(int[] verticesx, int[] verticesy) {
846
                
847
                int size = verticesx.length;
848
                if (size < 3) return true;
849
                
850
                Coordinate[] cc = new Coordinate[size];
851
                
852
                for (int i=0; i<size; i++) {
853
                        cc[i] = new Coordinate(verticesx[i], verticesy[i]);
854
                }
855
                
856
                boolean r = CGAlgorithms.isCCW(cc);
857
                return r;
858
        }
859
        
860
        private static ArrayList split(PathIterator pit) {
861

    
862
                ArrayList resp = new ArrayList();
863
                
864
                ArrayList x = new ArrayList();
865
                ArrayList y = new ArrayList();
866
                
867
                Point last_pt = null;
868

    
869
                float[] current = new float[6];
870

    
871
                while (!pit.isDone()) {
872

    
873
                        if (pit.currentSegment(current) == PathIterator.SEG_MOVETO) {
874
                                if (x.size() > 0) {
875
                                        int[] gx = integerArrayListToIntArray(x);
876
                                        int[] gy = integerArrayListToIntArray(y);
877
                                        resp.add(gx); resp.add(gy);
878
                                }
879
                                x = new ArrayList();
880
                                y = new ArrayList();
881
                                last_pt = null; 
882
                        }
883
                        
884
                        if ((last_pt == null)
885
                                        || (last_pt.x != ((int) current[0]))
886
                                        || (last_pt.y != ((int) current[1]))) {
887
                                
888
                                last_pt = new Point((int) current[0], (int) current[1]);
889
                                x.add(new Integer(last_pt.x));
890
                                y.add(new Integer(last_pt.y));
891
                        }
892
                        
893
                        pit.next();
894
                }
895
                
896
                int[] gx = integerArrayListToIntArray(x);
897
                int[] gy = integerArrayListToIntArray(y);
898
                resp.add(gx); resp.add(gy);
899

    
900
                return resp;
901
        }
902
        
903
        private static int[] getShellIndicesAndHoleCount(ArrayList parts) {
904
                
905
                ArrayList resp = new ArrayList();
906
                int size = parts.size() / 2;
907
                int[] cx, cy;
908
                
909
                if (size == 1) {
910
                        
911
                        // one item, we understand its a shell
912
                        resp.add(new Integer(0));
913
                        
914
                } else {
915
                        // ---------- more than one item
916
                        for (int i=0; i<size; i++) {
917
                                cx = (int[]) parts.get(2 * i);
918
                                cy = (int[]) parts.get(2 * i + 1);
919
                                if (isShell(cx, cy)) resp.add(new Integer(i));
920
                        }
921
                        // ---------- more than one item
922
                }
923
                
924
                
925
                resp.add(new Integer(size));
926
                int resp_size = resp.size() - 1;
927
                
928
                int[] indices = new int[2 * resp_size];
929
                for (int i=0; i<resp_size; i++) {
930
                        int this_index = ((Integer) resp.get(i)).intValue();
931
                        int next_index = ((Integer) resp.get(i + 1)).intValue();
932
                        indices[2 * i] = this_index; 
933
                        indices[2 * i + 1] = next_index - this_index - 1;
934
                }
935
                
936
                return indices;
937
        }
938
        
939
        private static Object[] groupParts(ArrayList parts, int[] indices) {
940
                
941
                int nofp = indices.length / 2;
942
                Object[] resp = new Object[3 * nofp];
943
                
944
                int shell_ind = 0;
945
                int nofholes = 0;
946
                
947
                for (int i=0; i<nofp; i++) {
948
                        
949
                        shell_ind = indices[2 * i];
950
                        nofholes = indices[2 * i + 1];
951
                        
952
                        resp[3 * i] = parts.get(2 * i);
953
                        resp[3 * i + 1] = parts.get(2 * i + 1);
954
                        
955
                        if (nofholes == 0) {
956
                                resp[3 * i + 2] = null;
957
                        } else {
958
                                ArrayList holesxy = new ArrayList();
959
                                for (int h=0; h<(2 * nofholes); h++)
960
                                        holesxy.add(parts.get(2 * shell_ind + 2 + h));
961
                                resp[3 * i + 2] = holesxy;
962
                        }
963
                }
964
                return resp;
965
        }
966
        
967
        private static void printIntArrayToLogger(int[] arr, String name) {
968
                
969
                logger.debug("--- ARRAY: <" + name + "> --- START ---");
970
                for (int i=0; i<arr.length; i++) {
971
                        logger.debug("-- ITEM [ " + i + " ] = " + arr[i]);
972
                }
973
                logger.debug("--- ARRAY: <" + name + "> --- END   ---");
974
                
975
        }
976
        
977
        /**
978
         * Draws the path iterator on the graphics object with the given affine transformation
979
         * @param g the graphics object
980
         * @param piter the path iterator
981
         * @param at the affine transformation (can be null)
982
         */
983
        public static void drawPathIterator(Graphics2D g, PathIterator piter, AffineTransform at) {
984
                ArrayList x = new ArrayList();
985
                ArrayList y = new ArrayList();
986
                float[] current = new float[6];
987

    
988
                while (!piter.isDone()) {
989
                        piter.currentSegment(current);
990
                        x.add(new Integer((int) current[0]));
991
                        y.add(new Integer((int) current[1]));
992
                        piter.next();
993
                }
994
                
995
                int[] gx = integerArrayListToIntArray(x);
996
                int[] gy = integerArrayListToIntArray(y);
997

    
998
                g.drawPolyline(gx, gy, gx.length);                
999
        }
1000

    
1001
        public static void drawPathIteratorLastVertices(
1002
                        Graphics2D g,
1003
                        PathIterator piter,
1004
                        AffineTransform at,
1005
                        int currentLength,
1006
                        int max_vertices) {
1007
                
1008
                ArrayList x = new ArrayList();
1009
                ArrayList y = new ArrayList();
1010
                float[] current = new float[6];
1011

    
1012
                int count = 0;
1013
                while (!piter.isDone()) {
1014
                        
1015
                        if ((currentLength - count) < max_vertices) {
1016
                                piter.currentSegment(current);
1017
                                x.add(new Integer((int) current[0]));
1018
                                y.add(new Integer((int) current[1]));
1019
                        }
1020
                        
1021
                        count++;
1022
                        piter.next();
1023
                }
1024
                
1025
                int[] gx = integerArrayListToIntArray(x);
1026
                int[] gy = integerArrayListToIntArray(y);
1027

    
1028
                g.drawPolyline(gx, gy, gx.length);                        
1029
                
1030
                
1031
                // TODO Auto-generated method stub
1032
                
1033
        }
1034
}