Statistics
| Revision:

root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / lighting / horizonBlockage / HorizonBlockageAlgorithm.java @ 59

History | View | Annotate | Download (8.87 KB)

1
package es.unex.sextante.lighting.horizonBlockage;
2

    
3
import java.awt.geom.Point2D;
4
import java.util.ArrayList;
5

    
6
import org.jfree.chart.ChartFactory;
7
import org.jfree.chart.ChartPanel;
8
import org.jfree.chart.JFreeChart;
9
import org.jfree.chart.plot.PlotOrientation;
10
import org.jfree.data.xy.XYSeries;
11
import org.jfree.data.xy.XYSeriesCollection;
12

    
13
import com.vividsolutions.jts.geom.Coordinate;
14
import com.vividsolutions.jts.geom.GeometryFactory;
15

    
16
import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue;
17
import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer;
18
import es.unex.sextante.core.GeoAlgorithm;
19
import es.unex.sextante.core.AnalysisExtent;
20
import es.unex.sextante.core.Sextante;
21
import es.unex.sextante.dataObjects.IRasterLayer;
22
import es.unex.sextante.dataObjects.IVectorLayer;
23
import es.unex.sextante.exceptions.RepeatedParameterNameException;
24
import es.unex.sextante.outputs.OutputVectorLayer;
25
import es.unex.sextante.rasterWrappers.GridCell;
26

    
27
public class HorizonBlockageAlgorithm
28
         extends
