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