Statistics
| Revision:

svn-gvsig-desktop / branches / gvSIG_03_SLD / applications / appgvSIG / src / com / iver / cit / gvsig / gui / thememanager / legendmanager / panels / NaturalIntervalGenerator.java @ 2166

History | View | Annotate | Download (28.7 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
import com.hardcode.gdbms.engine.values.FloatValue;
46
import com.hardcode.gdbms.engine.values.IntValue;
47
import com.hardcode.gdbms.engine.values.LongValue;
48
import com.hardcode.gdbms.engine.values.ShortValue;
49
import com.hardcode.gdbms.engine.values.Value;
50

    
51
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
52
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
53

    
54
import java.util.ArrayList;
55

    
56

    
57
/**
58
 * Calcula los intervalos naturales.
59
 *
60
 * @author Vicente Caballero Navarro
61
 */
62
public class NaturalIntervalGenerator {
63
        private AlphanumericData mLayer;
64
        private String msFieldName;
65
        private int miNumIntervalosSolicitados;
66
        private int miNumIntervalosGenerados;
67
        private double[] mdaValoresRuptura;
68
        private 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(AlphanumericData layer, String field,
78
                int numIntervals) {
79
                mLayer = layer;
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
        private 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 com.iver.cit.gvsig.fmap.DriverException, DriverException {
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
                        return false;
261
                }
262

    
263
                ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
264

    
265
                boolean lbMoverADerecha;
266
                boolean lbMoverAIzquierda;
267
                boolean lbIntentarDesplazamiento;
268
                int llIndiceRupturaOriginal;
269

    
270
                long k;
271
                double ldGVFentrepasadas;
272

    
273
                ldGVFentrepasadas = ldUltimaGVF[0];
274

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

    
284
                                //'Hay que decidir hacia donde hay que desplazar el ?ndice de ruptura
285
                                //'Probamos moviendo a derecha (si se puede)
286
                                lbIntentarDesplazamiento = false;
287

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

    
298
                                if (lbIntentarDesplazamiento) {
299
                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
300

    
301
                                        if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
302
                                                                llaIndicesRupturas, ldSDAM[0], ldNuevaGVF, i,
303
                                                                false)) {
304
                                                return false;
305
                                        }
306

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

    
317
                                lbIntentarDesplazamiento = false;
318

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

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

    
334
                                if (lbIntentarDesplazamiento) {
335
                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1;
336

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

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

    
353
                                lbIntentarDesplazamiento = false;
354

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

    
359
                                        boolean exit = false;
360

    
361
                                        while (!exit) {
362
                                                llIndiceRupturaOriginal = llaIndicesRupturas[i];
363

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

    
376
                                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
377
                                                } else { //'If lbMoverAIzquierda Then
378

    
379
                                                        if (i == 0) { //LBound(llaIndicesRupturas) Then
380

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

    
391
                                                        llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1; //////////////////
392
                                                } //'If lbMoverADerecha Then
393

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

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

    
413
                        if (ldUltimaGVF[0] <= ldGVFentrepasadas) {
414
                                i = 101;
415
                        }
416

    
417
                        ldGVFentrepasadas = ldUltimaGVF[0];
418
                }
419

    
420
                //   'A partir de aqu? ya no se puede cancelar nada
421
                mdaValoresRuptura = new double[llaIndicesRupturas.length];
422
                mdaValInit = new double[llaIndicesRupturas.length];
423

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

    
427
                        if ((llaIndicesRupturas[i] + 1) < lVectorDatos.size()) {
428
                                mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i] +
429
                                                1)).Valor;
430
                        } else {
431
                                mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i])).Valor;
432
                        }
433

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

    
440
                miNumIntervalosGenerados = mdaValoresRuptura.length + 2;
441

    
442
                ldaSDCM_Validos = null;
443
                ldaSDCM_Parciales = null;
444
                lVectorDatos = null;
445

    
446
                return true;
447
        }
448

    
449
        /**
450
         * DOCUMENT ME!
451
         *
452
         * @param array DOCUMENT ME!
453
         *
454
         * @return DOCUMENT ME!
455
         */
456
        private udtDatosClase[] getArray(udtDatosClase[] array) {
457
                udtDatosClase[] aux = new udtDatosClase[array.length];
458

    
459
                for (int i = 0; i < array.length; i++) {
460
                        aux[i] = new udtDatosClase();
461
                        aux[i].Media = array[i].Media;
462
                        aux[i].NumElementos = array[i].NumElementos;
463
                        aux[i].SDCM = array[i].SDCM;
464
                        aux[i].SumaCuadradoTotal = array[i].SumaCuadradoTotal;
465
                        aux[i].SumaTotal = array[i].SumaTotal;
466
                }
467

    
468
                return aux;
469
        }
470

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

    
485
                double rdSDAM = 0;
