Statistics
| Revision:

svn-gvsig-desktop / trunk / applications / appgvSIG / src / com / iver / cit / gvsig / project / documents / view / legend / NaturalIntervalGenerator.java @ 10626

History | View | Annotate | Download (29.9 KB)

1
/* 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
import java.awt.Component;
44
import java.util.ArrayList;
45

    
46
import javax.swing.JOptionPane;
47

    
48
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
49
import com.hardcode.gdbms.engine.data.driver.DriverException;
50
import com.hardcode.gdbms.engine.values.DoubleValue;
51
import com.hardcode.gdbms.engine.values.FloatValue;
52
import com.hardcode.gdbms.engine.values.IntValue;
53
import com.hardcode.gdbms.engine.values.LongValue;
54
import com.hardcode.gdbms.engine.values.NullValue;
55
import com.hardcode.gdbms.engine.values.ShortValue;
56
import com.hardcode.gdbms.engine.values.Value;
57
import com.iver.andami.PluginServices;
58
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
59
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
60

    
61

    
62
/**
63
 * Calcula los intervalos naturales.
64
 *
65
 * @author Vicente Caballero Navarro
66
 */
67
public class NaturalIntervalGenerator {
68
        private AlphanumericData mLayer;
69
        private String msFieldName;
70
        private int miNumIntervalosSolicitados;
71
        private int miNumIntervalosGenerados;
72
        private double[] mdaValoresRuptura;
73
        private double[] mdaValInit;
74

    
75
        /**
76
         * Crea un nuevo IntervalGenerator.
77
         *
78
         * @param layer AlphanumericData
79
         * @param field Nombre del campo.
80
         * @param numIntervals N�mero de intervalos.
81
         */
82
        public NaturalIntervalGenerator(AlphanumericData layer, String field,
83
                int numIntervals) {
84
                mLayer = layer;
85
                msFieldName = field;
86
                miNumIntervalosSolicitados = numIntervals;
87
        }
88

    
89
        /**
90
         * Esta funci�n busca en el vector de datos la posici�n que le corresponde
91
         * al valor almacenado en vdValor y devuelve dicha posici�n en
92
         * vdValorAInsertar. Para hallar la posici�n se realiza una b�squeda
93
         * binaria. Si se trata de un elemento que ya est� en el vector devolvemos
94
         * el �ndice que le corresponde en rlIndiceCorrespondiente y false en
95
         * rbNuevoElemento. Si se trata de un nuevo elemento que hay que
96
         * insertar... devolvemos el �ndice en el que ir�a y True en
97
         * rbNuevoElemento En caso de que ocurra alg�n error devuelve false
98
         *
99
         * @param rVectorDatos ArrayList con los datos.
100
         * @param vdValorAInsertar Valor a insertar.
101
         * @param rlIndiceCorrespondiente �ndice.
102
         * @param rbNuevoElemento True si es un nuevo elemento.
103
         *
104
         * @return True si ha conseguido correctamente la posici�n en el vector.
105
         */
106
        private boolean mbObtenerPosicionEnVector(ArrayList rVectorDatos,
107
                double vdValorAInsertar, int[] rlIndiceCorrespondiente,
108
                boolean[] rbNuevoElemento) {
109
                int llIndiceIzq;
110
                int llIndiceDer;
111
                int llMedio;
112

    
113
                double ldValorComparacion;
114

    
115
                rbNuevoElemento[0] = false;
116
                rlIndiceCorrespondiente[0] = -1;
117

    
118
                //'Si el vector estiviese vac�o... (tuviese un s�lo elemento y el n�mero de coincidencias fuese 0)
119
                if (rVectorDatos.size() == 1) {
120
                        if (((udtDatosEstudio) rVectorDatos.get(0)).Coincidencias == 0) {
121
                                rlIndiceCorrespondiente[0] = 0;
122
                                rbNuevoElemento[0] = false; //'No tenemos que a�adir un nuevo elemento al vector
123

    
124
                                return true;
125
                        }
126
                }
127

    
128
                llIndiceIzq = 0;
129
                llIndiceDer = rVectorDatos.size() - 1;
130
                llMedio = (llIndiceIzq + llIndiceDer) / 2; //'Divisi�n entera!
131

    
132
                while (llIndiceIzq <= llIndiceDer) {
133
                        //'Coger el valor situado en la mitad de la zona de b�squeda como valor de comparaci�n
134
                        ldValorComparacion = ((udtDatosEstudio) rVectorDatos.get(llMedio)).Valor;
135

    
136
                        //'Si el valor a insertar es mayor que el valor de comparaci�n...
137
                        if (vdValorAInsertar > ldValorComparacion) {
138
                                //      'La zona de b�squeda queda restringida a la parte de la derecha
139
                                llIndiceIzq = llMedio + 1;
140
                                llMedio = (llIndiceIzq + llIndiceDer) / 2;
141

    
142
                                //    'Si el valor a insertar es menor que el valor de comparaci�n...
143
                        } else if (vdValorAInsertar < ldValorComparacion) {
144
                                //          'La zona de b�squeda queda restringida a la parte de la derecha
145
                                llIndiceDer = llMedio - 1;
146
                                llMedio = (llIndiceIzq + llIndiceDer) / 2;
147

    
148
                                //        'Si el valor de comparaci�n coincide con el valor a insertar
149
                        } else if (vdValorAInsertar == ldValorComparacion) {
150
                                rlIndiceCorrespondiente[0] = llMedio;
151
                                rbNuevoElemento[0] = false;
152

    
153
                                return true;
154
                        }
155
                }
156

    
157
                //  'Si llegamos a este punto es que no hemos encontrado el valor a insertar en el vector, es decir,
158
                //  'seguro que tendremos que a�adir un nuevo elemento.
159
                rbNuevoElemento[0] = true;
160

    
161
                //  'Nota:
162
                //  'En este caso (cuando en rbNuevoElemento se devuelve True) lo que hay que hacer al salir de esta funci�n
163
                //  'es a�adir un nuevo elemento al vector y desplazar todos los valores correspondientes a partir de rlIndiceCorrespondiente
164
                //  '�D�nde va el nuevo elemento?
165
                //  'El �ltimo sitio estudiado viene dado por el valor de llMedio.
166
                //  'Si el valor a insertar es menor que el valor almacenado en la posici�n llMedio, el nuevo valor deber� ir a su izquierda.
167
                //  'Si fuera mayor deber�a ir a su derecha.
168
                ldValorComparacion = ((udtDatosEstudio) rVectorDatos.get(llMedio)).Valor;
169

    
170
                if (vdValorAInsertar > ldValorComparacion) {
171
                        rlIndiceCorrespondiente[0] = llMedio + 1;
172
                } else {
173
                        rlIndiceCorrespondiente[0] = llMedio;
174
                }
175

    
176
                return true;
177
        }
178

    
179
        /**
180
         * M�todo para generar los intervalos.
181
         *
182
         * @return true si se han generado correctamente.
183
         *
184
         * @throws com.iver.cit.gvsig.fmap.DriverException
185
         * @throws DriverException
186
         */
187
        public boolean generarIntervalos()
188
                throws ReadDriverException {
189
                ArrayList lVectorDatos;
190
                double[] ldMediaTotal = new double[1];
191
                double[] ldSDAM = new double[1];
192

    
193
                int[] llaIndicesRupturas;
194

    
195
                double[] ldUltimaGVF = new double[1];
196
                double[] ldNuevaGVF = new double[1];
197

    
198
                int i;
199
                int liNumClasesReales;
200
                int llNumElementosPorClase;
201

    
202
                //    'Obtener los datos a estudiar ordenados ascendentemente y obtener la media total
203
                //ReDim lVectorDatos(0)
204
                lVectorDatos = new ArrayList();
205

    
206
                lVectorDatos.add(new udtDatosEstudio());
207

    
208
                if (!mbObtenerDatos(lVectorDatos, ldMediaTotal)) {
209
                        return false; //SalidaSinMensaje
210
                }
211

    
212
                System.out.println("Analizando datos ...");
213

    
214
                /// Call gEstablecerDescripcionProceso("Analizando datos ...", False)
215
                //  'Calcular la suma de las desviaciones t�picas del total de los datos respecto de la media total
216
                ldSDAM[0] = mbGetSumSquaredDeviationArrayMean(lVectorDatos,
217
                                ldMediaTotal[0]);
218

    
219
                ///if (lVectorDatos.length==0){
220
                if (lVectorDatos.isEmpty()) {
221
                        //      'S�lo se pueden generar dos intervalos -> hay un valor de ruptura
222
                        ///ReDim mdaValoresRuptura(0)
223
                        mdaValoresRuptura[0] = ((udtDatosEstudio) lVectorDatos.get(0)).Valor;
224
                        mdaValInit[0] = ((udtDatosEstudio) lVectorDatos.get(0)).Valor;
225
                        miNumIntervalosGenerados = 2;
226

    
227
                        return true;
228
                }
229

    
230
                //  'Calculamos el n�mero m�ximo de clases reales que podemos generar.
231
                //  'Este n�mero ser�a igual al n� de elementos que tenga el vector de datos.
232
                if (miNumIntervalosSolicitados > (lVectorDatos.size())) {
233
                        liNumClasesReales = lVectorDatos.size() + 1;
234
                } else {
235
                        liNumClasesReales = miNumIntervalosSolicitados;
236
                }
237

    
238
                //  'Establecemos las clases iniciales especificando unos �ndices de ruptura en ppo. equidistantes
239
                llaIndicesRupturas = new int[liNumClasesReales - 1];
240
                llNumElementosPorClase = (lVectorDatos.size()) / liNumClasesReales;
241

    
242
                for (i = 0; i < llaIndicesRupturas.length; i++) {
243
                        if (i == 0) {
244
                                llaIndicesRupturas[i] = llNumElementosPorClase - 1;
245
                        } else {
246
                                llaIndicesRupturas[i] = llaIndicesRupturas[i - 1] +
247
                                        llNumElementosPorClase;
248
                        }
249
                }
250

    
251
                udtDatosClase[] ldaSDCM_Parciales = new udtDatosClase[llaIndicesRupturas.length +
252
                        1];
253
                udtDatosClase[] ldaSDCM_Validos = new udtDatosClase[llaIndicesRupturas.length +
254
                        1];
255

    
256
                ///ReDim ldaSDCM_Parciales(UBound(llaIndicesRupturas()) + 1)
257
                ///ReDim ldaSDCM_Validos(UBound(ldaSDCM_Parciales()) + 1)
258
                if (llaIndicesRupturas.length == 0) {
259
                        return true;
260
                }
261

    
262
                //  'Calcular la bondad inicial
263
                if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales, llaIndicesRupturas,
264
                                        ldSDAM[0], ldUltimaGVF, -1, false)) {
265
                        JOptionPane.showMessageDialog((Component)PluginServices.getMainFrame(),PluginServices.getText(this,"el_numero_maximo_de_intervalos_para_este_campo_es")+": "+lVectorDatos.size());
266
                        miNumIntervalosSolicitados=lVectorDatos.size();
267
                        generarIntervalos();
268
                        return false;
269
                }
