Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_mapcontext / src / org / gvsig / fmap / mapcontext / rendering / legend / AbstractIntervalLegend.java @ 28092

History | View | Annotate | Download (16.6 KB)

1 21200 vcaballero
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 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
42
/* CVS MESSAGES:
43
*
44
* $Id: AbstractIntervalLegend.java 21144 2008-06-03 15:47:31Z vcaballero $
45
* $Log$
46
* Revision 1.12  2007-09-19 16:25:39  jaume
47
* ReadExpansionFileException removed from this context and removed unnecessary imports
48
*
49
* Revision 1.11  2007/09/10 15:47:11  jaume
50
* *** empty log message ***
51
*
52
* Revision 1.10  2007/08/03 09:22:08  jaume
53
* refactored class names
54
*
55
* Revision 1.9  2007/08/02 10:19:03  jvidal
56
* implements IPersistance
57
*
58
* Revision 1.8  2007/08/01 11:45:59  jaume
59
* passing general tests (drawing test yet missing)
60
*
61
* Revision 1.7  2007/05/28 15:36:42  jaume
62
* *** empty log message ***
63
*
64
* Revision 1.6  2007/05/17 09:32:06  jaume
65
* *** empty log message ***
66
*
67
* Revision 1.5  2007/05/10 14:13:36  jaume
68
* *** empty log message ***
69
*
70
* Revision 1.4  2007/05/10 09:44:08  jaume
71
* Refactored legend interface names
72
*
73
* Revision 1.3  2007/03/27 09:28:40  jaume
74
* *** empty log message ***
75
*
76
* Revision 1.2  2007/03/09 11:20:56  jaume
77
* Advanced symbology (start committing)
78
*
79
* Revision 1.1.2.2  2007/02/15 16:23:44  jaume
80
* *** empty log message ***
81
*
82
* Revision 1.1.2.1  2007/02/13 16:19:19  jaume
83
* graduated symbol legends (start commiting)
84
*
85
*
86
*/
87
package org.gvsig.fmap.mapcontext.rendering.legend;
88
89
import java.util.ArrayList;
90
import java.util.Comparator;
91
import java.util.Date;
92
import java.util.Iterator;
93
import java.util.TreeMap;
94
95 24691 vcaballero
import org.gvsig.fmap.dal.exception.DataException;
96 27525 jmvivo
import org.gvsig.fmap.dal.feature.DisposableIterator;
97 24494 jmvivo
import org.gvsig.fmap.dal.feature.Feature;
98 24711 vcaballero
import org.gvsig.fmap.dal.feature.FeatureQuery;
99 24494 jmvivo
import org.gvsig.fmap.dal.feature.FeatureReference;
100 27525 jmvivo
import org.gvsig.fmap.dal.feature.FeatureSet;
101 24494 jmvivo
import org.gvsig.fmap.dal.feature.FeatureStore;
102 21200 vcaballero
import org.gvsig.fmap.mapcontext.Messages;
103
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
104
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
105
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbologyFactory;
106 25543 vcaballero
import org.slf4j.Logger;
107
import org.slf4j.LoggerFactory;
108 21200 vcaballero
109
110
public abstract class AbstractIntervalLegend extends AbstractClassifiedVectorLegend implements IVectorialIntervalLegend{
111
        protected int shapeType;
112
113
        public static final int EQUAL_INTERVALS = 0;
114
        public static final int NATURAL_INTERVALS = 1;
115
        public static final int QUANTILE_INTERVALS = 2;
116 22506 vcaballero
        protected TreeMap symbols = new TreeMap //<Object, ISymbol>
117
                        (new Comparator() { //<Object>
118 21200 vcaballero
                public int compare(Object o1, Object o2) {
119
                        if ((o1 != null) && (o2 != null)) {
120
                                if (o1 instanceof NullIntervalValue &&
121
                                                o2 instanceof NullIntervalValue) {
122
                                        return 0;
123
                                }
124
125
                                if (o2 instanceof NullIntervalValue) {
126
                                        return 1;
127
                                }
128
129
                                if (o1 instanceof NullIntervalValue) {
130
                                        return -1;
131
                                }
132
133
                                FInterval i2 = (FInterval) o2;
134
                                FInterval i1 = (FInterval) o1;
135
136
                                if (i1.getMin() > i2.getMin()) {
137
                                        return 1;
138
                                }
139
140
                                if (i1.getMin() < i2.getMin()) {
141
                                        return -1;
142
                                }
143
                                if (i1.getMax() < i2.getMax()) {
144
                                        return -1;
145
                                }
146
                                if (i1.getMax() > i2.getMax()) {
147
                                        return 1;
148
                                }
149
                        }
150
151
                        return 0;
152
                }
153
        });
154 22506 vcaballero
        protected ArrayList keys = new ArrayList(); //<Object>
155 21200 vcaballero
        protected int index = 0;
156
        protected String[] fieldNames;
157 25861 vcaballero
//        protected int fieldId;
158 21200 vcaballero
        protected ISymbol defaultSymbol;
159
        protected FeatureStore featureStore;
160
        protected int intervalType = NATURAL_INTERVALS;
161
        protected boolean useDefaultSymbol = false;
162
163 25543 vcaballero
        final static private Logger logger = LoggerFactory.getLogger(AbstractIntervalLegend.class);
164 21200 vcaballero
        public void addSymbol(Object key, ISymbol symbol) {
165
                symbols.put(key, symbol);
166
                keys.add(key);
167
                fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(null, symbol));
168
        }
