Statistics
| Revision:

gvsig-raster / org.gvsig.raster / branches / org.gvsig.raster_dataaccess_refactoring / org.gvsig.raster.fmap / src / main / java / org / gvsig / raster / fmap / layers / RasterDrawStrategy.java @ 2371

History | View | Annotate | Download (9.3 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
* 
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
* 
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU General Public License for more details.
15
* 
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
* MA  02110-1301, USA.
20
* 
21
*/
22
package org.gvsig.raster.fmap.layers;
23

    
24
import java.util.ArrayList;
25
import java.util.HashMap;
26

    
27
import org.gvsig.fmap.dal.coverage.RasterLocator;
28
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
29
import org.gvsig.fmap.dal.coverage.grid.render.Render;
30
import org.gvsig.fmap.mapcontext.MapContext;
31
import org.gvsig.fmap.mapcontext.layers.FLayer;
32
import org.gvsig.fmap.mapcontext.layers.FLayers;
33

    
34
/**
35
 * Aplica estrategias de dibujado para las capas raster. Hace que las 
36
 * capas que est?n ocultas por otras no sean dibujadas. Esta estrategia tiene que ser
37
 * aplicada a capas raster de FMap por falta de eficiencia en el dibujado. Esta clase
38
 * es totalmente dependiente de FMap y puede ser eliminada en caso de que este no exita.
39
 * 28/11/2007
40
 * @author Nacho Brodin nachobrodin@gmail.com
41
 */
42
public class RasterDrawStrategy {
43

    
44
        /**
45
         * Cada mapContext existente lleva asociadad una estrategia de dibujado
46
         */
47
        public static HashMap<MapContext, HashMap<DefaultFLyrRaster, Boolean>>        
48
                                     mapContextStrategy    = new HashMap<MapContext, HashMap<DefaultFLyrRaster, Boolean>> ();
49
        
50
        private MapContext           mapContext            = null;
51
        private DefaultFLyrRaster         lyrRaster             = null;
52

    
53
        /**
54
         * Estructura de datos para almacenar la asociaci?n entre el extent de una capa
55
         * y su informaci?n de transparencia. Esta es necesaria para la comprobaci?n de si la 
56
         * capa con la que se est? intersectando tiene transparencia o no la tiene. Con esto 
57
         * se puede decidir si dibujar la capa actual o no.
58
         * 16/06/2008
59
         * @author Nacho Brodin nachobrodin@gmail.com
60
         */
61
        public class LayerIntersection {
62
                public Extent  extent          = null;
63
                public boolean hasTransparency = false;
64
                /**
65
                 * Constructor. Asigna el Extent y la informaci?n de transparencia
66
                 * @param ext Extent
67
                 * @param transp Transparencia
68
                 */
69
                public LayerIntersection(Extent ext, boolean transp) {
70
                        this.extent = ext;
71
                        this.hasTransparency = transp;
72
                } 
73
        }
74
        /**
75
         * Al constructor le pasamos el contexto de dibujado para la toma de decisi?n.
76
         * @param mapContext Context
77
         * @throws ExpansionFileReadException
78
         * @throws ReadDriverException
79
         */
80
        public RasterDrawStrategy(MapContext mapContext, DefaultFLyrRaster lyrRaster) {
81
                this.mapContext = mapContext;
82
                this.lyrRaster = lyrRaster;
83
        }
84
        
85
        /**
86
         * <P>
87
         * Estrategia de dibujado para las capas raster que hace que si
88
         * una capa est? oculta completamente por otra que no tiene transparencias entonces
89
         * esta no ser? dibujada.
90
         * </P>
91
         * <P>
92
         * La estrategia la calcula solo la primera capa raster que aparezca. El resto
93
         * de las capas la preguntaran a esta.
94
         * </P>
95
         * <P>
96
         * <code>Estrategia:</code>
97
         * Analizamos la lista de capas desde la primera que se dibuja en el TOC hasta la ?ltima
98
         * <UL>
99
         * <LI>Si la capa tiene rotaci?n se dibuja siempre.</LI>
100
         * <LI>Si la capa no est? activa en el TOC no se dibuja nunca</LI>
101
         * <LI>Si la capa no es transparente y no hay extents en la lista se dibuja y se a?ade el extent a la lista</LI>
102
         * <LI>Si el extent de la capa intersecta con uno de la lista</LI>
103
         * </UL>
104
         * Comprobamos si est? detr?s de un extent de la lista. Si es as? no se dibuja
105
         * Si no est? est? detr?s de un extent comprobamos si tiene transparencias
106
         * Si no tiene transparencias a?adimos el extent a la lista
107
         * </P>
108
         * @param lyrs
109
         * @throws ReadDriverException 
110
         * @throws ExpansionFileReadException 
111
         */
112
        public void stackStrategy() {
113
                if(mapContext == null || lyrRaster == null)
114
                        return;
115
                
116
                ArrayList<FLayer> listLayers = new ArrayList<FLayer>();
117
                FLayers lyrs = mapContext.getLayers();
118
                listLayers = getLayerList(lyrs, listLayers);
119
                
120
                ArrayList<LayerIntersection> extentList = new ArrayList<LayerIntersection>();
121
                                
122
                //Solo la primera capa calcula la estrategia. Las dem?s se la preguntan a esta.
123
                
124
                //Calculamos cual es la primera capa raster de FLayers y contamos cuantas capas raster hay
125
                int posFirstRasterLayer = 0;
126
                int nRasterLayers = 0;
127
                boolean firstTime = true;
128
                for (int i = 0; i < listLayers.size(); i++) {
129
                        FLayer lyr = (FLayer) listLayers.get(i);
130
                        if(firstTime && lyr instanceof DefaultFLyrRaster && lyr.isVisible()) {
131
                                posFirstRasterLayer = i;
132
                                firstTime = false;
133
                        }
134
                        if(lyr instanceof DefaultFLyrRaster)
135
                                nRasterLayers ++;
136
                }
137
                
138
                //Si hay solo una capa raster no se calcula ninguna estrategia
139
                if(nRasterLayers == 1) {
140
                        mapContextStrategy.put(mapContext, null);
141
                        return;
142
                }
143
                
144
                //Si no es la primera capa se obtiene la estrategia que calcul? la primera capa
145
                if(lyrRaster != listLayers.get(posFirstRasterLayer)) {
146
                        if(!(listLayers.get(posFirstRasterLayer) instanceof DefaultFLyrRaster))
147
                                return;
148
                        mapContextStrategy.put(mapContext, ((DefaultFLyrRaster)listLayers.get(posFirstRasterLayer)).getRasterStrategy());
149
                        return;
150
                }
151
                
152
                HashMap<DefaultFLyrRaster, Boolean> layersToPaint = new HashMap<DefaultFLyrRaster, Boolean>();
153
                
154
                //Calculo de estrategia. Solo llega aqu? la primera capa.
155
                //La lista de capas en FLayers est? en orden inverso a lo que aparece en el TOC, es decir, la ?ltima capa
156
                //del TOC es la primera de la lista de FLayers y la primera del TOC es la ?ltima de la lista.
157
                for (int i = (listLayers.size() - 1); i >= 0; i--) {
158
                        FLayer lyr = (FLayer) listLayers.get(i);
159
                        
160
                        if (!(lyr instanceof DefaultFLyrRaster))
161
                                continue;
162
                        
163
                        DefaultFLyrRaster rLyr = ((DefaultFLyrRaster)lyr);
164
                        
165
                        if(rLyr.getRender() == null || rLyr.getRender().getFilterList() == null || rLyr.getFullEnvelope() == null)
166
                                continue;
167
                        
168
                        //Si no est? activa y/o visible no se dibuja nunca 
169
                        if(!rLyr.isVisible()) {
170
                                layersToPaint.put(rLyr, new Boolean(false));
171
                                continue;
172
                        }
173
                        
174
                        //Si tiene rotaci?n se dibuja siempre
175
                        if(rLyr.getAffineTransform() != null) {
176
                                if(        rLyr.getAffineTransform().getShearX() != 0 || 
177
                                                rLyr.getAffineTransform().getShearY() != 0) {
178
                                        layersToPaint.put(rLyr, new Boolean(true));
179
                                        continue;
180
                                }
181
                        }
182

    
183
                        //Si es la primera metemos el extent en la lista y se dibuja
184
                        //Si no es la primera y no intersecta con ning?n extent. Metemos el extent y dibujamos                        
185
                        LayerIntersection li = areIntersecting(extentList, rLyr);
186
                        if((i == (listLayers.size() - 1)) || li == null) {
187
                                boolean colorTableAlpha = false;
188
                                if(rLyr.getRender().getFilterList() != null) { 
189
                                        Render render = rLyr.getRender();
190
                                        if(render != null) {
191
                                                if(render.getColorTable() != null)
192
                                                        colorTableAlpha = render.getColorTable().hasAlpha();
193
                                        }
194
                                }
195
                                extentList.add(new LayerIntersection(rLyr.getFullRasterExtent(), (rLyr.existsAlphaBand() || rLyr.isTransparent() || colorTableAlpha)));
196
                                layersToPaint.put(rLyr, new Boolean(true));
197
                                continue;
198
                        }
199
                        
200
                        //Si con la que intersecta no tiene transparencia no se dibuja
201
                        if(li != null && !li.hasTransparency) {
202
                                layersToPaint.put(rLyr, new Boolean(false));
203
                                continue;
204
                        }
205
                        
206
                        if(!rLyr.isTransparent())
207
                                li.hasTransparency = false;
208
                        layersToPaint.put(rLyr, new Boolean(true));                        
209
                }
210
                
211
                mapContextStrategy.put(mapContext, layersToPaint);
212
        }
213
        
214
                
215
        /**
216
         * Obtiene la lista de capas del TOC. Si hay capas agrupadas lo tiene en cuenta y mira
217
         * dentro de la agrupaci?n.
218
         * @param srcLyrs
219
         * @param destLyrs
220
         * @return
221
         */
222
        public static ArrayList<FLayer> getLayerList(FLayers srcLyrs, ArrayList<FLayer> destLyrs) {
223
                for (int i = 0; i < srcLyrs.getLayersCount(); i++) {
224
                        if(srcLyrs.getLayer(i) instanceof DefaultFLyrRaster)
225
                                destLyrs.add(srcLyrs.getLayer(i));
226
                        if(srcLyrs.getLayer(i) instanceof FLayers)
227
                                destLyrs = getLayerList((FLayers)srcLyrs.getLayer(i), destLyrs);
228
                }
229
                return destLyrs;
230
        }
231
        
232
        /**
233
         * Comprueba si la capa que se pasa por par?metro est? oculta por alguno
234
         * de los extent de la lista
235
         * @param extentList Lista de extensiones
236
         * @param lyr Capa raster
237
         * @return 
238
         */
239
        private LayerIntersection areIntersecting(ArrayList<LayerIntersection> extentList, DefaultFLyrRaster lyr) {
240
                for (int i = 0; i < extentList.size(); i++) {
241
                        Extent ex = lyr.getFullRasterExtent();
242
                        Extent ex1 = ((LayerIntersection)extentList.get(i)).extent;
243
                        if(RasterLocator.getManager().getRasterUtils().isInside(ex, ex1))
244
                                return ((LayerIntersection)extentList.get(i));
245
                }
246
                return null;
247
        }
248
                
249
        /**
250
         * Obtiene un TreeMap con la lista de capas que se dibujan. Si se al TreeMap se
251
         * le pasa como par?metro una capa raster y devuelve null es que no se dibuja.
252
         *  
253
         * @return TreeMap con la lista de capas a dibujar.
254
         */
255
        public HashMap<DefaultFLyrRaster, Boolean> getStrategy() {
256
                return (HashMap<DefaultFLyrRaster, Boolean>)mapContextStrategy.get(mapContext);
257
        }
258
}