270

    
271
                ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
272

    
273
                boolean lbMoverADerecha;
274
                boolean lbMoverAIzquierda;
275
                boolean lbIntentarDesplazamiento;
276
                int llIndiceRupturaOriginal;
277

    
278
                long k;
279
                double ldGVFentrepasadas;
280

    
281
                ldGVFentrepasadas = ldUltimaGVF[0];
282

    
283
                //'liNumClasesReales no ser� muy grande (11 es el m�ximo)
284
                for (k = 1; k <= 100; k++) {
285
                        //      'Para cada �ndice de ruptura...
286
                        for (i = 0; i < (llaIndicesRupturas.length); i++) {
287
                                lbMoverADerecha = false;
288
                                lbMoverAIzquierda = false;
289
                                llIndiceRupturaOriginal = llaIndicesRupturas[i];
290
                                ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
291

    
292
                                //'Hay que decidir hacia donde hay que desplazar el �ndice de ruptura
293
                                //'Probamos moviendo a derecha (si se puede)
294
                                lbIntentarDesplazamiento = false;
295

    
296
                                if (i == (llaIndicesRupturas.length - 1)) {
297
                                        if ((llaIndicesRupturas[i] + 1) < lVectorDatos.size()) {
298
                                                lbIntentarDesplazamiento = true;
299
                                        }
300
                                } else {
301
                                        if ((llaIndicesRupturas[i] + 1) < llaIndicesRupturas[i + 1]) {
302
                                                lbIntentarDesplazamiento = true;
303
                                        } //'If (llaIndicesRupturas(i) + 1) < llaIndicesRupturas(i + 1) Then
304
                                } //'If i = UBound(llaIndicesRupturas) Then
305

    
306
                                if (lbIntentarDesplazamiento) {
307
                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
308

    
309
                                        if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
310
                                                                llaIndicesRupturas, ldSDAM[0], ldNuevaGVF, i,
311
                                                                false)) {
312
                                                return false;
313
                                        }
314

    
315
                                        if (ldNuevaGVF[0] > ldUltimaGVF[0]) {
316
                                                lbMoverADerecha = true;
317
                                                ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
318
                                        } else {
319
                                                //'Dejamos el �ndice de ruputura como estaba y probamos con un desplazamiento a izquierda
320
                                                llaIndicesRupturas[i] = llIndiceRupturaOriginal;
321
                                                ldaSDCM_Parciales = getArray(ldaSDCM_Validos);
322
                                        }
323
                                } //'If lbIntentarDesplazamiento Then
