Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / rendering / NaturalIntervalGenerator.java @ 25766

History | View | Annotate | Download (29.6 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.fmap.rendering;
42

    
43
import java.util.ArrayList;
44

    
45
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
46
import com.hardcode.gdbms.engine.data.DataSource;
47
import com.hardcode.gdbms.engine.data.driver.DriverException;
48
import com.hardcode.gdbms.engine.values.DoubleValue;
49
import com.hardcode.gdbms.engine.values.FloatValue;
50
import com.hardcode.gdbms.engine.values.IntValue;
51
import com.hardcode.gdbms.engine.values.LongValue;
52
import com.hardcode.gdbms.engine.values.NullValue;
53
import com.hardcode.gdbms.engine.values.ShortValue;
54
import com.hardcode.gdbms.engine.values.Value;
55

    
56

    
57
/**
58
 * Calcula los intervalos naturales.
59
 *
60
 * @author Vicente Caballero Navarro
61
 */
62
public class NaturalIntervalGenerator {
63
        protected DataSource ds;
64
        protected String msFieldName;
65
        protected int miNumIntervalosSolicitados;
66
        protected int miNumIntervalosGenerados;
67
        protected double[] mdaValoresRuptura;
68
        protected double[] mdaValInit;
69

    
70
        /**
71
         * Crea un nuevo IntervalGenerator.
72
         *
73
         * @param layer AlphanumericData
74
         * @param field Nombre del campo.
75
         * @param numIntervals N�mero de intervalos.
76
         */
77
        public NaturalIntervalGenerator(DataSource recordSet, String field,
78
                int numIntervals) {
79
                ds = recordSet;
80
                msFieldName = field;
81
                miNumIntervalosSolicitados = numIntervals;
82
        }
83

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

    
108
                double ldValorComparacion;
109

    
110
                rbNuevoElemento[0] = false;
111
                rlIndiceCorrespondiente[0] = -1;
112

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

    
119
                                return true;
120
                        }
121
                }
122

    
123
                llIndiceIzq = 0;
124
                llIndiceDer = rVectorDatos.size() - 1;
125
                llMedio = (llIndiceIzq + llIndiceDer) / 2; //'Divisi�n entera!
126

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

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

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

    
143
                                //        'Si el valor de comparaci�n coincide con el valor a insertar
144
                        } else if (vdValorAInsertar == ldValorComparacion) {
145
                                rlIndiceCorrespondiente[0] = llMedio;
146
                                rbNuevoElemento[0] = false;
147

    
148
                                return true;
149
                        }
150
                }
151

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

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

    
165
                if (vdValorAInsertar > ldValorComparacion) {
166
                        rlIndiceCorrespondiente[0] = llMedio + 1;
167
                } else {
168
                        rlIndiceCorrespondiente[0] = llMedio;
169
                }
170

    
171
                return true;
172
        }
173

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

    
188
                int[] llaIndicesRupturas;
189

    
190
                double[] ldUltimaGVF = new double[1];
191
                double[] ldNuevaGVF = new double[1];
192

    
193
                int i;
194
                int liNumClasesReales;
195
                int llNumElementosPorClase;
196

    
197
                //    'Obtener los datos a estudiar ordenados ascendentemente y obtener la media total
198
                //ReDim lVectorDatos(0)
199
                lVectorDatos = new ArrayList();
200

    
201
                lVectorDatos.add(new udtDatosEstudio());
202

    
203
                if (!mbObtenerDatos(lVectorDatos, ldMediaTotal)) {
204
                        return false; //SalidaSinMensaje
205
                }
206

    
207
                System.out.println("Analizando datos ...");
208

    
209
                /// Call gEstablecerDescripcionProceso("Analizando datos ...", False)
210
                //  'Calcular la suma de las desviaciones t�picas del total de los datos respecto de la media total
211
                ldSDAM[0] = mbGetSumSquaredDeviationArrayMean(lVectorDatos,
212
                                ldMediaTotal[0]);
