Statistics
| Revision:

root / branches / gvSIG_03_SLD / applications / appgvSIG / src / com / iver / cit / gvsig / gui / thememanager / legendmanager / panels / NaturalIntervalGenerator.java @ 2102

History | View | Annotate | Download (27.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.gui.thememanager.legendmanager.panels;
42

    
43
import com.hardcode.gdbms.engine.data.driver.DriverException;
44
import com.hardcode.gdbms.engine.values.DoubleValue;
45

    
46
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
47
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
48

    
49
import java.util.ArrayList;
50

    
51

    
52
/**
53
 * Calcula los intervalos naturales.
54
 *
55
 * @author Vicente Caballero Navarro
56
 */
57
public class NaturalIntervalGenerator {
58
        private AlphanumericData mLayer;
59
        private String msFieldName;
60
        private int miNumIntervalosSolicitados;
61
        private int miNumIntervalosGenerados;
62
        private double[] mdaValoresRuptura;
63
        private double[] mdaValInit;
64

    
65
        /**
66
         * Crea un nuevo IntervalGenerator.
67
         *
68
         * @param layer AlphanumericData
69
         * @param field Nombre del campo.
70
         * @param numIntervals N?mero de intervalos.
71
         */
72
        public NaturalIntervalGenerator(AlphanumericData layer, String field,
73
                int numIntervals) {
74
                mLayer = layer;
75
                msFieldName = field;
76
                miNumIntervalosSolicitados = numIntervals;
77
        }
78

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

    
103
                double ldValorComparacion;
104

    
105
                rbNuevoElemento[0] = false;
106
                rlIndiceCorrespondiente[0] = -1;
107

    
108
                //'Si el vector estiviese vac?o... (tuviese un s?lo elemento y el n?mero de coincidencias fuese 0)
109
                if (rVectorDatos.size() == 1) {
110
                        if (((udtDatosEstudio) rVectorDatos.get(0)).Coincidencias == 0) {
111
                                rlIndiceCorrespondiente[0] = 0;
112
                                rbNuevoElemento[0] = false; //'No tenemos que a?adir un nuevo elemento al vector
113

    
114
                                return true;
115
                        }
116
                }
117

    
118
                llIndiceIzq = 0;
119
                llIndiceDer = rVectorDatos.size() - 1;
120
                llMedio = (llIndiceIzq + llIndiceDer) / 2; //'Divisi?n entera!
121

    
122
                while (llIndiceIzq <= llIndiceDer) {
123
                        //'Coger el valor situado en la mitad de la zona de b?squeda como valor de comparaci?n
124
                        ldValorComparacion = ((udtDatosEstudio) rVectorDatos.get(llMedio)).Valor;
125

    
126
                        //'Si el valor a insertar es mayor que el valor de comparaci?n...
127
                        if (vdValorAInsertar > ldValorComparacion) {
128
                                //      'La zona de b?squeda queda restringida a la parte de la derecha
129
                                llIndiceIzq = llMedio + 1;
130
                                llMedio = (llIndiceIzq + llIndiceDer) / 2;
131

    
132
                                //    'Si el valor a insertar es menor que el valor de comparaci?n...
133
                        } else if (vdValorAInsertar < ldValorComparacion) {
134
                                //          'La zona de b?squeda queda restringida a la parte de la derecha
135
                                llIndiceDer = llMedio - 1;
136
                                llMedio = (llIndiceIzq + llIndiceDer) / 2;
137

    
138
                                //        'Si el valor de comparaci?n coincide con el valor a insertar
139
                        } else if (vdValorAInsertar == ldValorComparacion) {
140
                                rlIndiceCorrespondiente[0] = llMedio;
141
                                rbNuevoElemento[0] = false;
142

    
143
                                return true;
144
                        }
145
                }
146

    
147
                //  'Si llegamos a este punto es que no hemos encontrado el valor a insertar en el vector, es decir,
148
                //  'seguro que tendremos que a?adir un nuevo elemento.
149
                rbNuevoElemento[0] = true;
150

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

    
160
                if (vdValorAInsertar > ldValorComparacion) {
161
                        rlIndiceCorrespondiente[0] = llMedio + 1;
162
                } else {
163
                        rlIndiceCorrespondiente[0] = llMedio;
164
                }
165

    
166
                return true;
167
        }
168

    
169
        /**
170
         * M?todo para generar los intervalos.
171
         *
172
         * @return true si se han generado correctamente.
173
         *
174
         * @throws com.iver.cit.gvsig.fmap.DriverException
175
         * @throws DriverException
176
         */
177
        public boolean generarIntervalos()
178
                throws com.iver.cit.gvsig.fmap.DriverException, DriverException {
179
                ArrayList lVectorDatos;
180
                double[] ldMediaTotal = new double[1];
181
                double[] ldSDAM = new double[1];
182

    
183
                int[] llaIndicesRupturas;
184

    
185
                double[] ldUltimaGVF = new double[1];
186
                double[] ldNuevaGVF = new double[1];
187

    
188
                int i;
189
                int liNumClasesReales;
190
                int llNumElementosPorClase;
191

    
192
                //    'Obtener los datos a estudiar ordenados ascendentemente y obtener la media total
193
                //ReDim lVectorDatos(0)
194
                lVectorDatos = new ArrayList();
195

    
196
                lVectorDatos.add(new udtDatosEstudio());
197

    
198
                if (!mbObtenerDatos(lVectorDatos, ldMediaTotal)) {
199
                        return false; //SalidaSinMensaje
200
                }
201

    
202
                System.out.println("Analizando datos ...");
203

    
204
                /// Call gEstablecerDescripcionProceso("Analizando datos ...", False)
205
                //  'Calcular la suma de las desviaciones t?picas del total de los datos respecto de la media total
206
                ldSDAM[0] = mbGetSumSquaredDeviationArrayMean(lVectorDatos,
207
                                ldMediaTotal[0]);
208

    
209
                ///if (lVectorDatos.length==0){
210
                if (lVectorDatos.isEmpty()) {
211
                        //      'S?lo se pueden generar dos intervalos -> hay un valor de ruptura
212
                        ///ReDim mdaValoresRuptura(0)
213
                        mdaValoresRuptura[0] = ((udtDatosEstudio) lVectorDatos.get(0)).Valor;
214
                        mdaValInit[0] = ((udtDatosEstudio) lVectorDatos.get(0)).Valor;
215
                        miNumIntervalosGenerados = 2;
216

    
217
                        return true;
218
                }
219

    
220
                //  'Calculamos el n?mero m?ximo de clases reales que podemos generar.
221
                //  'Este n?mero ser?a igual al n? de elementos que tenga el vector de datos.
222
                if (miNumIntervalosSolicitados > (lVectorDatos.size())) {
223
                        liNumClasesReales = lVectorDatos.size() + 1;
224
                } else {
225
                        liNumClasesReales = miNumIntervalosSolicitados;
226
                }
227

    
228
                //  'Establecemos las clases iniciales especificando unos ?ndices de ruptura en ppo. equidistantes
229
                llaIndicesRupturas = new int[liNumClasesReales - 1];
230
                llNumElementosPorClase = (lVectorDatos.size()) / liNumClasesReales;
231

    
232
                for (i = 0; i < llaIndicesRupturas.length; i++) {
233
                        if (i == 0) {
234
                                llaIndicesRupturas[i] = llNumElementosPorClase - 1;
235
                        } else {
236
                                llaIndicesRupturas[i] = llaIndicesRupturas[i - 1] +
237
                                        llNumElementosPorClase;
238
                        }
239
                }
240

    
241
                udtDatosClase[] ldaSDCM_Parciales = new udtDatosClase[llaIndicesRupturas.length +
242
                        1];
243
                udtDatosClase[] ldaSDCM_Validos = new udtDatosClase[llaIndicesRupturas.length +
244
                        1];
245

    
246
                ///ReDim ldaSDCM_Parciales(UBound(llaIndicesRupturas()) + 1)
247
                ///ReDim ldaSDCM_Validos(UBound(ldaSDCM_Parciales()) + 1)
248
                if (llaIndicesRupturas.length == 0) {
249
                        return true;
250
                }
251

    
252
                //  'Calcular la bondad inicial
253
                if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales, llaIndicesRupturas,
254
                                        ldSDAM[0], ldUltimaGVF, -1, false)) {
255
                        return false;
256
                }
