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 | 59 | nbrodin | 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 | } |