213

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

    
222
                        return true;
223
                }
224

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

    
233
                //  'Establecemos las clases iniciales especificando unos �ndices de ruptura en ppo. equidistantes
234
                llaIndicesRupturas = new int[liNumClasesReales - 1];
235
                llNumElementosPorClase = (lVectorDatos.size()) / liNumClasesReales;
236

    
237
                for (i = 0; i < llaIndicesRupturas.length; i++) {
238
                        if (i == 0) {
239
                                llaIndicesRupturas[i] = llNumElementosPorClase - 1;
240
                        } else {
241
                                llaIndicesRupturas[i] = llaIndicesRupturas[i - 1] +
242
                                        llNumElementosPorClase;
243
                        }
244
                }
245

    
246
                udtDatosClase[] ldaSDCM_Parciales = new udtDatosClase[llaIndicesRupturas.length +
247
                        1];
248
                udtDatosClase[] ldaSDCM_Validos = new udtDatosClase[llaIndicesRupturas.length +
249
                        1];
250

    
251
                ///ReDim ldaSDCM_Parciales(UBound(llaIndicesRupturas()) + 1)
252
                ///ReDim ldaSDCM_Validos(UBound(ldaSDCM_Parciales()) + 1)
253
                if (llaIndicesRupturas.length == 0) {
254
                        return true;
255
                }
256

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

    
266
                ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
267

    
268
                boolean lbMoverADerecha;
269
                boolean lbMoverAIzquierda;
270
                boolean lbIntentarDesplazamiento;
271
                int llIndiceRupturaOriginal;
272

    
273
                long k;
274
                double ldGVFentrepasadas;
275

    
276
                ldGVFentrepasadas = ldUltimaGVF[0];
277

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

    
287
                                //'Hay que decidir hacia donde hay que desplazar el �ndice de ruptura
288
                                //'Probamos moviendo a derecha (si se puede)
289
                                lbIntentarDesplazamiento = false;
290

    
291
                                if (i == (llaIndicesRupturas.length - 1)) {
292
                                        if ((llaIndicesRupturas[i] + 1) < lVectorDatos.size()) {
293
                                                lbIntentarDesplazamiento = true;
294
                                        }
295
                                } else {
296
                                        if ((llaIndicesRupturas[i] + 1) < llaIndicesRupturas[i + 1]) {
297
                                                lbIntentarDesplazamiento = true;
298
                                        } //'If (llaIndicesRupturas(i) + 1) < llaIndicesRupturas(i + 1) Then
299
                                } //'If i = UBound(llaIndicesRupturas) Then
300

    
301
                                if (lbIntentarDesplazamiento) {
302
                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
303

    
304
                                        if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
305
                                                                llaIndicesRupturas, ldSDAM[0], ldNuevaGVF, i,
306
                                                                false)) {
307
                                                return false;
308
                                        }
309

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

    
320
                                lbIntentarDesplazamiento = false;
321

    
322
                                //'Probamos moviendo a izquierda (si se puede y no estamos moviendo ya a derechas)
323
                                if (!lbMoverADerecha) {
324
                                        if (i == 0) { //LBound(llaIndicesRupturas) Then
325

    
326
                                                if ((llaIndicesRupturas[i] - 1) >= 0) { //LBound(lVectorDatos()) Then
327
                                                        lbIntentarDesplazamiento = true;
328
                                                } //'If (llaIndicesRupturas(i) - 1) >= LBound(lVectorDatos()) Then
329
                                        } else {
330
                                                if ((llaIndicesRupturas[i] - 1) > llaIndicesRupturas[i -
331
                                                                1]) {
332
                                                        lbIntentarDesplazamiento = true;
333
                                                } //'If (llaIndicesRupturas(i) - 1) > llaIndicesRupturas(i - 1) Then
334
                                        } //'If i = LBound(llaIndicesRupturas) Then
335
                                } //'If Not lbMoverADerecha Then
