root / trunk / applications / appgvSIG / src / com / iver / cit / gvsig / project / documents / view / legend / NaturalIntervalGenerator.java @ 7738
History | View | Annotate | Download (29.9 KB)
1 | 7304 | caballero | /* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
|
---|---|---|---|
2 | *
|
||
3 | * Copyright (C) 2004 IVER T.I. 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 | * www.gvsig.gva.es
|
||
30 | *
|
||
31 | * or
|
||
32 | *
|
||
33 | * IVER T.I. S.A
|
||
34 | * Salamanca 50
|
||
35 | * 46005 Valencia
|
||
36 | * Spain
|
||
37 | *
|
||
38 | * +34 963163400
|
||
39 | * dac@iver.es
|
||
40 | */
|
||
41 | package com.iver.cit.gvsig.project.documents.view.legend; |
||
42 | |||
43 | 7738 | jaume | import java.awt.Component; |
44 | import java.util.ArrayList; |
||
45 | |||
46 | import javax.swing.JOptionPane; |
||
47 | |||
48 | 7304 | caballero | import com.hardcode.gdbms.engine.data.driver.DriverException; |
49 | import com.hardcode.gdbms.engine.values.DoubleValue; |
||
50 | import com.hardcode.gdbms.engine.values.FloatValue; |
||
51 | import com.hardcode.gdbms.engine.values.IntValue; |
||
52 | import com.hardcode.gdbms.engine.values.LongValue; |
||
53 | import com.hardcode.gdbms.engine.values.NullValue; |
||
54 | import com.hardcode.gdbms.engine.values.ShortValue; |
||
55 | import com.hardcode.gdbms.engine.values.Value; |
||
56 | import com.iver.andami.PluginServices; |
||
57 | import com.iver.cit.gvsig.fmap.layers.SelectableDataSource; |
||
58 | import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData; |
||
59 | |||
60 | |||
61 | /**
|
||
62 | * Calcula los intervalos naturales.
|
||
63 | *
|
||
64 | * @author Vicente Caballero Navarro
|
||
65 | */
|
||
66 | public class NaturalIntervalGenerator { |
||
67 | private AlphanumericData mLayer;
|
||
68 | private String msFieldName; |
||
69 | private int miNumIntervalosSolicitados; |
||
70 | private int miNumIntervalosGenerados; |
||
71 | private double[] mdaValoresRuptura; |
||
72 | private double[] mdaValInit; |
||
73 | |||
74 | /**
|
||
75 | * Crea un nuevo IntervalGenerator.
|
||
76 | *
|
||
77 | * @param layer AlphanumericData
|
||
78 | * @param field Nombre del campo.
|
||
79 | * @param numIntervals N�mero de intervalos.
|
||
80 | */
|
||
81 | public NaturalIntervalGenerator(AlphanumericData layer, String field, |
||
82 | int numIntervals) {
|
||
83 | mLayer = layer; |
||
84 | msFieldName = field; |
||
85 | miNumIntervalosSolicitados = numIntervals; |
||
86 | } |
||
87 | |||
88 | /**
|
||
89 | * Esta funci�n busca en el vector de datos la posici�n que le corresponde
|
||
90 | * al valor almacenado en vdValor y devuelve dicha posici�n en
|
||
91 | * vdValorAInsertar. Para hallar la posici�n se realiza una b�squeda
|
||
92 | * binaria. Si se trata de un elemento que ya est� en el vector devolvemos
|
||
93 | * el �ndice que le corresponde en rlIndiceCorrespondiente y false en
|
||
94 | * rbNuevoElemento. Si se trata de un nuevo elemento que hay que
|
||
95 | * insertar... devolvemos el �ndice en el que ir�a y True en
|
||
96 | * rbNuevoElemento En caso de que ocurra alg�n error devuelve false
|
||
97 | *
|
||
98 | * @param rVectorDatos ArrayList con los datos.
|
||
99 | * @param vdValorAInsertar Valor a insertar.
|
||
100 | * @param rlIndiceCorrespondiente �ndice.
|
||
101 | * @param rbNuevoElemento True si es un nuevo elemento.
|
||
102 | *
|
||
103 | * @return True si ha conseguido correctamente la posici�n en el vector.
|
||
104 | */
|
||
105 | private boolean mbObtenerPosicionEnVector(ArrayList rVectorDatos, |
||
106 | double vdValorAInsertar, int[] rlIndiceCorrespondiente, |
||
107 | boolean[] rbNuevoElemento) { |
||
108 | int llIndiceIzq;
|
||
109 | int llIndiceDer;
|
||
110 | int llMedio;
|
||
111 | |||
112 | double ldValorComparacion;
|
||
113 | |||
114 | rbNuevoElemento[0] = false; |
||
115 | rlIndiceCorrespondiente[0] = -1; |
||
116 | |||
117 | //'Si el vector estiviese vac�o... (tuviese un s�lo elemento y el n�mero de coincidencias fuese 0)
|
||
118 | if (rVectorDatos.size() == 1) { |
||
119 | if (((udtDatosEstudio) rVectorDatos.get(0)).Coincidencias == 0) { |
||
120 | rlIndiceCorrespondiente[0] = 0; |
||
121 | rbNuevoElemento[0] = false; //'No tenemos que a�adir un nuevo elemento al vector |
||
122 | |||
123 | return true; |
||
124 | } |
||
125 | } |
||
126 | |||
127 | llIndiceIzq = 0;
|
||
128 | llIndiceDer = rVectorDatos.size() - 1;
|
||
129 | llMedio = (llIndiceIzq + llIndiceDer) / 2; //'Divisi�n entera! |
||
130 | |||
131 | while (llIndiceIzq <= llIndiceDer) {
|
||
132 | //'Coger el valor situado en la mitad de la zona de b�squeda como valor de comparaci�n
|
||
133 | ldValorComparacion = ((udtDatosEstudio) rVectorDatos.get(llMedio)).Valor; |
||
134 | |||
135 | //'Si el valor a insertar es mayor que el valor de comparaci�n...
|
||
136 | if (vdValorAInsertar > ldValorComparacion) {
|
||
137 | // 'La zona de b�squeda queda restringida a la parte de la derecha
|
||
138 | llIndiceIzq = llMedio + 1;
|
||
139 | llMedio = (llIndiceIzq + llIndiceDer) / 2;
|
||
140 | |||
141 | // 'Si el valor a insertar es menor que el valor de comparaci�n...
|
||
142 | } else if (vdValorAInsertar < ldValorComparacion) { |
||
143 | // 'La zona de b�squeda queda restringida a la parte de la derecha
|
||
144 | llIndiceDer = llMedio - 1;
|
||
145 | llMedio = (llIndiceIzq + llIndiceDer) / 2;
|
||
146 | |||
147 | // 'Si el valor de comparaci�n coincide con el valor a insertar
|
||
148 | } else if (vdValorAInsertar == ldValorComparacion) { |
||
149 | rlIndiceCorrespondiente[0] = llMedio;
|
||
150 | rbNuevoElemento[0] = false; |
||
151 | |||
152 | return true; |
||
153 | } |
||
154 | } |
||
155 | |||
156 | // 'Si llegamos a este punto es que no hemos encontrado el valor a insertar en el vector, es decir,
|
||
157 | // 'seguro que tendremos que a�adir un nuevo elemento.
|
||
158 | rbNuevoElemento[0] = true; |
||
159 | |||
160 | // 'Nota:
|
||
161 | // 'En este caso (cuando en rbNuevoElemento se devuelve True) lo que hay que hacer al salir de esta funci�n
|
||
162 | // 'es a�adir un nuevo elemento al vector y desplazar todos los valores correspondientes a partir de rlIndiceCorrespondiente
|
||
163 | // '�D�nde va el nuevo elemento?
|
||
164 | // 'El �ltimo sitio estudiado viene dado por el valor de llMedio.
|
||
165 | // 'Si el valor a insertar es menor que el valor almacenado en la posici�n llMedio, el nuevo valor deber� ir a su izquierda.
|
||
166 | // 'Si fuera mayor deber�a ir a su derecha.
|
||
167 | ldValorComparacion = ((udtDatosEstudio) rVectorDatos.get(llMedio)).Valor; |
||
168 | |||
169 | if (vdValorAInsertar > ldValorComparacion) {
|
||
170 | rlIndiceCorrespondiente[0] = llMedio + 1; |
||
171 | } else {
|
||
172 | rlIndiceCorrespondiente[0] = llMedio;
|
||
173 | } |
||
174 | |||
175 | return true; |
||
176 | } |
||
177 | |||
178 | /**
|
||
179 | * M�todo para generar los intervalos.
|
||
180 | *
|
||
181 | * @return true si se han generado correctamente.
|
||
182 | *
|
||
183 | * @throws com.iver.cit.gvsig.fmap.DriverException
|
||
184 | * @throws DriverException
|
||
185 | */
|
||
186 | public boolean generarIntervalos() |
||
187 | throws com.iver.cit.gvsig.fmap.DriverException, DriverException {
|
||
188 | ArrayList lVectorDatos;
|
||
189 | double[] ldMediaTotal = new double[1]; |
||
190 | double[] ldSDAM = new double[1]; |
||
191 | |||
192 | int[] llaIndicesRupturas; |
||
193 | |||
194 | double[] ldUltimaGVF = new double[1]; |
||
195 | double[] ldNuevaGVF = new double[1]; |
||
196 | |||
197 | int i;
|
||
198 | int liNumClasesReales;
|
||
199 | int llNumElementosPorClase;
|
||
200 | |||
201 | // 'Obtener los datos a estudiar ordenados ascendentemente y obtener la media total
|
||
202 | //ReDim lVectorDatos(0)
|
||
203 | lVectorDatos = new ArrayList(); |
||
204 | |||
205 | lVectorDatos.add(new udtDatosEstudio());
|
||
206 | |||
207 | if (!mbObtenerDatos(lVectorDatos, ldMediaTotal)) {
|
||
208 | return false; //SalidaSinMensaje |
||
209 | } |
||
210 | |||
211 | System.out.println("Analizando datos ..."); |
||
212 | |||
213 | /// Call gEstablecerDescripcionProceso("Analizando datos ...", False)
|
||
214 | // 'Calcular la suma de las desviaciones t�picas del total de los datos respecto de la media total
|
||
215 | ldSDAM[0] = mbGetSumSquaredDeviationArrayMean(lVectorDatos,
|
||
216 | ldMediaTotal[0]);
|
||
217 | |||
218 | ///if (lVectorDatos.length==0){
|
||
219 | if (lVectorDatos.isEmpty()) {
|
||
220 | // 'S�lo se pueden generar dos intervalos -> hay un valor de ruptura
|
||
221 | ///ReDim mdaValoresRuptura(0)
|
||
222 | mdaValoresRuptura[0] = ((udtDatosEstudio) lVectorDatos.get(0)).Valor; |
||
223 | mdaValInit[0] = ((udtDatosEstudio) lVectorDatos.get(0)).Valor; |
||
224 | miNumIntervalosGenerados = 2;
|
||
225 | |||
226 | return true; |
||
227 | } |
||
228 | |||
229 | // 'Calculamos el n�mero m�ximo de clases reales que podemos generar.
|
||
230 | // 'Este n�mero ser�a igual al n� de elementos que tenga el vector de datos.
|
||
231 | if (miNumIntervalosSolicitados > (lVectorDatos.size())) {
|
||
232 | liNumClasesReales = lVectorDatos.size() + 1;
|
||
233 | } else {
|
||
234 | liNumClasesReales = miNumIntervalosSolicitados; |
||
235 | } |
||
236 | |||
237 | // 'Establecemos las clases iniciales especificando unos �ndices de ruptura en ppo. equidistantes
|
||
238 | llaIndicesRupturas = new int[liNumClasesReales - 1]; |
||
239 | llNumElementosPorClase = (lVectorDatos.size()) / liNumClasesReales; |
||
240 | |||
241 | for (i = 0; i < llaIndicesRupturas.length; i++) { |
||
242 | if (i == 0) { |
||
243 | llaIndicesRupturas[i] = llNumElementosPorClase - 1;
|
||
244 | } else {
|
||
245 | llaIndicesRupturas[i] = llaIndicesRupturas[i - 1] +
|
||
246 | llNumElementosPorClase; |
||
247 | } |
||
248 | } |
||
249 | |||
250 | udtDatosClase[] ldaSDCM_Parciales = new udtDatosClase[llaIndicesRupturas.length + |
||
251 | 1];
|
||
252 | udtDatosClase[] ldaSDCM_Validos = new udtDatosClase[llaIndicesRupturas.length + |
||
253 | 1];
|
||
254 | |||
255 | ///ReDim ldaSDCM_Parciales(UBound(llaIndicesRupturas()) + 1)
|
||
256 | ///ReDim ldaSDCM_Validos(UBound(ldaSDCM_Parciales()) + 1)
|
||
257 | if (llaIndicesRupturas.length == 0) { |
||
258 | return true; |
||
259 | } |
||
260 | |||
261 | // 'Calcular la bondad inicial
|
||
262 | if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales, llaIndicesRupturas,
|
||
263 | ldSDAM[0], ldUltimaGVF, -1, false)) { |
||
264 | JOptionPane.showMessageDialog((Component)PluginServices.getMainFrame(),PluginServices.getText(this,"el_numero_maximo_de_intervalos_para_este_campo_es")+": "+lVectorDatos.size()); |
||
265 | miNumIntervalosSolicitados=lVectorDatos.size(); |
||
266 | generarIntervalos(); |
||
267 | return false; |
||
268 | } |
||
269 | |||
270 | ldaSDCM_Validos = getArray(ldaSDCM_Parciales); |
||
271 | |||
272 | boolean lbMoverADerecha;
|
||
273 | boolean lbMoverAIzquierda;
|
||
274 | boolean lbIntentarDesplazamiento;
|
||
275 | int llIndiceRupturaOriginal;
|
||
276 | |||
277 | long k;
|
||
278 | double ldGVFentrepasadas;
|
||
279 | |||
280 | ldGVFentrepasadas = ldUltimaGVF[0];
|
||
281 | |||
282 | //'liNumClasesReales no ser� muy grande (11 es el m�ximo)
|
||
283 | for (k = 1; k <= 100; k++) { |
||
284 | // 'Para cada �ndice de ruptura...
|
||
285 | for (i = 0; i < (llaIndicesRupturas.length); i++) { |
||
286 | lbMoverADerecha = false;
|
||
287 | lbMoverAIzquierda = false;
|
||
288 | llIndiceRupturaOriginal = llaIndicesRupturas[i]; |
||
289 | ldaSDCM_Validos = getArray(ldaSDCM_Parciales); |
||
290 | |||
291 | //'Hay que decidir hacia donde hay que desplazar el �ndice de ruptura
|
||
292 | //'Probamos moviendo a derecha (si se puede)
|
||
293 | lbIntentarDesplazamiento = false;
|
||
294 | |||
295 | if (i == (llaIndicesRupturas.length - 1)) { |
||
296 | if ((llaIndicesRupturas[i] + 1) < lVectorDatos.size()) { |
||
297 | lbIntentarDesplazamiento = true;
|
||
298 | } |
||
299 | } else {
|
||
300 | if ((llaIndicesRupturas[i] + 1) < llaIndicesRupturas[i + 1]) { |
||
301 | lbIntentarDesplazamiento = true;
|
||
302 | } //'If (llaIndicesRupturas(i) + 1) < llaIndicesRupturas(i + 1) Then
|
||
303 | } //'If i = UBound(llaIndicesRupturas) Then
|
||
304 | |||
305 | if (lbIntentarDesplazamiento) {
|
||
306 | llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
|
||
307 | |||
308 | if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
|
||
309 | llaIndicesRupturas, ldSDAM[0], ldNuevaGVF, i,
|
||
310 | false)) {
|
||
311 | return false; |
||
312 | } |
||
313 | |||
314 | if (ldNuevaGVF[0] > ldUltimaGVF[0]) { |
||
315 | lbMoverADerecha = true;
|
||
316 | ldaSDCM_Validos = getArray(ldaSDCM_Parciales); |
||
317 | } else {
|
||
318 | //'Dejamos el �ndice de ruputura como estaba y probamos con un desplazamiento a izquierda
|
||
319 | llaIndicesRupturas[i] = llIndiceRupturaOriginal; |
||
320 | ldaSDCM_Parciales = getArray(ldaSDCM_Validos); |
||
321 | } |
||
322 | } //'If lbIntentarDesplazamiento Then
|
||
323 | |||
324 | lbIntentarDesplazamiento = false;
|
||
325 | |||
326 | //'Probamos moviendo a izquierda (si se puede y no estamos moviendo ya a derechas)
|
||
327 | if (!lbMoverADerecha) {
|
||
328 | if (i == 0) { //LBound(llaIndicesRupturas) Then |
||
329 | |||
330 | if ((llaIndicesRupturas[i] - 1) >= 0) { //LBound(lVectorDatos()) Then |
||
331 | lbIntentarDesplazamiento = true;
|
||
332 | } //'If (llaIndicesRupturas(i) - 1) >= LBound(lVectorDatos()) Then
|
||
333 | } else {
|
||
334 | if ((llaIndicesRupturas[i] - 1) > llaIndicesRupturas[i - |
||
335 | 1]) {
|
||
336 | lbIntentarDesplazamiento = true;
|
||
337 | } //'If (llaIndicesRupturas(i) - 1) > llaIndicesRupturas(i - 1) Then
|
||
338 | } //'If i = LBound(llaIndicesRupturas) Then
|
||
339 | } //'If Not lbMoverADerecha Then
|
||
340 | |||
341 | if (lbIntentarDesplazamiento) {
|
||
342 | llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1;
|
||
343 | |||
344 | if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
|
||
345 | llaIndicesRupturas, ldSDAM[0], ldNuevaGVF, i,
|
||
346 | true)) {
|
||
347 | return false; |
||
348 | } |
||
349 | |||
350 | if (ldNuevaGVF[0] > ldUltimaGVF[0]) { |
||
351 | lbMoverAIzquierda = true;
|
||
352 | ldaSDCM_Validos = getArray(ldaSDCM_Parciales); |
||
353 | } else {
|
||
354 | //'Dejamos el �ndice de ruputura como estaba
|
||
355 | llaIndicesRupturas[i] = llIndiceRupturaOriginal; |
||
356 | ldaSDCM_Parciales = getArray(ldaSDCM_Validos); |
||
357 | } |
||
358 | } //'If lbIntentarDesplazamiento Then
|
||
359 | |||
360 | lbIntentarDesplazamiento = false;
|
||
361 | |||
362 | //'Si se ha decidido desplazar el �ndice ... continuamos hasta que no podamos mejorar la GVF
|
||
363 | if (lbMoverAIzquierda || lbMoverADerecha) {
|
||
364 | ldUltimaGVF[0] = ldNuevaGVF[0]; |
||
365 | |||
366 | boolean exit = false; |
||
367 | |||
368 | while (!exit) {
|
||
369 | llIndiceRupturaOriginal = llaIndicesRupturas[i]; |
||
370 | |||
371 | if (lbMoverADerecha) {
|
||
372 | if (i == (llaIndicesRupturas.length - 1)) { |
||
373 | if ((llaIndicesRupturas[i] + 1) >= lVectorDatos.size()) { |
||
374 | exit = true;
|
||
375 | } |
||
376 | } else {
|
||
377 | if ((llaIndicesRupturas[i] + 1) >= llaIndicesRupturas[i + |
||
378 | 1]) {
|
||
379 | exit = true;
|
||
380 | } |
||
381 | } //'If i = UBound(llaIndicesRupturas) Then
|
||
382 | |||
383 | llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
|
||
384 | } else { //'If lbMoverAIzquierda Then |
||
385 | |||
386 | if (i == 0) { //LBound(llaIndicesRupturas) Then |
||
387 | |||
388 | if ((llaIndicesRupturas[i] - 1) < 0) { //LBound(lVectorDatos()) Then Exit Do |
||
389 | exit = true;
|
||
390 | } |
||
391 | } else {
|
||
392 | if ((llaIndicesRupturas[i] - 1) <= llaIndicesRupturas[i - |
||
393 | 1]) {
|
||
394 | exit = true;
|
||
395 | } |
||
396 | } //'If i = LBound(llaIndicesRupturas) Then
|
||
397 | |||
398 | llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1; ////////////////// |
||
399 | } //'If lbMoverADerecha Then
|
||
400 | |||
401 | if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
|
||
402 | llaIndicesRupturas, ldSDAM[0], ldNuevaGVF,
|
||
403 | i, lbMoverAIzquierda)) { |
||
404 | return false; |
||
405 | } |
||
406 | |||
407 | if (ldNuevaGVF[0] < ldUltimaGVF[0]) { |
||
408 | // 'Dejar el �ndice donde estaba
|
||
409 | llaIndicesRupturas[i] = llIndiceRupturaOriginal; |
||
410 | ldaSDCM_Parciales = getArray(ldaSDCM_Validos); |
||
411 | exit = true;
|
||
412 | } else {
|
||
413 | ldUltimaGVF[0] = ldNuevaGVF[0]; |
||
414 | ldaSDCM_Validos = getArray(ldaSDCM_Parciales); |
||
415 | } |
||
416 | } |
||
417 | } //'If lbMoverAIzquierda Or lbMoverADerecha Then
|
||
418 | } |
||
419 | |||
420 | if (ldUltimaGVF[0] <= ldGVFentrepasadas) { |
||
421 | i = 101;
|
||
422 | } |
||
423 | |||
424 | ldGVFentrepasadas = ldUltimaGVF[0];
|
||
425 | } |
||
426 | |||
427 | // 'A partir de aqu� ya no se puede cancelar nada
|
||
428 | mdaValoresRuptura = new double[llaIndicesRupturas.length]; |
||
429 | mdaValInit = new double[llaIndicesRupturas.length]; |
||
430 | |||
431 | for (i = 0; i < mdaValoresRuptura.length; i++) { // LBound(mdaValoresRuptura) To UBound(mdaValoresRuptura) |
||
432 | if (llaIndicesRupturas[i]==-1)llaIndicesRupturas[i]=1; |
||
433 | if (llaIndicesRupturas[i]>lVectorDatos.size()-1)llaIndicesRupturas[i]=lVectorDatos.size()-1; |
||
434 | mdaValoresRuptura[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i])).Valor; |
||
435 | |||
436 | if ((llaIndicesRupturas[i] + 1) < lVectorDatos.size()) { |
||
437 | mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i] + |
||
438 | 1)).Valor;
|
||
439 | } else {
|
||
440 | mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i])).Valor; |
||
441 | } |
||
442 | |||
443 | // 'Hay que aplicar una peque�a correcci�n a los valores de ruptura para que los intervalos que genera
|
||
444 | // 'mapobjects se aprechen en su totalidad, o lo que es lo mismo, vengan todos representados en el mapa.
|
||
445 | // 'Con esto tambi�n se consigue hallar intervalos equivalentes a los de ArcView. Esta correcci�n consiste
|
||
446 | //'en sumar el m�nimo incremento a los valores de ruptura. No lo hago aqu� sino en la ventana de propiedades de capa.
|
||
447 | } |
||
448 | |||
449 | miNumIntervalosGenerados = mdaValoresRuptura.length + 2;
|
||
450 | |||
451 | ldaSDCM_Validos = null;
|
||
452 | ldaSDCM_Parciales = null;
|
||
453 | lVectorDatos = null;
|
||
454 | |||
455 | return true; |
||
456 | } |
||
457 | |||
458 | /**
|
||
459 | * DOCUMENT ME!
|
||
460 | *
|
||
461 | * @param array DOCUMENT ME!
|
||
462 | *
|
||
463 | * @return DOCUMENT ME!
|
||
464 | */
|
||
465 | private udtDatosClase[] getArray(udtDatosClase[] array) { |
||
466 | udtDatosClase[] aux = new udtDatosClase[array.length]; |
||
467 | |||
468 | for (int i = 0; i < array.length; i++) { |
||
469 | aux[i] = new udtDatosClase();
|
||
470 | aux[i].Media = array[i].Media; |
||
471 | aux[i].NumElementos = array[i].NumElementos; |
||
472 | aux[i].SDCM = array[i].SDCM; |
||
473 | aux[i].SumaCuadradoTotal = array[i].SumaCuadradoTotal; |
||
474 | aux[i].SumaTotal = array[i].SumaTotal; |
||
475 | } |
||
476 | |||
477 | return aux;
|
||
478 | } |
||
479 | |||
480 | /**
|
||
481 | * Devuelve la "SDAM" de un conjunto de datos que vienen almacenados en el
|
||
482 | * vector rVectorDatos
|
||
483 | *
|
||
484 | * @param rVectorDatos Datos
|
||
485 | * @param vdMedia Media
|
||
486 | *
|
||
487 | * @return suma de las desviaciones t�picas del total de los datos respecto
|
||
488 | * de la media total
|
||
489 | */
|
||
490 | private double mbGetSumSquaredDeviationArrayMean(ArrayList rVectorDatos, |
||
491 | double vdMedia) {
|
||
492 | int i;
|
||
493 | |||
494 | double rdSDAM = 0; |
||
495 | |||
496 | for (i = 0; i < rVectorDatos.size(); i++) { // LBound(rVectorDatos) To UBound(rVectorDatos) |
||
497 | rdSDAM = rdSDAM + |
||
498 | (Math.pow((((udtDatosEstudio) rVectorDatos.get(i)).Valor -
|
||
499 | vdMedia), 2) * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias);
|
||
500 | } |
||
501 | |||
502 | return rdSDAM;
|
||
503 | } |
||
504 | |||
505 | /**
|
||
506 | * Esta funci�n obtiene los datos en los que queremos hallar las rupturas
|
||
507 | * naturales. Los datos se devuelven ordenados en un vector. Tambi�n
|
||
508 | * devuelve la media total
|
||
509 | *
|
||
510 | * @param rVectorDatos Datos
|
||
511 | * @param rdMediaTotal Media total
|
||
512 | *
|
||
513 | * @return True si se ha calculado correctamente.
|
||
514 | *
|
||
515 | * @throws com.iver.cit.gvsig.fmap.DriverException
|
||
516 | * @throws DriverException
|
||
517 | */
|
||
518 | private boolean mbObtenerDatos(ArrayList rVectorDatos, double[] rdMediaTotal) |
||
519 | throws com.iver.cit.gvsig.fmap.DriverException, DriverException {
|
||
520 | double ldValor;
|
||
521 | |||
522 | int i;
|
||
523 | long llRecordCount;
|
||
524 | |||
525 | int[] llIndice = new int[1]; |
||
526 | boolean[] lbNuevoElemento = new boolean[1]; |
||
527 | //int j;
|
||
528 | |||
529 | SelectableDataSource sds = mLayer.getRecordset(); |
||
530 | llRecordCount = sds.getRowCount(); |
||
531 | |||
532 | if (!gbExisteCampoEnRegistro(mLayer.getRecordset(), msFieldName)) {
|
||
533 | if (msFieldName == "") { |
||
534 | System.out.println(
|
||
535 | "No se ha establecido el nombre del campo origen!");
|
||
536 | } else {
|
||
537 | System.out.println("El campo '" + msFieldName + |
||
538 | "' no pertence a la capa!");
|
||
539 | } |
||
540 | |||
541 | return false; |
||
542 | } |
||
543 | |||
544 | // 'Nos cuidamos de recorrer todos los registros sin consultar la propiedad EOF del recordset
|
||
545 | for (i = 0; i < llRecordCount; i++) { |
||
546 | try{
|
||
547 | ldValor = getValue(sds.getFieldValue(i, |
||
548 | sds.getFieldIndexByName(msFieldName))); |
||
549 | }catch (Exception e) { |
||
550 | llRecordCount--; |
||
551 | continue;
|
||
552 | } |
||
553 | rdMediaTotal[0] = rdMediaTotal[0] + ldValor; |
||
554 | |||
555 | // 'Hay que insertar el valor en la posici�n adecuada. Para ello hacemos una b�squeda binaria
|
||
556 | if (!mbObtenerPosicionEnVector(rVectorDatos, ldValor, llIndice,
|
||
557 | lbNuevoElemento)) { |
||
558 | return false; |
||
559 | } |
||
560 | |||
561 | if (!lbNuevoElemento[0]) { |
||
562 | if ((llIndice[0] < 0) || (llIndice[0] > rVectorDatos.size())) { |
||
563 | System.out.println("�ndice incorrecto!"); |
||
564 | |||
565 | return false; |
||
566 | } |
||
567 | |||
568 | ((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Valor = ldValor; //'Por si fuese el primer elemento |
||
569 | |||
570 | //'Incrementamos el n� de coincidencias y damos el valor por insertado
|
||
571 | ((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Coincidencias = ((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Coincidencias + |
||
572 | 1;
|
||
573 | } else {
|
||
574 | udtDatosEstudio udt = new udtDatosEstudio();
|
||
575 | udt.Valor = ldValor; |
||
576 | udt.Coincidencias = 1;
|
||
577 | rVectorDatos.add(llIndice[0], udt);
|
||
578 | } |
||
579 | } |
||
580 | |||
581 | rdMediaTotal[0] = rdMediaTotal[0] / llRecordCount; |
||
582 | |||
583 | return true; |
||
584 | } |
||
585 | |||
586 | /**
|
||
587 | * Devuelve true si existe el campo en el registro.
|
||
588 | *
|
||
589 | * @param recordset Recordset.
|
||
590 | * @param msFieldName2 Nombre del campo.
|
||
591 | *
|
||
592 | * @return True si existe el campo.
|
||
593 | *
|
||
594 | * @throws DriverException
|
||
595 | */
|
||
596 | private boolean gbExisteCampoEnRegistro(SelectableDataSource recordset, |
||
597 | String msFieldName2) throws DriverException { |
||
598 | if (recordset.getFieldIndexByName(msFieldName2) == -1) { |
||
599 | return false; |
||
600 | } |
||
601 | |||
602 | return true; |
||
603 | } |
||
604 | |||
605 | /**
|
||
606 | * Esta funci�n s�lo calcula las SDCM de las clases adyacentes al �ndice de
|
||
607 | * ruptura actual. Si el �ndice de ruptura actual es -1 entonces las
|
||
608 | * calcula todas! . En este caso no importa el valor de
|
||
609 | * vbDesplazAIzquierda
|
||
610 | *
|
||
611 | * @param rVectorDatos Datos
|
||
612 | * @param raClases Clases encontradas
|
||
613 | * @param rlaIndicesRuptura �ndices de ruptura
|
||
614 | * @param vdSDAM suma de la desviaci�n standard.
|
||
615 | * @param rdGVF Desviaci�n standard de los intervalos.
|
||
616 | * @param vlIndiceRupturaActual �ndice de ruptura actual.
|
||
617 | *
|
||
618 | * @return True si se ha calcula do correctamente.
|
||
619 | */
|
||
620 | /*private boolean mbCalcularGVF(ArrayList rVectorDatos,
|
||
621 | udtDatosClase[] raClases, int[] rlaIndicesRuptura, double vdSDAM,
|
||
622 | double[] rdGVF, int vlIndiceRupturaActual ) {
|
||
623 | return mbCalcularGVF(rVectorDatos, raClases, rlaIndicesRuptura, vdSDAM,
|
||
624 | rdGVF, vlIndiceRupturaActual, true);
|
||
625 | }
|
||
626 | */
|
||
627 | /**
|
||
628 | * Esta funci�n s�lo calcula las SDCM de las clases adyacentes al �ndice de
|
||
629 | * ruptura actual. Si el �ndice de ruptura actual es -1 entonces las
|
||
630 | * calcula todas! . En este caso no importa el valor de
|
||
631 | * vbDesplazAIzquierda
|
||
632 | *
|
||
633 | * @param rVectorDatos Datos
|
||
634 | * @param raClases Calses que representan a los intervalos.
|
||
635 | * @param rlaIndicesRuptura �ndices de ruptura.
|
||
636 | * @param vdSDAM Desviaci�n standard.
|
||
637 | * @param rdGVF Desviaci�n standard de los intervalos.
|
||
638 | * @param vlIndiceRupturaActual �ndice de ruptura actual.
|
||
639 | * @param vbDesplazAIzquierda Desplazamiento a la izquierda.
|
||
640 | *
|
||
641 | * @return True si se ha calculado correctamente.
|
||
642 | */
|
||
643 | private boolean mbCalcularGVF(ArrayList rVectorDatos, |
||
644 | udtDatosClase[] raClases, int[] rlaIndicesRuptura, double vdSDAM, |
||
645 | double[] rdGVF, int vlIndiceRupturaActual /* As Long = -1*/, |
||
646 | boolean vbDesplazAIzquierda) {
|
||
647 | double ldSDCM_aux;
|
||
648 | |||
649 | int i;
|
||
650 | |||
651 | if (vlIndiceRupturaActual == -1) { |
||
652 | // 'Obtenemos los datos para todas las clases = intervalos
|
||
653 | for (i = 0; i < rlaIndicesRuptura.length; i++) { |
||
654 | if (i == 0) { // LBound(rlaIndicesRuptura) Then |
||
655 | |||
656 | if (!mbGetDatosClase(rVectorDatos, 0, rlaIndicesRuptura[i], |
||
657 | raClases, i)) { |
||
658 | return false; |
||
659 | } |
||
660 | } else {
|
||
661 | if (!mbGetDatosClase(rVectorDatos,
|
||
662 | rlaIndicesRuptura[i - 1] + 1, |
||
663 | rlaIndicesRuptura[i], raClases, i)) { |
||
664 | return false; |
||
665 | } |
||
666 | } |
||
667 | } |
||
668 | |||
669 | //'Falta la �ltima clase
|
||
670 | if (!mbGetDatosClase(rVectorDatos,
|
||
671 | rlaIndicesRuptura[rlaIndicesRuptura.length - 1] + 1, |
||
672 | rVectorDatos.size() - 1, raClases, raClases.length - 1)) { |
||
673 | return false; |
||
674 | } |
||
675 | } else {
|
||
676 | i = vlIndiceRupturaActual; |
||
677 | |||
678 | //'Hay que determinar para qu� clases debemos volver a recalcular los datos en funci�n del �ndice de ruptura que estamos modificando
|
||
679 | if (vbDesplazAIzquierda) {
|
||
680 | // 'Recalcular los datos de la clase izquierda
|
||
681 | if (!mbRecalcularDatosClase(raClases, i, rVectorDatos,
|
||
682 | rlaIndicesRuptura[i] + 1, vdSDAM, false)) { |
||
683 | return false; |
||
684 | } |
||
685 | |||
686 | // 'Recalcular los datos de la clase derecha
|
||
687 | if (!mbRecalcularDatosClase(raClases, i + 1, rVectorDatos, |
||
688 | rlaIndicesRuptura[i] + 1, vdSDAM, true)) { |
||
689 | return false; |
||
690 | } |
||
691 | } else {
|
||
692 | // 'Recalcular los datos de la clase izquierda
|
||
693 | if (!mbRecalcularDatosClase(raClases, i, rVectorDatos,
|
||
694 | rlaIndicesRuptura[i], vdSDAM, true)) {
|
||
695 | return false; |
||
696 | } |
||
697 | |||
698 | // 'Recalcular los datos de la clase derecha
|
||
699 | if (!mbRecalcularDatosClase(raClases, i + 1, rVectorDatos, |
||
700 | rlaIndicesRuptura[i], vdSDAM, false)) {
|
||
701 | return false; |
||
702 | } |
||
703 | } |
||
704 | } |
||
705 | |||
706 | ldSDCM_aux = 0;
|
||
707 | |||
708 | for (i = 0; i < raClases.length; i++) { //LBound(raClases) To UBound(raClases) |
||
709 | ldSDCM_aux = ldSDCM_aux + raClases[i].SDCM; |
||
710 | } |
||
711 | |||
712 | rdGVF[0] = (vdSDAM - ldSDCM_aux) / vdSDAM;
|
||
713 | //System.out.println(ldSDCM_aux);
|
||
714 | |||
715 | return true; |
||
716 | } |
||
717 | |||
718 | /**
|
||
719 | * Devuelve la "SDCM" de un conjunto de datos que vienen almacenados en el
|
||
720 | * vector rVectorDatos y que est�n delimitados por vlLimiteInf y
|
||
721 | * vlLimiteInf
|
||
722 | *
|
||
723 | * @param rVectorDatos Datos
|
||
724 | * @param vlLimiteInf L�mite inferior.
|
||
725 | * @param vlLimiteSup L�mite superior.
|
||
726 | * @param rClase Calses que representan a los intervalos.
|
||
727 | * @param numClas N�mero de calses.
|
||
728 | *
|
||
729 | * @return True si se ha calculado correctamente.
|
||
730 | */
|
||
731 | private boolean mbGetDatosClase(ArrayList rVectorDatos, int vlLimiteInf, |
||
732 | int vlLimiteSup, udtDatosClase[] rClase, int numClas) { |
||
733 | int i;
|
||
734 | |||
735 | if (vlLimiteInf < 0) { |
||
736 | return false; |
||
737 | } |
||
738 | |||
739 | if (vlLimiteSup > rVectorDatos.size()) {
|
||
740 | return false; |
||
741 | } |
||
742 | |||
743 | if (vlLimiteSup < vlLimiteInf) {
|
||
744 | return false; |
||
745 | } |
||
746 | |||
747 | // 'Inicializamos los datos de la clase
|
||
748 | rClase[numClas] = new udtDatosClase();
|
||
749 | |||
750 | //'Hallamos la media de la clase
|
||
751 | for (i = vlLimiteInf; i < (vlLimiteSup + 1); i++) { |
||
752 | rClase[numClas].NumElementos = rClase[numClas].NumElementos + |
||
753 | ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias; |
||
754 | |||
755 | //'rClase.Media = rClase.Media + (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
|
||
756 | rClase[numClas].SumaTotal = rClase[numClas].SumaTotal + |
||
757 | (((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias); |
||
758 | |||
759 | //'rClase.ProductoTotal = rClase.ProductoTotal * (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
|
||
760 | rClase[numClas].SumaCuadradoTotal = rClase[numClas].SumaCuadradoTotal + |
||
761 | (Math.pow(((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(
|
||
762 | i)).Coincidencias, 2));
|
||
763 | } |
||
764 | |||
765 | //'rClase.Media = rClase.Media / llTotalElementos
|
||
766 | rClase[numClas].Media = rClase[numClas].SumaTotal / rClase[numClas].NumElementos; |
||
767 | rClase[numClas].SDCM = (rClase[numClas].SumaCuadradoTotal) - |
||
768 | (2 * rClase[numClas].Media * rClase[numClas].SumaTotal) +
|
||
769 | (rClase[numClas].NumElementos * Math.pow(rClase[numClas].Media, 2)); |
||
770 | /*if (new Double(rClase[numClas].SDCM).isNaN()){
|
||
771 | System.out.println(rClase[numClas].SDCM);
|
||
772 | }*/
|
||
773 | return true; |
||
774 | } |
||
775 | |||
776 | /**
|
||
777 | * Recalcula los datos de las clases.
|
||
778 | *
|
||
779 | * @param rClase Clases.
|
||
780 | * @param i �adir �adir �adir �adir indica si a la clase se le a�ade un
|
||
781 | * elemento (True) o se le quita (False)
|
||
782 | * @param rVectorDatos Datos.
|
||
783 | * @param vlIndiceElemento es el �ndice del elemento que se le va a�adir o
|
||
784 | * a quitar a la clase
|
||
785 | * @param vdSDAM desviaci�n standard.
|
||
786 | * @param vbA �adir DOCUMENT ME!
|
||
787 | *
|
||
788 | * @return True si se ha calculado correctamente.
|
||
789 | */
|
||
790 | private boolean mbRecalcularDatosClase(udtDatosClase[] rClase, int i, |
||
791 | ArrayList rVectorDatos, int vlIndiceElemento, double vdSDAM, |
||
792 | boolean vbAnyadir) {
|
||
793 | double ldValor;
|
||
794 | long llNumCoincidencias;
|
||
795 | try{
|
||
796 | if (vlIndiceElemento>rVectorDatos.size()-1)return true; |
||
797 | ldValor = ((udtDatosEstudio) rVectorDatos.get(vlIndiceElemento)).Valor; |
||
798 | llNumCoincidencias = ((udtDatosEstudio) rVectorDatos.get(vlIndiceElemento)).Coincidencias; |
||
799 | |||
800 | if (vbAnyadir) {
|
||
801 | //'Actualizamos la suma total
|
||
802 | rClase[i].SumaTotal = rClase[i].SumaTotal + |
||
803 | (ldValor * llNumCoincidencias); |
||
804 | |||
805 | //'Actualizamos la suma de cuadrados total
|
||
806 | rClase[i].SumaCuadradoTotal = rClase[i].SumaCuadradoTotal + |
||
807 | (Math.pow((ldValor * llNumCoincidencias), 2)); |
||
808 | |||
809 | //'Actualizamos el producto total
|
||
810 | //'rClase.ProductoTotal = rClase.ProductoTotal * (ldValor * llNumCoincidencias)
|
||
811 | //'Actualizamos el n� de elementos
|
||
812 | rClase[i].NumElementos = rClase[i].NumElementos + |
||
813 | llNumCoincidencias; |
||
814 | } else {
|
||
815 | //'Actualizamos la suma total
|
||
816 | rClase[i].SumaTotal = rClase[i].SumaTotal - |
||
817 | (ldValor * llNumCoincidencias); |
||
818 | |||
819 | // 'Actualizamos la suma de cuadrados total
|
||
820 | rClase[i].SumaCuadradoTotal = rClase[i].SumaCuadradoTotal - |
||
821 | (Math.pow((ldValor * llNumCoincidencias), 2)); |
||
822 | |||
823 | // 'Actualizamos el producto total
|
||
824 | // 'rClase.ProductoTotal = rClase.ProductoTotal / (ldValor * llNumCoincidencias)
|
||
825 | // 'Actualizamos el n� de elementos
|
||
826 | rClase[i].NumElementos = rClase[i].NumElementos - |
||
827 | llNumCoincidencias; |
||
828 | } // 'If vbA�adir Then
|
||
829 | if (rClase[i].NumElementos<=0)rClase[i].NumElementos=1; |
||
830 | //'Obtenemos la nueva media
|
||
831 | rClase[i].Media = rClase[i].SumaTotal / rClase[i].NumElementos; |
||
832 | |||
833 | //'Actualizamos la SDCM
|
||
834 | rClase[i].SDCM = (rClase[i].SumaCuadradoTotal) - |
||
835 | (2 * rClase[i].Media * rClase[i].SumaTotal) +
|
||
836 | (rClase[i].NumElementos * Math.pow(rClase[i].Media, 2)); |
||
837 | |||
838 | }catch (Exception e) { |
||
839 | return false; |
||
840 | } |
||
841 | return true; |
||
842 | } |
||
843 | |||
844 | /**
|
||
845 | * Devuelve el valor de ruptura seg�n el �ndice que se le pasa como
|
||
846 | * par�metro.
|
||
847 | *
|
||
848 | * @param viIndice �nidice del valor de ruptura.
|
||
849 | *
|
||
850 | * @return Valor de ruptura.
|
||
851 | */
|
||
852 | public double getValorRuptura(int viIndice) { |
||
853 | return mdaValoresRuptura[viIndice];
|
||
854 | } |
||
855 | |||
856 | /**
|
||
857 | * Devuelve el valor inicial de cada intervalo
|
||
858 | *
|
||
859 | * @param index �ndice del intervalo
|
||
860 | *
|
||
861 | * @return valor del intervalo.
|
||
862 | */
|
||
863 | public double getValInit(int index) { |
||
864 | return mdaValInit[index];
|
||
865 | } |
||
866 | |||
867 | /**
|
||
868 | * Devuelve el n�mero de intervalos que se pueden representar, no tiene
|
||
869 | * porque coincidir con el n�mero de intervalos que se piden.
|
||
870 | *
|
||
871 | * @return N�mero de intervalos calculados.
|
||
872 | */
|
||
873 | public int getNumIntervals() { |
||
874 | return miNumIntervalosGenerados;
|
||
875 | } |
||
876 | |||
877 | /**
|
||
878 | * Clase para contener los atributos Valor y coincidencias.
|
||
879 | *
|
||
880 | * @author Vicente Caballero Navarro
|
||
881 | */
|
||
882 | private class udtDatosEstudio { |
||
883 | private double Valor; // |
||
884 | private long Coincidencias; |
||
885 | } |
||
886 | |||
887 | /**
|
||
888 | * Clase para contener los atributos: N�mero de Elementos. Media.
|
||
889 | * SumaTotal. SumaCuadradoTotal. Desviaci�n standard.
|
||
890 | *
|
||
891 | * @author Vicente Caballero Navarro
|
||
892 | */
|
||
893 | private class udtDatosClase { |
||
894 | private long NumElementos; // 'N� total de elementos que hay en la clase |
||
895 | private double Media; // 'Media de la clase |
||
896 | private double SumaTotal; // 'Suma total de los elementos |
||
897 | |||
898 | //'ProductoTotal 'Producto total de los elementos '�dar� problemas de desbordamiento?
|
||
899 | private double SumaCuadradoTotal; // 'Suma del total de los cuadrados de los elementos |
||
900 | private double SDCM; // 'Suma de la desviaci�n t�pica de los elementos de la clase respecto de la media de la clase |
||
901 | } |
||
902 | /**
|
||
903 | * Devuelve el valor en un double del Value que se pasa como par�metro.
|
||
904 | *
|
||
905 | * @param value Value.
|
||
906 | *
|
||
907 | * @return valor.
|
||
908 | * @throws Exception
|
||
909 | */
|
||
910 | private double getValue(Value value) throws Exception { |
||
911 | if (value instanceof IntValue) { |
||
912 | return ((IntValue) value).intValue();
|
||
913 | } else if (value instanceof LongValue) { |
||
914 | return ((LongValue) value).longValue();
|
||
915 | } else if (value instanceof FloatValue) { |
||
916 | return ((FloatValue) value).floatValue();
|
||
917 | } else if (value instanceof ShortValue) { |
||
918 | return ((ShortValue) value).shortValue();
|
||
919 | } else if (value instanceof NullValue){ |
||
920 | throw new Exception(); |
||
921 | } |
||
922 | |||
923 | return ((DoubleValue) value).doubleValue();
|
||
924 | } |
||
925 | } |