Revision 415
org.gvsig.toolbox/tags/org.gvsig.toolbox-1.0.76/org.gvsig.toolbox.algorithm/MANIFEST.MF | ||
---|---|---|
1 |
Manifest-Version: 1.0 |
|
2 |
Ant-Version: Apache Ant 1.7.1 |
|
3 |
Created-By: 20.1-b02 (Sun Microsystems Inc.) |
|
4 |
Implementation-Version: 0.7 |
|
5 |
Built-Date: 2013-02-23 00:34:19 |
|
6 |
|
|
0 | 7 |
org.gvsig.toolbox/tags/org.gvsig.toolbox-1.0.76/org.gvsig.toolbox.algorithm/src/main/java/es/unex/sextante/gridAnalysis/costInRoutes/CostInRoutesAlgorithm.java | ||
---|---|---|
1 |
package es.unex.sextante.gridAnalysis.costInRoutes; |
|
2 |
|
|
3 |
|
|
4 |
import com.vividsolutions.jts.geom.Coordinate; |
|
5 |
import com.vividsolutions.jts.geom.Geometry; |
|
6 |
|
|
7 |
import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer; |
|
8 |
import es.unex.sextante.core.GeoAlgorithm; |
|
9 |
import es.unex.sextante.core.Sextante; |
|
10 |
import es.unex.sextante.dataObjects.IFeature; |
|
11 |
import es.unex.sextante.dataObjects.IFeatureIterator; |
|
12 |
import es.unex.sextante.dataObjects.IRasterLayer; |
|
13 |
import es.unex.sextante.dataObjects.IVectorLayer; |
|
14 |
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
|
15 |
import es.unex.sextante.exceptions.RepeatedParameterNameException; |
|
16 |
import es.unex.sextante.outputs.IOutputChannel; |
|
17 |
import es.unex.sextante.outputs.Output; |
|
18 |
import es.unex.sextante.outputs.OutputVectorLayer; |
|
19 |
import es.unex.sextante.shapesTools.ShapesTools; |
|
20 |
|
|
21 |
public class CostInRoutesAlgorithm |
|
22 |
extends |
|
23 |
GeoAlgorithm { |
|
24 |
|
|
25 |
public static final String ROUTES = "ROUTES"; |
|
26 |
public static final String COST = "COST"; |
|
27 |
public static final String RESULT = "RESULT"; |
|
28 |
|
|
29 |
private IRasterLayer m_Cost; |
|
30 |
private double[] m_dDist; |
|
31 |
private double[] m_dCost; |
|
32 |
private double m_dLastX, m_dLastY; |
|
33 |
private int m_iPoints = 0; |
|
34 |
private int m_iCurrentRoute; |
|
35 |
|
|
36 |
|
|
37 |
@Override |
|
38 |
public void defineCharacteristics() { |
|
39 |
|
|
40 |
setName(Sextante.getText("Cost_for_predefined_routes")); |
|
41 |
setGroup(Sextante.getText("Cost_distances_and_routes")); |
|
42 |
setUserCanDefineAnalysisExtent(true); |
|
43 |
|
|
44 |
try { |
|
45 |
m_Parameters.addInputVectorLayer(ROUTES, Sextante.getText("Routes"), AdditionalInfoVectorLayer.SHAPE_TYPE_LINE, true); |
|
46 |
m_Parameters.addInputRasterLayer(COST, Sextante.getText("Cost"), true); |
|
47 |
addOutputVectorLayer(RESULT, Sextante.getText("Routes_and_cost")); |
|
48 |
} |
|
49 |
catch (final RepeatedParameterNameException e) { |
|
50 |
Sextante.addErrorToLog(e); |
|
51 |
} |
|
52 |
|
|
53 |
} |
|
54 |
|
|
55 |
|
|
56 |
@Override |
|
57 |
public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
|
58 |
|
|
59 |
final IVectorLayer routes = m_Parameters.getParameterValueAsVectorLayer(ROUTES); |
|
60 |
m_Cost = m_Parameters.getParameterValueAsRasterLayer(COST); |
|
61 |
|
|
62 |
if (routes.getShapesCount() == 0) { |
|
63 |
return false; |
|
64 |
} |
|
65 |
|
|
66 |
final int iShapesCount = routes.getShapesCount(); |
|
67 |
m_iCurrentRoute = 0; |
|
68 |
m_Cost.setFullExtent(); |
|
69 |
m_dCost = new double[routes.getShapesCount()]; |
|
70 |
m_dDist = new double[routes.getShapesCount()]; |
|
71 |
final IFeatureIterator iter = routes.iterator(); |
|
72 |
while (iter.hasNext() && setProgress(m_iCurrentRoute, iShapesCount)) { |
|
73 |
m_iPoints = 0; |
|
74 |
final IFeature feature = iter.next(); |
|
75 |
final Geometry geom = feature.getGeometry(); |
|
76 |
processLine(geom.getCoordinates()); |
|
77 |
m_iCurrentRoute++; |
|
78 |
} |
|
79 |
iter.close(); |
|
80 |
|
|
81 |
if (m_Task.isCanceled()) { |
|
82 |
return false; |
|
83 |
} |
|
84 |
|
|
85 |
final Object[][] values = new Object[2][routes.getShapesCount()]; |
|
86 |
final String[] sFields = { Sextante.getText("Distance"), Sextante.getText("Cost") }; |
|
87 |
final Class[] types = { Double.class, Double.class }; |
|
88 |
for (int i = 0; i < routes.getShapesCount(); i++) { |
|
89 |
values[0][i] = new Double(m_dDist[i]); |
|
90 |
values[1][i] = new Double(m_dCost[i]); |
|
91 |
} |
|
92 |
final IOutputChannel channel = getOutputChannel(RESULT); |
|
93 |
final Output out = new OutputVectorLayer(); |
|
94 |
out.setName(RESULT); |
|
95 |
out.setDescription(Sextante.getText("Routes")); |
|
96 |
out.setOutputChannel(channel); |
|
97 |
out.setOutputObject(ShapesTools.addFields(m_OutputFactory, routes, channel, sFields, values, types)); |
|
98 |
addOutputObject(out); |
|
99 |
|
|
100 |
return true; |
|
101 |
|
|
102 |
} |
|
103 |
|
|
104 |
|
|
105 |
private void processLine(final Coordinate coords[]) { |
|
106 |
|
|
107 |
int i; |
|
108 |
double x, y, x2, y2; |
|
109 |
|
|
110 |
for (i = 0; i < coords.length - 1; i++) { |
|
111 |
x = coords[i].x; |
|
112 |
y = coords[i].y; |
|
113 |
x2 = coords[i + 1].x; |
|
114 |
y2 = coords[i + 1].y; |
|
115 |
processSegment(x, y, x2, y2); |
|
116 |
} |
|
117 |
|
|
118 |
} |
|
119 |
|
|
120 |
|
|
121 |
private void processSegment(double x, |
|
122 |
double y, |
|
123 |
final double x2, |
|
124 |
final double y2) { |
|
125 |
|
|
126 |
double dx, dy, d, n; |
|
127 |
|
|
128 |
dx = Math.abs(x2 - x); |
|
129 |
dy = Math.abs(y2 - y); |
|
130 |
|
|
131 |
if ((dx > 0.0) || (dy > 0.0)) { |
|
132 |
if (dx > dy) { |
|
133 |
dx /= m_Cost.getWindowCellSize(); |
|
134 |
n = dx; |
|
135 |
dy /= dx; |
|
136 |
dx = m_Cost.getWindowCellSize(); |
|
137 |
} |
|
138 |
else { |
|
139 |
dy /= m_Cost.getWindowCellSize(); |
|
140 |
n = dy; |
|
141 |
dx /= dy; |
|
142 |
dy = m_Cost.getWindowCellSize(); |
|
143 |
} |
|
144 |
|
|
145 |
if (x2 < x) { |
|
146 |
dx = -dx; |
|
147 |
} |
|
148 |
|
|
149 |
if (y2 < y) { |
|
150 |
dy = -dy; |
|
151 |
} |
|
152 |
|
|
153 |
for (d = 0.0; d <= n; d++, x += dx, y += dy) { |
|
154 |
addPoint(x, y); |
|
155 |
} |
|
156 |
} |
|
157 |
|
|
158 |
} |
|
159 |
|
|
160 |
|
|
161 |
private void addPoint(final double x, |
|
162 |
final double y) { |
|
163 |
|
|
164 |
double dDX, dDY; |
|
165 |
|
|
166 |
final double z = m_Cost.getValueAt(x, y); |
|
167 |
|
|
168 |
if (m_iPoints == 0) { |
|
169 |
m_dDist[m_iCurrentRoute] = 0.0; |
|
170 |
m_dCost[m_iCurrentRoute] = 0.0; |
|
171 |
} |
|
172 |
else { |
|
173 |
dDX = x - m_dLastX; |
|
174 |
dDY = y - m_dLastY; |
|
175 |
m_dDist[m_iCurrentRoute] += Math.sqrt(dDX * dDX + dDY * dDY); |
|
176 |
if (!m_Cost.isNoDataValue(z)) { |
|
177 |
m_dCost[m_iCurrentRoute] += z; |
|
178 |
} |
|
179 |
} |
|
180 |
|
|
181 |
m_dLastX = x; |
|
182 |
m_dLastY = y; |
|
183 |
m_iPoints++; |
|
184 |
|
|
185 |
} |
|
186 |
|
|
187 |
} |
|
0 | 188 |
org.gvsig.toolbox/tags/org.gvsig.toolbox-1.0.76/org.gvsig.toolbox.algorithm/src/main/java/es/unex/sextante/gridAnalysis/predictiveModels/PredictiveModelsAlgorithm.java | ||
---|---|---|
1 |
|
|
2 |
|
|
3 |
package es.unex.sextante.gridAnalysis.predictiveModels; |
|
4 |
|
|
5 |
|
|
6 |
import java.util.ArrayList; |
|
7 |
|
|
8 |
import Jama.Matrix; |
|
9 |
|
|
10 |
import com.vividsolutions.jts.geom.Coordinate; |
|
11 |
|
|
12 |
import es.unex.sextante.additionalInfo.AdditionalInfoMultipleInput; |
|
13 |
import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue; |
|
14 |
import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer; |
|
15 |
import es.unex.sextante.core.GeoAlgorithm; |
|
16 |
import es.unex.sextante.core.Sextante; |
|
17 |
import es.unex.sextante.dataObjects.IFeature; |
|
18 |
import es.unex.sextante.dataObjects.IFeatureIterator; |
|
19 |
import es.unex.sextante.dataObjects.IRasterLayer; |
|
20 |
import es.unex.sextante.dataObjects.IVectorLayer; |
|
21 |
import es.unex.sextante.dataObjects.vectorFilters.BoundingBoxFilter; |
|
22 |
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
|
23 |
import es.unex.sextante.exceptions.RepeatedParameterNameException; |
|
24 |
import es.unex.sextante.rasterWrappers.GridWrapper; |
|
25 |
|
|
26 |
|
|
27 |
public class PredictiveModelsAlgorithm |
|
28 |
extends |
|
29 |
GeoAlgorithm { |
|
30 |
|
|
31 |
public static final String INPUT = "INPUT"; |
|
32 |
public static final String POINTS = "POINTS"; |
|
33 |
public static final String METHOD = "METHOD"; |
|
34 |
public static final String CUTOFF = "CUTOFF"; |
|
35 |
public static final String RESULT = "RESULT"; |
|
36 |
|
|
37 |
private static final double NODATA = -99999999999999.; |
|
38 |
private static final int DISTTOAVG = 0; |
|
39 |
private static final int MAHALANOBIS = 1; |
|
40 |
private static final int BIOCLIM = 2; |
|
41 |
|
|
42 |
private int m_iNX, m_iNY; |
|
43 |
private int m_iMethod; |
|
44 |
private double m_dCutoff; |
|
45 |
private double m_dMean[]; |
|
46 |
private double m_dMin[]; |
|
47 |
private double m_dMax[]; |
|
48 |
private double m_dStdDev[]; |
|
49 |
private ArrayList m_RasterLayers; |
|
50 |
private IVectorLayer m_Points; |
|
51 |
private IRasterLayer m_Windows[]; |
|
52 |
private IRasterLayer m_Result; |
|
53 |
private Matrix m_Inverse; |
|
54 |
|
|
55 |
|
|
56 |
@Override |
|
57 |
public void defineCharacteristics() { |
|
58 |
|
|
59 |
final String sOptions[] = { Sextante.getText("Distance_to_mean_value"), Sextante.getText("Mahalanobis_distance"), |
|
60 |
Sextante.getText("BIOCLIM") }; |
|
61 |
|
|
62 |
setUserCanDefineAnalysisExtent(true); |
|
63 |
setGroup(Sextante.getText("Raster_layer_analysis")); |
|
64 |
setName(Sextante.getText("Predictive_models")); |
|
65 |
|
|
66 |
try { |
|
67 |
m_Parameters.addMultipleInput(INPUT, Sextante.getText("Predictors"), AdditionalInfoMultipleInput.DATA_TYPE_RASTER, true); |
|
68 |
m_Parameters.addInputVectorLayer(POINTS, Sextante.getText("Presence_points"), |
|
69 |
AdditionalInfoVectorLayer.SHAPE_TYPE_POINT, true); |
|
70 |
m_Parameters.addSelection(METHOD, Sextante.getText("Method"), sOptions); |
|
71 |
m_Parameters.addNumericalValue(CUTOFF, Sextante.getText("Cutoff__BIOCLIM"), |
|
72 |
AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE, 0.1, 0, Double.MAX_VALUE); |
|
73 |
addOutputRasterLayer(RESULT, Sextante.getText("Suitability")); |
|
74 |
} |
|
75 |
catch (final RepeatedParameterNameException e) { |
|
76 |
Sextante.addErrorToLog(e); |
|
77 |
} |
|
78 |
|
|
79 |
} |
|
80 |
|
|
81 |
|
|
82 |
@Override |
|
83 |
public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
|
84 |
|
|
85 |
int i; |
|
86 |
int iCount; |
|
87 |
|
|
88 |
m_RasterLayers = m_Parameters.getParameterValueAsArrayList(INPUT); |
|
89 |
m_Points = m_Parameters.getParameterValueAsVectorLayer(POINTS); |
|
90 |
m_iMethod = m_Parameters.getParameterValueAsInt(METHOD); |
|
91 |
m_dCutoff = m_Parameters.getParameterValueAsDouble(CUTOFF); |
|
92 |
|
|
93 |
if (!m_bIsAutoExtent) { |
|
94 |
m_Points.addFilter(new BoundingBoxFilter(m_AnalysisExtent)); |
|
95 |
} |
|
96 |
|
|
97 |
iCount = m_Points.getShapesCount(); |
|
98 |
|
|
99 |
if ((m_RasterLayers.size() == 0) || (iCount < 3)) { |
|
100 |
throw new GeoAlgorithmExecutionException(Sextante.getText("Numero_insuficiente_de_puntos")); |
|
101 |
} |
|
102 |
|
|
103 |
m_Result = getNewRasterLayer(RESULT, Sextante.getText("Suitability"), IRasterLayer.RASTER_DATA_TYPE_DOUBLE); |
|
104 |
|
|
105 |
m_Windows = new IRasterLayer[m_RasterLayers.size()]; |
|
106 |
|
|
107 |
for (i = 0; i < m_RasterLayers.size(); i++) { |
|
108 |
m_Windows[i] = (IRasterLayer) m_RasterLayers.get(i); |
|
109 |
m_Windows[i].setWindowExtent(m_Result.getWindowGridExtent()); |
|
110 |
m_Windows[i].setInterpolationMethod(GridWrapper.INTERPOLATION_BSpline); |
|
111 |
} |
|
112 |
|
|
113 |
m_iNX = m_Result.getWindowGridExtent().getNX(); |
|
114 |
m_iNY = m_Result.getWindowGridExtent().getNY(); |
|
115 |
|
|
116 |
calculateStatisticalValues(); |
|
117 |
|
|
118 |
calculateSuitability(); |
|
119 |
|
|
120 |
return !m_Task.isCanceled(); |
|
121 |
|
|
122 |
|
|
123 |
} |
|
124 |
|
|
125 |
|
|
126 |
private void calculateSuitability() { |
|
127 |
|
|
128 |
switch (m_iMethod) { |
|
129 |
case DISTTOAVG: |
|
130 |
calculateDistanceToAverage(); |
|
131 |
break; |
|
132 |
case MAHALANOBIS: |
|
133 |
calculateMahalanobisDistance(); |
|
134 |
break; |
|
135 |
case BIOCLIM: |
|
136 |
calculateBioclim(); |
|
137 |
break; |
|
138 |
} |
|
139 |
|
|
140 |
} |
|
141 |
|
|
142 |
|
|
143 |
private void calculateBioclim() { |
|
144 |
|
|
145 |
int i; |
|
146 |
int x, y; |
|
147 |
double dValue; |
|
148 |
double dSuitability; |
|
149 |
boolean bNoDataValue; |
|
150 |
|
|
151 |
setProgressText(Sextante.getText("Calculating_distances")); |
|
152 |
for (y = 0; (y < m_iNY) && setProgress(y, m_iNY); y++) { |
|
153 |
for (x = 0; x < m_iNX; x++) { |
|
154 |
bNoDataValue = false; |
|
155 |
dSuitability = 1; |
|
156 |
for (i = 0; i < m_Windows.length; i++) { |
|
157 |
dValue = m_Windows[i].getCellValueAsDouble(x, y); |
|
158 |
if (m_Windows[i].isNoDataValue(dValue)) { |
|
159 |
bNoDataValue = true; |
|
160 |
break; |
|
161 |
} |
|
162 |
else { |
|
163 |
if (Math.abs(dValue - m_dMean[i]) > m_dCutoff * m_dStdDev[i]) { |
|
164 |
if ((dValue > m_dMax[i]) && (dValue < m_dMin[i])) { |
|
165 |
dSuitability = 0.5; |
|
166 |
} |
|
167 |
else { |
|
168 |
dSuitability = 0; |
|
169 |
break; |
|
170 |
} |
|
171 |
} |
|
172 |
} |
|
173 |
} |
|
174 |
if (bNoDataValue) { |
|
175 |
m_Result.setNoData(x, y); |
|
176 |
} |
|
177 |
else { |
|
178 |
m_Result.setCellValue(x, y, dSuitability); |
|
179 |
} |
|
180 |
} |
|
181 |
} |
|
182 |
|
|
183 |
} |
|
184 |
|
|
185 |
|
|
186 |
private void calculateDistanceToAverage() { |
|
187 |
|
|
188 |
int i; |
|
189 |
int x, y; |
|
190 |
double dValue; |
|
191 |
double dDist; |
|
192 |
boolean bNoDataValue; |
|
193 |
final double dNormalizeFactor = Math.sqrt(m_Windows.length); |
|
194 |
|
|
195 |
setProgressText(Sextante.getText("Calculating_distances")); |
|
196 |
for (y = 0; (y < m_iNY) && setProgress(y, m_iNY); y++) { |
|
197 |
for (x = 0; x < m_iNX; x++) { |
|
198 |
bNoDataValue = false; |
|
199 |
dDist = 0; |
|
200 |
for (i = 0; i < m_Windows.length; i++) { |
|
201 |
dValue = m_Windows[i].getCellValueAsDouble(x, y); |
|
202 |
if (m_Windows[i].isNoDataValue(dValue)) { |
|
203 |
bNoDataValue = true; |
|
204 |
break; |
|
205 |
} |
|
206 |
else { |
|
207 |
dDist += Math.pow((dValue - m_dMean[i]) / (m_dMax[i] - m_dMin[i]), 2.); |
|
208 |
} |
|
209 |
} |
|
210 |
if (bNoDataValue) { |
|
211 |
m_Result.setNoData(x, y); |
|
212 |
} |
|
213 |
else { |
|
214 |
m_Result.setCellValue(x, y, dDist / dNormalizeFactor); |
|
215 |
} |
|
216 |
} |
|
217 |
} |
|
218 |
|
|
219 |
} |
|
220 |
|
|
221 |
|
|
222 |
private void calculateMahalanobisDistance() { |
|
223 |
|
|
224 |
int i; |
|
225 |
int x, y; |
|
226 |
double dValue; |
|
227 |
double dDist; |
|
228 |
boolean bNoDataValue; |
|
229 |
final Matrix values = new Matrix(1, m_Windows.length); |
|
230 |
|
|
231 |
setProgressText(Sextante.getText("Calculating_distances")); |
|
232 |
for (y = 0; (y < m_iNY) && setProgress(y, m_iNY); y++) { |
|
233 |
for (x = 0; x < m_iNX; x++) { |
|
234 |
bNoDataValue = false; |
|
235 |
for (i = 0; i < m_Windows.length; i++) { |
|
236 |
dValue = m_Windows[i].getCellValueAsDouble(x, y); |
|
237 |
if (m_Windows[i].isNoDataValue(dValue)) { |
|
238 |
bNoDataValue = true; |
|
239 |
break; |
|
240 |
} |
|
241 |
else { |
|
242 |
values.set(0, i, dValue - m_dMean[i]); |
|
243 |
} |
|
244 |
} |
|
245 |
if (bNoDataValue) { |
|
246 |
m_Result.setNoData(x, y); |
|
247 |
} |
|
248 |
else { |
|
249 |
final Matrix temp = values.times(m_Inverse); |
|
250 |
dDist = temp.times(values.transpose()).get(0, 0); |
|
251 |
m_Result.setCellValue(x, y, dDist); |
|
252 |
} |
|
253 |
} |
|
254 |
} |
|
255 |
|
|
256 |
} |
|
257 |
|
|
258 |
|
|
259 |
private void calculateStatisticalValues() throws GeoAlgorithmExecutionException { |
|
260 |
|
|
261 |
int i, j; |
|
262 |
int iCount; |
|
263 |
int iRow, iCol; |
|
264 |
int iValues[]; |
|
265 |
double dValue; |
|
266 |
double dCov; |
|
267 |
final double covariances[][] = new double[m_Windows.length][m_Windows.length]; |
|
268 |
double values[][]; |
|
269 |
Coordinate pt; |
|
270 |
|
|
271 |
try { |
|
272 |
iCount = m_Points.getShapesCount(); |
|
273 |
values = new double[m_Windows.length][iCount]; |
|
274 |
iValues = new int[m_Windows.length]; |
|
275 |
m_dMean = new double[m_Windows.length]; |
|
276 |
m_dMin = new double[m_Windows.length]; |
|
277 |
m_dMax = new double[m_Windows.length]; |
|
278 |
m_dStdDev = new double[m_Windows.length]; |
|
279 |
for (i = 0; i < m_Windows.length; i++) { |
|
280 |
m_dMin[i] = Double.MAX_VALUE; |
|
281 |
m_dMax[i] = Double.NEGATIVE_INFINITY; |
|
282 |
} |
|
283 |
setProgressText(Sextante.getText("Calculating_statistical_values")); |
|
284 |
final IFeatureIterator iter = m_Points.iterator(); |
|
285 |
i = 0; |
|
286 |
while (iter.hasNext() && setProgress(i, iCount)) { |
|
287 |
final IFeature feature = iter.next(); |
|
288 |
pt = feature.getGeometry().getCoordinate(); |
|
289 |
for (j = 0; j < m_Windows.length; j++) { |
|
290 |
dValue = m_Windows[j].getValueAt(pt.x, pt.y); |
|
291 |
if (!m_Windows[j].isNoDataValue(dValue)) { |
|
292 |
values[j][i] = dValue; |
|
293 |
m_dMean[j] += dValue; |
|
294 |
m_dMin[j] = Math.min(m_dMin[j], dValue); |
|
295 |
m_dMax[j] = Math.max(m_dMax[j], dValue); |
|
296 |
iValues[j]++; |
|
297 |
} |
|
298 |
else { |
|
299 |
values[j][i] = NODATA; |
|
300 |
} |
|
301 |
} |
|
302 |
i++; |
|
303 |
} |
|
304 |
iter.close(); |
|
305 |
|
|
306 |
if (m_Task.isCanceled()) { |
|
307 |
return; |
|
308 |
} |
|
309 |
|
|
310 |
for (i = 0; i < m_Windows.length; i++) { |
|
311 |
if (iValues[i] != 0) { |
|
312 |
m_dMean[i] /= iValues[i]; |
|
313 |
} |
|
314 |
else { |
|
315 |
throw new GeoAlgorithmExecutionException(Sextante.getText("Error_calculando_valores_estadisticos")); |
|
316 |
} |
|
317 |
} |
|
318 |
|
|
319 |
if (m_iMethod == MAHALANOBIS) { |
|
320 |
for (iRow = 0; iRow < m_Windows.length; iRow++) { |
|
321 |
for (iCol = 0; iCol < iRow + 1; iCol++) { |
|
322 |
dCov = calculateCovariance(values[iCol], m_dMean[iCol], values[iRow], m_dMean[iRow]); |
|
323 |
if (dCov != NODATA) { |
|
324 |
covariances[iRow][iCol] = dCov; |
|
325 |
covariances[iCol][iRow] = dCov; |
|
326 |
} |
|
327 |
else { |
|
328 |
throw new GeoAlgorithmExecutionException(Sextante.getText("Error_calculando_valores_estadisticos")); |
|
329 |
} |
|
330 |
} |
|
331 |
} |
|
332 |
|
|
333 |
final Matrix C = new Matrix(covariances); |
|
334 |
m_Inverse = C.inverse(); |
|
335 |
} |
|
336 |
else if (m_iMethod == BIOCLIM) { |
|
337 |
for (i = 0; i < m_Windows.length; i++) { |
|
338 |
m_dStdDev[i] = calculateCovariance(values[i], m_dMean[i], values[i], m_dMean[i]); |
|
339 |
} |
|
340 |
} |
|
341 |
|
|
342 |
|
|
343 |
} |
|
344 |
catch (final Exception e) { |
|
345 |
throw new GeoAlgorithmExecutionException(Sextante.getText("Error_calculando_valores_estadisticos")); |
|
346 |
} |
|
347 |
} |
|
348 |
|
|
349 |
|
|
350 |
private double calculateCovariance(final double[] xx, |
|
351 |
final double x, |
|
352 |
final double[] yy, |
|
353 |
final double y) { |
|
354 |
|
|
355 |
double dSum = 0; |
|
356 |
int iValues = 0; |
|
357 |
|
|
358 |
for (int i = 0; i < yy.length; i++) { |
|
359 |
if ((xx[i] != NODATA) && (yy[i] != NODATA)) { |
|
360 |
dSum += (xx[i] - x) * (yy[i] - y); |
|
361 |
iValues++; |
|
362 |
} |
|
363 |
} |
|
364 |
if (iValues > 1) { |
|
365 |
return dSum / (iValues - 1); |
|
366 |
} |
|
367 |
else { |
|
368 |
return NODATA; |
|
369 |
} |
|
370 |
|
|
371 |
} |
|
372 |
|
|
373 |
} |
|
0 | 374 |
org.gvsig.toolbox/tags/org.gvsig.toolbox-1.0.76/org.gvsig.toolbox.algorithm/src/main/java/es/unex/sextante/gridAnalysis/supervisedClassification/SupervisedClassificationAlgorithm.java | ||
---|---|---|
1 |
package es.unex.sextante.gridAnalysis.supervisedClassification; |
|
2 |
|
|
3 |
import java.awt.geom.Rectangle2D; |
|
4 |
import java.util.ArrayList; |
|
5 |
import java.util.Arrays; |
|
6 |
import java.util.HashMap; |
|
7 |
import java.util.Iterator; |
|
8 |
import java.util.Set; |
|
9 |
|
|
10 |
import com.vividsolutions.jts.geom.Coordinate; |
|
11 |
import com.vividsolutions.jts.geom.Envelope; |
|
12 |
import com.vividsolutions.jts.geom.Geometry; |
|
13 |
|
|
14 |
import es.unex.sextante.additionalInfo.AdditionalInfoMultipleInput; |
|
15 |
import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer; |
|
16 |
import es.unex.sextante.core.AnalysisExtent; |
|
17 |
import es.unex.sextante.core.GeoAlgorithm; |
|
18 |
import es.unex.sextante.core.Sextante; |
|
19 |
import es.unex.sextante.dataObjects.IFeature; |
|
20 |
import es.unex.sextante.dataObjects.IFeatureIterator; |
|
21 |
import es.unex.sextante.dataObjects.IRasterLayer; |
|
22 |
import es.unex.sextante.dataObjects.ITable; |
|
23 |
import es.unex.sextante.dataObjects.IVectorLayer; |
|
24 |
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
|
25 |
import es.unex.sextante.exceptions.IteratorException; |
|
26 |
import es.unex.sextante.exceptions.OptionalParentParameterException; |
|
27 |
import es.unex.sextante.exceptions.RepeatedParameterNameException; |
|
28 |
import es.unex.sextante.exceptions.UndefinedParentParameterNameException; |
|
29 |
import es.unex.sextante.exceptions.UnsupportedOutputChannelException; |
|
30 |
import es.unex.sextante.math.simpleStats.SimpleStats; |
|
31 |
import es.unex.sextante.parameters.RasterLayerAndBand; |
|
32 |
|
|
33 |
public class SupervisedClassificationAlgorithm |
|
34 |
extends |
|
35 |
GeoAlgorithm { |
|
36 |
|
|
37 |
public static final String INPUT = "INPUT"; |
|
38 |
public static final String POLYGONS = "POLYGONS"; |
|
39 |
public static final String FIELD = "FIELD"; |
|
40 |
public static final String METHOD = "METHOD"; |
|
41 |
public static final String CLASSIFICATION = "CLASSIFICATION"; |
|
42 |
public static final String CLASSES = "CLASSES"; |
|
43 |
|
|
44 |
public static final int METHOD_PARALELLPIPED = 0; |
|
45 |
public static final int METHOD_MIN_DISTANCE = 1; |
|
46 |
public static final int METHOD_MAX_LIKELIHOOD = 2; |
|
47 |
|
|
48 |
private int m_iMinX, m_iMinY; |
|
49 |
private int m_iField; |
|
50 |
private IRasterLayer[] m_Window; |
|
51 |
private IRasterLayer m_Output; |
|
52 |
private ArrayList m_Bands; |
|
53 |
private IVectorLayer m_Polygons; |
|
54 |
private ITable m_Table; |
|
55 |
private HashMap m_Classes; |
|
56 |
private int[] m_iBands; |
|
57 |
|
|
58 |
|
|
59 |
@Override |
|
60 |
public void defineCharacteristics() { |
|
61 |
|
|
62 |
final String sMethod[] = { Sextante.getText("Parallelepiped"), Sextante.getText("Minimum_distance"), |
|
63 |
Sextante.getText("Maximum_likelihood") }; |
|
64 |
|
|
65 |
setName(Sextante.getText("Supervised_classification")); |
|
66 |
setGroup(Sextante.getText("Raster_layer_analysis")); |
|
67 |
setUserCanDefineAnalysisExtent(true); |
|
68 |
|
|
69 |
try { |
|
70 |
m_Parameters.addMultipleInput(INPUT, Sextante.getText("Bands"), AdditionalInfoMultipleInput.DATA_TYPE_BAND, true); |
|
71 |
m_Parameters.addInputVectorLayer(POLYGONS, Sextante.getText("Polygons"), AdditionalInfoVectorLayer.SHAPE_TYPE_POLYGON, |
|
72 |
true); |
|
73 |
m_Parameters.addTableField(FIELD, Sextante.getText("Field_with_class_value"), "POLYGONS"); |
|
74 |
m_Parameters.addSelection(METHOD, Sextante.getText("Method"), sMethod); |
|
75 |
addOutputRasterLayer(CLASSIFICATION, Sextante.getText("Classification")); |
|
76 |
addOutputTable(CLASSES, Sextante.getText("Classes")); |
|
77 |
} |
|
78 |
catch (final RepeatedParameterNameException e) { |
|
79 |
Sextante.addErrorToLog(e); |
|
80 |
} |
|
81 |
catch (final OptionalParentParameterException e) { |
|
82 |
Sextante.addErrorToLog(e); |
|
83 |
} |
|
84 |
catch (final UndefinedParentParameterNameException e) { |
|
85 |
Sextante.addErrorToLog(e); |
|
86 |
} |
|
87 |
|
|
88 |
} |
|
89 |
|
|
90 |
|
|
91 |
@Override |
|
92 |
public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
|
93 |
|
|
94 |
int i; |
|
95 |
AnalysisExtent ge; |
|
96 |
|
|
97 |
final int iMethod = m_Parameters.getParameterValueAsInt(METHOD); |
|
98 |
m_iField = m_Parameters.getParameterValueAsInt(FIELD); |
|
99 |
m_Bands = m_Parameters.getParameterValueAsArrayList(INPUT); |
|
100 |
m_Polygons = m_Parameters.getParameterValueAsVectorLayer(POLYGONS); |
|
101 |
|
|
102 |
if (m_Bands.size() == 0) { |
|
103 |
throw new GeoAlgorithmExecutionException("At least one band is needed to run this algorithm"); |
|
104 |
} |
|
105 |
|
|
106 |
m_Classes = new HashMap(); |
|
107 |
|
|
108 |
getClassInformation(); |
|
109 |
|
|
110 |
if (m_Task.isCanceled()) { |
|
111 |
return false; |
|
112 |
} |
|
113 |
|
|
114 |
m_Output = getNewRasterLayer(CLASSIFICATION, Sextante.getText("Classification"), IRasterLayer.RASTER_DATA_TYPE_SHORT); |
|
115 |
m_Output.setNoDataValue(-1); |
|
116 |
ge = m_Output.getWindowGridExtent(); |
|
117 |
|
|
118 |
for (i = 0; i < m_Window.length; i++) { |
|
119 |
m_Window[i].setWindowExtent(ge); |
|
120 |
} |
|
121 |
|
|
122 |
switch (iMethod) { |
|
123 |
case 0: |
|
124 |
doParalellpiped(); |
|
125 |
case 1: |
|
126 |
default: |
|
127 |
doMinimumDistance(); |
|
128 |
case 2: |
|
129 |
doMaximumLikelihood(); |
|
130 |
} |
|
131 |
|
|
132 |
return !m_Task.isCanceled(); |
|
133 |
|
|
134 |
} |
|
135 |
|
|
136 |
|
|
137 |
private void getClassInformation() throws UnsupportedOutputChannelException { |
|
138 |
|
|
139 |
int i, j; |
|
140 |
int iGrid; |
|
141 |
Object classID; |
|
142 |
Set set; |
|
143 |
Iterator iter; |
|
144 |
RasterLayerAndBand band; |
|
145 |
ArrayList stats; |
|
146 |
String sClass; |
|
147 |
final String sField[] = new String[1 + m_Bands.size() * 2]; |
|
148 |
final Class types[] = new Class[1 + m_Bands.size() * 2]; |
|
149 |
final Object values[] = new Object[m_Bands.size() * 2 + 1]; |
|
150 |
SimpleStats substats; |
|
151 |
|
|
152 |
sField[0] = Sextante.getText("Name"); |
|
153 |
types[0] = String.class; |
|
154 |
m_Window = new IRasterLayer[m_Bands.size()]; |
|
155 |
for (i = 0; i < m_Bands.size(); i++) { |
|
156 |
band = (RasterLayerAndBand) m_Bands.get(i); |
|
157 |
m_iBands = new int[m_Bands.size()]; |
|
158 |
m_iBands[i] = band.getBand(); |
|
159 |
m_Window[i] = band.getRasterLayer(); |
|
160 |
final AnalysisExtent extent = getAdjustedGridExtent(i); |
|
161 |
m_Window[i].setWindowExtent(extent); |
|
162 |
sField[i * 2 + 1] = band.getRasterLayer().getName() + "|" + Integer.toString(band.getBand()); |
|
163 |
sField[i * 2 + 2] = band.getRasterLayer().getName() + "|" + Integer.toString(band.getBand()); |
|
164 |
types[i * 2 + 1] = Double.class; |
|
165 |
types[i * 2 + 2] = Double.class; |
|
166 |
} |
|
167 |
|
|
168 |
|
|
169 |
setProgressText(Sextante.getText("Calculating_spectral_signatures")); |
|
170 |
i = 0; |
|
171 |
final int iShapeCount = m_Polygons.getShapesCount(); |
|
172 |
final IFeatureIterator featureIter = m_Polygons.iterator(); |
|
173 |
while (featureIter.hasNext() && setProgress(i, iShapeCount)) { |
|
174 |
IFeature feature; |
|
175 |
try { |
|
176 |
feature = featureIter.next(); |
|
177 |
final Geometry geometry = feature.getGeometry(); |
|
178 |
final Object[] record = feature.getRecord().getValues(); |
|
179 |
sClass = record[m_iField].toString(); |
|
180 |
if (m_Classes.containsKey(sClass)) { |
|
181 |
stats = (ArrayList) m_Classes.get(sClass); |
|
182 |
} |
|
183 |
else { |
|
184 |
stats = new ArrayList(); |
|
185 |
for (j = 0; j < m_Bands.size(); j++) { |
|
186 |
stats.add(new SimpleStats()); |
|
187 |
} |
|
188 |
m_Classes.put(sClass, stats); |
|
189 |
} |
|
190 |
doPolygon(geometry, stats); |
|
191 |
i++; |
|
192 |
} |
|
193 |
catch (final IteratorException e) { |
|
194 |
//we ignore wrong features |
|
195 |
} |
|
196 |
} |
|
197 |
featureIter.close(); |
|
198 |
|
|
199 |
if (m_Task.isCanceled()) { |
|
200 |
return; |
|
201 |
} |
|
202 |
|
|
203 |
m_Table = getNewTable(CLASSES, Sextante.getText("Classes"), types, sField); |
|
204 |
|
|
205 |
set = m_Classes.keySet(); |
|
206 |
iter = set.iterator(); |
|
207 |
|
|
208 |
while (iter.hasNext()) { |
|
209 |
classID = iter.next(); |
|
210 |
stats = (ArrayList) m_Classes.get(classID); |
|
211 |
values[0] = new String(classID.toString()); |
|
212 |
for (iGrid = 0; iGrid < m_Bands.size(); iGrid++) { |
|
213 |
substats = (SimpleStats) stats.get(iGrid); |
|
214 |
values[1 + iGrid * 2] = new Double(substats.getMean()); |
|
215 |
values[2 + iGrid * 2] = new Double(substats.getStdDev()); |
|
216 |
} |
|
217 |
m_Table.addRecord(values); |
|
218 |
} |
|
219 |
|
|
220 |
} |
|
221 |
|
|
222 |
|
|
223 |
private void doPolygon(final Geometry geom, |
|
224 |
final ArrayList stats) { |
|
225 |
|
|
226 |
for (int i = 0; i < geom.getNumGeometries(); i++) { |
|
227 |
final Geometry part = geom.getGeometryN(i); |
|
228 |
doPolygonPart(part, stats); |
|
229 |
} |
|
230 |
|
|
231 |
} |
|
232 |
|
|
233 |
|
|
234 |
private boolean getCrossing(final Coordinate crossing, |
|
235 |
final Coordinate a1, |
|
236 |
final Coordinate a2, |
|
237 |
final Coordinate b1, |
|
238 |
final Coordinate b2) { |
|
239 |
|
|
240 |
double lambda, div, a_dx, a_dy, b_dx, b_dy; |
|
241 |
|
|
242 |
a_dx = a2.x - a1.x; |
|
243 |
a_dy = a2.y - a1.y; |
|
244 |
|
|
245 |
b_dx = b2.x - b1.x; |
|
246 |
b_dy = b2.y - b1.y; |
|
247 |
|
|
248 |
if ((div = a_dx * b_dy - b_dx * a_dy) != 0.0) { |
|
249 |
lambda = ((b1.x - a1.x) * b_dy - b_dx * (b1.y - a1.y)) / div; |
|
250 |
|
|
251 |
crossing.x = a1.x + lambda * a_dx; |
|
252 |
crossing.y = a1.y + lambda * a_dy; |
|
253 |
|
|
254 |
return true; |
|
255 |
|
|
256 |
} |
|
257 |
|
|
258 |
return false; |
|
259 |
|
|
260 |
} |
|
261 |
|
|
262 |
|
|
263 |
private AnalysisExtent getAdjustedGridExtent(final int iLayer) { |
|
264 |
|
|
265 |
double iMaxX, iMaxY; |
|
266 |
double dMinX, dMinY; |
|
267 |
double dMinX2, dMinY2, dMaxX2, dMaxY2; |
|
268 |
double dCellSize; |
|
269 |
final AnalysisExtent ge = new AnalysisExtent(); |
|
270 |
|
|
271 |
final Rectangle2D rect = m_Polygons.getFullExtent(); |
|
272 |
dMinX = m_Window[iLayer].getLayerGridExtent().getXMin(); |
|
273 |
dMinY = m_Window[iLayer].getLayerGridExtent().getYMin(); |
|
274 |
dCellSize = m_Window[iLayer].getLayerGridExtent().getCellSize(); |
|
275 |
|
|
276 |
m_iMinX = (int) Math.floor((rect.getMinX() - dMinX) / dCellSize); |
|
277 |
iMaxX = Math.ceil((rect.getMaxX() - dMinX) / dCellSize); |
|
278 |
m_iMinY = (int) Math.floor((rect.getMinY() - dMinY) / dCellSize); |
|
279 |
iMaxY = Math.ceil((rect.getMaxY() - dMinY) / dCellSize); |
|
280 |
|
|
281 |
dMinX2 = dMinX + m_iMinX * dCellSize; |
|
282 |
dMinY2 = dMinY + m_iMinY * dCellSize; |
|
283 |
dMaxX2 = dMinX + iMaxX * dCellSize; |
|
284 |
dMaxY2 = dMinY + iMaxY * dCellSize; |
|
285 |
|
|
286 |
ge.setCellSize(dCellSize); |
|
287 |
ge.setXRange(dMinX2, dMaxX2, true); |
|
288 |
ge.setYRange(dMinY2, dMaxY2, true); |
|
289 |
|
|
290 |
return ge; |
|
291 |
|
|
292 |
} |
|
293 |
|
|
294 |
|
|
295 |
private void doPolygonPart(final Geometry geom, |
|
296 |
final ArrayList stats) { |
|
297 |
|
|
298 |
boolean bFill; |
|
299 |
boolean bCrossing[]; |
|
300 |
int iNX, iNY; |
|
301 |
int i; |
|
302 |
int x, y, ix, xStart, xStop; |
|
303 |
int iPoint; |
|
304 |
double yPos; |
|
305 |
double dValue; |
|
306 |
AnalysisExtent ge; |
|
307 |
SimpleStats substats; |
|
308 |
Coordinate pLeft, pRight, pa, pb, p; |
|
309 |
|
|
310 |
final Envelope extent = geom.getEnvelopeInternal(); |
|
311 |
|
|
312 |
final Coordinate[] points = geom.getCoordinates(); |
|
313 |
|
|
314 |
for (i = 0; i < m_Window.length; i++) { |
|
315 |
p = new Coordinate(); |
|
316 |
substats = (SimpleStats) stats.get(i); |
|
317 |
ge = m_Window[i].getWindowGridExtent(); |
|
318 |
iNX = ge.getNX(); |
|
319 |
iNY = ge.getNY(); |
|
320 |
bCrossing = new boolean[iNX]; |
|
321 |
|
|
322 |
xStart = (int) ((extent.getMinX() - ge.getXMin()) / ge.getCellSize()) - 1; |
|
323 |
if (xStart < 0) { |
|
324 |
xStart = 0; |
|
325 |
} |
|
326 |
|
|
327 |
xStop = (int) ((extent.getMaxX() - ge.getXMin()) / ge.getCellSize()) + 1; |
|
328 |
if (xStop >= iNX) { |
|
329 |
xStop = iNX - 1; |
|
330 |
} |
|
331 |
|
|
332 |
for (y = 0, yPos = ge.getYMax(); y < iNY; y++, yPos -= ge.getCellSize()) { |
|
333 |
if ((yPos >= extent.getMinY()) && (yPos <= extent.getMaxY())) { |
|
334 |
Arrays.fill(bCrossing, false); |
|
335 |
pLeft = new Coordinate(ge.getXMin() - 1.0, yPos); |
|
336 |
pRight = new Coordinate(ge.getXMax() + 1.0, yPos); |
|
337 |
|
|
338 |
pb = points[points.length - 1]; |
|
339 |
|
|
340 |
for (iPoint = 0; iPoint < points.length; iPoint++) { |
|
341 |
pa = pb; |
|
342 |
pb = points[iPoint]; |
|
343 |
|
|
344 |
if ((((pa.y <= yPos) && (yPos < pb.y)) || ((pa.y > yPos) && (yPos >= pb.y)))) { |
|
345 |
getCrossing(p, pa, pb, pLeft, pRight); |
|
346 |
|
|
347 |
ix = (int) ((p.x - ge.getXMin()) / ge.getCellSize() + 1.0); |
|
348 |
|
|
349 |
if (ix < 0) { |
|
350 |
ix = 0; |
|
351 |
} |
|
352 |
else if (ix >= iNX) { |
|
353 |
ix = iNX - 1; |
|
354 |
} |
|
355 |
|
|
356 |
bCrossing[ix] = !bCrossing[ix]; |
|
357 |
} |
|
358 |
} |
|
359 |
|
|
360 |
for (x = xStart, bFill = false; x <= xStop; x++) { |
|
361 |
if (bCrossing[x]) { |
|
362 |
bFill = !bFill; |
|
363 |
} |
|
364 |
if (bFill) { |
|
365 |
dValue = m_Window[i].getCellValueAsDouble(x /*+ m_iMinX - 1*/, y /*+ m_iMinY - 1*/); |
|
366 |
if (!m_Window[i].isNoDataValue(dValue)) { |
|
367 |
substats.addValue(dValue); |
|
368 |
} |
|
369 |
} |
|
370 |
} |
|
371 |
} |
|
372 |
} |
|
373 |
} |
|
374 |
|
|
375 |
} |
|
376 |
|
|
377 |
|
|
378 |
private void doParalellpiped() { |
|
379 |
|
|
380 |
int iNX, iNY; |
|
381 |
int x, y; |
|
382 |
int iMatchingClass = 0; |
|
383 |
int iClass, iGrid; |
|
384 |
final double dMean[][] = new double[m_Classes.size()][m_Window.length]; |
|
385 |
final double dStdDev[][] = new double[m_Classes.size()][m_Window.length]; |
|
386 |
double dValue; |
|
387 |
ArrayList stats; |
|
388 |
SimpleStats substats; |
|
389 |
Set set; |
|
390 |
Iterator iter; |
|
391 |
|
|
392 |
iNX = m_Output.getWindowGridExtent().getNX(); |
|
393 |
iNY = m_Output.getWindowGridExtent().getNY(); |
|
394 |
|
|
395 |
set = m_Classes.keySet(); |
|
396 |
iter = set.iterator(); |
|
397 |
iClass = 0; |
|
398 |
while (iter.hasNext()) { |
|
399 |
stats = (ArrayList) m_Classes.get(iter.next()); |
|
400 |
for (iGrid = 0; iGrid < m_Window.length; iGrid++) { |
|
401 |
substats = ((SimpleStats) stats.get(iGrid)); |
|
402 |
dMean[iClass][iGrid] = substats.getMean(); |
|
403 |
dStdDev[iClass][iGrid] = Math.sqrt(substats.getVariance()); |
|
404 |
} |
|
405 |
iClass++; |
|
406 |
} |
|
407 |
|
|
408 |
for (y = 0; y < iNY; y++) { |
|
409 |
for (x = 0; x < iNX; x++) { |
|
410 |
for (iClass = 0; iClass < m_Classes.size(); iClass++) { |
|
411 |
iMatchingClass = iClass; |
|
412 |
for (iGrid = 0; iGrid < m_Window.length; iGrid++) { |
|
413 |
dValue = m_Window[iGrid].getCellValueAsDouble(x, y); |
|
414 |
if (!m_Window[iGrid].isNoDataValue(dValue)) { |
|
415 |
if (Math.abs(m_Window[iGrid].getCellValueAsDouble(x, y) - dMean[iClass][iGrid]) > dStdDev[iClass][iGrid]) { |
|
416 |
iMatchingClass = -1; |
|
417 |
break; |
|
418 |
} |
|
419 |
} |
|
420 |
else { |
|
421 |
break; |
|
422 |
} |
|
423 |
} |
|
424 |
if (iMatchingClass != -1) { |
|
425 |
break; |
|
426 |
} |
|
427 |
} |
|
428 |
if (iMatchingClass != -1) { |
|
429 |
m_Output.setCellValue(x, y, iMatchingClass + 1); |
|
430 |
} |
|
431 |
else { |
|
432 |
m_Output.setNoData(x, y); |
|
433 |
} |
|
434 |
} |
|
435 |
} |
|
436 |
|
|
437 |
} |
|
438 |
|
|
439 |
|
|
440 |
private void doMinimumDistance() { |
|
441 |
|
|
442 |
int iNX, iNY; |
|
443 |
int x, y; |
|
444 |
int iClass, iGrid, iMin = 0; |
|
445 |
final double dMean[][] = new double[m_Classes.size()][m_Window.length]; |
|
446 |
double dMin, d, e; |
|
447 |
double dValue; |
|
448 |
ArrayList stats; |
|
449 |
Set set; |
|
450 |
Iterator iter; |
|
451 |
|
|
452 |
iNX = m_Output.getWindowGridExtent().getNX(); |
|
453 |
iNY = m_Output.getWindowGridExtent().getNY(); |
|
454 |
|
|
455 |
set = m_Classes.keySet(); |
|
456 |
iter = set.iterator(); |
|
457 |
iClass = 0; |
|
458 |
while (iter.hasNext()) { |
|
459 |
stats = (ArrayList) m_Classes.get(iter.next()); |
|
460 |
for (iGrid = 0; iGrid < m_Window.length; iGrid++) { |
|
461 |
dMean[iClass][iGrid] = ((SimpleStats) stats.get(iGrid)).getMean(); |
|
462 |
} |
|
463 |
iClass++; |
|
464 |
} |
|
465 |
|
|
466 |
for (y = 0; y < iNY; y++) { |
|
467 |
for (x = 0; x < iNX; x++) { |
|
468 |
for (iClass = 0, dMin = -1.0; iClass < m_Classes.size(); iClass++) { |
|
469 |
for (iGrid = 0, d = 0.0; iGrid < m_Window.length; iGrid++) { |
|
470 |
dValue = m_Window[iGrid].getCellValueAsDouble(x, y); |
|
471 |
if (!m_Window[iGrid].isNoDataValue(dValue)) { |
|
472 |
e = m_Window[iGrid].getCellValueAsDouble(x, y) - dMean[iClass][iGrid]; |
|
473 |
d += e * e; |
|
474 |
if ((dMin < 0.0) || (dMin > d)) { |
|
475 |
dMin = d; |
|
476 |
iMin = iClass; |
|
477 |
} |
|
478 |
} |
|
479 |
else { |
|
480 |
dMin = -1; |
|
481 |
} |
|
482 |
} |
|
483 |
} |
|
484 |
|
|
485 |
if (dMin >= 0.0) { |
|
486 |
m_Output.setCellValue(x, y, iMin + 1); |
|
487 |
} |
|
488 |
else { |
|
489 |
m_Output.setNoData(x, y); |
|
490 |
} |
|
491 |
} |
|
492 |
} |
|
493 |
|
|
494 |
} |
|
495 |
|
|
496 |
|
|
497 |
private void doMaximumLikelihood() { |
|
498 |
|
|
499 |
int iNX, iNY; |
|
500 |
int x, y; |
|
501 |
int iClass, iGrid, iMax = 0; |
|
502 |
final double dMean[][] = new double[m_Classes.size()][m_Window.length]; |
|
503 |
final double dStdDev[][] = new double[m_Classes.size()][m_Window.length]; |
|
504 |
final double dK[][] = new double[m_Classes.size()][m_Window.length]; |
|
505 |
double dMax, d, e; |
|
506 |
double dValue; |
|
507 |
ArrayList stats; |
|
508 |
SimpleStats substats; |
|
509 |
Set set; |
|
510 |
Iterator iter; |
|
511 |
|
|
512 |
iNX = m_Output.getWindowGridExtent().getNX(); |
|
513 |
iNY = m_Output.getWindowGridExtent().getNY(); |
|
514 |
|
|
515 |
set = m_Classes.keySet(); |
|
516 |
iter = set.iterator(); |
|
517 |
iClass = 0; |
|
518 |
while (iter.hasNext()) { |
|
519 |
stats = (ArrayList) m_Classes.get(iter.next()); |
|
520 |
for (iGrid = 0; iGrid < m_Window.length; iGrid++) { |
|
521 |
substats = ((SimpleStats) stats.get(iGrid)); |
|
522 |
dMean[iClass][iGrid] = substats.getMean(); |
|
523 |
dStdDev[iClass][iGrid] = Math.sqrt(substats.getVariance()); |
|
524 |
dK[iClass][iGrid] = 1.0 / (dStdDev[iClass][iGrid] * Math.sqrt(2.0 * Math.PI)); |
|
525 |
} |
|
526 |
iClass++; |
|
527 |
} |
|
528 |
|
|
529 |
for (y = 0; y < iNY; y++) { |
|
530 |
for (x = 0; x < iNX; x++) { |
|
531 |
for (iClass = 0, dMax = 0.0; iClass < m_Classes.size(); iClass++) { |
|
532 |
for (iGrid = 0, d = 0.0; iGrid < m_Window.length; iGrid++) { |
|
533 |
dValue = m_Window[iGrid].getCellValueAsDouble(x, y); |
|
534 |
if (!m_Window[iGrid].isNoDataValue(dValue)) { |
|
535 |
e = (m_Window[iGrid].getCellValueAsDouble(x, y) - dMean[iClass][iGrid]) / dStdDev[iClass][iGrid]; |
|
536 |
e = dK[iClass][iGrid] * Math.exp(-0.5 * e * e); |
|
537 |
d += e * e; |
|
538 |
if (dMax < d) { |
|
539 |
dMax = d; |
|
540 |
iMax = iClass; |
|
541 |
} |
|
542 |
} |
|
543 |
else { |
|
544 |
dMax = -1; |
|
545 |
} |
|
546 |
} |
|
547 |
} |
|
548 |
|
|
549 |
if (dMax > 0.0) { |
|
550 |
m_Output.setCellValue(x, y, iMax + 1); |
|
551 |
} |
|
552 |
else { |
|
553 |
m_Output.setNoData(x, y); |
|
554 |
} |
|
555 |
} |
|
556 |
} |
|
557 |
|
|
558 |
} |
|
559 |
|
|
560 |
|
|
561 |
} |
|
0 | 562 |
org.gvsig.toolbox/tags/org.gvsig.toolbox-1.0.76/org.gvsig.toolbox.algorithm/src/main/java/es/unex/sextante/gridAnalysis/fuzzify/FuzzifyAlgorithm.java | ||
---|---|---|
1 |
package es.unex.sextante.gridAnalysis.fuzzify; |
|
2 |
|
|
3 |
import java.util.Arrays; |
|
4 |
|
|
5 |
import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue; |
|
6 |
import es.unex.sextante.core.GeoAlgorithm; |
|
7 |
import es.unex.sextante.core.AnalysisExtent; |
|
8 |
import es.unex.sextante.core.Sextante; |
|
9 |
import es.unex.sextante.dataObjects.IRasterLayer; |
|
10 |
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
|
11 |
import es.unex.sextante.exceptions.RepeatedParameterNameException; |
|
12 |
import es.unex.sextante.rasterWrappers.GridWrapper; |
|
13 |
|
|
14 |
public class FuzzifyAlgorithm |
|
15 |
extends |
|
16 |
GeoAlgorithm { |
|
17 |
|
|
18 |
public static final String INPUT = "INPUT"; |
|
19 |
public static final String FUNCTIONTYPE = "FUNCTIONTYPE"; |
|
20 |
public static final String RESULT = "RESULT"; |
|
21 |
public static final String A = "A"; |
|
22 |
public static final String B = "B"; |
|
23 |
public static final String C = "C"; |
|
24 |
public static final String D = "D"; |
|
25 |
|
|
26 |
public static final int MEMBER_FUNCTION_LINEAL = 0; |
|
27 |
public static final int MEMBER_FUNCTION_SIGMOIDAL = 1; |
|
28 |
public static final int MEMBER_FUNCTION_J_SHAPED = 2; |
|
29 |
|
|
30 |
|
|
31 |
int m_iNX, m_iNY; |
|
32 |
IRasterLayer m_Grid; |
|
33 |
IRasterLayer m_Result; |
|
34 |
|
|
35 |
|
|
36 |
@Override |
|
37 |
public void defineCharacteristics() { |
|
38 |
|
|
39 |
final String[] sOptions = { Sextante.getText("Linear"), Sextante.getText("Sigmoidal"), Sextante.getText("J-shaped") }; |
|
40 |
|
|
41 |
setName(Sextante.getText("Fuzzify")); |
|
42 |
setGroup(Sextante.getText("Fuzzy_logic")); |
|
43 |
setUserCanDefineAnalysisExtent(true); |
|
44 |
|
|
45 |
try { |
|
46 |
m_Parameters.addInputRasterLayer(INPUT, Sextante.getText("Input_Layer"), true); |
|
47 |
m_Parameters.addSelection(FUNCTIONTYPE, Sextante.getText("Member_function"), sOptions); |
|
48 |
m_Parameters.addNumericalValue(A, Sextante.getText("Control_point_A"), 10, |
|
49 |
AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE); |
|
50 |
m_Parameters.addNumericalValue(B, Sextante.getText("Control_point_B"), 10, |
|
51 |
AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE); |
|
52 |
m_Parameters.addNumericalValue(C, Sextante.getText("Control_point_C"), 10, |
|
53 |
AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE); |
|
54 |
m_Parameters.addNumericalValue(D, Sextante.getText("Control_point_D"), 10, |
|
55 |
AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE); |
|
56 |
addOutputRasterLayer(RESULT, Sextante.getText("Result")); |
|
57 |
} |
|
58 |
catch (final RepeatedParameterNameException e) { |
|
59 |
Sextante.addErrorToLog(e); |
|
60 |
} |
|
61 |
|
|
62 |
} |
|
63 |
|
|
64 |
|
|
65 |
@Override |
|
66 |
public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
|
67 |
|
|
68 |
int x, y; |
|
69 |
double dX; |
|
70 |
double dW; |
|
71 |
double dValue; |
|
72 |
|
|
73 |
m_Grid = m_Parameters.getParameterValueAsRasterLayer(INPUT); |
|
74 |
final int iType = m_Parameters.getParameterValueAsInt(FUNCTIONTYPE); |
|
75 |
double dA = m_Parameters.getParameterValueAsDouble(A); |
|
76 |
double dB = m_Parameters.getParameterValueAsDouble(B); |
|
77 |
double dC = m_Parameters.getParameterValueAsDouble(C); |
|
78 |
double dD = m_Parameters.getParameterValueAsDouble(D); |
|
79 |
|
|
80 |
final double dPts[] = new double[4]; |
|
81 |
dPts[0] = dA; |
|
82 |
dPts[1] = dB; |
|
83 |
dPts[2] = dC; |
|
84 |
dPts[3] = dD; |
|
85 |
Arrays.sort(dPts); |
|
86 |
dA = dPts[0]; |
|
87 |
dB = dPts[1]; |
|
88 |
dC = dPts[2]; |
|
89 |
dD = dPts[3]; |
|
90 |
|
|
91 |
m_Result = getNewRasterLayer(RESULT, m_Grid.getName() + "_" + Sextante.getText("[fuzzy]"), |
|
92 |
IRasterLayer.RASTER_DATA_TYPE_DOUBLE); |
|
93 |
|
|
94 |
final AnalysisExtent extent = m_Result.getWindowGridExtent(); |
|
95 |
|
|
96 |
m_Grid.setWindowExtent(extent); |
|
97 |
m_Grid.setInterpolationMethod(GridWrapper.INTERPOLATION_BSpline); |
|
98 |
|
|
99 |
final int iNX = m_Grid.getNX(); |
|
100 |
final int iNY = m_Grid.getNY(); |
|
101 |
|
|
102 |
for (y = 0; (y < iNY) & setProgress(y, iNY); y++) { |
|
103 |
for (x = 0; x < iNX; x++) { |
|
104 |
dValue = m_Grid.getCellValueAsDouble(x, y); |
|
105 |
if (!m_Grid.isNoDataValue(dValue)) { |
|
106 |
if ((dValue <= dA) || (dValue >= dD)) { |
|
107 |
m_Result.setCellValue(x, y, 0); |
|
108 |
} |
|
109 |
else if ((dValue >= dB) && (dValue <= dC)) { |
|
110 |
m_Result.setCellValue(x, y, 1); |
|
111 |
} |
|
112 |
else { |
|
113 |
if (dValue < dB) { |
|
114 |
dX = dValue - dA; |
|
115 |
dW = dB - dA; |
|
116 |
} |
|
117 |
else { |
|
118 |
dX = dD - dValue; |
|
119 |
dW = dD - dC; |
|
120 |
} |
|
121 |
switch (iType) { |
|
122 |
case 0: |
|
123 |
m_Result.setCellValue(x, y, dX / dW); |
|
124 |
break; |
|
125 |
case 1: |
|
126 |
m_Result.setCellValue(x, y, Math.pow(Math.sin(dX / dW * Math.PI / 2.), 2.)); |
|
127 |
break; |
|
128 |
case 2: |
|
129 |
m_Result.setCellValue(x, y, 1. / (1 + Math.pow((dW - dX) / dW, 2.))); |
|
130 |
break; |
|
131 |
} |
|
132 |
} |
|
133 |
} |
|
134 |
else { |
|
135 |
m_Result.setNoData(x, y); |
|
136 |
} |
|
137 |
} |
|
138 |
} |
|
139 |
|
|
140 |
return !m_Task.isCanceled(); |
|
141 |
|
|
142 |
} |
|
143 |
|
|
144 |
} |
|
0 | 145 |
org.gvsig.toolbox/tags/org.gvsig.toolbox-1.0.76/org.gvsig.toolbox.algorithm/src/main/java/es/unex/sextante/gridAnalysis/supervisedClassificationB/SupervisedClassificationBAlgorithm.java | ||
---|---|---|
1 |
package es.unex.sextante.gridAnalysis.supervisedClassificationB; |
|
2 |
|
|
3 |
import java.util.ArrayList; |
|
4 |
import java.util.HashMap; |
|
5 |
import java.util.Iterator; |
|
6 |
import java.util.Set; |
|
7 |
|
|
8 |
import es.unex.sextante.additionalInfo.AdditionalInfoMultipleInput; |
|
9 |
import es.unex.sextante.core.AnalysisExtent; |
|
10 |
import es.unex.sextante.core.GeoAlgorithm; |
|
11 |
import es.unex.sextante.core.Sextante; |
|
12 |
import es.unex.sextante.dataObjects.IRasterLayer; |
|
13 |
import es.unex.sextante.dataObjects.IRecord; |
|
14 |
import es.unex.sextante.dataObjects.IRecordsetIterator; |
|
15 |
import es.unex.sextante.dataObjects.ITable; |
|
16 |
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
|
17 |
import es.unex.sextante.exceptions.RepeatedParameterNameException; |
|
18 |
import es.unex.sextante.parameters.RasterLayerAndBand; |
|
19 |
|
|
20 |
public class SupervisedClassificationBAlgorithm |
|
21 |
extends |
|
22 |
GeoAlgorithm { |
|
23 |
|
|
24 |
public static final String INPUT = "INPUT"; |
|
25 |
public static final String METHOD = "METHOD"; |
|
26 |
public static final String CLASSIFICATION = "CLASSIFICATION"; |
|
27 |
public static final String CLASSES = "CLASSES"; |
|
28 |
public static final String TABLE = "TABLE"; |
|
29 |
|
|
30 |
public static final int METHOD_PARALELLPIPED = 0; |
|
31 |
public static final int METHOD_MIN_DISTANCE = 1; |
|
32 |
public static final int METHOD_MAX_LIKELIHOOD = 2; |
|
33 |
|
|
34 |
private IRasterLayer[] m_Window; |
|
35 |
private IRasterLayer m_Output; |
|
36 |
private ArrayList m_Bands; |
|
37 |
private HashMap m_Classes; |
|
38 |
private int[] m_iBands; |
|
39 |
|
|
40 |
|
|
41 |
@Override |
|
42 |
public void defineCharacteristics() { |
|
43 |
|
|
44 |
final String sMethod[] = { Sextante.getText("Parallelepiped"), Sextante.getText("Minimum_distance"), |
|
45 |
Sextante.getText("Maximum_likelihood") }; |
|
46 |
|
|
47 |
setName(Sextante.getText("Supervised_classification") + "(B)"); |
|
48 |
setGroup(Sextante.getText("Raster_layer_analysis")); |
|
49 |
setUserCanDefineAnalysisExtent(true); |
|
50 |
|
|
51 |
try { |
|
52 |
m_Parameters.addMultipleInput(INPUT, Sextante.getText("Bands"), AdditionalInfoMultipleInput.DATA_TYPE_BAND, true); |
|
53 |
m_Parameters.addInputTable(TABLE, Sextante.getText("Classes"), true); |
|
54 |
m_Parameters.addSelection(METHOD, Sextante.getText("Method"), sMethod); |
|
55 |
addOutputRasterLayer(CLASSIFICATION, Sextante.getText("Classification")); |
|
56 |
//addOutputTable(CLASSES, Sextante.getText("Classes")); |
|
57 |
} |
|
58 |
catch (final RepeatedParameterNameException e) { |
|
59 |
Sextante.addErrorToLog(e); |
|
60 |
} |
|
61 |
|
|
62 |
} |
|
63 |
|
|
64 |
|
|
65 |
@Override |
|
66 |
public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
|
67 |
|
|
68 |
int i; |
|
69 |
AnalysisExtent ge; |
|
70 |
|
|
71 |
final int iMethod = m_Parameters.getParameterValueAsInt(METHOD); |
|
72 |
m_Bands = m_Parameters.getParameterValueAsArrayList(INPUT); |
|
73 |
|
|
74 |
|
|
75 |
if (m_Bands.size() == 0) { |
|
76 |
return false; |
|
77 |
} |
|
78 |
|
|
79 |
m_Classes = new HashMap(); |
|
80 |
|
|
81 |
getClassInformation(); |
|
82 |
|
|
83 |
if (m_Task.isCanceled()) { |
|
84 |
return false; |
|
85 |
} |
|
86 |
|
|
87 |
m_Output = getNewRasterLayer(CLASSIFICATION, Sextante.getText("Classification"), IRasterLayer.RASTER_DATA_TYPE_SHORT); |
|
88 |
m_Output.setNoDataValue(-1); |
|
89 |
ge = m_Output.getWindowGridExtent(); |
|
90 |
|
|
91 |
m_Window = new IRasterLayer[m_Bands.size()]; |
|
92 |
m_iBands = new int[m_Bands.size()]; |
|
93 |
for (i = 0; i < m_Window.length; i++) { |
|
94 |
final RasterLayerAndBand band = (RasterLayerAndBand) m_Bands.get(i); |
|
95 |
m_iBands[i] = band.getBand(); |
|
96 |
m_Window[i] = band.getRasterLayer(); |
|
97 |
m_Window[i].setWindowExtent(ge); |
|
98 |
} |
|
99 |
|
|
100 |
switch (iMethod) { |
|
101 |
case 0: |
|
102 |
doParalellpiped(); |
|
103 |
case 1: |
|
104 |
default: |
|
105 |
doMinimumDistance(); |
|
106 |
case 2: |
|
107 |
doMaximumLikelihood(); |
|
108 |
} |
|
109 |
|
|
110 |
return !m_Task.isCanceled(); |
|
111 |
|
|
112 |
} |
|
113 |
|
|
114 |
|
|
115 |
private void getClassInformation() throws GeoAlgorithmExecutionException { |
|
116 |
|
|
117 |
try { |
|
118 |
final ITable table = m_Parameters.getParameterValueAsTable(TABLE); |
|
119 |
m_Window = new IRasterLayer[m_Bands.size()]; |
|
120 |
|
|
121 |
final IRecordsetIterator iter = table.iterator(); |
|
122 |
while (iter.hasNext()) { |
|
123 |
final IRecord record = iter.next(); |
|
124 |
final String sClassName = record.getValue(0).toString(); |
|
125 |
final ArrayList stats = new ArrayList(); |
|
126 |
for (int i = 0; i < m_Window.length; i++) { |
|
127 |
final String sFieldName = m_Window[i].getName() + "|" + Integer.toString(m_iBands[i] + 1); |
|
128 |
final MeanAndStdDev masd = new MeanAndStdDev(); |
|
129 |
boolean bMatchFound = false; |
|
130 |
for (int j = 1; j < table.getFieldCount(); j += 2) { |
|
131 |
if (table.getFieldName(j).equals(sFieldName)) { |
|
132 |
masd.mean = Double.parseDouble(record.getValue(j).toString()); |
|
133 |
masd.stdDev = Double.parseDouble(record.getValue(j + 1).toString()); |
|
134 |
bMatchFound = true; |
|
135 |
} |
|
136 |
} |
|
137 |
if (!bMatchFound) { |
|
138 |
throw new GeoAlgorithmExecutionException(Sextante.getText("Error_reading_table")); |
|
139 |
} |
|
140 |
stats.add(masd); |
Also available in: Unified diff