336

    
337
                                if (lbIntentarDesplazamiento) {
338
                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1;
339

    
340
                                        if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
341
                                                                llaIndicesRupturas, ldSDAM[0], ldNuevaGVF, i,
342
                                                                true)) {
343
                                                return false;
344
                                        }
345

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

    
356
                                lbIntentarDesplazamiento = false;
357

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

    
362
                                        boolean exit = false;
363

    
364
                                        while (!exit) {
365
                                                llIndiceRupturaOriginal = llaIndicesRupturas[i];
366

    
367
                                                if (lbMoverADerecha) {
368
                                                        if (i == (llaIndicesRupturas.length - 1)) {
369
                                                                if ((llaIndicesRupturas[i] + 1) >= lVectorDatos.size()) {
370
                                                                        exit = true;
371
                                                                }
372
                                                        } else {
373
                                                                if ((llaIndicesRupturas[i] + 1) >= llaIndicesRupturas[i +
374
                                                                                1]) {
375
                                                                        exit = true;
376
                                                                }
377
                                                        } //'If i = UBound(llaIndicesRupturas) Then
378

    
379
                                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
380
                                                } else { //'If lbMoverAIzquierda Then
381

    
382
                                                        if (i == 0) { //LBound(llaIndicesRupturas) Then
383

    
384
                                                                if ((llaIndicesRupturas[i] - 1) < 0) { //LBound(lVectorDatos()) Then Exit Do
385
                                                                        exit = true;
386
                                                                }
387
                                                        } else {
388
                                                                if ((llaIndicesRupturas[i] - 1) <= llaIndicesRupturas[i -
389
                                                                                1]) {
390
                                                                        exit = true;
391
                                                                }
392
                                                        } //'If i = LBound(llaIndicesRupturas) Then
393

    
394
                                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1; //////////////////
395
                                                } //'If lbMoverADerecha Then
396

    
397
                                                if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
398
                                                                        llaIndicesRupturas, ldSDAM[0], ldNuevaGVF,
399
                                                                        i, lbMoverAIzquierda)) {
400
                                                        return false;
401
                                                }
402

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

    
416
                        if (ldUltimaGVF[0] <= ldGVFentrepasadas) {
417
                                i = 101;
418
                        }
419

    
420
                        ldGVFentrepasadas = ldUltimaGVF[0];
421
                }
422

    
423
                //   'A partir de aqu� ya no se puede cancelar nada
424
                mdaValoresRuptura = new double[llaIndicesRupturas.length];
425
                mdaValInit = new double[llaIndicesRupturas.length];
426

    
427
                for (i = 0; i < mdaValoresRuptura.length; i++) { // LBound(mdaValoresRuptura) To UBound(mdaValoresRuptura)
428
                        if (llaIndicesRupturas[i]==-1)llaIndicesRupturas[i]=1;
429
                        if (llaIndicesRupturas[i]>lVectorDatos.size()-1)llaIndicesRupturas[i]=lVectorDatos.size()-1;
430
                        mdaValoresRuptura[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i])).Valor;
431

    
432
                        if ((llaIndicesRupturas[i] + 1) < lVectorDatos.size()) {
433
                                mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i] +
434
                                                1)).Valor;
435
                        } else {
436
                                mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i])).Valor;
437
                        }
438

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

    
445
                miNumIntervalosGenerados = mdaValoresRuptura.length + 2;
446

    
447
                ldaSDCM_Validos = null;
448
                ldaSDCM_Parciales = null;
449
                lVectorDatos = null;
450

    
451
                return true;
452
        }
453

    
454
        /**
455
         * DOCUMENT ME!
456
         *
457
         * @param array DOCUMENT ME!
458
         *
459
         * @return DOCUMENT ME!
460
         */
