Statistics
| Revision:

root / org.gvsig.legend.heatmap / trunk / org.gvsig.legend.heatmap / org.gvsig.legend.heatmap.lib / org.gvsig.legend.heatmap.lib.impl / src / main / java / org / gvsig / legend / heatmap / lib / impl / DefaultHeatmapLegend.java @ 2402

History | View | Annotate | Download (22.5 KB)

1 1717 jjdelcerro
package org.gvsig.legend.heatmap.lib.impl;
2
3
import java.awt.Color;
4
import java.awt.Graphics2D;
5 1766 jjdelcerro
import java.awt.Image;
6 1717 jjdelcerro
import java.awt.image.BufferedImage;
7
import java.util.Map;
8 1853 fdiaz
9 1766 jjdelcerro
import org.apache.commons.lang3.StringUtils;
10 1717 jjdelcerro
import org.cresques.cts.ICoordTrans;
11 2267 jjdelcerro
import org.gvsig.compat.print.PrintAttributes;
12 1853 fdiaz
13 1717 jjdelcerro
import org.gvsig.fmap.dal.exception.DataException;
14
import org.gvsig.fmap.dal.feature.Feature;
15
import org.gvsig.fmap.dal.feature.FeatureQuery;
16
import org.gvsig.fmap.dal.feature.FeatureSelection;
17
import org.gvsig.fmap.dal.feature.FeatureSet;
18
import org.gvsig.fmap.dal.feature.FeatureStore;
19 1766 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
20 1717 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
21 2400 omartinez
import org.gvsig.fmap.geom.GeometryUtils;
22 1717 jjdelcerro
import org.gvsig.fmap.geom.primitive.Point;
23
import org.gvsig.fmap.mapcontext.MapContextException;
24
import org.gvsig.fmap.mapcontext.ViewPort;
25 1766 jjdelcerro
import org.gvsig.fmap.mapcontext.layers.operations.IHasImageLegend;
26 1717 jjdelcerro
import org.gvsig.fmap.mapcontext.rendering.legend.LegendException;
27 1766 jjdelcerro
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
28 1717 jjdelcerro
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
29 1766 jjdelcerro
import org.gvsig.gui.ColorTablePainter;
30
import org.gvsig.gui.DefaultColorTablePainter;
31 1717 jjdelcerro
import org.gvsig.legend.heatmap.lib.api.HeatmapLegend;
32
import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.AbstractVectorialLegend;
33
import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.DefaultFeatureDrawnNotification;
34
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.impl.SimpleTextSymbol;
35
import org.gvsig.tools.exception.BaseException;
36 1851 jjdelcerro
import org.gvsig.tools.persistence.PersistentState;
37
import org.gvsig.tools.persistence.exception.PersistenceException;
38
import org.gvsig.tools.swing.api.ToolsSwingLocator;
39
import org.gvsig.tools.swing.api.ToolsSwingManager;
40 1717 jjdelcerro
import org.gvsig.tools.task.Cancellable;
41
import org.gvsig.tools.visitor.VisitCanceledException;
42
import org.gvsig.tools.visitor.Visitor;
43
44 1766 jjdelcerro
public class DefaultHeatmapLegend extends AbstractVectorialLegend implements HeatmapLegend, IHasImageLegend {
45 1723 fdiaz
46 1717 jjdelcerro
    private class DensityAlgorithm {
47
48
        private double[][] grid;
49
        private double[][] kernel;
50
        private int distance;
51
        private int height;
52
        private int with;
53
        private double maxValue;
54
        private double minValue;
55
56
        public DensityAlgorithm(int distance) {
57
            this.setDistance(distance);
58
        }
59 1723 fdiaz
60 1717 jjdelcerro
        public void setDistance(int distance) {
61 2267 jjdelcerro
            if( this.distance == distance ) {
62
                return;
63
            }
64 1717 jjdelcerro
            this.distance = distance;
65
            this.kernel = new double[2 * this.distance + 1][2 * this.distance + 1];
66
            for( int y = -this.distance; y < this.distance + 1; y++ ) {
67
                for( int x = -this.distance; x < this.distance + 1; x++ ) {
68
                    final double dDist = Math.sqrt(x * x + y * y);
69
                    if( dDist < this.distance ) {
70
                        this.kernel[x + this.distance][y + this.distance] = Math.pow(1 - (dDist * dDist) / (this.distance * this.distance), 2);
71
                    } else {
72
                        this.kernel[x + this.distance][y + this.distance] = 0;
73
                    }
74
                }
75
            }
76
        }
77
78
        public int getDistance() {
79
            return this.distance;
80
        }
81
82
        public void init(int with, int height) {
83
            this.with = with;
84
            this.height = height;
85
            this.grid = new double[with][height];
86
            this.maxValue = 0;
87
            this.minValue = 0;
88
        }
89
90
        public void add(int px, int py) {
91
            add(px, py, 1);
92
        }
93
94
        public void add(int px, int py, double value) {
95
            for( int y = -this.distance; y < this.distance + 1; y++ ) {
96
                for( int x = -this.distance; x < this.distance + 1; x++ ) {
97
                    if( this.kernel[x + this.distance][y + this.distance] != 0 ) {
98
                        addValue(px + x, py + y, value * this.kernel[x + this.distance][y + this.distance]);
99
                    }
100
                }
101
            }
102
        }
103
104
        private void addValue(int px, int py, double value) {
105 1766 jjdelcerro
            if( px < 0 || py < 0 || px >= with || py >= height ) {
106 1717 jjdelcerro
                return;
107
            }
108
            value += this.grid[px][py];
109
            this.grid[px][py] = value;
110
            if( value > this.maxValue ) {
111
                this.maxValue = value;
112
            }
113
            if( value < this.minValue ) {
114
                this.minValue = value;
115
            }
116
        }
117
118 2400 omartinez
        public void drawWithOpaqueColors(BufferedImage img, Graphics2D g, Color[] colorTable, Cancellable cancel, Geometry roi) {
119 1717 jjdelcerro
            try {
120 1851 jjdelcerro
                ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
121 1766 jjdelcerro
                Color c;
122 1851 jjdelcerro
                int maxIndexColor = colorTable.length-1;
123 1717 jjdelcerro
                for( int x = 0; x < with; x++ ) {
124
                    for( int y = 0; y < height; y++ ) {
125
                        if( cancel.isCanceled() ) {
126
                            return;
127
                        }
128 2400 omartinez
                        if (roi!=null) {
129
                            Point point = GeometryUtils.createPoint(x, y);
130
                            if (!roi.intersects(point)) {
131
                                continue;
132
                            }
133
                        }
134 1717 jjdelcerro
                        double value = this.grid[x][y];
135
                        if( value > 0 ) {
136 1847 fdiaz
                            int icolor = (int) (value * maxIndexColor / maxValue);
137 1851 jjdelcerro
                            c = toolsSwingManager.alphaBlendingWithOpaqueBackground(
138
                                    new Color(img.getRGB(x, y)),
139
                                    colorTable[icolor]
140
                            );
141 1717 jjdelcerro
                            img.setRGB(x, y, c.getRGB());
142
                        }
143
                    }
144
                }
145
            } catch (Exception ex) {
146
                LOG.warn("Problems drawing heatmap", ex);
147
            }
148
        }
149 2267 jjdelcerro
150 2400 omartinez
        public void drawWithAlphaColors(BufferedImage img, Graphics2D g, Color[] colorTable, Cancellable cancel, Geometry roi) {
151 2267 jjdelcerro
            try {
152
                Color c;
153
                int maxIndexColor = colorTable.length-1;
154
                for( int x = 0; x < with; x++ ) {
155
                    for( int y = 0; y < height; y++ ) {
156
                        if( cancel.isCanceled() ) {
157
                            return;
158
                        }
159 2400 omartinez
                        if (roi!=null) {
160
                            Point point = GeometryUtils.createPoint(x, y);
161
                            if (!roi.intersects(point)) {
162
                                continue;
163
                            }
164
                        }
165 2267 jjdelcerro
                        double value = this.grid[x][y];
166
                        if( value > 0 ) {
167
                            int icolor = (int) (value * maxIndexColor / maxValue);
168
                            c = colorTable[icolor];
169
                            img.setRGB(x, y, c.getRGB());
170
                        }
171
                    }
172
                }
173
            } catch (Exception ex) {
174
                LOG.warn("Problems drawing heatmap", ex);
175
            }
176
        }
177 1717 jjdelcerro
    }
178
179 1851 jjdelcerro
    private ISymbol defaultSymbol;
180
    private DensityAlgorithm algorithm;
181 1766 jjdelcerro
    private boolean isRamp;
182 1847 fdiaz
    private Color[] sourceColorTable;
183 1766 jjdelcerro
    private int colorTableHotColorAlpha;
184
    private int colorTableColdColorAlpha;
185 1851 jjdelcerro
    private boolean useAlphaInColorTable;
186 1766 jjdelcerro
    private String fieldName;
187
    private Image imageLegend;
188 1847 fdiaz
    private HeatmapColorTable hmColorTable;
189 1853 fdiaz
    private Color rampColdColor;
190
    private Color rampHotColor;
191
    private int rampNumColors;
192 2400 omartinez
    private Geometry roi;
193
194 1717 jjdelcerro
    public DefaultHeatmapLegend() {
195 2400 omartinez
196 1717 jjdelcerro
        this.defaultSymbol = new SimpleTextSymbol();
197
        this.algorithm = new DensityAlgorithm(30);
198 1766 jjdelcerro
        this.colorTableHotColorAlpha = 255;
199
        this.colorTableColdColorAlpha = 0;
200
        this.useAlphaInColorTable = false;
201 1847 fdiaz
        this.setColorTable(100, new Color(0, 0, 255, 0), new Color(255, 0, 0, 255));
202 1766 jjdelcerro
        this.imageLegend = null;
203 1851 jjdelcerro
        this.hmColorTable = null;
204
        this.fieldName = null;
205 1717 jjdelcerro
    }
206
207
    @Override
208
    protected String[] getRequiredFeatureAttributeNames(FeatureStore featureStore) throws DataException {
209 1766 jjdelcerro
        FeatureType ftype = featureStore.getDefaultFeatureType();
210
        if( StringUtils.isEmpty(this.fieldName) ) {
211
            return new String[]{
212
                ftype.getDefaultGeometryAttributeName()
213
            };
214
        }
215 1717 jjdelcerro
        return new String[]{
216 1766 jjdelcerro
            ftype.getDefaultGeometryAttributeName(),
217
            this.fieldName
218
        };
219 1717 jjdelcerro
    }
220
221
    @Override
222
    public ISymbol getDefaultSymbol() {
223
        return this.defaultSymbol;
224
    }
225
226
    @Override
227
    public void setDefaultSymbol(ISymbol is) {
228
    }
229 2402 omartinez
230 1717 jjdelcerro
    @Override
231
    public ISymbol getSymbolByFeature(Feature ftr) throws MapContextException {
232
        return this.defaultSymbol;
233
    }
234
235
    @Override
236
    public int getShapeType() {
237
        return Geometry.TYPES.GEOMETRY;
238
    }
239
240
    @Override
241
    public void setShapeType(int i) {
242
    }
243
244
    @Override
245
    public boolean isUseDefaultSymbol() {
246
        return true;
247
    }
248
249
    @Override
250
    public void useDefaultSymbol(boolean bln) {
251
    }
252
253
    @Override
254
    public boolean isSuitableForShapeType(int shapeType) {
255
        return true;
256
    }
257
258
    @Override
259
    protected void draw(BufferedImage image, Graphics2D g, ViewPort viewPort, Cancellable cancel, double scale, Map queryParameters, ICoordTrans coordTrans, FeatureStore featureStore, FeatureQuery featureQuery, double dpi) throws LegendException {
260 2267 jjdelcerro
        int saved_distance = this.algorithm.getDistance();
261
        try {
262 2402 omartinez
            int distance = (int) (this.algorithm.getDistance() * (dpi / 72));
263 2400 omartinez
            Geometry theROI = null;
264
            if (this.roi!=null) {
265
                theROI = this.roi.cloneGeometry();
266
                theROI.transform(viewPort.getAffineTransform());
267
            }
268 2267 jjdelcerro
            this.algorithm.setDistance(distance);
269
            this.algorithm.init(image.getWidth(), image.getHeight());
270
            super.draw(image, g, viewPort, cancel, scale, queryParameters, coordTrans, featureStore, featureQuery, dpi);
271
            if( !cancel.isCanceled() ) {
272 2400 omartinez
                this.algorithm.drawWithOpaqueColors(image, g, this.getHeatMapColorTable().getColorTable(), cancel, theROI);
273 2267 jjdelcerro
            }
274
        } finally {
275
            this.algorithm.setDistance(saved_distance);
276
277 1717 jjdelcerro
        }
278
    }
279 2267 jjdelcerro
280
    @Override
281
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
282
            double scale, Map queryParameters, ICoordTrans coordTrans,
283
            FeatureStore featureStore, FeatureQuery featureQuery, PrintAttributes properties)