169
170
        /*
171
         * @see com.iver.cit.gvsig.fmap.rendering.IVectorialLegend#getSymbol(int)
172
         */
173 24691 vcaballero
        public ISymbol getSymbol(FeatureReference featureID) throws DataException {
174 25861 vcaballero
                Object val = featureStore.getFeatureByReference(featureID).get(getClassifyingFieldNames()[0]);
175 21200 vcaballero
                IInterval interval = getInterval(val);
176
                ISymbol theSymbol = getSymbolByInterval(interval);
177
178
179
                if (theSymbol != null) {
180
                        return theSymbol;
181
                } else if (useDefaultSymbol) {
182
                        return getDefaultSymbol();
183
                }
184
185
                return null;
186
        }
187
188
        public ISymbol getSymbolByFeature(Feature feat) {
189 25861 vcaballero
                Object val = feat.get(getClassifyingFieldNames()[0]);
190 21200 vcaballero
                IInterval interval = getInterval(val);
191
                ISymbol theSymbol = getSymbolByInterval(interval);
192
193
                return theSymbol;
194
        }
195
196
197
        public FInterval[] calculateIntervals(FeatureStore featureStore, String fieldName, int numIntervalos, int shapeType)
198 24711 vcaballero
        throws LegendLayerException, DataException {
199 21200 vcaballero
                logger.debug("elRs.start()");
200
//                recordSet.start();
201
202 27525 jmvivo
//                int idField = -1;
203
                FeatureSet set = null;
204
                DisposableIterator iterator = null;
205
                try {
206 21200 vcaballero
207
                setClassifyingFieldNames(new String[] {fieldName});
208
209
                String[] fieldNames = getClassifyingFieldNames();
210 24711 vcaballero
                FeatureQuery featureQuery=featureStore.createFeatureQuery();
211 27525 jmvivo
                featureQuery.setAttributeNames(fieldNames);
212
                set = featureStore.getFeatureSet(featureQuery);
213
                        iterator = set.fastIterator();
214 21200 vcaballero
215
216
//                for (int i = 0; i < recordSet.getFieldCount(); i++) {
217
//                        String nomAux = recordSet.getFieldName(i).trim();
218
//
219
//                        if (fieldNames[0].compareToIgnoreCase(nomAux) == 0) {
220
//                                idField = i;
221
//
222
//                                break;
223
//                        }
224
//                }
225
226 22478 vcaballero
//                if (idField == -1) {
227
//                        logger.error("Campo no reconocido " + fieldNames);
228
//
229
//                        return null;
230
//                }
231 21200 vcaballero
232
                double minValue = Double.MAX_VALUE;
233
                double maxValue = Double.NEGATIVE_INFINITY;
234
235
                VectorialIntervalLegend auxLegend = LegendFactory.
236
                    createVectorialIntervalLegend(shapeType);
237
238
                Object clave;
239
240
                while (iterator.hasNext()) {
241
                        Feature feature = (Feature) iterator.next();
242
243
//                for (int j = 0; j < recordSet.getRowCount(); j++) {
244 22478 vcaballero
                        clave = feature.get(fieldName);
245 21200 vcaballero
246
                        IInterval interval = auxLegend.getInterval(clave);
247
248
                        ////Comprobar que no esta repetido y no hace falta introducir en el hashtable el campo junto con el simbolo.
249
                        if (auxLegend.getSymbolByInterval(interval) == null) {
250
                                //si no esta creado el simbolo se crea
251
                                double valor = 0;
252
253
254
                                if (clave instanceof Number) {
255
                                        valor=((Number)clave).doubleValue();
256
                                }else if (clave instanceof Date) {
257
                                        //TODO POR IMPLEMENTAR
258
                                        ///valorDate = elRs.getFieldValueAsDate(idField);
259
                                        ///if (valorDate.before(minValueDate)) minValueDate = valorDate;
260
                                        ///if (valorDate.after(maxValueDate)) maxValueDate = valorDate;
261
                                } else if (clave instanceof NullValue) {
262
                                        continue;
263
                                }
264
265
                                if (valor < minValue) {
266
                                        minValue = valor;
267
                                }
268
269
                                if (valor > maxValue) {
270
                                        maxValue = valor;
271
                                }
272
                        }
273
                }
274
275
                FInterval[] intervalArray = null;
276
                switch (getIntervalType()) {
277
                case VectorialIntervalLegend.EQUAL_INTERVALS:
278
                        intervalArray = calculateEqualIntervals(numIntervalos,
279
                                        minValue, maxValue, fieldName);
280
281
                        break;
282
283
                case VectorialIntervalLegend.NATURAL_INTERVALS:
284
                        intervalArray = calculateNaturalIntervals(featureStore, numIntervalos,
285
                                        minValue, maxValue, fieldName);
286
287
                        break;
288
289
                case VectorialIntervalLegend.QUANTILE_INTERVALS:
290
                        intervalArray = calculateQuantileIntervals(featureStore, numIntervalos,
291
                                        minValue, maxValue, fieldName);
292
293
                        break;
294
                }
295
//                recordSet.stop();
296 27525 jmvivo
                return intervalArray;
297
                } finally {
298
                        if (iterator != null) {
299
                                iterator.dispose();
300
                        }
301
                        if (set != null) {
302
                                set.dispose();
303
                        }
304
                }
305 21200 vcaballero
        }
