Statistics
| Revision:

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
}