257

    
258
                ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
259

    
260
                boolean lbMoverADerecha;
261
                boolean lbMoverAIzquierda;
262
                boolean lbIntentarDesplazamiento;
263
                int llIndiceRupturaOriginal;
264

    
265
                long k;
266
                double ldGVFentrepasadas;
267

    
268
                ldGVFentrepasadas = ldUltimaGVF[0];
269

    
270
                //'liNumClasesReales no ser? muy grande (11 es el m?ximo)
271
                for (k = 1; k <= 100; k++) {
272
                        //      'Para cada ?ndice de ruptura...
273
                        for (i = 0; i < (llaIndicesRupturas.length); i++) {
274
                                lbMoverADerecha = false;
275
                                lbMoverAIzquierda = false;
276
                                llIndiceRupturaOriginal = llaIndicesRupturas[i];
277
                                ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
278

    
279
                                //'Hay que decidir hacia donde hay que desplazar el ?ndice de ruptura
280
                                //'Probamos moviendo a derecha (si se puede)
281
                                lbIntentarDesplazamiento = false;
282

    
283
                                if (i == (llaIndicesRupturas.length - 1)) {
284
                                        if ((llaIndicesRupturas[i] + 1) < lVectorDatos.size()) {
285
                                                lbIntentarDesplazamiento = true;
286
                                        }
287
                                } else {
288
                                        if ((llaIndicesRupturas[i] + 1) < llaIndicesRupturas[i + 1]) {
289
                                                lbIntentarDesplazamiento = true;
290
                                        } //'If (llaIndicesRupturas(i) + 1) < llaIndicesRupturas(i + 1) Then
291
                                } //'If i = UBound(llaIndicesRupturas) Then
292

    
293
                                if (lbIntentarDesplazamiento) {
294
                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
295

    
296
                                        if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
297
                                                                llaIndicesRupturas, ldSDAM[0], ldNuevaGVF, i,
298
                                                                false)) {
299
                                                return false;
300
                                        }
301

    
302
                                        if (ldNuevaGVF[0] > ldUltimaGVF[0]) {
303
                                                lbMoverADerecha = true;
304
                                                ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
305
                                        } else {
306
                                                //'Dejamos el ?ndice de ruputura como estaba y probamos con un desplazamiento a izquierda
307
                                                llaIndicesRupturas[i] = llIndiceRupturaOriginal;
308
                                                ldaSDCM_Parciales = getArray(ldaSDCM_Validos);
309
                                        }
310
                                } //'If lbIntentarDesplazamiento Then