284
            throws LegendException {
285
        int saved_distance = this.algorithm.getDistance();
286
        try {
287
            double dpi = viewPort.getDPI();
288
            // Ver CartographicSupportToolkit.getCartographicLength
289 2402 omartinez
            int distance = (int) (this.algorithm.getDistance() * (dpi / 72));
290 2400 omartinez
            Geometry theROI = null;
291
            if (this.roi!=null) {
292
                theROI = this.roi.cloneGeometry();
293
                theROI.transform(viewPort.getAffineTransform());
294
            }
295 2267 jjdelcerro
            this.algorithm.setDistance(distance);
296
            this.algorithm.init(viewPort.getImageWidth(), viewPort.getImageHeight());
297
            BufferedImage image = new BufferedImage(viewPort.getImageWidth(), viewPort.getImageHeight(), BufferedImage.TYPE_INT_ARGB);
298
            super.draw(image, g, viewPort, cancel, scale, queryParameters, coordTrans, featureStore, featureQuery, dpi);
299
            if (!cancel.isCanceled()) {
300 2400 omartinez
                this.algorithm.drawWithAlphaColors(image, g, this.getHeatMapColorTable().getColorTable(), cancel, theROI);
301 2267 jjdelcerro
                g.drawImage(image, 0, 0, null);
302
            }
303
        } finally {
304
            this.algorithm.setDistance(saved_distance);
305 1717 jjdelcerro
306 2267 jjdelcerro
        }
307
    }