461
        private udtDatosClase[] getArray(udtDatosClase[] array) {
462
                udtDatosClase[] aux = new udtDatosClase[array.length];
463

    
464
                for (int i = 0; i < array.length; i++) {
465
                        aux[i] = new udtDatosClase();
466
                        aux[i].Media = array[i].Media;
467
                        aux[i].NumElementos = array[i].NumElementos;
468
                        aux[i].SDCM = array[i].SDCM;
469
                        aux[i].SumaCuadradoTotal = array[i].SumaCuadradoTotal;
470
                        aux[i].SumaTotal = array[i].SumaTotal;
471
                }
472

    
473
                return aux;
474
        }
475

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

    
490
                double rdSDAM = 0;
491

    
492
                for (i = 0; i < rVectorDatos.size(); i++) { // LBound(rVectorDatos) To UBound(rVectorDatos)
493
                        rdSDAM = rdSDAM +
494
                                (Math.pow((((udtDatosEstudio) rVectorDatos.get(i)).Valor -
495
                                        vdMedia), 2) * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias);
496
                }
497

    
498
                return rdSDAM;
499
        }
500

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

    
518
                int i;
519
                long llRecordCount;
520

    
521
                int[] llIndice = new int[1];
522
                boolean[] lbNuevoElemento = new boolean[1];
523
                //int j;
524

    
525
                llRecordCount = ds.getRowCount();
526

    
527
                if (!gbExisteCampoEnRegistro(ds, msFieldName)) {
528
                        if (msFieldName == "") {
529
                                System.out.println(
530
                                        "No se ha establecido el nombre del campo origen!");
531
                        } else {
532
                                System.out.println("El campo '" + msFieldName +
533
                                        "' no pertence a la capa!");
534
                        }
535

    
536
                        return false;
537
                }
538

    
539
                // 'Nos cuidamos de recorrer todos los registros sin consultar la propiedad EOF del recordset