486

    
487
                for (i = 0; i < rVectorDatos.size(); i++) { // LBound(rVectorDatos) To UBound(rVectorDatos)
488
                        rdSDAM = rdSDAM +
489
                                (Math.pow((((udtDatosEstudio) rVectorDatos.get(i)).Valor -
490
                                        vdMedia), 2) * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias);
491
                }
492

    
493
                return rdSDAM;
494
        }
495

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

    
513
                int i;
514
                long llRecordCount;
515

    
516
                int[] llIndice = new int[1];
517
                boolean[] lbNuevoElemento = new boolean[1];
518
                int j;
519

    
520
                SelectableDataSource sds = mLayer.getRecordset();
521
                llRecordCount = sds.getRowCount();
522

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

    
532
                        return false;
533
                }
534

    
535
                // 'Nos cuidamos de recorrer todos los registros sin consultar la propiedad EOF del recordset
536
                for (i = 0; i < llRecordCount; i++) {
537
                        ldValor =  getValue(sds.getFieldValue(i,
538
                                        sds.getFieldIndexByName(msFieldName))); //.Fields(msFieldName).Value;
539

    
540
                        rdMediaTotal[0] = rdMediaTotal[0] + ldValor;
541

    
542
                        //       'Hay que insertar el valor en la posici?n adecuada. Para ello hacemos una b?squeda binaria
543
                        if (!mbObtenerPosicionEnVector(rVectorDatos, ldValor, llIndice,
544
                                                lbNuevoElemento)) {
545
                                return false;
546
                        }
547

    
548
                        if (!lbNuevoElemento[0]) {
549
                                if ((llIndice[0] < 0) || (llIndice[0] > rVectorDatos.size())) {
550
                                        System.out.println("?ndice incorrecto!");
551

    
552
                                        return false;
553
                                }
554

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

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

    
568
                rdMediaTotal[0] = rdMediaTotal[0] / llRecordCount;
569

    
570
                return true;
571
        }
572

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

    
589
                return true;
590
        }
591

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

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

    
636
                int i;
637

    
638
                if (vlIndiceRupturaActual == -1) {
639
                        // 'Obtenemos los datos para todas las clases = intervalos
640
                        for (i = 0; i < rlaIndicesRuptura.length; i++) {
641
                                if (i == 0) { // LBound(rlaIndicesRuptura) Then
642

    
643
                                        if (!mbGetDatosClase(rVectorDatos, 0, rlaIndicesRuptura[i],
644
                                                                raClases, i)) {
645
                                                return false;
646
                                        }
647
                                } else {
648
                                        if (!mbGetDatosClase(rVectorDatos,
649
                                                                rlaIndicesRuptura[i - 1] + 1,
650
                                                                rlaIndicesRuptura[i], raClases, i)) {
651
                                                return false;
652
                                        }
653
                                }
654
                        }
655

    
656
                        //'Falta la ?ltima clase
657
                        if (!mbGetDatosClase(rVectorDatos,
658
                                                rlaIndicesRuptura[rlaIndicesRuptura.length - 1] + 1,
659
                                                rVectorDatos.size() - 1, raClases, raClases.length - 1)) {
660
                                return false;
661
                        }
662
                } else {
663
                        i = vlIndiceRupturaActual;
664

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

    
673
                                //  'Recalcular los datos de la clase derecha
674
                                if (!mbRecalcularDatosClase(raClases, i + 1, rVectorDatos,
675
                                                        rlaIndicesRuptura[i] + 1, vdSDAM, true)) {
676
                                        return false;
677
                                }
678
                        } else {
679
                                //  'Recalcular los datos de la clase izquierda
680
                                if (!mbRecalcularDatosClase(raClases, i, rVectorDatos,
681
                                                        rlaIndicesRuptura[i], vdSDAM, true)) {
682
                                        return false;
683
                                }
684

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

    
693
                ldSDCM_aux = 0;
694

    
695
                for (i = 0; i < raClases.length; i++) { //LBound(raClases) To UBound(raClases)
696
                        ldSDCM_aux = ldSDCM_aux + raClases[i].SDCM;
697
                }
698

    
699
                rdGVF[0] = (vdSDAM - ldSDCM_aux) / vdSDAM;
700

    
701
                return true;
702
        }
703

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

    
721
                if (vlLimiteInf < 0) {
722
                        return false;
723
                }
724

    
725
                if (vlLimiteSup > rVectorDatos.size()) {
726
                        return false;
727
                }
728

    
729
                if (vlLimiteSup < vlLimiteInf) {
730
                        return false;
731
                }
732

    
733
                // 'Inicializamos los datos de la clase
734
                rClase[numClas] = new udtDatosClase();
735

    
736
                //'Hallamos la media de la clase