324

    
325
                                lbIntentarDesplazamiento = false;
326

    
327
                                //'Probamos moviendo a izquierda (si se puede y no estamos moviendo ya a derechas)
328
                                if (!lbMoverADerecha) {
329
                                        if (i == 0) { //LBound(llaIndicesRupturas) Then
330

    
331
                                                if ((llaIndicesRupturas[i] - 1) >= 0) { //LBound(lVectorDatos()) Then
332
                                                        lbIntentarDesplazamiento = true;
333
                                                } //'If (llaIndicesRupturas(i) - 1) >= LBound(lVectorDatos()) Then
334
                                        } else {
335
                                                if ((llaIndicesRupturas[i] - 1) > llaIndicesRupturas[i -
336
                                                                1]) {
337
                                                        lbIntentarDesplazamiento = true;
338
                                                } //'If (llaIndicesRupturas(i) - 1) > llaIndicesRupturas(i - 1) Then
339
                                        } //'If i = LBound(llaIndicesRupturas) Then
340
                                } //'If Not lbMoverADerecha Then
341

    
342
                                if (lbIntentarDesplazamiento) {
343
                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1;
344

    
345
                                        if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
346
                                                                llaIndicesRupturas, ldSDAM[0], ldNuevaGVF, i,
347
                                                                true)) {
348
                                                return false;
349
                                        }