29
            GeoAlgorithm {
30

    
31
   public static final String DEM        = "DEM";
32
   public static final String POINT      = "POINT";
33
   public static final String HEIGHT     = "HEIGHT";
34
   public static final String RADIUS     = "RADIUS";
35

    
36
   public static final String RESULT     = "RESULT";
37
   public static final String GRAPHSLOPE = "GRAPHSLOPE";
38
   public static final String GRAPHDIST  = "GRAPHDIST";
39

    
40
   private int                m_iNX, m_iNY;
41
   private IRasterLayer       m_DEM      = null;
42
   private GridCell           m_Point;
43
   private double             m_dHeight;
44
   private int                m_iRadius;
45
   private IVectorLayer       m_Horizon;
46
   private HorizonData[]      m_HorizonData;
47
   private double             m_dLineLength;
48

    
49

    
50
   @Override
51
   public boolean processAlgorithm() {
52

    
53
      try {
54

    
55
         m_DEM = m_Parameters.getParameterValueAsRasterLayer(DEM);
56
         final Point2D pt = m_Parameters.getParameterValueAsPoint(POINT);
57
         m_dHeight = m_Parameters.getParameterValueAsDouble(HEIGHT);
58

    
59
         final AnalysisExtent gridExtent = new AnalysisExtent(m_DEM);
60
         m_DEM.setFullExtent();
61
         m_Horizon = getNewVectorLayer(RESULT, Sextante.getText("Horizon"), AdditionalInfoVectorLayer.SHAPE_TYPE_LINE,
62
                  new Class[] { Integer.class }, new String[] { "ID" });
63

    
64
         m_iRadius = (int) (m_Parameters.getParameterValueAsInt(RADIUS) / gridExtent.getCellSize());
65

    
66
         if (m_iRadius <= 0) {
67
            m_iRadius = Integer.MAX_VALUE;
68
         }
69

    
70
         m_iNX = m_DEM.getNX();
71
         m_iNY = m_DEM.getNY();
72

    
73
         m_Point = gridExtent.getGridCoordsFromWorldCoords(pt);
74

    
75
         m_dLineLength = Math.sqrt(m_iNX * m_iNX + m_iNY * m_iNY);
76

    
77
         calculateHorizon();
78
         createResults();
79

    
80
      }
81
      catch (final Exception e) {
82
         Sextante.addErrorToLog(e);
83
         return false;
84
      }
85

    
86
      return !m_Task.isCanceled();
87
   }
88

    
89

    
90
   @Override
91
   public void defineCharacteristics() {
92

    
93
      setName(Sextante.getText("Horizon_blockage"));
94
      setGroup(Sextante.getText("Visibility_and_lighting"));
95
      setUserCanDefineAnalysisExtent(false);
96

    
97
      try {
98
         m_Parameters.addInputRasterLayer(DEM, Sextante.getText("Elevation"), true);
99
         m_Parameters.addPoint(POINT, Sextante.getText("Coordinates_of_emitter-receiver"));
100
         m_Parameters.addNumericalValue(HEIGHT, Sextante.getText("Height_of_emitter-receiver"), 10,
101
                  AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE);
102
         m_Parameters.addNumericalValue(RADIUS, Sextante.getText("Radius"), 0,
103
                  AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE);
104
         addOutputVectorLayer(RESULT, Sextante.getText("Horizon"), OutputVectorLayer.SHAPE_TYPE_LINE);
105
         addOutputChart(GRAPHSLOPE, Sextante.getText("Angle"));
106
         addOutputChart(GRAPHDIST, Sextante.getText("Distance"));
107
      }
108
      catch (final RepeatedParameterNameException e) {
109
         Sextante.addErrorToLog(e);
110
      }
111

    
112
   }
113

    
114

    
115
   private void calculateHorizon() {
116

    
117
      m_HorizonData = new HorizonData[360];
118

    
119
      for (int i = 0; i < 360; i++) {
120
         final GridCell cell = getCellAtAngle(Math.toRadians(i));
121
         m_HorizonData[i] = calculateHorizonData(cell);
122
      }
123

    
124
   }
125

    
126

    
127
   private GridCell getCellAtAngle(final double dAngle) {
128

    
129
      final int x = (int) (m_Point.getX() + m_dLineLength * Math.sin(dAngle));
130
      final int y = (int) (m_Point.getY() + m_dLineLength * Math.cos(dAngle));
131

    
132
      return new GridCell(x, y, 0);
133

    
134
   }
135

    
136

    
137
   private HorizonData calculateHorizonData(final GridCell cell) {
138

    
139
      double dx = cell.getX() - m_Point.getX();
140
      double dy = cell.getY() - m_Point.getY();
141
      double ix, iy, z, id, d, dist;
142
      double dMaxDist = 0;
143
      int iMaxX = 0, iMaxY = 0;
144
      double dSlope, dMaxSlope = Double.NEGATIVE_INFINITY;
145
      int x, y;
146

    
147
      z = m_DEM.getCellValueAsDouble(m_Point.getX(), m_Point.getY()) + m_dHeight;
148

    
149
      d = Math.abs(dx) > Math.abs(dy) ? Math.abs(dx) : Math.abs(dy);
150

    
151
      if (d > 0) {
152
         dist = Math.sqrt(dx * dx + dy * dy);
153

    
154
         dx /= d;
155
         dy /= d;
156

    
157
         d = dist / d;
158

    
159
         id = 0.0;
160
         ix = m_Point.getX() + 0.5;
161
         iy = m_Point.getY() + 0.5;
162

    
163
         while (id < dist) {
164
            id += d;
165

    
166
            ix += dx;
167
            iy += dy;
168

    
169
            x = (int) ix;
170
            y = (int) iy;
171

    
172
            if (!m_DEM.getWindowGridExtent().containsCell(x, y) || (id > m_iRadius)) {
173
               break;
174
            }
175

    
176
            dSlope = (m_DEM.getCellValueAsDouble(x, y) - z) / id;
177
            if (dSlope > dMaxSlope) {
178
               dMaxSlope = dSlope;
179
               dMaxDist = id;
180
               iMaxX = x;
181
               iMaxY = y;
182
            }
183

    
184
         }
185

    
186
      }
187

    
188
      return new HorizonData(dMaxSlope, dMaxDist, iMaxX, iMaxY);
189

    
190
   }
191

    
192

    
193
   private void createResults() {
194

    
195
      final boolean bFirstPoint = true;
196
      double x, y;
197

    
198
      final XYSeriesCollection datasetSlope = new XYSeriesCollection();
199
      final XYSeries serieSlope = new XYSeries(Sextante.getText("Angle"));
200
      datasetSlope.addSeries(serieSlope);
201

    
202
      final XYSeriesCollection datasetDist = new XYSeriesCollection();
203
      final XYSeries serieDist = new XYSeries(Sextante.getText("Distance"));
204
      datasetDist.addSeries(serieDist);
205

    
206
      final ArrayList coordinates = new ArrayList();
207

    
208
      for (int i = 0; i < m_HorizonData.length; i++) {
209
         final double dAngle = Math.toDegrees(Math.atan(m_HorizonData[i].dAngle));
210
         serieDist.add(i, m_HorizonData[i].dDistance);
211
         serieSlope.add(i, dAngle);
212
         x = m_HorizonData[i].x;
213
         y = m_HorizonData[i].y;
214
         if ((x != 0) || (y != 0)) {
215
            final Point2D pt = m_DEM.getWindowGridExtent().getWorldCoordsFromGridCoords(new GridCell((int) x, (int) y, 0));
216
            x = pt.getX();
217
            y = pt.getY();
218
            coordinates.add(new Coordinate(x, y));
219
         }
220

    
221
      }
222

    
223
      final JFreeChart chartSlope = ChartFactory.createXYLineChart(null, null, null, datasetSlope, PlotOrientation.VERTICAL,
224
               false, true, true);
225

    
226
      final ChartPanel jPanelChartSlope = new ChartPanel(chartSlope);
227
      jPanelChartSlope.setPreferredSize(new java.awt.Dimension(500, 300));
228
      jPanelChartSlope.setPreferredSize(new java.awt.Dimension(500, 300));
229
      jPanelChartSlope.setBorder(javax.swing.BorderFactory.createLineBorder(java.awt.Color.gray, 1));
230

    
231
      addOutputChart("GRAPHSLOPE", Sextante.getText("Angle"), jPanelChartSlope);
232

    
233
      final JFreeChart chartDist = ChartFactory.createXYLineChart(null, null, null, datasetDist, PlotOrientation.VERTICAL, false,
234
               true, true);
235

    
236
      final ChartPanel jPanelChartDist = new ChartPanel(chartDist);
237
      jPanelChartDist.setPreferredSize(new java.awt.Dimension(500, 300));
238
      jPanelChartDist.setPreferredSize(new java.awt.Dimension(500, 300));
239
      jPanelChartDist.setBorder(javax.swing.BorderFactory.createLineBorder(java.awt.Color.gray, 1));
240

    
241
      addOutputChart("GRAPHDIST", Sextante.getText("Distance"), jPanelChartDist);
242

    
243
      final Object value[] = new Object[1];
244
      value[0] = new Integer(1);
245

    
246
      final Coordinate[] coords = new Coordinate[coordinates.size()];
247
      for (int i = 0; i < coords.length; i++) {
248
         coords[i] = (Coordinate) coordinates.get(i);
249
      }
250
      m_Horizon.addFeature(new GeometryFactory().createLineString(coords), value);
251

    
252
   }
253

    
254
   private class HorizonData {
255

    
256
      HorizonData(final double dA,
257
                  final double dD,
258
                  final int iX,
259
                  final int iY) {
260

    
261
         dAngle = dA;
262
         dDistance = dD;
263
         x = iX;
264
         y = iY;
265

    
266
      }
267

    
268
      public int    x, y;
269
      public double dAngle    = 0;
270
      public double dDistance = 0;
271

    
272
   }
273

    
274

    
275
}