308
309 1717 jjdelcerro
    @Override
310
    protected void drawFeatures(
311
        BufferedImage image,
312
        Graphics2D g,
313
        final ViewPort viewPort,
314
        final Cancellable cancel,
315
        final ICoordTrans coordTrans,
316
        double dpi,
317
        DefaultFeatureDrawnNotification drawnNotification,
318
        FeatureSet featureSet,
319
        FeatureSelection selection
320
    ) throws BaseException {
321 1766 jjdelcerro
        int x = -1;
322
        if( !StringUtils.isEmpty(this.fieldName) ) {
323
            x = featureSet.getDefaultFeatureType().getIndex(this.fieldName);
324
        }
325
        final int n = x;
326 1717 jjdelcerro
        featureSet.accept(new Visitor() {
327
            @Override
328
            public void visit(Object o) throws VisitCanceledException, BaseException {
329
                if( cancel.isCanceled() ) {
330
                    throw new VisitCanceledException();
331
                }
332
                Feature feature = (Feature) o;
333
                Geometry geom = feature.getDefaultGeometry();
334
                if( geom != null ) {
335
                    Point pointGeo = geom.centroid();
336
                    if( coordTrans != null ) {
337
                        pointGeo.reProject(coordTrans);
338
                    }
339
                    Point pointPixels = (Point) pointGeo.cloneGeometry();
340
                    pointPixels.transform(viewPort.getAffineTransform());
341 1766 jjdelcerro
                    if( n >= 0 ) {
342
                        double value = 0;
343
                        try {
344
                            value = feature.getDouble(n);
345 1847 fdiaz
                        } catch(Exception ex) {
346 1766 jjdelcerro
                        }
347
                        if( value >0 ) {
348
                            algorithm.add((int) pointPixels.getX(), (int) pointPixels.getY(), value);
349
                        }
350
                    } else {
351
                        algorithm.add((int) pointPixels.getX(), (int) pointPixels.getY());
352
                    }
353 1717 jjdelcerro
                }
354
            }
355
        });
356
    }