350

    
351
                                        if (ldNuevaGVF[0] > ldUltimaGVF[0]) {
352
                                                lbMoverAIzquierda = true;
353
                                                ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
354
                                        } else {
355
                                                //'Dejamos el �ndice de ruputura como estaba
356
                                                llaIndicesRupturas[i] = llIndiceRupturaOriginal;
357
                                                ldaSDCM_Parciales = getArray(ldaSDCM_Validos);
358
                                        }
359
                                } //'If lbIntentarDesplazamiento Then
360

    
361
                                lbIntentarDesplazamiento = false;
362

    
363
                                //'Si se ha decidido desplazar el �ndice ... continuamos hasta que no podamos mejorar la GVF
364
                                if (lbMoverAIzquierda || lbMoverADerecha) {
365
                                        ldUltimaGVF[0] = ldNuevaGVF[0];
366

    
367
                                        boolean exit = false;
368

    
369
                                        while (!exit) {
370
                                                llIndiceRupturaOriginal = llaIndicesRupturas[i];
371

    
372
                                                if (lbMoverADerecha) {
373
                                                        if (i == (llaIndicesRupturas.length - 1)) {
374
                                                                if ((llaIndicesRupturas[i] + 1) >= lVectorDatos.size()) {
375
                                                                        exit = true;
376
                                                                }
377
                                                        } else {
378
                                                                if ((llaIndicesRupturas[i] + 1) >= llaIndicesRupturas[i +
379
                                                                                1]) {
380
                                                                        exit = true;
381
                                                                }
382
                                                        } //'If i = UBound(llaIndicesRupturas) Then
383

    
384
                                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
385
                                                } else { //'If lbMoverAIzquierda Then
386

    
387
                                                        if (i == 0) { //LBound(llaIndicesRupturas) Then
388

    
389
                                                                if ((llaIndicesRupturas[i] - 1) < 0) { //LBound(lVectorDatos()) Then Exit Do
390
                                                                        exit = true;
391
                                                                }
392
                                                        } else {
393
                                                                if ((llaIndicesRupturas[i] - 1) <= llaIndicesRupturas[i -
394
                                                                                1]) {
395
                                                                        exit = true;
396
                                                                }
397
                                                        } //'If i = LBound(llaIndicesRupturas) Then
398

    
399
                                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1; //////////////////
400
                                                } //'If lbMoverADerecha Then
401

    
402
                                                if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
403
                                                                        llaIndicesRupturas, ldSDAM[0], ldNuevaGVF,
404
                                                                        i, lbMoverAIzquierda)) {
405
                                                        return false;
406
                                                }
407

    
408
                                                if (ldNuevaGVF[0] < ldUltimaGVF[0]) {
409
                                                        // 'Dejar el �ndice donde estaba
410
                                                        llaIndicesRupturas[i] = llIndiceRupturaOriginal;
411
                                                        ldaSDCM_Parciales = getArray(ldaSDCM_Validos);
412
                                                        exit = true;
413
                                                } else {
414
                                                        ldUltimaGVF[0] = ldNuevaGVF[0];
415
                                                        ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
416
                                                }
417
                                        }
418
                                } //'If lbMoverAIzquierda Or lbMoverADerecha Then
419
                        }
420

    
421
                        if (ldUltimaGVF[0] <= ldGVFentrepasadas) {
422
                                i = 101;
423
                        }
424

    
425
                        ldGVFentrepasadas = ldUltimaGVF[0];
426
                }
427

    
428
                //   'A partir de aqu� ya no se puede cancelar nada
429
                mdaValoresRuptura = new double[llaIndicesRupturas.length];
430
                mdaValInit = new double[llaIndicesRupturas.length];
431

    
432
                for (i = 0; i < mdaValoresRuptura.length; i++) { // LBound(mdaValoresRuptura) To UBound(mdaValoresRuptura)
433
                        if (llaIndicesRupturas[i]==-1)llaIndicesRupturas[i]=1;
434
                        if (llaIndicesRupturas[i]>lVectorDatos.size()-1)llaIndicesRupturas[i]=lVectorDatos.size()-1;
435
                        mdaValoresRuptura[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i])).Valor;
436

    
437
                        if ((llaIndicesRupturas[i] + 1) < lVectorDatos.size()) {
438
                                mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i] +
439
                                                1)).Valor;
440
                        } else {
441
                                mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i])).Valor;
442
                        }
443

    
444
                        //      'Hay que aplicar una peque�a correcci�n a los valores de ruptura para que los intervalos que genera
445
                        //    'mapobjects se aprechen en su totalidad, o lo que es lo mismo, vengan todos representados en el mapa.
446
                        //  'Con esto tambi�n se consigue hallar intervalos equivalentes a los de ArcView. Esta correcci�n consiste
447
                        //'en sumar el m�nimo incremento a los valores de ruptura. No lo hago aqu� sino en la ventana de propiedades de capa.
448
                }
449

    
450
                miNumIntervalosGenerados = mdaValoresRuptura.length + 2;
451

    
452
                ldaSDCM_Validos = null;
453
                ldaSDCM_Parciales = null;