540
                for (i = 0; i < llRecordCount; i++) {
541
                        try{
542
                                ldValor =  getValue(ds.getFieldValue(i,
543
                                                        ds.getFieldIndexByName(msFieldName)));
544
                        }catch (Exception e) {
545
                                llRecordCount--;
546
                                continue;
547
                        }
548
                        rdMediaTotal[0] = rdMediaTotal[0] + ldValor;
549

    
550
                        //       'Hay que insertar el valor en la posici�n adecuada. Para ello hacemos una b�squeda binaria
551
                        if (!mbObtenerPosicionEnVector(rVectorDatos, ldValor, llIndice,
552
                                                lbNuevoElemento)) {
553
                                return false;
554
                        }
555

    
556
                        if (!lbNuevoElemento[0]) {
557
                                if ((llIndice[0] < 0) || (llIndice[0] > rVectorDatos.size())) {
558
                                        System.out.println("�ndice incorrecto!");
559

    
560
                                        return false;
561
                                }
562

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

    
565
                                //'Incrementamos el n� de coincidencias y damos el valor por insertado
566
                                ((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Coincidencias = ((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Coincidencias +
567
                                        1;
568
                        } else {
569
                                udtDatosEstudio udt = new udtDatosEstudio();
570
                                udt.Valor = ldValor;
571
                                udt.Coincidencias = 1;
572
                                rVectorDatos.add(llIndice[0], udt);
573
                        }
574
                }
575

    
576
                rdMediaTotal[0] = rdMediaTotal[0] / llRecordCount;
577

    
578
                return true;
579
        }
580

    
581
        /**
582
         * Devuelve true si existe el campo en el registro.
583
         *
584
         * @param recordset Recordset.
585
         * @param msFieldName2 Nombre del campo.
586
         *
587
         * @return True si existe el campo.
588
         * @throws ReadDriverException
589
         *
590
         */
591
        private boolean gbExisteCampoEnRegistro(DataSource recordset,
592
                String msFieldName2) throws ReadDriverException  {
593
                if (recordset.getFieldIndexByName(msFieldName2) == -1) {
594
                        return false;
595
                }
596

    
597
                return true;
598
        }
599

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

    
644
                int i;
645

    
646
                if (vlIndiceRupturaActual == -1) {
647
                        // 'Obtenemos los datos para todas las clases = intervalos
648
                        for (i = 0; i < rlaIndicesRuptura.length; i++) {
649
                                if (i == 0) { // LBound(rlaIndicesRuptura) Then
650

    
651
                                        if (!mbGetDatosClase(rVectorDatos, 0, rlaIndicesRuptura[i],
652
                                                                raClases, i)) {
653
                                                return false;
654
                                        }
655
                                } else {
656
                                        if (!mbGetDatosClase(rVectorDatos,
657
                                                                rlaIndicesRuptura[i - 1] + 1,
658
                                                                rlaIndicesRuptura[i], raClases, i)) {
659
                                                return false;
660
                                        }
661
                                }
662
                        }
663

    
664
                        //'Falta la �ltima clase
665
                        if (!mbGetDatosClase(rVectorDatos,
666
                                                rlaIndicesRuptura[rlaIndicesRuptura.length - 1] + 1,
667
                                                rVectorDatos.size() - 1, raClases, raClases.length - 1)) {
668
                                return false;
669
                        }
670
                } else {
671
                        i = vlIndiceRupturaActual;
672

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

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

    
693
                                //  'Recalcular los datos de la clase derecha
694
                                if (!mbRecalcularDatosClase(raClases, i + 1, rVectorDatos,
695
                                                        rlaIndicesRuptura[i], vdSDAM, false)) {
696
                                        return false;
697
                                }
698
                        }
699
                }
700

    
701
                ldSDCM_aux = 0;
702

    
703
                for (i = 0; i < raClases.length; i++) { //LBound(raClases) To UBound(raClases)
704
                        ldSDCM_aux = ldSDCM_aux + raClases[i].SDCM;
705
                }
706

    
707
                rdGVF[0] = (vdSDAM - ldSDCM_aux) / vdSDAM;
708
                //System.out.println(ldSDCM_aux);
709

    
710
                return true;
711
        }
712

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

    
730
                if (vlLimiteInf < 0) {
731
                        return false;
732
                }
733

    
734
                if (vlLimiteSup > rVectorDatos.size()) {
735
                        return false;
736
                }
737

    
738
                if (vlLimiteSup < vlLimiteInf) {
739
                        return false;
740
                }
741

    
742
                // 'Inicializamos los datos de la clase
743
                rClase[numClas] = new udtDatosClase();
744

    
745
                //'Hallamos la media de la clase
746
                for (i = vlLimiteInf; i < (vlLimiteSup + 1); i++) {
747
                        rClase[numClas].NumElementos = rClase[numClas].NumElementos +
748
                                ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias;
749

    
750
                        //'rClase.Media = rClase.Media + (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
751
                        rClase[numClas].SumaTotal = rClase[numClas].SumaTotal +
752
                                (((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias);
753

    
754
                        //'rClase.ProductoTotal = rClase.ProductoTotal * (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
755
                        rClase[numClas].SumaCuadradoTotal = rClase[numClas].SumaCuadradoTotal +
756
                                (Math.pow(((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(
757
                                                i)).Coincidencias, 2));
758
                }
759

    
760
                //'rClase.Media = rClase.Media / llTotalElementos
761
                rClase[numClas].Media = rClase[numClas].SumaTotal / rClase[numClas].NumElementos;
762
                rClase[numClas].SDCM = (rClase[numClas].SumaCuadradoTotal) -
763
                        (2 * rClase[numClas].Media * rClase[numClas].SumaTotal) +
764
                        (rClase[numClas].NumElementos * Math.pow(rClase[numClas].Media, 2));
765
                /*if (new Double(rClase[numClas].SDCM).isNaN()){
766
                        System.out.println(rClase[numClas].SDCM);
767
                }*/
768
                return true;
769
        }
770

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

    
795
                if (vbAnyadir) {
796
                        //'Actualizamos la suma total
797
                        rClase[i].SumaTotal = rClase[i].SumaTotal +
798
                                (ldValor * llNumCoincidencias);
799

    
800
                        //'Actualizamos la suma de cuadrados total
801
                        rClase[i].SumaCuadradoTotal = rClase[i].SumaCuadradoTotal +
802
                                (Math.pow((ldValor * llNumCoincidencias), 2));
803

    
804
                        //'Actualizamos el producto total
805
                        //'rClase.ProductoTotal = rClase.ProductoTotal * (ldValor * llNumCoincidencias)
806
                        //'Actualizamos el n� de elementos
807
                        rClase[i].NumElementos = rClase[i].NumElementos +
808
                                llNumCoincidencias;
809
                } else {
810
                        //'Actualizamos la suma total
811
                        rClase[i].SumaTotal = rClase[i].SumaTotal -
812
                                (ldValor * llNumCoincidencias);
813

    
814
                        // 'Actualizamos la suma de cuadrados total
815
                        rClase[i].SumaCuadradoTotal = rClase[i].SumaCuadradoTotal -
816
                                (Math.pow((ldValor * llNumCoincidencias), 2));
817

    
818
                        // 'Actualizamos el producto total
819
                        // 'rClase.ProductoTotal = rClase.ProductoTotal / (ldValor * llNumCoincidencias)
820
                        // 'Actualizamos el n� de elementos
821
                        rClase[i].NumElementos = rClase[i].NumElementos -
822
                                llNumCoincidencias;
823
                } // 'If vbA�adir Then
824
                if (rClase[i].NumElementos<=0)rClase[i].NumElementos=1;
825
                //'Obtenemos la nueva media
826
                rClase[i].Media = rClase[i].SumaTotal / rClase[i].NumElementos;
827

    
828
                //'Actualizamos la SDCM
829
                rClase[i].SDCM = (rClase[i].SumaCuadradoTotal) -
830
                        (2 * rClase[i].Media * rClase[i].SumaTotal) +
831
                        (rClase[i].NumElementos * Math.pow(rClase[i].Media, 2));
832

    
833
}catch (Exception e) {
834
        return false;
835
}
836
                return true;
837
        }
838

    
839
        /**
840
         * Devuelve el valor de ruptura seg�n el �ndice que se le pasa como
841
         * par�metro.
842
         *
843
         * @param viIndice �nidice del valor de ruptura.
844
         *
845
         * @return Valor de ruptura.
846
         */
847
        public double getValorRuptura(int viIndice) {
848
                return mdaValoresRuptura[viIndice];
849
        }
850

    
851
        /**
852
         * Devuelve el valor inicial de cada intervalo
853
         *
854
         * @param index �ndice del intervalo
855
         *
856
         * @return valor del intervalo.
857
         */
858
        public double getValInit(int index) {
859
                return mdaValInit[index];
860
        }
861

    
862
        /**
863
         * Devuelve el n�mero de intervalos que se pueden representar, no tiene
864
         * porque coincidir con el n�mero de intervalos que se piden.
865
         *
866
         * @return N�mero de intervalos calculados.
867
         */
868
        public int getNumIntervals() {
869
                return miNumIntervalosGenerados;
870
        }
871

    
872
        /**
873
         * Clase para contener los atributos Valor y coincidencias.
874
         *
875
         * @author Vicente Caballero Navarro
876
         */
877
        public class udtDatosEstudio {
878
                public double Valor; //
879
                public long Coincidencias;
880
        }
881

    
882
        /**
883
         * Clase para contener los atributos: N�mero de Elementos. Media.
884
         * SumaTotal. SumaCuadradoTotal. Desviaci�n standard.
885
         *
886
         * @author Vicente Caballero Navarro
887
         */
888
        public class udtDatosClase {
889
                public long NumElementos; //             'N� total de elementos que hay en la clase
890
                public double Media; //                 'Media de la clase
891
                public double SumaTotal; //              'Suma total de los elementos
892

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

    
918
                return ((DoubleValue) value).doubleValue();
919
        }
920
}