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