root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / lighting / visibility / VisibilityAlgorithm.java @ 59
History | View | Annotate | Download (8.53 KB)
1 | 59 | nbrodin | package es.unex.sextante.lighting.visibility; |
---|---|---|---|
2 | |||
3 | import java.awt.geom.Point2D; |
||
4 | |||
5 | import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue; |
||
6 | import es.unex.sextante.core.GeoAlgorithm; |
||
7 | import es.unex.sextante.core.Sextante; |
||
8 | import es.unex.sextante.dataObjects.IRasterLayer; |
||
9 | import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
||
10 | import es.unex.sextante.exceptions.RepeatedParameterNameException; |
||
11 | import es.unex.sextante.rasterWrappers.GridCell; |
||
12 | |||
13 | public class VisibilityAlgorithm |
||
14 | extends
|
||
15 | GeoAlgorithm { |
||
16 | |||
17 | public static final String DEM = "DEM"; |
||
18 | public static final String POINT = "POINT"; |
||
19 | public static final String METHOD = "METHOD"; |
||
20 | public static final String HEIGHT = "HEIGHT"; |
||
21 | public static final String HEIGHTOBS = "HEIGHTOBS"; |
||
22 | public static final String RADIUS = "RADIUS"; |
||
23 | public static final String RESULT = "RESULT"; |
||
24 | |||
25 | private static final double DEG_90_IN_RAD = Math.toRadians(90); |
||
26 | |||
27 | private int m_iNX, m_iNY; |
||
28 | private IRasterLayer m_DEM = null; |
||
29 | private IRasterLayer m_Visibility;
|
||
30 | private GridCell m_Point;
|
||
31 | private double m_dHeight, m_dHeightObs; |
||
32 | private int m_iMethod; |
||
33 | private int m_iRadius, m_iRadius2; |
||
34 | |||
35 | |||
36 | @Override
|
||
37 | public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
||
38 | |||
39 | int iDataType;
|
||
40 | |||
41 | m_iMethod = m_Parameters.getParameterValueAsInt("METHOD");
|
||
42 | if (m_iMethod == 0) { |
||
43 | iDataType = IRasterLayer.RASTER_DATA_TYPE_INT; |
||
44 | } |
||
45 | else {
|
||
46 | iDataType = IRasterLayer.RASTER_DATA_TYPE_FLOAT; |
||
47 | } |
||
48 | |||
49 | m_DEM = m_Parameters.getParameterValueAsRasterLayer(DEM); |
||
50 | final Point2D pt = m_Parameters.getParameterValueAsPoint(POINT); |
||
51 | m_dHeight = m_Parameters.getParameterValueAsDouble(HEIGHT); |
||
52 | m_dHeightObs = m_Parameters.getParameterValueAsDouble(HEIGHTOBS); |
||
53 | |||
54 | m_DEM.setWindowExtent(getAnalysisExtent()); |
||
55 | m_Visibility = getNewRasterLayer(RESULT, Sextante.getText("Visibility"), iDataType);
|
||
56 | |||
57 | m_iRadius = (int) (m_Parameters.getParameterValueAsInt(RADIUS) / m_DEM.getWindowCellSize());
|
||
58 | m_iRadius2 = m_iRadius * m_iRadius; |
||
59 | |||
60 | m_iNX = m_DEM.getNX(); |
||
61 | m_iNY = m_DEM.getNY(); |
||
62 | |||
63 | m_Point = m_DEM.getWindowGridExtent().getGridCoordsFromWorldCoords(pt); |
||
64 | |||
65 | calculateVisibility(m_Point.getX(), m_Point.getY()); |
||
66 | |||
67 | return !m_Task.isCanceled();
|
||
68 | } |
||
69 | |||
70 | |||
71 | @Override
|
||
72 | public void defineCharacteristics() { |
||
73 | |||
74 | final String sMethod[] = { Sextante.getText("Visibility"), Sextante.getText("Lighting"), Sextante.getText("Distance"), |
||
75 | Sextante.getText("Height") };
|
||
76 | |||
77 | setName(Sextante.getText("Visibility"));
|
||
78 | setGroup(Sextante.getText("Visibility_and_lighting"));
|
||
79 | setUserCanDefineAnalysisExtent(true);
|
||
80 | |||
81 | try {
|
||
82 | m_Parameters.addInputRasterLayer(DEM, Sextante.getText("Elevation"), true); |
||
83 | m_Parameters.addSelection(METHOD, Sextante.getText("Method"), sMethod);
|
||
84 | m_Parameters.addPoint(POINT, Sextante.getText("Coordinates_of_emitter-receiver"));
|
||
85 | m_Parameters.addNumericalValue(HEIGHT, Sextante.getText("Height_of_emitter-receiver"), 10, |
||
86 | AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE); |
||
87 | m_Parameters.addNumericalValue(HEIGHTOBS, Sextante.getText("Height_of_mobile_receiver-emitter"), 0, |
||
88 | AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE); |
||
89 | m_Parameters.addNumericalValue(RADIUS, Sextante.getText("Radius"), 0, |
||
90 | AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE); |
||
91 | addOutputRasterLayer(RESULT, Sextante.getText("Visibility"));
|
||
92 | } |
||
93 | catch (final RepeatedParameterNameException e) { |
||
94 | Sextante.addErrorToLog(e); |
||
95 | } |
||
96 | |||
97 | } |
||
98 | |||
99 | |||
100 | private void calculateVisibility(final int x_Pos, |
||
101 | final int y_Pos) { |
||
102 | |||
103 | int x, y;
|
||
104 | int dx, dy;
|
||
105 | int iXMin, iYMin;
|
||
106 | int iXMax, iYMax;
|
||
107 | int iDist;
|
||
108 | double z;
|
||
109 | double z_Pos, aziDTM, decDTM, aziSrc, decSrc, d, dz;
|
||
110 | final double Exaggeration = 1.0; |
||
111 | |||
112 | z_Pos = m_DEM.getCellValueAsDouble(x_Pos, y_Pos); |
||
113 | if (m_DEM.isNoDataValue(z_Pos)) {
|
||
114 | return;
|
||
115 | } |
||
116 | |||
117 | z_Pos += m_dHeight; |
||
118 | |||
119 | if (m_iRadius > 0) { |
||
120 | iXMin = Math.max(0, x_Pos - m_iRadius); |
||
121 | iYMin = Math.max(0, y_Pos - m_iRadius); |
||
122 | iXMax = Math.min(m_iNX, x_Pos + m_iRadius);
|
||
123 | iYMax = Math.min(m_iNY, y_Pos + m_iRadius);
|
||
124 | } |
||
125 | else {
|
||
126 | iXMin = 0;
|
||
127 | iXMax = m_iNX; |
||
128 | iYMin = 0;
|
||
129 | iYMax = m_iNY; |
||
130 | } |
||
131 | |||
132 | for (y = iYMin; (y < iYMax) && setProgress(y, m_iNY); y++) {
|
||
133 | for (x = iXMin; x < iXMax; x++) {
|
||
134 | dx = x_Pos - x; |
||
135 | dy = y_Pos - y; |
||
136 | iDist = dx * dx + dy * dy; |
||
137 | if ((iDist < m_iRadius2) || (m_iRadius2 <= 0)) { |
||
138 | z = m_DEM.getCellValueAsDouble(x, y) + m_dHeightObs; |
||
139 | if (m_DEM.isNoDataValue(z)) {
|
||
140 | m_Visibility.setNoData(x, y); |
||
141 | } |
||
142 | else {
|
||
143 | dz = z_Pos - z; |
||
144 | if (tracePoint(x, y, dx, dy, dz)) {
|
||
145 | switch (m_iMethod) {
|
||
146 | case 0: // Visibility |
||
147 | m_Visibility.setCellValue(x, y, 1);
|
||
148 | break;
|
||
149 | case 1: // Shade |
||
150 | decDTM = m_DEM.getSlope(x, y); |
||
151 | aziDTM = m_DEM.getAspect(x, y); |
||
152 | decDTM = DEG_90_IN_RAD - Math.atan(Exaggeration * Math.tan(decDTM)); |
||
153 | |||
154 | decSrc = Math.atan2(dz, Math.sqrt(dx * dx + dy * dy)); |
||
155 | aziSrc = Math.atan2(dx, dy);
|
||
156 | |||
157 | d = Math.acos(Math.sin(decDTM) * Math.sin(decSrc) + Math.cos(decDTM) * Math.cos(decSrc) |
||
158 | * Math.cos(aziDTM - aziSrc));
|
||
159 | |||
160 | m_Visibility.setCellValue(x, y, d < DEG_90_IN_RAD ? d : DEG_90_IN_RAD); |
||
161 | break;
|
||
162 | case 2: // Distance |
||
163 | m_Visibility.setCellValue(x, y, m_DEM.getWindowCellSize() * Math.sqrt(dx * dx + dy * dy));
|
||
164 | break;
|
||
165 | case 3: // Size |
||
166 | if ((d = m_DEM.getWindowCellSize() * Math.sqrt(dx * dx + dy * dy)) > 0.0) { |
||
167 | m_Visibility.setCellValue(x, y, Math.atan2(m_dHeight, d));
|
||
168 | } |
||
169 | else {
|
||
170 | m_Visibility.setNoData(x, y); |
||
171 | } |
||
172 | break;
|
||
173 | } |
||
174 | } |
||
175 | |||
176 | else {
|
||
177 | switch (m_iMethod) {
|
||
178 | case 0: // Visibility |
||
179 | m_Visibility.setCellValue(x, y, 0);
|
||
180 | break;
|
||
181 | case 1: // Shade |
||
182 | m_Visibility.setCellValue(x, y, DEG_90_IN_RAD); |
||
183 | break;
|
||
184 | case 2: // Distance |
||
185 | case 3: // Size |
||
186 | m_Visibility.setNoData(x, y); |
||
187 | break;
|
||
188 | } |
||
189 | } |
||
190 | } |
||
191 | } |
||
192 | } |
||
193 | } |
||
194 | |||
195 | } |
||
196 | |||
197 | |||
198 | boolean tracePoint(int x, |
||
199 | int y,
|
||
200 | double dx,
|
||
201 | double dy,
|
||
202 | double dz) {
|
||
203 | |||
204 | double ix, iy, iz, id, d, dist, zmax;
|
||
205 | |||
206 | d = Math.abs(dx) > Math.abs(dy) ? Math.abs(dx) : Math.abs(dy); |
||
207 | |||
208 | zmax = m_DEM.getMaxValue(); |
||
209 | |||
210 | if (d > 0) { |
||
211 | dist = Math.sqrt(dx * dx + dy * dy);
|
||
212 | |||
213 | dx /= d; |
||
214 | dy /= d; |
||
215 | dz /= d; |
||
216 | |||
217 | d = dist / d; |
||
218 | |||
219 | id = 0.0;
|
||
220 | ix = x + 0.5;
|
||
221 | iy = y + 0.5;
|
||
222 | iz = m_DEM.getCellValueAsDouble(x, y); |
||
223 | |||
224 | while (id < dist) {
|
||
225 | id += d; |
||
226 | |||
227 | ix += dx; |
||
228 | iy += dy; |
||
229 | iz += dz; |
||
230 | |||
231 | x = (int) ix;
|
||
232 | y = (int) iy;
|
||
233 | |||
234 | if (!m_DEM.getWindowGridExtent().containsCell(x, y)) {
|
||
235 | return true; |
||
236 | } |
||
237 | else if (iz < m_DEM.getCellValueAsDouble(x, y)) { |
||
238 | return false; |
||
239 | } |
||
240 | else if (iz > zmax) { |
||
241 | return true; |
||
242 | } |
||
243 | } |
||
244 | } |
||
245 | |||
246 | return (true); |
||
247 | } |
||
248 | |||
249 | |||
250 | } |