root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / rasterize / rasterizeVectorLayerForMask / RasterizeVectorLayerForMaskAlgorithm.java @ 59
History | View | Annotate | Download (10.3 KB)
1 | 59 | nbrodin | |
---|---|---|---|
2 | |||
3 | package es.unex.sextante.rasterize.rasterizeVectorLayerForMask; |
||
4 | |||
5 | import java.util.Arrays; |
||
6 | |||
7 | import com.vividsolutions.jts.geom.Coordinate; |
||
8 | import com.vividsolutions.jts.geom.Envelope; |
||
9 | import com.vividsolutions.jts.geom.Geometry; |
||
10 | import com.vividsolutions.jts.geom.GeometryFactory; |
||
11 | import com.vividsolutions.jts.geom.LinearRing; |
||
12 | import com.vividsolutions.jts.geom.Polygon; |
||
13 | |||
14 | import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer; |
||
15 | import es.unex.sextante.core.AnalysisExtent; |
||
16 | import es.unex.sextante.core.GeoAlgorithm; |
||
17 | import es.unex.sextante.core.Sextante; |
||
18 | import es.unex.sextante.dataObjects.IFeature; |
||
19 | import es.unex.sextante.dataObjects.IFeatureIterator; |
||
20 | import es.unex.sextante.dataObjects.IRasterLayer; |
||
21 | import es.unex.sextante.dataObjects.IRecord; |
||
22 | import es.unex.sextante.dataObjects.IVectorLayer; |
||
23 | import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
||
24 | import es.unex.sextante.exceptions.RepeatedParameterNameException; |
||
25 | import es.unex.sextante.rasterWrappers.GridCell; |
||
26 | |||
27 | |||
28 | public class RasterizeVectorLayerForMaskAlgorithm |
||
29 | extends
|
||
30 | GeoAlgorithm { |
||
31 | |||
32 | private double NO_DATA; |
||
33 | |||
34 | public static final String LAYER = "LAYER"; |
||
35 | public static final String FIELD = "FIELD"; |
||
36 | public static final String RESULT = "RESULT"; |
||
37 | |||
38 | private int m_iNX, m_iNY; |
||
39 | private IVectorLayer m_Layer;
|
||
40 | private IRasterLayer m_Result;
|
||
41 | private AnalysisExtent m_Extent;
|
||
42 | |||
43 | |||
44 | @Override
|
||
45 | public void defineCharacteristics() { |
||
46 | |||
47 | setName(Sextante.getText("Rasterize_vector_layer_for_mask"));
|
||
48 | setGroup(Sextante.getText("Rasterization_and_interpolation"));
|
||
49 | setUserCanDefineAnalysisExtent(true);
|
||
50 | |||
51 | try {
|
||
52 | m_Parameters.addInputVectorLayer(LAYER, Sextante.getText("Vector_layer"), AdditionalInfoVectorLayer.SHAPE_TYPE_ANY, true); |
||
53 | addOutputRasterLayer(RESULT, Sextante.getText("Result"));
|
||
54 | } |
||
55 | catch (final RepeatedParameterNameException e) { |
||
56 | Sextante.addErrorToLog(e); |
||
57 | } |
||
58 | |||
59 | } |
||
60 | |||
61 | |||
62 | @Override
|
||
63 | public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
||
64 | |||
65 | int i;
|
||
66 | int iType;
|
||
67 | int iShapeCount;
|
||
68 | |||
69 | NO_DATA = 0;
|
||
70 | |||
71 | m_Layer = m_Parameters.getParameterValueAsVectorLayer(LAYER); |
||
72 | |||
73 | m_Result = getNewRasterLayer(RESULT, m_Layer.getName() + Sextante.getText("[rasterizedo]"),
|
||
74 | IRasterLayer.RASTER_DATA_TYPE_DOUBLE); |
||
75 | m_Result.setNoDataValue(NO_DATA); |
||
76 | m_Result.assignNoData(); |
||
77 | |||
78 | m_Extent = m_Result.getWindowGridExtent(); |
||
79 | |||
80 | m_iNX = m_Extent.getNX(); |
||
81 | m_iNY = m_Extent.getNY(); |
||
82 | |||
83 | final Coordinate[] coords = new Coordinate[5]; |
||
84 | coords[0] = new Coordinate(m_Extent.getXMin(), m_Extent.getYMin()); |
||
85 | coords[1] = new Coordinate(m_Extent.getXMin(), m_Extent.getYMax()); |
||
86 | coords[2] = new Coordinate(m_Extent.getXMax(), m_Extent.getYMax()); |
||
87 | coords[3] = new Coordinate(m_Extent.getXMax(), m_Extent.getYMin()); |
||
88 | coords[4] = new Coordinate(m_Extent.getXMin(), m_Extent.getYMin()); |
||
89 | final GeometryFactory gf = new GeometryFactory(); |
||
90 | final LinearRing ring = gf.createLinearRing(coords);
|
||
91 | final Polygon extent = gf.createPolygon(ring, null); |
||
92 | |||
93 | i = 0;
|
||
94 | iType = m_Layer.getShapeType(); |
||
95 | iShapeCount = m_Layer.getShapesCount(); |
||
96 | final IFeatureIterator iter = m_Layer.iterator();
|
||
97 | while (iter.hasNext() && setProgress(i, iShapeCount)) {
|
||
98 | final IFeature feature = iter.next();
|
||
99 | final IRecord record = feature.getRecord();
|
||
100 | |||
101 | final Geometry geometry = feature.getGeometry();
|
||
102 | |||
103 | if (geometry.intersects(extent)) {
|
||
104 | switch (iType) {
|
||
105 | case IVectorLayer.SHAPE_TYPE_POINT:
|
||
106 | doPoint(geometry, 1);
|
||
107 | break;
|
||
108 | case IVectorLayer.SHAPE_TYPE_LINE:
|
||
109 | doLine(geometry, 1);
|
||
110 | break;
|
||
111 | case IVectorLayer.SHAPE_TYPE_POLYGON:
|
||
112 | doPolygon(geometry, 1);
|
||
113 | break;
|
||
114 | } |
||
115 | } |
||
116 | i++; |
||
117 | } |
||
118 | iter.close(); |
||
119 | |||
120 | return !m_Task.isCanceled();
|
||
121 | |||
122 | |||
123 | } |
||
124 | |||
125 | |||
126 | private void doPolygon(final Geometry geom, |
||
127 | final double dValue) { |
||
128 | |||
129 | final GeometryFactory gf = new GeometryFactory(); |
||
130 | for (int i = 0; i < geom.getNumGeometries(); i++) { |
||
131 | final Polygon poly = (Polygon) geom.getGeometryN(i); |
||
132 | LinearRing lr = gf.createLinearRing(poly.getExteriorRing().getCoordinates()); |
||
133 | Polygon part = gf.createPolygon(lr, null); |
||
134 | doPolygonPart(part, dValue, false);
|
||
135 | for (int j = 0; j < poly.getNumInteriorRing(); j++) { |
||
136 | lr = gf.createLinearRing(poly.getInteriorRingN(j).getCoordinates()); |
||
137 | part = gf.createPolygon(lr, null);
|
||
138 | doPolygonPart(part, dValue, true);
|
||
139 | } |
||
140 | } |
||
141 | |||
142 | } |
||
143 | |||
144 | |||
145 | private void doPolygonPart(final Polygon geom, |
||
146 | final double dValue, |
||
147 | final boolean bIsHole) { |
||
148 | |||
149 | boolean bFill;
|
||
150 | boolean bCrossing[]; |
||
151 | int x, y, ix, xStart, xStop, iPoint;
|
||
152 | double yPos;;
|
||
153 | Coordinate pLeft, pRight, pa, pb; |
||
154 | final Coordinate p = new Coordinate(); |
||
155 | bCrossing = new boolean[m_iNX]; |
||
156 | |||
157 | final Envelope extent = geom.getEnvelopeInternal();
|
||
158 | |||
159 | xStart = (int) ((extent.getMinX() - m_Extent.getXMin()) / m_Extent.getCellSize()) - 1; |
||
160 | if (xStart < 0) { |
||
161 | xStart = 0;
|
||
162 | } |
||
163 | |||
164 | xStop = (int) ((extent.getMaxX() - m_Extent.getXMin()) / m_Extent.getCellSize()) + 1; |
||
165 | if (xStop >= m_iNX) {
|
||
166 | xStop = m_iNX - 1;
|
||
167 | } |
||
168 | |||
169 | final Coordinate[] points = geom.getCoordinates(); |
||
170 | |||
171 | for (y = 0, yPos = m_Extent.getYMax(); y < m_iNY; y++, yPos -= m_Extent.getCellSize()) { |
||
172 | if ((yPos >= extent.getMinY()) && (yPos <= extent.getMaxY())) {
|
||
173 | Arrays.fill(bCrossing, false); |
||
174 | pLeft = new Coordinate(m_Extent.getXMin() - 1.0, yPos); |
||
175 | pRight = new Coordinate(m_Extent.getXMax() + 1.0, yPos); |
||
176 | |||
177 | pb = points[points.length - 1];
|
||
178 | |||
179 | for (iPoint = 0; iPoint < points.length; iPoint++) { |
||
180 | pa = pb; |
||
181 | pb = points[iPoint]; |
||
182 | |||
183 | if ((((pa.y <= yPos) && (yPos < pb.y)) || ((pa.y > yPos) && (yPos >= pb.y)))) {
|
||
184 | getCrossing(p, pa, pb, pLeft, pRight); |
||
185 | |||
186 | ix = (int) ((p.x - m_Extent.getXMin()) / m_Extent.getCellSize() + 1.0); |
||
187 | |||
188 | if (ix < 0) { |
||
189 | ix = 0;
|
||
190 | } |
||
191 | else if (ix >= m_iNX) { |
||
192 | ix = m_iNX - 1;
|
||
193 | } |
||
194 | |||
195 | bCrossing[ix] = !bCrossing[ix]; |
||
196 | } |
||
197 | } |
||
198 | |||
199 | for (x = xStart, bFill = false; x <= xStop; x++) { |
||
200 | if (bCrossing[x]) {
|
||
201 | bFill = !bFill; |
||
202 | } |
||
203 | if (bFill) {
|
||
204 | final double dPrevValue = m_Result.getCellValueAsDouble(x, y); |
||
205 | if (bIsHole) {
|
||
206 | if (dPrevValue == dValue) {
|
||
207 | m_Result.setNoData(x, y); |
||
208 | } |
||
209 | } |
||
210 | else {
|
||
211 | if (dPrevValue == NO_DATA) {
|
||
212 | m_Result.setCellValue(x, y, dValue); |
||
213 | } |
||
214 | } |
||
215 | } |
||
216 | } |
||
217 | } |
||
218 | } |
||
219 | |||
220 | } |
||
221 | |||
222 | |||
223 | private void doLine(final Geometry geom, |
||
224 | final double dValue) { |
||
225 | |||
226 | for (int i = 0; i < geom.getNumGeometries(); i++) { |
||
227 | final Geometry part = geom.getGeometryN(i);
|
||
228 | doLineString(part, dValue); |
||
229 | } |
||
230 | |||
231 | } |
||
232 | |||
233 | |||
234 | private void doLineString(final Geometry geom, |
||
235 | final double dValue) { |
||
236 | |||
237 | int i;
|
||
238 | double x, y, x2, y2;
|
||
239 | final Coordinate[] coords = geom.getCoordinates(); |
||
240 | for (i = 0; i < coords.length - 1; i++) { |
||
241 | x = coords[i].x; |
||
242 | y = coords[i].y; |
||
243 | x2 = coords[i + 1].x;
|
||
244 | y2 = coords[i + 1].y;
|
||
245 | writeSegment(x, y, x2, y2, dValue); |
||
246 | } |
||
247 | |||
248 | } |
||
249 | |||
250 | |||
251 | private void writeSegment(double x, |
||
252 | double y,
|
||
253 | final double x2, |
||
254 | final double y2, |
||
255 | final double dValue) { |
||
256 | |||
257 | double dx, dy, d, n;
|
||
258 | GridCell cell; |
||
259 | |||
260 | dx = Math.abs(x2 - x);
|
||
261 | dy = Math.abs(y2 - y);
|
||
262 | |||
263 | if ((dx > 0.0) || (dy > 0.0)) { |
||
264 | if (dx > dy) {
|
||
265 | dx /= m_Result.getWindowCellSize(); |
||
266 | n = dx; |
||
267 | dy /= dx; |
||
268 | dx = m_Result.getWindowCellSize(); |
||
269 | } |
||
270 | else {
|
||
271 | dy /= m_Result.getWindowCellSize(); |
||
272 | n = dy; |
||
273 | dx /= dy; |
||
274 | dy = m_Result.getWindowCellSize(); |
||
275 | } |
||
276 | |||
277 | if (x2 < x) {
|
||
278 | dx = -dx; |
||
279 | } |
||
280 | |||
281 | if (y2 < y) {
|
||
282 | dy = -dy; |
||
283 | } |
||
284 | |||
285 | for (d = 0.0; d <= n; d++, x += dx, y += dy) { |
||
286 | if (m_Extent.contains(x, y)) {
|
||
287 | cell = m_Extent.getGridCoordsFromWorldCoords(x, y); |
||
288 | //System.out.println(cell.getX() + " " + cell.getY());
|
||
289 | m_Result.setCellValue(cell.getX(), cell.getY(), dValue); |
||
290 | } |
||
291 | } |
||
292 | } |
||
293 | |||
294 | } |
||
295 | |||
296 | |||
297 | private void doPoint(final Geometry geometry, |
||
298 | final double dValue) { |
||
299 | |||
300 | final Coordinate coord = geometry.getCoordinate();
|
||
301 | final GridCell cell = m_Extent.getGridCoordsFromWorldCoords(coord.x, coord.y);
|
||
302 | m_Result.setCellValue(cell.getX(), cell.getY(), dValue); |
||
303 | |||
304 | } |
||
305 | |||
306 | |||
307 | private boolean getCrossing(final Coordinate crossing, |
||
308 | final Coordinate a1,
|
||
309 | final Coordinate a2,
|
||
310 | final Coordinate b1,
|
||
311 | final Coordinate b2) {
|
||
312 | |||
313 | double lambda, div, a_dx, a_dy, b_dx, b_dy;
|
||
314 | |||
315 | a_dx = a2.x - a1.x; |
||
316 | a_dy = a2.y - a1.y; |
||
317 | |||
318 | b_dx = b2.x - b1.x; |
||
319 | b_dy = b2.y - b1.y; |
||
320 | |||
321 | if ((div = a_dx * b_dy - b_dx * a_dy) != 0.0) { |
||
322 | lambda = ((b1.x - a1.x) * b_dy - b_dx * (b1.y - a1.y)) / div; |
||
323 | |||
324 | crossing.x = a1.x + lambda * a_dx; |
||
325 | crossing.y = a1.y + lambda * a_dy; |
||
326 | |||
327 | return true; |
||
328 | |||
329 | } |
||
330 | |||
331 | return false; |
||
332 | } |
||
333 | |||
334 | } |