306
307
308
    /**
309
     * EQUAL INTERVAL Devuelve un Array con el n?mero de intervalos que se
310
     * quieren crear. Los intervalos se crean con un tama?o igual entre ellos.
311
     * @param numIntervals n?mero de intervalos
312
     * @param minValue Valor m?nimo.
313
     * @param maxValue Valor m?ximo.
314
     * @param fieldName Nombre del campo
315
     *
316
     * @return Array con los intervalos.
317
     */
318
    private FInterval[] calculateEqualIntervals(int numIntervals, double minValue,
319
        double maxValue, String fieldName) {
320
        FInterval[] theIntervalArray = new FInterval[numIntervals];
321
        double step = (maxValue - minValue) / numIntervals;
322
323
        if (numIntervals > 1) {
324
            theIntervalArray[0] = new FInterval(minValue, minValue + step);
325
326
            for (int i = 1; i < (numIntervals - 1); i++) {
327
                theIntervalArray[i] = new FInterval(minValue + (i * step) +
328
                        0.01, minValue + ((i + 1) * step));
329
            }
330
331
            theIntervalArray[numIntervals - 1] = new FInterval(minValue +
332
                    ((numIntervals - 1) * step) + 0.01, maxValue);
333
        } else {
334
            theIntervalArray[0] = new FInterval(minValue, maxValue);
335
        }
336
337
        return theIntervalArray;
338
    }
339
340
    /**
341
     * NATURAL INTERVAL Devuelve un Array con el n?mero de intervalos que se
342
     * quieren crear. Los intervalos se distribuyen de forma natural.
343
     *
344
     * @param numIntervals n?mero de intervalos
345
     * @param minValue Valor m?nimo.
346
     * @param maxValue Valor m?ximo.
347
     * @param fieldName Nombre del campo
348
     *
349
     * @return Array con los intervalos.
350
     * @throws LegendLayerException
351
     */