357
358 1766 jjdelcerro
    /**
359
     * @return the distance
360
     */
361
    @Override
362
    public int getDistance() {
363
        return this.algorithm.getDistance();
364 2402 omartinez
    }
365 1717 jjdelcerro
366 1766 jjdelcerro
    /**
367
     * @param distance the distance to set
368
     */
369
    @Override
370
    public void setDistance(int distance) {
371
        this.algorithm.setDistance(distance);
372
    }
373 1723 fdiaz
374 1766 jjdelcerro
    @Override
375
    public void setColorTable(Color[] colorTable) {
376
        this.isRamp = false;
377 1847 fdiaz
        this.sourceColorTable = colorTable;
378 1766 jjdelcerro
        this.imageLegend = null;
379 1852 jjdelcerro
        this.hmColorTable = null;
380 1766 jjdelcerro
        this.fireDefaultSymbolChangedEvent(new SymbolLegendEvent(null,null));
381
    }
382 1723 fdiaz
383 1766 jjdelcerro
    @Override
384 1853 fdiaz
    public void setColorTable(int numColors, Color coldColor, Color hotColor) {
385 1766 jjdelcerro
        this.isRamp = true;
386 1853 fdiaz
        this.rampColdColor = coldColor;
387
        this.rampHotColor = hotColor;
388
        this.rampNumColors = numColors;
389 1766 jjdelcerro
        this.imageLegend = null;
390 1852 jjdelcerro
        this.hmColorTable = null;
391 1766 jjdelcerro
        this.fireDefaultSymbolChangedEvent(new SymbolLegendEvent(null,null));
392
    }
