gvsig-raster / org.gvsig.raster / trunk / org.gvsig.raster / org.gvsig.raster.fmap / src / main / java / org / gvsig / raster / fmap / layers / RasterDrawStrategy.java @ 5462
History | View | Annotate | Download (9.3 KB)
1 | 2443 | nbrodin | /* 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 | } |