311

    
312
                                lbIntentarDesplazamiento = false;
313

    
314
                                //'Probamos moviendo a izquierda (si se puede y no estamos moviendo ya a derechas)
315
                                if (!lbMoverADerecha) {
316
                                        if (i == 0) { //LBound(llaIndicesRupturas) Then
317

    
318
                                                if ((llaIndicesRupturas[i] - 1) >= 0) { //LBound(lVectorDatos()) Then
319
                                                        lbIntentarDesplazamiento = true;
320
                                                } //'If (llaIndicesRupturas(i) - 1) >= LBound(lVectorDatos()) Then
321
                                        } else {
322
                                                if ((llaIndicesRupturas[i] - 1) > llaIndicesRupturas[i -
323
                                                                1]) {
324
                                                        lbIntentarDesplazamiento = true;
325
                                                } //'If (llaIndicesRupturas(i) - 1) > llaIndicesRupturas(i - 1) Then
326
                                        } //'If i = LBound(llaIndicesRupturas) Then
327
                                } //'If Not lbMoverADerecha Then
328

    
329
                                if (lbIntentarDesplazamiento) {
330
                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1;
331

    
332
                                        if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
333
                                                                llaIndicesRupturas, ldSDAM[0], ldNuevaGVF, i,
334
                                                                true)) {
335
                                                return false;
336
                                        }
337

    
338
                                        if (ldNuevaGVF[0] > ldUltimaGVF[0]) {
339
                                                lbMoverAIzquierda = true;
340
                                                ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
341
                                        } else {
342
                                                //'Dejamos el ?ndice de ruputura como estaba
343
                                                llaIndicesRupturas[i] = llIndiceRupturaOriginal;
344
                                                ldaSDCM_Parciales = getArray(ldaSDCM_Validos);
345
                                        }
346
                                } //'If lbIntentarDesplazamiento Then
347

    
348
                                lbIntentarDesplazamiento = false;
349

    
350
                                //'Si se ha decidido desplazar el ?ndice ... continuamos hasta que no podamos mejorar la GVF