454
                lVectorDatos = null;
455

    
456
                return true;
457
        }
458

    
459
        /**
460
         * DOCUMENT ME!
461
         *
462
         * @param array DOCUMENT ME!
463
         *
464
         * @return DOCUMENT ME!
465
         */
466
        private udtDatosClase[] getArray(udtDatosClase[] array) {
467
                udtDatosClase[] aux = new udtDatosClase[array.length];
468

    
469
                for (int i = 0; i < array.length; i++) {
470
                        aux[i] = new udtDatosClase();
471
                        aux[i].Media = array[i].Media;
472
                        aux[i].NumElementos = array[i].NumElementos;
473
                        aux[i].SDCM = array[i].SDCM;
474
                        aux[i].SumaCuadradoTotal = array[i].SumaCuadradoTotal;
475
                        aux[i].SumaTotal = array[i].SumaTotal;
476
                }
477

    
478
                return aux;
479
        }
480

    
481
        /**
482
         * Devuelve la "SDAM" de un conjunto de datos que vienen almacenados en el
483
         * vector rVectorDatos
484
         *
485
         * @param rVectorDatos Datos
486
         * @param vdMedia Media
487
         *
488
         * @return suma de las desviaciones t�picas del total de los datos respecto
489
         *                    de la media total
490
         */
491
        private double mbGetSumSquaredDeviationArrayMean(ArrayList rVectorDatos,
492
                double vdMedia) {
493
                int i;
494

    
495
                double rdSDAM = 0;
496

    
497
                for (i = 0; i < rVectorDatos.size(); i++) { // LBound(rVectorDatos) To UBound(rVectorDatos)
498
                        rdSDAM = rdSDAM +
499
                                (Math.pow((((udtDatosEstudio) rVectorDatos.get(i)).Valor -
500
                                        vdMedia), 2) * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias);
501
                }
502

    
503
                return rdSDAM;
504
        }
505

    
506
        /**
507
         * Esta funci�n obtiene los datos en los que queremos hallar las rupturas
508
         * naturales. Los datos se devuelven ordenados en un vector. Tambi�n
509
         * devuelve la media total
510
         *
511
         * @param rVectorDatos Datos
512
         * @param rdMediaTotal Media total
513
         *
514
         * @return True si se ha calculado correctamente.
515
         *
516
         * @throws com.iver.cit.gvsig.fmap.DriverException
517
         * @throws DriverException
518
         */
519
        private boolean mbObtenerDatos(ArrayList rVectorDatos, double[] rdMediaTotal)
