Statistics
| Revision:

root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / vectorTools / vectorSpatialCluster / VectorSpatialClusterAlgorithm.java @ 59

History | View | Annotate | Download (7.25 KB)

1

    
2

    
3
package es.unex.sextante.vectorTools.vectorSpatialCluster;
4

    
5
import java.util.Arrays;
6

    
7
import com.vividsolutions.jts.geom.Coordinate;
8

    
9
import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue;
10
import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer;
11
import es.unex.sextante.core.GeoAlgorithm;
12
import es.unex.sextante.core.Sextante;
13
import es.unex.sextante.dataObjects.IFeature;
14
import es.unex.sextante.dataObjects.IFeatureIterator;
15
import es.unex.sextante.dataObjects.IVectorLayer;
16
import es.unex.sextante.dataObjects.vectorFilters.BoundingBoxFilter;
17
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException;
18
import es.unex.sextante.exceptions.RepeatedParameterNameException;
19
import es.unex.sextante.outputs.IOutputChannel;
20
import es.unex.sextante.outputs.Output;
21
import es.unex.sextante.outputs.OutputVectorLayer;
22
import es.unex.sextante.shapesTools.ShapesTools;
23

    
24

    
25
public class VectorSpatialClusterAlgorithm
26
         extends
27
            GeoAlgorithm {
28

    
29
   public static final String RESULT        = "RESULT";
30
   public static final String NUMCLASS      = "NUMCLASS";
31
   public static final String LAYER         = "LAYER";
32

    
33
   private ValueAndClass[]    m_Classes;
34
   private double             m_dMean[][];
35
   private int                m_iClasses;
36
   private int                m_iThreshold;
37
   private IVectorLayer       m_LayerIn;
38

    
39
   private static double      NO_DATA       = Double.NEGATIVE_INFINITY;
40
   private static int         NO_DATA_CLASS = Integer.MAX_VALUE;
41

    
42

    
43
   @Override
44
   public boolean processAlgorithm() throws GeoAlgorithmExecutionException {
45

    
46
      int i;
47
      final Class[] types = { Integer.class };
48
      final String[] sFields = { Sextante.getText("Class") };
49

    
50
      m_iClasses = m_Parameters.getParameterValueAsInt(NUMCLASS);
51
      m_LayerIn = m_Parameters.getParameterValueAsVectorLayer(LAYER);
52
      if (!m_bIsAutoExtent) {
53
         m_LayerIn.addFilter(new BoundingBoxFilter(m_AnalysisExtent));
54
      }
55

    
56
      m_Classes = new ValueAndClass[m_LayerIn.getShapesCount()];
57
      final IFeatureIterator iter = m_LayerIn.iterator();
58
      i = 0;
59
      while (iter.hasNext()) {
60
         final IFeature feature = iter.next();
61
         final Coordinate coord = feature.getGeometry().getCoordinate();
62
         m_Classes[i] = new ValueAndClass(2);
63
         m_Classes[i].dValue[0] = coord.x;
64
         m_Classes[i].dValue[1] = coord.y;
65
         i++;
66
      }
67

    
68
      classify();
69

    
70
      final Object[][] values = new Object[1][m_LayerIn.getShapesCount()];
71
      for (i = 0; i < m_Classes.length; i++) {
72
         values[0][i] = new Integer(m_Classes[i].iClass);
73
      }
74
      final IOutputChannel channel = getOutputChannel(RESULT);
75
      final Output out = new OutputVectorLayer();
76
      out.setDescription(Sextante.getText("Result"));
77
      out.setName(RESULT);
78
      out.setOutputChannel(channel);
79
      out.setOutputObject(ShapesTools.addFields(m_OutputFactory, m_LayerIn, channel, sFields, values, types));
80
      addOutputObject(out);
81

    
82
      return !m_Task.isCanceled();
83

    
84
   }
85

    
86

    
87
   @Override
88
   public void defineCharacteristics() {
89

    
90
      setName(Sextante.getText("Spatial_cluster"));
91
      setGroup(Sextante.getText("Tools_for_point_layers"));
92
      setUserCanDefineAnalysisExtent(true);
93

    
94
      try {
95
         m_Parameters.addInputVectorLayer(LAYER, Sextante.getText("Layer"), AdditionalInfoVectorLayer.SHAPE_TYPE_POINT, true);
96
         m_Parameters.addNumericalValue(NUMCLASS, Sextante.getText("Number_of_classes"),
97
                  AdditionalInfoNumericalValue.NUMERICAL_VALUE_INTEGER, 3, 2, Integer.MAX_VALUE);
98
         addOutputVectorLayer(RESULT, Sextante.getText("Result"), OutputVectorLayer.SHAPE_TYPE_POINT);
99
      }
100
      catch (final RepeatedParameterNameException e) {
101
         Sextante.addErrorToLog(e);
102
      }
103

    
104
   }
105

    
106

    
107
   private void initValues() {
108

    
109
      int i;
110
      int iValues = 0;
111
      boolean bNoData;
112
      double dStep;
113
      double dValue;
114
      final double dMin[] = new double[2];
115
      final double dMax[] = new double[2];
116

    
117
      for (i = 0; i < 2; i++) {
118
         dMin[i] = Double.MAX_VALUE;
119
         dMax[i] = Double.NEGATIVE_INFINITY;
120
      }
121

    
122
      for (i = 0; i < m_Classes.length; i++) {
123
         bNoData = false;
124
         for (int j = 0; j < m_Classes[i].dValue.length; j++) {
125
            dValue = m_Classes[i].dValue[j];
126
            if (dValue != NO_DATA) {
127
               dMin[j] = Math.min(dMin[j], dValue);
128
               dMax[j] = Math.max(dMax[j], dValue);
129
            }
130
            else {
131
               bNoData = true;
132
            }
133
         }
134
         if (bNoData) {
135
            m_Classes[i].iClass = NO_DATA_CLASS;
136
         }
137
         else {
138
            iValues++;
139
            m_Classes[i].iClass = 0;
140
         }
141
      }
142

    
143
      m_dMean = new double[m_iClasses][2];
144

    
145
      for (i = 0; i < 2; i++) {
146
         dStep = (dMax[i] - dMin[i]) / ((m_iClasses + 1));
147
         for (int j = 0; j < m_iClasses; j++) {
148
            m_dMean[j][i] = dMin[i] + dStep * (j + 1);
149
         }
150
      }
151

    
152
      m_iThreshold = (int) (iValues * 0.02);
153

    
154
   }
155

    
156

    
157
   private boolean classify() {
158

    
159
      int i, j;
160
      int iChangedCells;
161
      int iPrevClass;
162
      int iClass;
163
      final int iCells[] = new int[m_iClasses];
164
      double dNewMean[][];
165
      double swap[][];
166

    
167
      initValues();
168

    
169
      dNewMean = new double[m_iClasses][2];
170

    
171
      do {
172
         Arrays.fill(iCells, 0);
173
         iChangedCells = 0;
174

    
175
         for (i = 0; i < m_iClasses; i++) {
176
            Arrays.fill(dNewMean[i], 0.0);
177
         }
178
         for (i = 0; i < m_Classes.length; i++) {
179
            iPrevClass = m_Classes[i].iClass;
180
            if (iPrevClass != NO_DATA_CLASS) {
181
               iClass = getClass(m_Classes[i].dValue);
182
               m_Classes[i].iClass = iClass;
183
               for (j = 0; j < 2; j++) {
184
                  dNewMean[iClass][j] += m_Classes[i].dValue[j];
185
               }
186
               iCells[iClass]++;
187
               if (iClass != iPrevClass) {
188
                  iChangedCells++;
189
               }
190
            }
191
         }
192

    
193
         for (i = 0; i < 2; i++) {
194
            for (j = 0; j < m_iClasses; j++) {
195
               dNewMean[j][i] /= iCells[j];
196
            }
197
         }
198

    
199
         swap = m_dMean;
200
         m_dMean = dNewMean;
201
         dNewMean = swap;
202

    
203
         setProgressText(Sextante.getText("Modified_classes") + Integer.toString(iChangedCells));
204

    
205
         if (m_Task.isCanceled()) {
206
            return false;
207
         }
208

    
209
      }
210
      while (iChangedCells > m_iThreshold);
211

    
212
      return true;
213

    
214
   }
215

    
216

    
217
   private int getClass(final double[] dValues) {
218

    
219
      int iClass = 0;
220
      double dMinDist = Double.MAX_VALUE;
221
      double dDist;
222
      double dDif;
223

    
224
      for (int i = 0; i < m_iClasses; i++) {
225
         dDist = 0;
226
         for (int j = 0; j < dValues.length; j++) {
227
            dDif = m_dMean[i][j] - dValues[j];
228
            dDist += (dDif * dDif);
229
         }
230
         if (dDist < dMinDist) {
231
            dMinDist = dDist;
232
            iClass = i;
233
         }
234
      }
235

    
236
      return iClass;
237
   }
238

    
239
   private class ValueAndClass {
240

    
241
      public double dValue[];
242
      public int    iClass;
243

    
244

    
245
      public ValueAndClass(final int i) {
246

    
247
         dValue = new double[i];
248

    
249
      }
250

    
251
   }
252

    
253

    
254
}