351
                                if (lbMoverAIzquierda || lbMoverADerecha) {
352
                                        ldUltimaGVF[0] = ldNuevaGVF[0];
353

    
354
                                        boolean exit = false;
355

    
356
                                        while (!exit) {
357
                                                llIndiceRupturaOriginal = llaIndicesRupturas[i];
358

    
359
                                                if (lbMoverADerecha) {
360
                                                        if (i == (llaIndicesRupturas.length - 1)) {
361
                                                                if ((llaIndicesRupturas[i] + 1) >= lVectorDatos.size()) {
362
                                                                        exit = true;
363
                                                                }
364
                                                        } else {
365
                                                                if ((llaIndicesRupturas[i] + 1) >= llaIndicesRupturas[i +
366
                                                                                1]) {
367
                                                                        exit = true;
368
                                                                }
369
                                                        } //'If i = UBound(llaIndicesRupturas) Then
370

    
371
                                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
372
                                                } else { //'If lbMoverAIzquierda Then
373

    
374
                                                        if (i == 0) { //LBound(llaIndicesRupturas) Then
375

    
376
                                                                if ((llaIndicesRupturas[i] - 1) < 0) { //LBound(lVectorDatos()) Then Exit Do
377
                                                                        exit = true;
378
                                                                }
379
                                                        } else {
380
                                                                if ((llaIndicesRupturas[i] - 1) <= llaIndicesRupturas[i -
381
                                                                                1]) {
382
                                                                        exit = true;
383
                                                                }
384
                                                        } //'If i = LBound(llaIndicesRupturas) Then
385

    
386
                                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1; //////////////////
387
                                                } //'If lbMoverADerecha Then
388

    
389
                                                if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
390
                                                                        llaIndicesRupturas, ldSDAM[0], ldNuevaGVF,
391
                                                                        i, lbMoverAIzquierda)) {
392
                                                        return false;
393
                                                }
394

    
395
                                                if (ldNuevaGVF[0] < ldUltimaGVF[0]) {
396
                                                        // 'Dejar el ?ndice donde estaba
397
                                                        llaIndicesRupturas[i] = llIndiceRupturaOriginal;
398
                                                        ldaSDCM_Parciales = getArray(ldaSDCM_Validos);
399
                                                        exit = true;
400
                                                } else {
401
                                                        ldUltimaGVF[0] = ldNuevaGVF[0];
402
                                                        ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
403
                                                }
404
                                        }
405
                                } //'If lbMoverAIzquierda Or lbMoverADerecha Then
406
                        }
407

    
408
                        if (ldUltimaGVF[0] <= ldGVFentrepasadas) {
409
                                i = 101;
410
                        }
411

    
412
                        ldGVFentrepasadas = ldUltimaGVF[0];
413
                }
414

    
415
                //   'A partir de aqu? ya no se puede cancelar nada
416
                mdaValoresRuptura = new double[llaIndicesRupturas.length];
417
                mdaValInit = new double[llaIndicesRupturas.length];
418

    
419
                for (i = 0; i < mdaValoresRuptura.length; i++) { // LBound(mdaValoresRuptura) To UBound(mdaValoresRuptura)
420
                        mdaValoresRuptura[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i])).Valor;
421

    
422
                        if ((llaIndicesRupturas[i] + 1) < lVectorDatos.size()) {
423
                                mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i] +
424
                                                1)).Valor;
425
                        } else {
426
                                mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i])).Valor;
427
                        }
428

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

    
435
                miNumIntervalosGenerados = mdaValoresRuptura.length + 2;
436

    
437
                ldaSDCM_Validos = null;
438
                ldaSDCM_Parciales = null;
439
                lVectorDatos = null;
440

    
441
                return true;
442
        }
443

    
444
        /**
445
         * DOCUMENT ME!
446
         *
447
         * @param array DOCUMENT ME!
448
         *
449
         * @return DOCUMENT ME!
450
         */
451
        private udtDatosClase[] getArray(udtDatosClase[] array) {
452
                udtDatosClase[] aux = new udtDatosClase[array.length];
453

    
454
                for (int i = 0; i < array.length; i++) {
455
                        aux[i] = new udtDatosClase();
456
                        aux[i].Media = array[i].Media;
457
                        aux[i].NumElementos = array[i].NumElementos;
458
                        aux[i].SDCM = array[i].SDCM;
459
                        aux[i].SumaCuadradoTotal = array[i].SumaCuadradoTotal;
460
                        aux[i].SumaTotal = array[i].SumaTotal;
461
                }
462

    
463
                return aux;
464
        }
465

    
466
        /**
467
         * Devuelve la "SDAM" de un conjunto de datos que vienen almacenados en el
468
         * vector rVectorDatos
469
         *
470
         * @param rVectorDatos Datos
471
         * @param vdMedia Media
472
         *
473
         * @return suma de las desviaciones t?picas del total de los datos respecto
474
         *                    de la media total
475
         */