393 1723 fdiaz
394 1766 jjdelcerro
    @Override
395 1847 fdiaz
    public Color[] getSourceColorTable() {
396
        return this.sourceColorTable;
397 1766 jjdelcerro
    }
398 1723 fdiaz
399 1766 jjdelcerro
    @Override
400 1847 fdiaz
    public Color[] getTargetColorTable() {
401 1852 jjdelcerro
        return this.getHeatMapColorTable().getColorTable();
402 1847 fdiaz
    }
403
404 1852 jjdelcerro
    private HeatmapColorTable getHeatMapColorTable() {
405 1847 fdiaz
        if (this.hmColorTable == null) {
406 1853 fdiaz
            if (this.useRamp()) {
407
                this.hmColorTable = new HeatmapColorTable(this.rampColdColor, this.rampHotColor, this.rampNumColors);
408 1847 fdiaz
            } else {
409 1853 fdiaz
                if(useAlphaInColorTable) {
410
                    this.hmColorTable = new HeatmapColorTable(this.getSourceColorTable(), colorTableColdColorAlpha, colorTableHotColorAlpha);
411
                } else {
412 1847 fdiaz
                this.hmColorTable =
413 1853 fdiaz
                    this.hmColorTable = new HeatmapColorTable(this.getSourceColorTable());
414
                }
415 1847 fdiaz
            }
416
        }
417
        return this.hmColorTable;
418
    }
419
420
421
    @Override
422 1766 jjdelcerro
    public boolean useRamp() {
423
        return this.isRamp;
424 1717 jjdelcerro
    }
425
426
    @Override
427 1766 jjdelcerro
    public String getFieldName() {
428
        return this.fieldName;
429 1717 jjdelcerro
    }
430
431
    @Override
432 1766 jjdelcerro
    public void setFieldName(String fieldName) {
433
        this.fieldName = fieldName;
434 1717 jjdelcerro
    }
435
436 1766 jjdelcerro
    @Override
437
    public int getColorTableHotColorAlpha() {
438
        return colorTableHotColorAlpha;
439
    }
