root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / gridTools / locateExtremeValues / LocateExtremeValuesAlgorithm.java @ 59
History | View | Annotate | Download (7.89 KB)
1 | 59 | nbrodin | |
---|---|---|---|
2 | |||
3 | package es.unex.sextante.gridTools.locateExtremeValues; |
||
4 | |||
5 | import java.awt.geom.Point2D; |
||
6 | import java.util.Arrays; |
||
7 | |||
8 | import com.vividsolutions.jts.geom.Coordinate; |
||
9 | import com.vividsolutions.jts.geom.Envelope; |
||
10 | import com.vividsolutions.jts.geom.Geometry; |
||
11 | import com.vividsolutions.jts.geom.GeometryFactory; |
||
12 | import com.vividsolutions.jts.geom.LinearRing; |
||
13 | import com.vividsolutions.jts.geom.Point; |
||
14 | import com.vividsolutions.jts.geom.Polygon; |
||
15 | |||
16 | import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer; |
||
17 | import es.unex.sextante.core.AnalysisExtent; |
||
18 | import es.unex.sextante.core.GeoAlgorithm; |
||
19 | import es.unex.sextante.core.Sextante; |
||
20 | import es.unex.sextante.dataObjects.IFeature; |
||
21 | import es.unex.sextante.dataObjects.IFeatureIterator; |
||
22 | import es.unex.sextante.dataObjects.IRasterLayer; |
||
23 | import es.unex.sextante.dataObjects.IVectorLayer; |
||
24 | import es.unex.sextante.dataObjects.vectorFilters.BoundingBoxFilter; |
||
25 | import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
||
26 | import es.unex.sextante.exceptions.RepeatedParameterNameException; |
||
27 | import es.unex.sextante.outputs.OutputVectorLayer; |
||
28 | |||
29 | |||
30 | public class LocateExtremeValuesAlgorithm |
||
31 | extends
|
||
32 | GeoAlgorithm { |
||
33 | |||
34 | public static final String RESULT = "RESULT"; |
||
35 | public static final String GRID = "GRID"; |
||
36 | public static final String POLYGONS = "POLYGONS"; |
||
37 | public static final String EXTREME_VALUE_TYPE = "EXTREME_VALUE_TYPE"; |
||
38 | |||
39 | private int m_iNX, m_iNY; |
||
40 | private IVectorLayer m_Layer;
|
||
41 | private AnalysisExtent m_Extent;
|
||
42 | private IRasterLayer m_Window;
|
||
43 | private Coordinate m_Coordinate;
|
||
44 | private double m_dExtremeValue; |
||
45 | private IVectorLayer m_Output;
|
||
46 | |||
47 | |||
48 | @Override
|
||
49 | public void defineCharacteristics() { |
||
50 | |||
51 | setName(Sextante.getText("Locate_max_values"));
|
||
52 | setGroup(Sextante.getText("Basic_tools_for_raster_layers"));
|
||
53 | setUserCanDefineAnalysisExtent(true);
|
||
54 | |||
55 | try {
|
||
56 | m_Parameters.addInputVectorLayer(POLYGONS, Sextante.getText("Polygons"), AdditionalInfoVectorLayer.SHAPE_TYPE_POLYGON,
|
||
57 | true);
|
||
58 | m_Parameters.addInputRasterLayer(GRID, Sextante.getText("Grid"), true); |
||
59 | addOutputVectorLayer(RESULT, Sextante.getText("Max_values"), OutputVectorLayer.SHAPE_TYPE_POINT);
|
||
60 | } |
||
61 | catch (final RepeatedParameterNameException e) { |
||
62 | Sextante.addErrorToLog(e); |
||
63 | } |
||
64 | |||
65 | } |
||
66 | |||
67 | |||
68 | @Override
|
||
69 | public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
||
70 | |||
71 | int i = 0; |
||
72 | int iShapeCount;
|
||
73 | final GeometryFactory gf = new GeometryFactory(); |
||
74 | |||
75 | m_Coordinate = new Coordinate();
|
||
76 | m_Layer = m_Parameters.getParameterValueAsVectorLayer(POLYGONS); |
||
77 | m_Window = m_Parameters.getParameterValueAsRasterLayer(GRID); |
||
78 | |||
79 | final String[] sNames = { m_Window.getName() }; |
||
80 | final Class[] types = { Double.class }; |
||
81 | |||
82 | m_Output = getNewVectorLayer(RESULT, Sextante.getText("Result"), IVectorLayer.SHAPE_TYPE_POINT, types, sNames);
|
||
83 | |||
84 | if (!m_bIsAutoExtent) {
|
||
85 | m_Layer.addFilter(new BoundingBoxFilter(m_AnalysisExtent));
|
||
86 | } |
||
87 | iShapeCount = m_Layer.getShapesCount(); |
||
88 | |||
89 | m_Window.setFullExtent(); |
||
90 | m_Extent = m_Window.getWindowGridExtent(); |
||
91 | final Coordinate[] coords = new Coordinate[5]; |
||
92 | coords[0] = new Coordinate(m_Extent.getXMin(), m_Extent.getYMin()); |
||
93 | coords[1] = new Coordinate(m_Extent.getXMin(), m_Extent.getYMax()); |
||
94 | coords[2] = new Coordinate(m_Extent.getYMax(), m_Extent.getYMax()); |
||
95 | coords[3] = new Coordinate(m_Extent.getXMax(), m_Extent.getYMin()); |
||
96 | coords[4] = new Coordinate(m_Extent.getXMin(), m_Extent.getYMin()); |
||
97 | |||
98 | final LinearRing ring = gf.createLinearRing(coords);
|
||
99 | final Polygon extent = gf.createPolygon(ring, null); |
||
100 | m_iNX = m_Window.getNX(); |
||
101 | m_iNY = m_Window.getNY(); |
||
102 | final IFeatureIterator iter = m_Layer.iterator();
|
||
103 | i = 0;
|
||
104 | while (iter.hasNext() && setProgress(i, iShapeCount)) {
|
||
105 | final IFeature feature = iter.next();
|
||
106 | final Geometry geom = feature.getGeometry();
|
||
107 | if (geom.intersects(extent)) {
|
||
108 | m_dExtremeValue = Double.NEGATIVE_INFINITY;
|
||
109 | doPolygon(geom); |
||
110 | final Point pt = gf.createPoint(new Coordinate(m_Coordinate.x, m_Coordinate.y)); |
||
111 | m_Output.addFeature(pt, new Object[] { new Double(m_dExtremeValue) }); |
||
112 | } |
||
113 | i++; |
||
114 | } |
||
115 | iter.close(); |
||
116 | |||
117 | return !m_Task.isCanceled();
|
||
118 | |||
119 | } |
||
120 | |||
121 | |||
122 | private void doPolygon(final Geometry geom) { |
||
123 | |||
124 | for (int i = 0; i < geom.getNumGeometries(); i++) { |
||
125 | final Geometry part = geom.getGeometryN(i);
|
||
126 | doPolygonPart(part); |
||
127 | } |
||
128 | |||
129 | |||
130 | } |
||
131 | |||
132 | |||
133 | private void doPolygonPart(final Geometry geom) { |
||
134 | |||
135 | boolean bFill;
|
||
136 | boolean bCrossing[]; |
||
137 | int x, y, ix, xStart, xStop, iPoint;
|
||
138 | double yPos;
|
||
139 | double dValue;
|
||
140 | Coordinate pLeft, pRight, pa, pb; |
||
141 | final Coordinate p = new Coordinate(); |
||
142 | bCrossing = new boolean[m_iNX]; |
||
143 | |||
144 | final Envelope extent = geom.getEnvelopeInternal();
|
||
145 | |||
146 | xStart = (int) ((extent.getMinX() - m_Extent.getXMin()) / m_Extent.getCellSize()) - 1; |
||
147 | if (xStart < 0) { |
||
148 | xStart = 0;
|
||
149 | } |
||
150 | |||
151 | xStop = (int) ((extent.getMaxX() - m_Extent.getXMin()) / m_Extent.getCellSize()) + 1; |
||
152 | if (xStop >= m_iNX) {
|
||
153 | xStop = m_iNX - 1;
|
||
154 | } |
||
155 | |||
156 | final Coordinate[] points = geom.getCoordinates(); |
||
157 | |||
158 | for (y = 0, yPos = m_Extent.getYMax(); y < m_iNY; y++, yPos -= m_Extent.getCellSize()) { |
||
159 | if ((yPos >= extent.getMinY()) && (yPos <= extent.getMaxY())) {
|
||
160 | Arrays.fill(bCrossing, false); |
||
161 | pLeft = new Coordinate(m_Extent.getXMin() - 1.0, yPos); |
||
162 | pRight = new Coordinate(m_Extent.getXMax() + 1.0, yPos); |
||
163 | |||
164 | pb = points[points.length - 1];
|
||
165 | |||
166 | for (iPoint = 0; iPoint < points.length; iPoint++) { |
||
167 | pa = pb; |
||
168 | pb = points[iPoint]; |
||
169 | |||
170 | if ((((pa.y <= yPos) && (yPos < pb.y)) || ((pa.y > yPos) && (yPos >= pb.y)))) {
|
||
171 | getCrossing(p, pa, pb, pLeft, pRight); |
||
172 | |||
173 | ix = (int) ((p.x - m_Extent.getXMin()) / m_Extent.getCellSize() + 1.0); |
||
174 | |||
175 | if (ix < 0) { |
||
176 | ix = 0;
|
||
177 | } |
||
178 | else if (ix >= m_iNX) { |
||
179 | ix = m_iNX - 1;
|
||
180 | } |
||
181 | |||
182 | bCrossing[ix] = !bCrossing[ix]; |
||
183 | } |
||
184 | } |
||
185 | |||
186 | for (x = xStart, bFill = false; x <= xStop; x++) { |
||
187 | if (bCrossing[x]) {
|
||
188 | bFill = !bFill; |
||
189 | } |
||
190 | if (bFill) {
|
||
191 | dValue = m_Window.getCellValueAsDouble(x, y); |
||
192 | if (!m_Window.isNoDataValue(dValue)) {
|
||
193 | if (dValue > m_dExtremeValue) {
|
||
194 | m_dExtremeValue = dValue; |
||
195 | final Point2D coord = m_Extent.getWorldCoordsFromGridCoords(x, y); |
||
196 | m_Coordinate.x = coord.getX(); |
||
197 | m_Coordinate.y = coord.getY(); |
||
198 | } |
||
199 | } |
||
200 | } |
||
201 | } |
||
202 | } |
||
203 | } |
||
204 | |||
205 | } |
||
206 | |||
207 | |||
208 | private boolean getCrossing(final Coordinate crossing, |
||
209 | final Coordinate a1,
|
||
210 | final Coordinate a2,
|
||
211 | final Coordinate b1,
|
||
212 | final Coordinate b2) {
|
||
213 | |||
214 | double lambda, div, a_dx, a_dy, b_dx, b_dy;
|
||
215 | |||
216 | a_dx = a2.x - a1.x; |
||
217 | a_dy = a2.y - a1.y; |
||
218 | |||
219 | b_dx = b2.x - b1.x; |
||
220 | b_dy = b2.y - b1.y; |
||
221 | |||
222 | if ((div = a_dx * b_dy - b_dx * a_dy) != 0.0) { |
||
223 | lambda = ((b1.x - a1.x) * b_dy - b_dx * (b1.y - a1.y)) / div; |
||
224 | |||
225 | crossing.x = a1.x + lambda * a_dx; |
||
226 | crossing.y = a1.y + lambda * a_dy; |
||
227 | |||
228 | return true; |
||
229 | |||
230 | } |
||
231 | |||
232 | return false; |
||
233 | } |
||
234 | |||
235 | } |