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