440
441
    @Override
442
    public void setColorTableHotColorAlpha(int colorTableHotColorAlpha) {
443
        this.colorTableHotColorAlpha = colorTableHotColorAlpha;
444 1847 fdiaz
        this.imageLegend = null;
445 1853 fdiaz
        this.hmColorTable = null;
446 1766 jjdelcerro
    }
447
448
    @Override
449
    public int getColorTableColdColorAlpha() {
450
        return colorTableColdColorAlpha;
451
    }
452
453
    @Override
454
    public void setColorTableColdColorAlpha(int colorTableColdColorAlpha) {
455
        this.colorTableColdColorAlpha = colorTableColdColorAlpha;
456 1847 fdiaz
        this.imageLegend = null;
457 1853 fdiaz
        this.hmColorTable = null;
458 1766 jjdelcerro
    }
459
460
    @Override
461
    public boolean useAlphaInColorTable() {
462
        return this.useAlphaInColorTable;
463
    }
464
465
    @Override
466
    public boolean setUseAlphaInColorTable(boolean use) {
467
        boolean x = this.useAlphaInColorTable;
468
        this.useAlphaInColorTable = use;
469 1853 fdiaz
        this.hmColorTable = null;
470
471 1766 jjdelcerro
        return x;
472
    }
473 2400 omartinez
    @Override
474
    public void setROI(Geometry roi) {
475
        this.roi = roi;
476
    }
477 1766 jjdelcerro
478
    @Override
479 2400 omartinez
    public Geometry getROI() {
480
        return this.roi;
481
    }
482
483
    @Override
484 1766 jjdelcerro
    public Image getImageLegend() {
485
        if( this.imageLegend==null ) {
486
            BufferedImage img = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
487 1847 fdiaz
            ColorTablePainter painter = new DefaultColorTablePainter(this.getTargetColorTable(),"");
488 1766 jjdelcerro
            Graphics2D g = img.createGraphics();
489 1847 fdiaz
            g.setClip(0, 0, 80, 20);
490
            g.setBackground(Color.WHITE);
491
            g.fillRect(0, 0, 80, 20);
492 1766 jjdelcerro
            painter.paint(g, false);
493
            this.imageLegend = img;
494
        }
495
        return this.imageLegend;
496
    }
497
498
    @Override
499
    public String getPathImage() {
500
        return null;
501
    }
502
503 1851 jjdelcerro
    @Override
504
    public void loadFromState(PersistentState state) throws PersistenceException {
505
        this.defaultSymbol = new SimpleTextSymbol();
506
        this.imageLegend = null;
507
        this.hmColorTable = null;
508
509
        super.loadFromState(state);
510
        this.isRamp = state.getBoolean("isRamp");
511
        this.sourceColorTable = (Color[]) state.getArray("sourceColorTable",Color.class);
512
        this.colorTableHotColorAlpha = state.getInt("colorTableHotColorAlpha");
513
        this.colorTableColdColorAlpha = state.getInt("colorTableColdColorAlpha");
514
        this.useAlphaInColorTable = state.getBoolean("useAlphaInColorTable");
515
        this.fieldName = state.getString("fieldName");
516 1853 fdiaz
        this.rampNumColors = state.getInt("rampNumColors");
517
        this.rampColdColor = (Color)state.get("rampColdColor");
518
        this.rampHotColor = (Color)state.get("rampHotColor");
519 1851 jjdelcerro
520
        this.algorithm = new DensityAlgorithm(state.getInt("distance"));
521
    }
522
523
    @Override
524 1853 fdiaz
    public int getRampNumColors() {
525
        return this.rampNumColors;
526
    }
527
528
    @Override
529
    public Color getRampColdColor() {
530
        return this.rampColdColor;
531
    }
532
533
    @Override
534
    public Color getRampHotColor() {
535
        return this.rampHotColor;
536
    }
537
538
    @Override