520
                throws ReadDriverException {
521
                double ldValor;
522

    
523
                int i;
524
                long llRecordCount;
525

    
526
                int[] llIndice = new int[1];
527
                boolean[] lbNuevoElemento = new boolean[1];
528
                //int j;
529

    
530
                SelectableDataSource sds = mLayer.getRecordset();
531
                llRecordCount = sds.getRowCount();
532

    
533
                if (!gbExisteCampoEnRegistro(mLayer.getRecordset(), msFieldName)) {
534
                        if (msFieldName == "") {
535
                                System.out.println(
536
                                        "No se ha establecido el nombre del campo origen!");
537
                        } else {
538
                                System.out.println("El campo '" + msFieldName +
539
                                        "' no pertence a la capa!");
540
                        }
541

    
542
                        return false;
543
                }
544

    
545
                // 'Nos cuidamos de recorrer todos los registros sin consultar la propiedad EOF del recordset
546
                for (i = 0; i < llRecordCount; i++) {
547
                        try{
548
                                ldValor =  getValue(sds.getFieldValue(i,
549
                                                        sds.getFieldIndexByName(msFieldName)));
550
                        }catch (Exception e) {
551
                                llRecordCount--;
552
                                continue;
553
                        }
554
                        rdMediaTotal[0] = rdMediaTotal[0] + ldValor;
555

    
556
                        //       'Hay que insertar el valor en la posici�n adecuada. Para ello hacemos una b�squeda binaria
557
                        if (!mbObtenerPosicionEnVector(rVectorDatos, ldValor, llIndice,
558
                                                lbNuevoElemento)) {
559
                                return false;
560
                        }
561

    
562
                        if (!lbNuevoElemento[0]) {
563
                                if ((llIndice[0] < 0) || (llIndice[0] > rVectorDatos.size())) {
564
                                        System.out.println("�ndice incorrecto!");
565

    
566
                                        return false;
567
                                }
568

    
569
                                ((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Valor = ldValor; //'Por si fuese el primer elemento
570

    
571
                                //'Incrementamos el n� de coincidencias y damos el valor por insertado
572
                                ((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Coincidencias = ((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Coincidencias +
573
                                        1;
574
                        } else {
575
                                udtDatosEstudio udt = new udtDatosEstudio();
576
                                udt.Valor = ldValor;
577
                                udt.Coincidencias = 1;
578
                                rVectorDatos.add(llIndice[0], udt);
579
                        }
580
                }
581

    
582
                rdMediaTotal[0] = rdMediaTotal[0] / llRecordCount;
583

    
584
                return true;
585
        }
586

    
587
        /**
588
         * Devuelve true si existe el campo en el registro.
589
         *
590
         * @param recordset Recordset.
591
         * @param msFieldName2 Nombre del campo.
592
         *
593
         * @return True si existe el campo.
594
         * @throws ReadDriverException
595
         *
596
         */
597
        private boolean gbExisteCampoEnRegistro(SelectableDataSource recordset,
598
                String msFieldName2) throws ReadDriverException  {
599
                if (recordset.getFieldIndexByName(msFieldName2) == -1) {
600
                        return false;
601
                }
602

    
603
                return true;
604
        }
605

    
606
        /**
607
         * Esta funci�n s�lo calcula las SDCM de las clases adyacentes al �ndice de
608
         * ruptura actual. Si el �ndice de ruptura actual es -1 entonces las
609
         * calcula todas! . En este caso no importa el valor de
610
         * vbDesplazAIzquierda
611
         *
612
         * @param rVectorDatos Datos
613
         * @param raClases Clases encontradas
614
         * @param rlaIndicesRuptura �ndices de ruptura
615
         * @param vdSDAM suma de la desviaci�n standard.
616
         * @param rdGVF Desviaci�n standard de los intervalos.
617
         * @param vlIndiceRupturaActual �ndice de ruptura actual.
618
         *
619
         * @return True si se ha calcula do correctamente.
620
         */
621
        /*private boolean mbCalcularGVF(ArrayList rVectorDatos,
622
                udtDatosClase[] raClases, int[] rlaIndicesRuptura, double vdSDAM,
623
                double[] rdGVF, int vlIndiceRupturaActual ) {
624
                return mbCalcularGVF(rVectorDatos, raClases, rlaIndicesRuptura, vdSDAM,
625
                        rdGVF, vlIndiceRupturaActual, true);
626
        }
627
*/
628
        /**
629
         * Esta funci�n s�lo calcula las SDCM de las clases adyacentes al �ndice de
630
         * ruptura actual. Si el �ndice de ruptura actual es -1 entonces las
631
         * calcula todas! . En este caso no importa el valor de
632
         * vbDesplazAIzquierda
633
         *
634
         * @param rVectorDatos Datos
635
         * @param raClases Calses que representan a los intervalos.
636
         * @param rlaIndicesRuptura �ndices de ruptura.
637
         * @param vdSDAM Desviaci�n standard.
638
         * @param rdGVF Desviaci�n standard de los intervalos.
639
         * @param vlIndiceRupturaActual �ndice de ruptura actual.
640
         * @param vbDesplazAIzquierda Desplazamiento a la izquierda.
641
         *
642
         * @return True si se ha calculado correctamente.
643
         */
644
        private boolean mbCalcularGVF(ArrayList rVectorDatos,
645
                udtDatosClase[] raClases, int[] rlaIndicesRuptura, double vdSDAM,
646
                double[] rdGVF, int vlIndiceRupturaActual /* As Long = -1*/,
647
                boolean vbDesplazAIzquierda) {
648
                double ldSDCM_aux;
649

    
650
                int i;
651

    
652
                if (vlIndiceRupturaActual == -1) {
653
                        // 'Obtenemos los datos para todas las clases = intervalos
654
                        for (i = 0; i < rlaIndicesRuptura.length; i++) {
655
                                if (i == 0) { // LBound(rlaIndicesRuptura) Then
656

    
657
                                        if (!mbGetDatosClase(rVectorDatos, 0, rlaIndicesRuptura[i],
658
                                                                raClases, i)) {
659
                                                return false;
660
                                        }
661
                                } else {
662
                                        if (!mbGetDatosClase(rVectorDatos,
663
                                                                rlaIndicesRuptura[i - 1] + 1,
664
                                                                rlaIndicesRuptura[i], raClases, i)) {
665
                                                return false;
666
                                        }
667
                                }
668
                        }
669

    
670
                        //'Falta la �ltima clase
671
                        if (!mbGetDatosClase(rVectorDatos,
672
                                                rlaIndicesRuptura[rlaIndicesRuptura.length - 1] + 1,
673
                                                rVectorDatos.size() - 1, raClases, raClases.length - 1)) {
674
                                return false;
675
                        }
676
                } else {
677
                        i = vlIndiceRupturaActual;
678

    
679
                        //'Hay que determinar para qu� clases debemos volver a recalcular los datos en funci�n del �ndice de ruptura que estamos modificando
680
                        if (vbDesplazAIzquierda) {
681
                                //  'Recalcular los datos de la clase izquierda
682
                                if (!mbRecalcularDatosClase(raClases, i, rVectorDatos,
683
                                                        rlaIndicesRuptura[i] + 1, vdSDAM, false)) {
684
                                        return false;
685
                                }
686

    
687
                                //  'Recalcular los datos de la clase derecha
688
                                if (!mbRecalcularDatosClase(raClases, i + 1, rVectorDatos,
689
                                                        rlaIndicesRuptura[i] + 1, vdSDAM, true)) {
690
                                        return false;
691
                                }
692
                        } else {
693
                                //  'Recalcular los datos de la clase izquierda
694
                                if (!mbRecalcularDatosClase(raClases, i, rVectorDatos,
695
                                                        rlaIndicesRuptura[i], vdSDAM, true)) {
696
                                        return false;
697
                                }
698

    
699
                                //  'Recalcular los datos de la clase derecha
700
                                if (!mbRecalcularDatosClase(raClases, i + 1, rVectorDatos,
701
                                                        rlaIndicesRuptura[i], vdSDAM, false)) {
702
                                        return false;
703
                                }
704
                        }
705
                }
706

    
707
                ldSDCM_aux = 0;
708

    
709
                for (i = 0; i < raClases.length; i++) { //LBound(raClases) To UBound(raClases)
710
                        ldSDCM_aux = ldSDCM_aux + raClases[i].SDCM;
711
                }
712

    
713
                rdGVF[0] = (vdSDAM - ldSDCM_aux) / vdSDAM;
714
                //System.out.println(ldSDCM_aux);
715

    
716
                return true;
717
        }
718

    
719
        /**
720
         * Devuelve la "SDCM" de un conjunto de datos que vienen almacenados en el
721
         * vector rVectorDatos y que est�n delimitados por vlLimiteInf y
722
         * vlLimiteInf
723
         *
724
         * @param rVectorDatos Datos
725
         * @param vlLimiteInf L�mite inferior.
726
         * @param vlLimiteSup L�mite superior.
727
         * @param rClase Calses que representan a los intervalos.
728
         * @param numClas N�mero de calses.
729
         *
730
         * @return True si se ha calculado correctamente.
731
         */
732
        private boolean mbGetDatosClase(ArrayList rVectorDatos, int vlLimiteInf,
733
                int vlLimiteSup, udtDatosClase[] rClase, int numClas) {
734
                int i;
735

    
736
                if (vlLimiteInf < 0) {
737
                        return false;
738
                }
739

    
740
                if (vlLimiteSup > rVectorDatos.size()) {
741
                        return false;
742
                }
743

    
744
                if (vlLimiteSup < vlLimiteInf) {
745
                        return false;
746
                }
747

    
748
                // 'Inicializamos los datos de la clase
749
                rClase[numClas] = new udtDatosClase();
750

    
751
                //'Hallamos la media de la clase
752
                for (i = vlLimiteInf; i < (vlLimiteSup + 1); i++) {
753
                        rClase[numClas].NumElementos = rClase[numClas].NumElementos +
754
                                ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias;
755

    
756
                        //'rClase.Media = rClase.Media + (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
757
                        rClase[numClas].SumaTotal = rClase[numClas].SumaTotal +
758
                                (((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias);
759

    
760
                        //'rClase.ProductoTotal = rClase.ProductoTotal * (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
761
                        rClase[numClas].SumaCuadradoTotal = rClase[numClas].SumaCuadradoTotal +
762
                                (Math.pow(((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(
763
                                                i)).Coincidencias, 2));
764
                }
765

    
766
                //'rClase.Media = rClase.Media / llTotalElementos
767
                rClase[numClas].Media = rClase[numClas].SumaTotal / rClase[numClas].NumElementos;
768
                rClase[numClas].SDCM = (rClase[numClas].SumaCuadradoTotal) -
769
                        (2 * rClase[numClas].Media * rClase[numClas].SumaTotal) +
770
                        (rClase[numClas].NumElementos * Math.pow(rClase[numClas].Media, 2));
771
                /*if (new Double(rClase[numClas].SDCM).isNaN()){
772
                        System.out.println(rClase[numClas].SDCM);
773
                }*/
774
                return true;
775
        }
776

    
777
        /**
778
         * Recalcula los datos de las clases.
779
         *
780
         * @param rClase Clases.
781
         * @param i �adir �adir �adir �adir indica si a la clase se le a�ade un
782
         *                   elemento (True) o se le quita (False)
783
         * @param rVectorDatos Datos.
784
         * @param vlIndiceElemento es el �ndice del elemento que se le va a�adir o
785
         *                   a quitar a la clase
786
         * @param vdSDAM desviaci�n standard.
787
         * @param vbA �adir DOCUMENT ME!
788
         *
789
         * @return True si se ha calculado correctamente.
790
         */
791
        private boolean mbRecalcularDatosClase(udtDatosClase[] rClase, int i,
792
                ArrayList rVectorDatos, int vlIndiceElemento, double vdSDAM,
793
                boolean vbAnyadir) {
794
                double ldValor;
795
                long llNumCoincidencias;
796
try{
797
        if (vlIndiceElemento>rVectorDatos.size()-1)return true;
798
                ldValor = ((udtDatosEstudio) rVectorDatos.get(vlIndiceElemento)).Valor;
799
                llNumCoincidencias = ((udtDatosEstudio) rVectorDatos.get(vlIndiceElemento)).Coincidencias;
800

    
801
                if (vbAnyadir) {
802
                        //'Actualizamos la suma total
803
                        rClase[i].SumaTotal = rClase[i].SumaTotal +
804
                                (ldValor * llNumCoincidencias);
805

    
806
                        //'Actualizamos la suma de cuadrados total
807
                        rClase[i].SumaCuadradoTotal = rClase[i].SumaCuadradoTotal +
808
                                (Math.pow((ldValor * llNumCoincidencias), 2));
809

    
810
                        //'Actualizamos el producto total
811
                        //'rClase.ProductoTotal = rClase.ProductoTotal * (ldValor * llNumCoincidencias)
812
                        //'Actualizamos el n� de elementos
813
                        rClase[i].NumElementos = rClase[i].NumElementos +
814
                                llNumCoincidencias;
815
                } else {
816
                        //'Actualizamos la suma total
817
                        rClase[i].SumaTotal = rClase[i].SumaTotal -
818
                                (ldValor * llNumCoincidencias);
819

    
820
                        // 'Actualizamos la suma de cuadrados total
821
                        rClase[i].SumaCuadradoTotal = rClase[i].SumaCuadradoTotal -
822
                                (Math.pow((ldValor * llNumCoincidencias), 2));
823

    
824
                        // 'Actualizamos el producto total
825
                        // 'rClase.ProductoTotal = rClase.ProductoTotal / (ldValor * llNumCoincidencias)
826
                        // 'Actualizamos el n� de elementos
827
                        rClase[i].NumElementos = rClase[i].NumElementos -
828
                                llNumCoincidencias;
829
                } // 'If vbA�adir Then
830
                if (rClase[i].NumElementos<=0)rClase[i].NumElementos=1;
831
                //'Obtenemos la nueva media
832
                rClase[i].Media = rClase[i].SumaTotal / rClase[i].NumElementos;
833

    
834
                //'Actualizamos la SDCM
835
                rClase[i].SDCM = (rClase[i].SumaCuadradoTotal) -
836
                        (2 * rClase[i].Media * rClase[i].SumaTotal) +
837
                        (rClase[i].NumElementos * Math.pow(rClase[i].Media, 2));
838

    
839
}catch (Exception e) {
840
        return false;
841
}
842
                return true;
843
        }
844

    
845
        /**
846
         * Devuelve el valor de ruptura seg�n el �ndice que se le pasa como
847
         * par�metro.
848
         *
849
         * @param viIndice �nidice del valor de ruptura.
850
         *
851
         * @return Valor de ruptura.
852
         */
853
        public double getValorRuptura(int viIndice) {
854
                return mdaValoresRuptura[viIndice];
855
        }
856

    
857
        /**
858
         * Devuelve el valor inicial de cada intervalo
859
         *
860
         * @param index �ndice del intervalo
861
         *
862
         * @return valor del intervalo.
863
         */
864
        public double getValInit(int index) {
865
                return mdaValInit[index];
866
        }
867

    
868
        /**
869
         * Devuelve el n�mero de intervalos que se pueden representar, no tiene
870
         * porque coincidir con el n�mero de intervalos que se piden.
871
         *
872
         * @return N�mero de intervalos calculados.
873
         */
874
        public int getNumIntervals() {
875
                return miNumIntervalosGenerados;
876
        }
877

    
878
        /**
879
         * Clase para contener los atributos Valor y coincidencias.
880
         *
881
         * @author Vicente Caballero Navarro
882
         */
883
        private class udtDatosEstudio {
884
                private double Valor; //
885
                private long Coincidencias;
886
        }
887

    
888
        /**
889
         * Clase para contener los atributos: N�mero de Elementos. Media.
890
         * SumaTotal. SumaCuadradoTotal. Desviaci�n standard.
891
         *
892
         * @author Vicente Caballero Navarro
893
         */
894
        private class udtDatosClase {
895
                private long NumElementos; //             'N� total de elementos que hay en la clase
896
                private double Media; //                 'Media de la clase
897
                private double SumaTotal; //              'Suma total de los elementos
898

    
899
                //'ProductoTotal          'Producto total de los elementos '�dar� problemas de desbordamiento?
900
                private double SumaCuadradoTotal; //      'Suma del total de los cuadrados de los elementos
901
                private double SDCM; //                  'Suma de la desviaci�n t�pica de los elementos de la clase respecto de la media de la clase
902
        }
903
        /**
904
         * Devuelve el valor en un double del Value que se pasa como par�metro.
905
         *
906
         * @param value Value.
907
         *
908
         * @return valor.
909
         * @throws Exception
910
         */
911
        private double getValue(Value value) throws Exception {
912
                if (value instanceof IntValue) {
913
                        return ((IntValue) value).intValue();
914
                } else if (value instanceof LongValue) {
915
                        return ((LongValue) value).longValue();
916
                } else if (value instanceof FloatValue) {
917
                        return ((FloatValue) value).floatValue();
918
                } else if (value instanceof ShortValue) {
919
                        return ((ShortValue) value).shortValue();
920
                } else if (value instanceof NullValue){
921
                        throw new Exception();
922
                }
923

    
924
                return ((DoubleValue) value).doubleValue();
925
        }
926
}