root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / gridAnalysis / supervisedClassification / SupervisedClassificationAlgorithm.java @ 59
History | View | Annotate | Download (18.7 KB)
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 |
} |