476
        private double mbGetSumSquaredDeviationArrayMean(ArrayList rVectorDatos,
477
                double vdMedia) {
478
                int i;
479

    
480
                double rdSDAM = 0;
481

    
482
                for (i = 0; i < rVectorDatos.size(); i++) { // LBound(rVectorDatos) To UBound(rVectorDatos)
483
                        rdSDAM = rdSDAM +
484
                                (Math.pow((((udtDatosEstudio) rVectorDatos.get(i)).Valor -
485
                                        vdMedia), 2) * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias);
486
                }
487

    
488
                return rdSDAM;
489
        }
490

    
491
        /**
492
         * Esta funci?n obtiene los datos en los que queremos hallar las rupturas
493
         * naturales. Los datos se devuelven ordenados en un vector. Tambi?n
494
         * devuelve la media total
495
         *
496
         * @param rVectorDatos Datos
497
         * @param rdMediaTotal Media total
498
         *
499
         * @return True si se ha calculado correctamente.
500
         *
501
         * @throws com.iver.cit.gvsig.fmap.DriverException
502
         * @throws DriverException
503
         */
504
        private boolean mbObtenerDatos(ArrayList rVectorDatos, double[] rdMediaTotal)
505
                throws com.iver.cit.gvsig.fmap.DriverException, DriverException {
506
                double ldValor;
507

    
508
                int i;
509
                long llRecordCount;
510

    
511
                int[] llIndice = new int[1];
512
                boolean[] lbNuevoElemento = new boolean[1];
513
                int j;
514

    
515
                SelectableDataSource sds = mLayer.getRecordset();
516
                llRecordCount = sds.getRowCount();
517

    
518
                if (!gbExisteCampoEnRegistro(mLayer.getRecordset(), msFieldName)) {
519
                        if (msFieldName == "") {
520
                                System.out.println(
521
                                        "No se ha establecido el nombre del campo origen!");
522
                        } else {
523
                                System.out.println("El campo '" + msFieldName +
524
                                        "' no pertence a la capa!");
525
                        }
526

    
527
                        return false;
528
                }
529

    
530
                // 'Nos cuidamos de recorrer todos los registros sin consultar la propiedad EOF del recordset
531
                for (i = 0; i < llRecordCount; i++) {
532
                        ldValor = ((DoubleValue) sds.getFieldValue(i,
533
                                        sds.getFieldIndexByName(msFieldName))).doubleValue(); //.Fields(msFieldName).Value;
534

    
535
                        rdMediaTotal[0] = rdMediaTotal[0] + ldValor;
536

    
537
                        //       'Hay que insertar el valor en la posici?n adecuada. Para ello hacemos una b?squeda binaria
538
                        if (!mbObtenerPosicionEnVector(rVectorDatos, ldValor, llIndice,
539
                                                lbNuevoElemento)) {
540
                                return false;
541
                        }
542

    
543
                        if (!lbNuevoElemento[0]) {
544
                                if ((llIndice[0] < 0) || (llIndice[0] > rVectorDatos.size())) {
545
                                        System.out.println("?ndice incorrecto!");
546

    
547
                                        return false;
548
                                }
549

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

    
552
                                //'Incrementamos el n? de coincidencias y damos el valor por insertado
553
                                ((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Coincidencias = ((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Coincidencias +
554
                                        1;
555
                        } else {
556
                                udtDatosEstudio udt = new udtDatosEstudio();
557
                                udt.Valor = ldValor;
558
                                udt.Coincidencias = 1;
559
                                rVectorDatos.add(llIndice[0], udt);
560
                        }
561
                }
562

    
563
                rdMediaTotal[0] = rdMediaTotal[0] / llRecordCount;
564

    
565
                return true;
566
        }
567

    
568
        /**
569
         * Devuelve true si existe el campo en el registro.
570
         *
571
         * @param recordset Recordset.
572
         * @param msFieldName2 Nombre del campo.
573
         *
574
         * @return True si existe el campo.
575
         *
576
         * @throws DriverException
577
         */
578
        private boolean gbExisteCampoEnRegistro(SelectableDataSource recordset,
579
                String msFieldName2) throws DriverException {
580
                if (recordset.getFieldIndexByName(msFieldName2) == -1) {
581
                        return false;
582
                }
583

    
584
                return true;
585
        }
586

    
587
        /**
588
         * Esta funci?n s?lo calcula las SDCM de las clases adyacentes al ?ndice de
589
         * ruptura actual. Si el ?ndice de ruptura actual es -1 entonces las
590
         * calcula todas! . En este caso no importa el valor de
591
         * vbDesplazAIzquierda
592
         *
593
         * @param rVectorDatos Datos
594
         * @param raClases Clases encontradas
595
         * @param rlaIndicesRuptura ?ndices de ruptura
596
         * @param vdSDAM suma de la desviaci?n standard.
597
         * @param rdGVF Desviaci?n standard de los intervalos.
598
         * @param vlIndiceRupturaActual ?ndice de ruptura actual.
599
         *
600
         * @return True si se ha calcula do correctamente.
601
         */
602
        private boolean mbCalcularGVF(ArrayList rVectorDatos,
603
                udtDatosClase[] raClases, int[] rlaIndicesRuptura, double vdSDAM,
604
                double[] rdGVF, int vlIndiceRupturaActual /* As Long = -1*/) {
605
                return mbCalcularGVF(rVectorDatos, raClases, rlaIndicesRuptura, vdSDAM,
606
                        rdGVF, vlIndiceRupturaActual, true);
607
        }
608

    
609
        /**
610
         * Esta funci?n s?lo calcula las SDCM de las clases adyacentes al ?ndice de
611
         * ruptura actual. Si el ?ndice de ruptura actual es -1 entonces las
612
         * calcula todas! . En este caso no importa el valor de
613
         * vbDesplazAIzquierda
614
         *
615
         * @param rVectorDatos Datos
616
         * @param raClases Calses que representan a los intervalos.
617
         * @param rlaIndicesRuptura ?ndices de ruptura.
618
         * @param vdSDAM Desviaci?n standard.
619
         * @param rdGVF Desviaci?n standard de los intervalos.
620
         * @param vlIndiceRupturaActual ?ndice de ruptura actual.
621
         * @param vbDesplazAIzquierda Desplazamiento a la izquierda.
622
         *
623
         * @return True si se ha calculado correctamente.
624
         */
625
        private boolean mbCalcularGVF(ArrayList rVectorDatos,
626
                udtDatosClase[] raClases, int[] rlaIndicesRuptura, double vdSDAM,
627
                double[] rdGVF, int vlIndiceRupturaActual /* As Long = -1*/,
628
                boolean vbDesplazAIzquierda) {
629
                double ldSDCM_aux;
630

    
631
                int i;
632

    
633
                if (vlIndiceRupturaActual == -1) {
634
                        // 'Obtenemos los datos para todas las clases = intervalos
635
                        for (i = 0; i < rlaIndicesRuptura.length; i++) {
636
                                if (i == 0) { // LBound(rlaIndicesRuptura) Then
637

    
638
                                        if (!mbGetDatosClase(rVectorDatos, 0, rlaIndicesRuptura[i],
639
                                                                raClases, i)) {
640
                                                return false;
641
                                        }
642
                                } else {
643
                                        if (!mbGetDatosClase(rVectorDatos,
644
                                                                rlaIndicesRuptura[i - 1] + 1,
645
                                                                rlaIndicesRuptura[i], raClases, i)) {
646
                                                return false;
647
                                        }
648
                                }
649
                        }
650

    
651
                        //'Falta la ?ltima clase
652
                        if (!mbGetDatosClase(rVectorDatos,
653
                                                rlaIndicesRuptura[rlaIndicesRuptura.length - 1] + 1,
654
                                                rVectorDatos.size() - 1, raClases, raClases.length - 1)) {
655
                                return false;
656
                        }
657
                } else {
658
                        i = vlIndiceRupturaActual;
659

    
660
                        //'Hay que determinar para qu? clases debemos volver a recalcular los datos en funci?n del ?ndice de ruptura que estamos modificando
661
                        if (vbDesplazAIzquierda) {
662
                                //  'Recalcular los datos de la clase izquierda
663
                                if (!mbRecalcularDatosClase(raClases, i, rVectorDatos,
664
                                                        rlaIndicesRuptura[i] + 1, vdSDAM, false)) {
665
                                        return false;
666
                                }
667

    
668
                                //  'Recalcular los datos de la clase derecha
669
                                if (!mbRecalcularDatosClase(raClases, i + 1, rVectorDatos,
670
                                                        rlaIndicesRuptura[i] + 1, vdSDAM, true)) {
671
                                        return false;
672
                                }
673
                        } else {
674
                                //  'Recalcular los datos de la clase izquierda
675
                                if (!mbRecalcularDatosClase(raClases, i, rVectorDatos,
676
                                                        rlaIndicesRuptura[i], vdSDAM, true)) {
677
                                        return false;
678
                                }
679

    
680
                                //  'Recalcular los datos de la clase derecha
681
                                if (!mbRecalcularDatosClase(raClases, i + 1, rVectorDatos,
682
                                                        rlaIndicesRuptura[i], vdSDAM, false)) {
683
                                        return false;
684
                                }
685
                        }
686
                }
687

    
688
                ldSDCM_aux = 0;
689

    
690
                for (i = 0; i < raClases.length; i++) { //LBound(raClases) To UBound(raClases)
691
                        ldSDCM_aux = ldSDCM_aux + raClases[i].SDCM;
692
                }
693

    
694
                rdGVF[0] = (vdSDAM - ldSDCM_aux) / vdSDAM;
695

    
696
                return true;
697
        }
698

    
699
        /**
700
         * Devuelve la "SDCM" de un conjunto de datos que vienen almacenados en el
701
         * vector rVectorDatos y que est?n delimitados por vlLimiteInf y
702
         * vlLimiteInf
703
         *
704
         * @param rVectorDatos Datos
705
         * @param vlLimiteInf L?mite inferior.
706
         * @param vlLimiteSup L?mite superior.
707
         * @param rClase Calses que representan a los intervalos.
708
         * @param numClas N?mero de calses.
709
         *
710
         * @return True si se ha calculado correctamente.
711
         */
712
        private boolean mbGetDatosClase(ArrayList rVectorDatos, int vlLimiteInf,
713
                int vlLimiteSup, udtDatosClase[] rClase, int numClas) {
714
                int i;
715

    
716
                if (vlLimiteInf < 0) {
717
                        return false;
718
                }
719

    
720
                if (vlLimiteSup > rVectorDatos.size()) {
721
                        return false;
722
                }
723

    
724
                if (vlLimiteSup < vlLimiteInf) {
725
                        return false;
726
                }
727

    
728
                // 'Inicializamos los datos de la clase
729
                rClase[numClas] = new udtDatosClase();
730

    
731
                //'Hallamos la media de la clase
732
                for (i = vlLimiteInf; i < (vlLimiteSup + 1); i++) {
733
                        rClase[numClas].NumElementos = rClase[numClas].NumElementos +
734
                                ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias;
735

    
736
                        //'rClase.Media = rClase.Media + (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
737
                        rClase[numClas].SumaTotal = rClase[numClas].SumaTotal +
738
                                (((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias);
739

    
740
                        //'rClase.ProductoTotal = rClase.ProductoTotal * (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
741
                        rClase[numClas].SumaCuadradoTotal = rClase[numClas].SumaCuadradoTotal +
742
                                (Math.pow(((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(
743
                                                i)).Coincidencias, 2));
744
                }
745

    
746
                //'rClase.Media = rClase.Media / llTotalElementos
747
                rClase[numClas].Media = rClase[numClas].SumaTotal / rClase[numClas].NumElementos;
748
                rClase[numClas].SDCM = (rClase[numClas].SumaCuadradoTotal) -
749
                        (2 * rClase[numClas].Media * rClase[numClas].SumaTotal) +
750
                        (rClase[numClas].NumElementos * Math.pow(rClase[numClas].Media, 2));
751

    
752
                return true;
753
        }
754

    
755
        /**
756
         * Recalcula los datos de las clases.
757
         *
758
         * @param rClase Clases.
759
         * @param i ?adir ?adir ?adir ?adir indica si a la clase se le a?ade un
760
         *                   elemento (True) o se le quita (False)
761
         * @param rVectorDatos Datos.
762
         * @param vlIndiceElemento es el ?ndice del elemento que se le va a?adir o
763
         *                   a quitar a la clase
764
         * @param vdSDAM desviaci?n standard.
765
         * @param vbA ?adir DOCUMENT ME!
766
         *
767
         * @return True si se ha calculado correctamente.
768
         */
769
        private boolean mbRecalcularDatosClase(udtDatosClase[] rClase, int i,
770
                ArrayList rVectorDatos, int vlIndiceElemento, double vdSDAM,
771
                boolean vbA?adir) {
772
                double ldValor;
773
                long llNumCoincidencias;
774

    
775
                ldValor = ((udtDatosEstudio) rVectorDatos.get(vlIndiceElemento)).Valor;
776
                llNumCoincidencias = ((udtDatosEstudio) rVectorDatos.get(vlIndiceElemento)).Coincidencias;
777

    
778
                if (vbA?adir) {
779
                        //'Actualizamos la suma total
780
                        rClase[i].SumaTotal = rClase[i].SumaTotal +
781
                                (ldValor * llNumCoincidencias);
782

    
783
                        //'Actualizamos la suma de cuadrados total
784
                        rClase[i].SumaCuadradoTotal = rClase[i].SumaCuadradoTotal +
785
                                (Math.pow((ldValor * llNumCoincidencias), 2));
786

    
787
                        //'Actualizamos el producto total
788
                        //'rClase.ProductoTotal = rClase.ProductoTotal * (ldValor * llNumCoincidencias)
789
                        //'Actualizamos el n? de elementos
790
                        rClase[i].NumElementos = rClase[i].NumElementos +
791
                                llNumCoincidencias;
792
                } else {
793
                        //'Actualizamos la suma total
794
                        rClase[i].SumaTotal = rClase[i].SumaTotal -
795
                                (ldValor * llNumCoincidencias);
796

    
797
                        // 'Actualizamos la suma de cuadrados total
798
                        rClase[i].SumaCuadradoTotal = rClase[i].SumaCuadradoTotal -
799
                                (Math.pow((ldValor * llNumCoincidencias), 2));
800

    
801
                        // 'Actualizamos el producto total
802
                        // 'rClase.ProductoTotal = rClase.ProductoTotal / (ldValor * llNumCoincidencias)
803
                        // 'Actualizamos el n? de elementos
804
                        rClase[i].NumElementos = rClase[i].NumElementos -
805
                                llNumCoincidencias;
806
                } // 'If vbA?adir Then
807

    
808
                //'Obtenemos la nueva media
809
                rClase[i].Media = rClase[i].SumaTotal / rClase[i].NumElementos;
810

    
811
                //'Actualizamos la SDCM
812
                rClase[i].SDCM = (rClase[i].SumaCuadradoTotal) -
813
                        (2 * rClase[i].Media * rClase[i].SumaTotal) +
814
                        (rClase[i].NumElementos * Math.pow(rClase[i].Media, 2));
815

    
816
                return true;
817
        }
818

    
819
        /**
820
         * Devuelve el valor de ruptura seg?n el ?ndice que se le pasa como
821
         * par?metro.
822
         *
823
         * @param viIndice ?nidice del valor de ruptura.
824
         *
825
         * @return Valor de ruptura.
826
         */
827
        public double getValorRuptura(int viIndice) {
828
                return mdaValoresRuptura[viIndice];
829
        }
830

    
831
        /**
832
         * Devuelve el valor inicial de cada intervalo
833
         *
834
         * @param index ?ndice del intervalo
835
         *
836
         * @return valor del intervalo.
837
         */
838
        public double getValInit(int index) {
839
                return mdaValInit[index];
840
        }
841

    
842
        /**
843
         * Devuelve el n?mero de intervalos que se pueden representar, no tiene
844
         * porque coincidir con el n?mero de intervalos que se piden.
845
         *
846
         * @return N?mero de intervalos calculados.
847
         */
848
        public int getNumIntervals() {
849
                return miNumIntervalosGenerados;
850
        }
851

    
852
        /**
853
         * Clase para contener los atributos Valor y coincidencias.
854
         *
855
         * @author Vicente Caballero Navarro
856
         */
857
        private class udtDatosEstudio {
858
                private double Valor; // 
859
                private long Coincidencias;
860
        }
861

    
862
        /**
863
         * Clase para contener los atributos: N?mero de Elementos. Media.
864
         * SumaTotal. SumaCuadradoTotal. Desviaci?n standard.
865
         *
866
         * @author Vicente Caballero Navarro
867
         */
868
        private class udtDatosClase {
869
                private long NumElementos; //             'N? total de elementos que hay en la clase
870
                private double Media; //                 'Media de la clase
871
                private double SumaTotal; //              'Suma total de los elementos
872

    
873
                //'ProductoTotal          'Producto total de los elementos '?dar? problemas de desbordamiento?
874
                private double SumaCuadradoTotal; //      'Suma del total de los cuadrados de los elementos
875
                private double SDCM; //                  'Suma de la desviaci?n t?pica de los elementos de la clase respecto de la media de la clase
876
        }
877
}