352
    private FInterval[] calculateNaturalIntervals(FeatureStore featureStore, int numIntervals, double minValue,
353
        double maxValue, String fieldName) throws LegendLayerException {
354
        NaturalIntervalGenerator intervalGenerator = new NaturalIntervalGenerator(
355
                        featureStore, fieldName, numIntervals);
356
357
        try {
358
            intervalGenerator.generarIntervalos();
359 24711 vcaballero
        } catch (DataException e) {
360 21200 vcaballero
                throw new LegendLayerException(Messages.getString("failed_calculating_intervals"), e);
361
        }
362
363
        int numIntervalsGen = intervalGenerator.getNumIntervals() - 1;
364
365
        if (numIntervalsGen == -1) {
366
            //TODO cuando no puede calcular los intervalos.
367
            numIntervalsGen = 1;
368
        }
369
370
        FInterval[] theIntervalArray = new FInterval[numIntervalsGen];
371
372
        if (numIntervalsGen > 1) {
373
            theIntervalArray[0] = new FInterval(minValue,
374
                    intervalGenerator.getValorRuptura(0));
375
376
            for (int i = 1; i < (numIntervalsGen - 1); i++) {
377
                theIntervalArray[i] = new FInterval(intervalGenerator.getValInit(i -
378
                            1), intervalGenerator.getValorRuptura(i));
379
            }
380
381
            theIntervalArray[numIntervalsGen - 1] = new FInterval(intervalGenerator.getValInit(numIntervalsGen -
382
                        2), maxValue);
383
        } else {
384
            theIntervalArray[numIntervalsGen - 1] = new FInterval(minValue,
385
                    maxValue);
386
        }
387
388
        return theIntervalArray;
389
    }
390
391
    /**
392
     * QUANTILE INTERVAL Devuelve un Array con el n?mero de intervalos que se
393
     * quieren crear. Los intervalos se distribuyen de forma quantile.
394
     * @param recordSet
395
     *
396
     * @param numIntervals n?mero de intervalos
397
     * @param minValue Valor m?nimo.
398
     * @param maxValue Valor m?ximo.
399
     * @param fieldName Nombre del campo
400
     *
401
     * @return Array con los intervalos.
402
     * @throws LegendLayerException
403
     */
404
    private FInterval[] calculateQuantileIntervals(FeatureStore featureStore, int numIntervals, double minValue,
405
        double maxValue, String fieldName) throws LegendLayerException {
406
        QuantileIntervalGenerator intervalGenerator = new QuantileIntervalGenerator(
407
                        featureStore, fieldName, numIntervals);
408
409
        try {
410
            intervalGenerator.generarIntervalos();
411 24711 vcaballero
        } catch (DataException e) {
412 21200 vcaballero
                throw new LegendLayerException(Messages.getString("failed_calculating_intervals"), e);
413
        }
414
415
        int numIntervalsGen = intervalGenerator.getNumIntervalGen();
416
        FInterval[] theIntervalArray = new FInterval[numIntervalsGen];
417
418
        if (intervalGenerator.getNumIntervalGen() > 1) {
419
            theIntervalArray[0] = new FInterval(minValue,
420
                    intervalGenerator.getValRuptura(0));
421
422
            for (int i = 1; i < (numIntervalsGen - 1); i++) {
423
                theIntervalArray[i] = new FInterval(intervalGenerator.getValInit(i -
424
                            1), intervalGenerator.getValRuptura(i));
425
            }
426
427
            theIntervalArray[numIntervalsGen - 1] = new FInterval(intervalGenerator.getValInit(numIntervalsGen -
428
                        2), maxValue);
429
        } else {
430
            theIntervalArray[numIntervalsGen - 1] = new FInterval(minValue,
431
                    maxValue);
432
        }
433
434
        return theIntervalArray;
435
    }
436
437 22751 vcaballero
    public ISymbol getSymbolByInterval(IInterval key) {
438
439
                if (key == null){
440 27525 jmvivo
                        if (isUseDefaultSymbol()) {
441 22751 vcaballero
                                return defaultSymbol;
442 27525 jmvivo
                        }
443 21200 vcaballero
                        return null;
444
                }
445
                if (symbols.containsKey(key)) {
446
                        return (ISymbol) symbols.get(key);
447
                }
448
449 27525 jmvivo
                if (isUseDefaultSymbol()) {
450 22751 vcaballero
                        return defaultSymbol;
451 27525 jmvivo
                }
452 22751 vcaballero
453 21200 vcaballero
                return null;
454
        }