737
                for (i = vlLimiteInf; i < (vlLimiteSup + 1); i++) {
738
                        rClase[numClas].NumElementos = rClase[numClas].NumElementos +
739
                                ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias;
740

    
741
                        //'rClase.Media = rClase.Media + (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
742
                        rClase[numClas].SumaTotal = rClase[numClas].SumaTotal +
743
                                (((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias);
744

    
745
                        //'rClase.ProductoTotal = rClase.ProductoTotal * (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
746
                        rClase[numClas].SumaCuadradoTotal = rClase[numClas].SumaCuadradoTotal +
747
                                (Math.pow(((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(
748
                                                i)).Coincidencias, 2));
749
                }
750

    
751
                //'rClase.Media = rClase.Media / llTotalElementos
752
                rClase[numClas].Media = rClase[numClas].SumaTotal / rClase[numClas].NumElementos;
753
                rClase[numClas].SDCM = (rClase[numClas].SumaCuadradoTotal) -
754
                        (2 * rClase[numClas].Media * rClase[numClas].SumaTotal) +
755
                        (rClase[numClas].NumElementos * Math.pow(rClase[numClas].Media, 2));
756

    
757
                return true;
758
        }
759

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

    
780
                ldValor = ((udtDatosEstudio) rVectorDatos.get(vlIndiceElemento)).Valor;
781
                llNumCoincidencias = ((udtDatosEstudio) rVectorDatos.get(vlIndiceElemento)).Coincidencias;
782

    
783
                if (vbA?adir) {
784
                        //'Actualizamos la suma total
785
                        rClase[i].SumaTotal = rClase[i].SumaTotal +
786
                                (ldValor * llNumCoincidencias);
787

    
788
                        //'Actualizamos la suma de cuadrados total
789
                        rClase[i].SumaCuadradoTotal = rClase[i].SumaCuadradoTotal +
790
                                (Math.pow((ldValor * llNumCoincidencias), 2));
791

    
792
                        //'Actualizamos el producto total
793
                        //'rClase.ProductoTotal = rClase.ProductoTotal * (ldValor * llNumCoincidencias)
794
                        //'Actualizamos el n? de elementos
795
                        rClase[i].NumElementos = rClase[i].NumElementos +
796
                                llNumCoincidencias;
797
                } else {
798
                        //'Actualizamos la suma total
799
                        rClase[i].SumaTotal = rClase[i].SumaTotal -
800
                                (ldValor * llNumCoincidencias);
801

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

    
806
                        // 'Actualizamos el producto total
807
                        // 'rClase.ProductoTotal = rClase.ProductoTotal / (ldValor * llNumCoincidencias)
808
                        // 'Actualizamos el n? de elementos
809
                        rClase[i].NumElementos = rClase[i].NumElementos -
810
                                llNumCoincidencias;
811
                } // 'If vbA?adir Then
812

    
813
                //'Obtenemos la nueva media
814
                rClase[i].Media = rClase[i].SumaTotal / rClase[i].NumElementos;
815

    
816
                //'Actualizamos la SDCM
817
                rClase[i].SDCM = (rClase[i].SumaCuadradoTotal) -
818
                        (2 * rClase[i].Media * rClase[i].SumaTotal) +
819
                        (rClase[i].NumElementos * Math.pow(rClase[i].Media, 2));
820

    
821
                return true;
822
        }
823

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

    
836
        /**
837
         * Devuelve el valor inicial de cada intervalo
838
         *
839
         * @param index ?ndice del intervalo
840
         *
841
         * @return valor del intervalo.
842
         */
843
        public double getValInit(int index) {
844
                return mdaValInit[index];
845
        }
846

    
847
        /**
848
         * Devuelve el n?mero de intervalos que se pueden representar, no tiene
849
         * porque coincidir con el n?mero de intervalos que se piden.
850
         *
851
         * @return N?mero de intervalos calculados.
852
         */
853
        public int getNumIntervals() {
854
                return miNumIntervalosGenerados;
855
        }
856

    
857
        /**
858
         * Clase para contener los atributos Valor y coincidencias.
859
         *
860
         * @author Vicente Caballero Navarro
861
         */
862
        private class udtDatosEstudio {
863
                private double Valor; // 
864
                private long Coincidencias;
865
        }
866

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

    
878
                //'ProductoTotal          'Producto total de los elementos '?dar? problemas de desbordamiento?
879
                private double SumaCuadradoTotal; //      'Suma del total de los cuadrados de los elementos
880
                private double SDCM; //                  'Suma de la desviaci?n t?pica de los elementos de la clase respecto de la media de la clase
881
        }
882
        /**
883
         * Devuelve el valor en un double del Value que se pasa como par?metro.
884
         *
885
         * @param value Value.
886
         *
887
         * @return valor.
888
         */
889
        private double getValue(Value value) {
890
                if (value instanceof IntValue) {
891
                        return ((IntValue) value).intValue();
892
                } else if (value instanceof LongValue) {
893
                        return ((LongValue) value).longValue();
894
                } else if (value instanceof FloatValue) {
895
                        return ((FloatValue) value).floatValue();
896
                } else if (value instanceof ShortValue) {
897
                        return ((ShortValue) value).shortValue();
898
                }
899

    
900
                return ((DoubleValue) value).doubleValue();
901
        }
902
}