539 1851 jjdelcerro
    public void saveToState(PersistentState state) throws PersistenceException {
540
        super.saveToState(state);
541
        state.set("isRamp", isRamp);
542
        state.set("sourceColorTable", sourceColorTable);
543
        state.set("colorTableHotColorAlpha", colorTableHotColorAlpha);
544
        state.set("colorTableColdColorAlpha", colorTableColdColorAlpha);
545
        state.set("useAlphaInColorTable", useAlphaInColorTable);
546
        state.set("fieldName", fieldName);
547
        state.set("distance", algorithm.distance);
548 1853 fdiaz
549
        state.set("rampNumColors", rampNumColors);
550
        state.set("rampColdColor", rampColdColor);
551
        state.set("rampHotColor", rampHotColor);
552 1851 jjdelcerro
    }
553 1853 fdiaz
554
555 1847 fdiaz
    private static class HeatmapColorTable {
556
557
        private Color[] sourceColorTable = null;
558
        private int coldAlpha = -1;
559
        private int hotAlpha = -1;
560
        private Color coldColor = null;
561
        private Color hotColor = null;
562
        private Color[] targetColorTable = null;
563
        private int length = -1;
564
565
        public HeatmapColorTable(Color[] sourceColorTable){
566
            this.sourceColorTable  = sourceColorTable;
567
        }
568
569
        public HeatmapColorTable(Color[] sourceColorTable, int coldAlpha, int hotAlpha){
570
            this.sourceColorTable  = sourceColorTable;
571
            this.coldAlpha = coldAlpha;
572
            this.hotAlpha = hotAlpha;
573
        }
574
575 1853 fdiaz
        public HeatmapColorTable(Color coldColor, Color hotColor, int length){
576 1847 fdiaz
            this.coldColor = coldColor;
577
            this.hotColor = hotColor;
578
            this.length = length;
579
        }
580
581
        public Color[] getColorTable(){
582
            if(targetColorTable==null){
583
                if(sourceColorTable!=null){ //Tenemos tabla de color
584 1853 fdiaz
                    if (coldAlpha >= 0 || hotAlpha >= 0) { //Se usa alpha para la tabla de color
585
                        double alphaDelta = getDelta(coldAlpha, hotAlpha, sourceColorTable.length);
586
                        targetColorTable = new Color[sourceColorTable.length];
587
                        for (int i = 0; i < sourceColorTable.length; i++) {
588
                            Color sourceColor = sourceColorTable[i];
589
                            if (coldAlpha >= 0 && hotAlpha >= 0) {
590
                                targetColorTable[i] =
591
                                    new Color(sourceColor.getRed(), sourceColor.getGreen(), sourceColor.getBlue(),
592
                                        coldAlpha + (int) (i * alphaDelta));
593
                            } else {
594
                                targetColorTable[i] = sourceColor;
595
                            }
596 1847 fdiaz
                        }
597 1853 fdiaz
                    } else { //No se usa alpha para la tabla de color
598
                        targetColorTable = sourceColorTable;
599 1847 fdiaz
                    }
600 1853 fdiaz
                } else { // Tenemos gradiente
601 1847 fdiaz
                    targetColorTable = new Color[length];
602 1853 fdiaz
603
                    double deltaRed = (hotColor.getRed() - coldColor.getRed()) / length;
604
                    double deltaGreen = (hotColor.getGreen() - coldColor.getGreen()) / length;
605
                    double deltaBlue = (hotColor.getBlue() - coldColor.getBlue()) / length;
606
                    double deltaAlpha = (hotColor.getAlpha() - coldColor.getAlpha()) / length;
607
                    for (int i = 0; i < length; i++) {
608 1847 fdiaz
                        targetColorTable[i] =
609 1853 fdiaz
                            new Color(
610
                                (int) (coldColor.getRed() + i * deltaRed),
611
                                (int) (coldColor.getGreen() + i * deltaGreen),
612
                                (int) (coldColor.getBlue() + i * deltaBlue),
613
                                (int) (coldColor.getAlpha() + i * deltaAlpha));
614 1847 fdiaz
                    }
615
                }
616
            }
617
            return targetColorTable;
618
        }
619
620
        private double getDelta(int x1, int x2, int lenght){
621
            return (x2-x1)/((double)lenght-1);
622
        }
623
    }
624 1717 jjdelcerro
}