root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / gridAnalysis / costInRoutesAnisotropicB / CostInRoutesAnisotropicBAlgorithm.java @ 59
History | View | Annotate | Download (9.66 KB)
1 |
package es.unex.sextante.gridAnalysis.costInRoutesAnisotropicB; |
---|---|
2 |
|
3 |
import com.vividsolutions.jts.geom.Coordinate; |
4 |
import com.vividsolutions.jts.geom.Geometry; |
5 |
|
6 |
import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer; |
7 |
import es.unex.sextante.core.GeoAlgorithm; |
8 |
import es.unex.sextante.core.Sextante; |
9 |
import es.unex.sextante.dataObjects.IFeature; |
10 |
import es.unex.sextante.dataObjects.IFeatureIterator; |
11 |
import es.unex.sextante.dataObjects.IRasterLayer; |
12 |
import es.unex.sextante.dataObjects.IVectorLayer; |
13 |
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
14 |
import es.unex.sextante.exceptions.RepeatedParameterNameException; |
15 |
import es.unex.sextante.outputs.IOutputChannel; |
16 |
import es.unex.sextante.outputs.Output; |
17 |
import es.unex.sextante.outputs.OutputVectorLayer; |
18 |
import es.unex.sextante.parameters.FixedTableModel; |
19 |
import es.unex.sextante.rasterWrappers.GridCell; |
20 |
import es.unex.sextante.shapesTools.ShapesTools; |
21 |
|
22 |
public class CostInRoutesAnisotropicBAlgorithm |
23 |
extends
|
24 |
GeoAlgorithm { |
25 |
|
26 |
public static final String ROUTES = "ROUTES"; |
27 |
public static final String COST = "COST"; |
28 |
public static final String COSTDIR = "COSTDIR"; |
29 |
public static final String RESULT = "RESULT"; |
30 |
public static final String FACTORS = "FACTORS"; |
31 |
|
32 |
private static final double ANGLES[][] = { { 135, 180, 225 }, { 90, 0, 270 }, { 45, 0, 315 } }; |
33 |
private static final double NO_DATA = -99999; |
34 |
|
35 |
private IRasterLayer m_Cost;
|
36 |
private double[] m_dDist; |
37 |
private double[] m_dCost; |
38 |
private int m_iLastX, m_iLastY; |
39 |
private int m_iPoints = 0; |
40 |
private int m_iCurrentRoute; |
41 |
private IRasterLayer m_CostDir;
|
42 |
private DeviationAndFactor[] m_Factors; |
43 |
|
44 |
|
45 |
@Override
|
46 |
public void defineCharacteristics() { |
47 |
|
48 |
final String sColumnNames[] = new String[] { Sextante.getText("Difference"), Sextante.getText("Factor") }; |
49 |
|
50 |
setName(Sextante.getText("Cost_for_predefined_routes__anisotropic") + "(B)"); |
51 |
setGroup(Sextante.getText("Cost_distances_and_routes"));
|
52 |
setUserCanDefineAnalysisExtent(true);
|
53 |
|
54 |
try {
|
55 |
m_Parameters.addInputVectorLayer(ROUTES, Sextante.getText("Routes"), AdditionalInfoVectorLayer.SHAPE_TYPE_LINE, true); |
56 |
m_Parameters.addInputRasterLayer(COST, Sextante.getText("Maximum_unitary_cost"), true); |
57 |
m_Parameters.addInputRasterLayer(COSTDIR, Sextante.getText("Direction_of_maximum_cost_[degrees]"), true); |
58 |
m_Parameters.addFixedTable(FACTORS, Sextante.getText("Cost_variation_factors"), sColumnNames, 5, false); |
59 |
addOutputVectorLayer(RESULT, Sextante.getText("Routes_and_cost"), OutputVectorLayer.SHAPE_TYPE_LINE);
|
60 |
} |
61 |
catch (final RepeatedParameterNameException e) { |
62 |
Sextante.addErrorToLog(e); |
63 |
} |
64 |
|
65 |
} |
66 |
|
67 |
|
68 |
@Override
|
69 |
public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
70 |
|
71 |
m_Cost = m_Parameters.getParameterValueAsRasterLayer(COST); |
72 |
m_CostDir = m_Parameters.getParameterValueAsRasterLayer(COSTDIR); |
73 |
|
74 |
final FixedTableModel factors = (FixedTableModel) m_Parameters.getParameterValueAsObject(FACTORS);
|
75 |
|
76 |
m_Factors = new DeviationAndFactor[factors.getRowCount()];
|
77 |
for (int i = 0; i < factors.getRowCount(); i++) { |
78 |
final double dDeviation = Double.parseDouble(factors.getValueAt(i, 0).toString()); |
79 |
final double dFactor = Double.parseDouble(factors.getValueAt(i, 1).toString()); |
80 |
m_Factors[i] = new DeviationAndFactor(dDeviation, dFactor);
|
81 |
} |
82 |
|
83 |
m_Cost.setFullExtent(); |
84 |
|
85 |
m_CostDir.setWindowExtent(m_Cost.getWindowGridExtent()); |
86 |
|
87 |
final IVectorLayer routes = m_Parameters.getParameterValueAsVectorLayer(ROUTES);
|
88 |
|
89 |
if (routes.getShapesCount() == 0) { |
90 |
return false; |
91 |
} |
92 |
final int iShapesCount = routes.getShapesCount(); |
93 |
m_iCurrentRoute = 0;
|
94 |
m_Cost.setFullExtent(); |
95 |
m_dCost = new double[routes.getShapesCount()]; |
96 |
m_dDist = new double[routes.getShapesCount()]; |
97 |
final IFeatureIterator iter = routes.iterator();
|
98 |
while (iter.hasNext() && setProgress(m_iCurrentRoute, iShapesCount)) {
|
99 |
m_iPoints = 0;
|
100 |
final IFeature feature = iter.next();
|
101 |
final Geometry geom = feature.getGeometry();
|
102 |
processLine(geom.getCoordinates()); |
103 |
m_iCurrentRoute++; |
104 |
} |
105 |
iter.close(); |
106 |
|
107 |
if (m_Task.isCanceled()) {
|
108 |
return false; |
109 |
} |
110 |
|
111 |
final Object[][] values = new Object[2][routes.getShapesCount()]; |
112 |
final String[] sFields = { Sextante.getText("Distance"), Sextante.getText("Cost") }; |
113 |
final Class[] types = { Double.class, Double.class }; |
114 |
for (int i = 0; i < routes.getShapesCount(); i++) { |
115 |
values[0][i] = new Double(m_dDist[i]); |
116 |
values[1][i] = new Double(m_dCost[i]); |
117 |
} |
118 |
|
119 |
final IOutputChannel channel = getOutputChannel(RESULT);
|
120 |
final Output out = new OutputVectorLayer(); |
121 |
out.setName(RESULT); |
122 |
out.setDescription(Sextante.getText("Routes"));
|
123 |
out.setOutputChannel(channel); |
124 |
out.setOutputObject(ShapesTools.addFields(m_OutputFactory, routes, channel, sFields, values, types)); |
125 |
addOutputObject(out); |
126 |
|
127 |
return true; |
128 |
|
129 |
} |
130 |
|
131 |
|
132 |
private void processLine(final Coordinate coords[]) { |
133 |
|
134 |
int i;
|
135 |
double x, y, x2, y2;
|
136 |
|
137 |
for (i = 0; i < coords.length - 1; i++) { |
138 |
x = coords[i].x; |
139 |
y = coords[i].y; |
140 |
x2 = coords[i + 1].x;
|
141 |
y2 = coords[i + 1].y;
|
142 |
processSegment(x, y, x2, y2); |
143 |
} |
144 |
|
145 |
} |
146 |
|
147 |
|
148 |
private void processSegment(double x, |
149 |
double y,
|
150 |
final double x2, |
151 |
final double y2) { |
152 |
|
153 |
double dx, dy, d, n;
|
154 |
|
155 |
dx = Math.abs(x2 - x);
|
156 |
dy = Math.abs(y2 - y);
|
157 |
|
158 |
if ((dx > 0.0) || (dy > 0.0)) { |
159 |
if (dx > dy) {
|
160 |
dx /= m_Cost.getWindowCellSize(); |
161 |
n = dx; |
162 |
dy /= dx; |
163 |
dx = m_Cost.getWindowCellSize(); |
164 |
} |
165 |
else {
|
166 |
dy /= m_Cost.getWindowCellSize(); |
167 |
n = dy; |
168 |
dx /= dy; |
169 |
dy = m_Cost.getWindowCellSize(); |
170 |
} |
171 |
|
172 |
if (x2 < x) {
|
173 |
dx = -dx; |
174 |
} |
175 |
|
176 |
if (y2 < y) {
|
177 |
dy = -dy; |
178 |
} |
179 |
|
180 |
for (d = 0.0; d <= n; d++, x += dx, y += dy) { |
181 |
addPoint(x, y); |
182 |
} |
183 |
} |
184 |
|
185 |
} |
186 |
|
187 |
|
188 |
private void addPoint(final double x, |
189 |
final double y) { |
190 |
|
191 |
int iDX, iDY;
|
192 |
final GridCell cell = m_Cost.getWindowGridExtent().getGridCoordsFromWorldCoords(x, y);
|
193 |
final int iX = cell.getX(); |
194 |
final int iY = cell.getY(); |
195 |
|
196 |
if (m_iPoints == 0) { |
197 |
m_dDist[m_iCurrentRoute] = 0.0;
|
198 |
m_dCost[m_iCurrentRoute] = 0.0;
|
199 |
m_iLastX = cell.getX(); |
200 |
m_iLastY = cell.getY(); |
201 |
} |
202 |
else {
|
203 |
iDX = iX - m_iLastX; |
204 |
iDY = iY - m_iLastY; |
205 |
m_dDist[m_iCurrentRoute] += Math.sqrt(iDX * iDX + iDY * iDY) * m_Cost.getWindowCellSize();
|
206 |
final double dCost = getCostInDir(m_iLastX, m_iLastY, iDX, iDY); |
207 |
if (dCost != NO_DATA) {
|
208 |
m_dCost[m_iCurrentRoute] += dCost; |
209 |
} |
210 |
m_iLastX = iX; |
211 |
m_iLastY = iY; |
212 |
} |
213 |
|
214 |
m_iLastX = iX; |
215 |
m_iLastY = iY; |
216 |
m_iPoints++; |
217 |
|
218 |
} |
219 |
|
220 |
|
221 |
private double getCostInDir(final int x, |
222 |
final int y, |
223 |
final int iH, |
224 |
final int iV) { |
225 |
|
226 |
final double dAngle = ANGLES[iV + 1][iH + 1]; |
227 |
|
228 |
final int x2 = x + iH; |
229 |
final int y2 = y + iV; |
230 |
|
231 |
final double dCostDir1 = m_CostDir.getCellValueAsDouble(x, y); |
232 |
final double dCostDir2 = m_CostDir.getCellValueAsDouble(x2, y2); |
233 |
double dCost1 = m_Cost.getCellValueAsDouble(x, y);
|
234 |
double dCost2 = m_Cost.getCellValueAsDouble(x2, y2);
|
235 |
|
236 |
if (m_Cost.isNoDataValue(dCost1) || m_Cost.isNoDataValue(dCost1) || m_CostDir.isNoDataValue(dCostDir1)
|
237 |
|| m_CostDir.isNoDataValue(dCostDir1)) { |
238 |
return NO_DATA;
|
239 |
} |
240 |
else {
|
241 |
final double dDifAngle1 = Math.abs(dCostDir1 - dAngle); |
242 |
final double dDifAngle2 = Math.abs(dCostDir2 - dAngle); |
243 |
|
244 |
dCost1 = getWeigthedCost(dCost1, dDifAngle1); |
245 |
dCost2 = getWeigthedCost(dCost2, dDifAngle2); |
246 |
|
247 |
return dCost1 + dCost2;
|
248 |
} |
249 |
|
250 |
} |
251 |
|
252 |
|
253 |
private double getWeigthedCost(final double cost, |
254 |
final double difAngle) { |
255 |
|
256 |
for (int i = 0; i < m_Factors.length - 1; i++) { |
257 |
if ((m_Factors[i].deviation < difAngle) || (m_Factors[i + 1].deviation >= difAngle)) { |
258 |
return m_Factors[i].factor * cost / 2.; |
259 |
} |
260 |
} |
261 |
|
262 |
return cost / 2.; |
263 |
|
264 |
} |
265 |
|
266 |
private class DeviationAndFactor |
267 |
implements
|
268 |
Comparable {
|
269 |
|
270 |
public double factor; |
271 |
public double deviation; |
272 |
|
273 |
|
274 |
DeviationAndFactor(final double dDeviation, |
275 |
final double dFactor) { |
276 |
|
277 |
deviation = dDeviation; |
278 |
factor = dFactor; |
279 |
} |
280 |
|
281 |
|
282 |
public int compareTo(final Object ob) throws ClassCastException { |
283 |
|
284 |
if (!(ob instanceof DeviationAndFactor)) { |
285 |
throw new ClassCastException(); |
286 |
} |
287 |
|
288 |
final double dDeviation = ((DeviationAndFactor) ob).deviation; |
289 |
final double dDif = this.deviation - dDeviation; |
290 |
|
291 |
if (dDif > 0.0) { |
292 |
return 1; |
293 |
} |
294 |
else if (dDif < 0.0) { |
295 |
return -1; |
296 |
} |
297 |
else {
|
298 |
return 0; |
299 |
} |
300 |
|
301 |
} |
302 |
} |
303 |
|
304 |
} |