455
456 22751 vcaballero
457 21200 vcaballero
        public String[] getDescriptions() {
458
                String[] descriptions = new String[symbols.size()];
459
                ISymbol[] auxSym = getSymbols();
460
461 27525 jmvivo
                for (int i = 0; i < descriptions.length; i++) {
462 21200 vcaballero
                        descriptions[i] = auxSym[i].getDescription();
463 27525 jmvivo
                }
464 21200 vcaballero
465
                return descriptions;
466
        }
467
468
469
        public Object[] getValues() {
470
                return symbols.keySet().toArray();
471
        }
472
473
        public void clear() {
474
                index = 0;
475
                keys.clear();
476
                symbols.clear();
477
        }
478
479
        public ISymbol[] getSymbols() {
480
                return (ISymbol[]) symbols.values().toArray(new ISymbol[0]);
481
        }
482
483
        public String[] getClassifyingFieldNames() {
484
                return fieldNames;
485
        }
486
487
        public void setDefaultSymbol(ISymbol s) {
488
            ISymbol old = defaultSymbol;
489 27525 jmvivo
                if (s == null) {
490
                        throw new NullPointerException("Default symbol cannot be null");
491
                }
492 21200 vcaballero
                defaultSymbol = s;
493
                fireDefaultSymbolChangedEvent(new SymbolLegendEvent(old, defaultSymbol));
494
        }
495
496
        public void setClassifyingFieldNames(String[] fieldNames) {
497
                this.fieldNames = fieldNames;
498
        }
499
500
        public ISymbol getDefaultSymbol() {
501
                NullIntervalValue niv=new NullIntervalValue();
502 27525 jmvivo
                if (symbols.containsKey(niv)) {
503 21200 vcaballero
                        return (ISymbol)symbols.get(niv);
504 27525 jmvivo
                }
505 21200 vcaballero
506 27525 jmvivo
                if(defaultSymbol==null) {
507 22751 vcaballero
                        defaultSymbol=SymbologyFactory.createDefaultSymbolByShapeType(shapeType);
508 27525 jmvivo
                }
509 21200 vcaballero
                return defaultSymbol;
510
        }
511
512
513 22751 vcaballero
514 21200 vcaballero
    public void setFeatureStore(FeatureStore featureStore)
515 24691 vcaballero
        throws DataException {
516 21200 vcaballero
                    /*
517
                     * when we move definitely to feature iterators this
518
                     * method
519
                     */
520
                    this.featureStore = featureStore;
521 25861 vcaballero
//                    fieldId = ((FeatureType)featureStore.getFeatureTypes().get(0)).getIndex(fieldNames[0]);
522 21200 vcaballero
    }
523
524
525
        public IInterval getInterval(Object v) {
526
                for (int i = 0; i < keys.size(); i++) {
527
                        if (((IInterval) keys.get(i)).isInInterval(v)) {
528
                                return (IInterval) keys.get(i);
529
                        }
530
                }
531
532
                return null;
533
        }
534
535
        public void setIntervalType(int intervalType) {
536
                this.intervalType = intervalType;
537
        }
538
539
540
        public int getIntervalType() {
541
                return intervalType;
542
        }
543
544
        public void useDefaultSymbol(boolean b) {
545
                useDefaultSymbol = b;
546
        }
547
548
549
        public boolean isUseDefaultSymbol() {
550
                return useDefaultSymbol;
551
        }
552
553
554
        public void delSymbol(Object obj) {
555
                keys.remove(obj);
556
                symbols.remove(obj);
557
                fireClassifiedSymbolChangeEvent(
558
                                new SymbolLegendEvent(
559 22506 vcaballero
                                                (ISymbol)symbols.remove(obj),
560 21200 vcaballero
                                                null));
561
        }
562
563
564
        public void replace(ISymbol oldSymbol, ISymbol newSymbol) {
565
                if (symbols.containsValue(oldSymbol)) {
566
                        Iterator it = symbols.keySet().iterator();
567
                        while (it.hasNext()) {
568
                                Object key = it.next();
569
                                if (symbols.get(key).equals(oldSymbol)) {
570
                                        symbols.remove(key);
571
                                        symbols.put(key, newSymbol);
572 22751 vcaballero
                                        fireClassifiedSymbolChangeEvent(
573
                                                        new SymbolLegendEvent(oldSymbol, newSymbol));
574 21200 vcaballero
                                }
575
                        }
576
                }
577
        }
578
}