gvsig-geoprocess / org.gvsig.geoprocess / trunk / org.gvsig.geoprocess / org.gvsig.geoprocess.algorithm / org.gvsig.geoprocess.algorithm.buffer / src / main / java / org / gvsig / geoprocess / algorithm / buffer / BufferAlgorithm.java @ 332
History | View | Annotate | Download (14.4 KB)
1 | 237 | cordinyana | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | 175 | cordinyana | *
|
4 | 245 | cordinyana | * Copyright (C) 2007-2012 gvSIG Association.
|
5 | 175 | cordinyana | *
|
6 | * This program is free software; you can redistribute it and/or
|
||
7 | * modify it under the terms of the GNU General Public License
|
||
8 | * as published by the Free Software Foundation; either version 2
|
||
9 | * of the License, or (at your option) any later version.
|
||
10 | *
|
||
11 | * This program is distributed in the hope that it will be useful,
|
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
14 | * GNU General Public License for more details.
|
||
15 | *
|
||
16 | * You should have received a copy of the GNU General Public License
|
||
17 | * along with this program; if not, write to the Free Software
|
||
18 | 237 | cordinyana | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
19 | * MA 02110-1301, USA.
|
||
20 | 245 | cordinyana | *
|
21 | * For any additional information, do not hesitate to contact us
|
||
22 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
23 | 175 | cordinyana | */
|
24 | package org.gvsig.geoprocess.algorithm.buffer; |
||
25 | |||
26 | 277 | nbrodin | import java.io.File; |
27 | |||
28 | 175 | cordinyana | import javax.swing.JOptionPane; |
29 | |||
30 | 277 | nbrodin | import org.cresques.cts.IProjection; |
31 | import org.gvsig.fmap.dal.DALLocator; |
||
32 | import org.gvsig.fmap.dal.DataManager; |
||
33 | 278 | nbrodin | import org.gvsig.fmap.dal.DataStoreParameters; |
34 | 277 | nbrodin | import org.gvsig.fmap.dal.DataTypes; |
35 | 271 | nbrodin | import org.gvsig.fmap.dal.exception.DataException; |
36 | 278 | nbrodin | import org.gvsig.fmap.dal.exception.InitializeException; |
37 | import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException; |
||
38 | 277 | nbrodin | import org.gvsig.fmap.dal.exception.ValidateDataParametersException; |
39 | import org.gvsig.fmap.dal.feature.EditableFeatureType; |
||
40 | 271 | nbrodin | import org.gvsig.fmap.dal.feature.FeatureSet; |
41 | import org.gvsig.fmap.dal.feature.FeatureStore; |
||
42 | import org.gvsig.fmap.dal.feature.FeatureType; |
||
43 | 277 | nbrodin | import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters; |
44 | import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer; |
||
45 | import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters; |
||
46 | import org.gvsig.fmap.geom.Geometry; |
||
47 | import org.gvsig.geoprocess.algorithm.fusespatially.FuseSpatiallyAlgorithm; |
||
48 | 332 | nbrodin | import org.gvsig.geoprocess.lib.api.GeoProcessLocator; |
49 | 271 | nbrodin | import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess; |
50 | import org.gvsig.geoprocess.lib.sextante.dataObjects.FlyrVectIVectorLayer; |
||
51 | 278 | nbrodin | import org.hsqldb.Types; |
52 | 271 | nbrodin | |
53 | 175 | cordinyana | import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue; |
54 | import es.unex.sextante.core.Sextante; |
||
55 | import es.unex.sextante.dataObjects.IVectorLayer; |
||
56 | import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
||
57 | import es.unex.sextante.exceptions.OptionalParentParameterException; |
||
58 | import es.unex.sextante.exceptions.RepeatedParameterNameException; |
||
59 | import es.unex.sextante.exceptions.UndefinedParentParameterNameException; |
||
60 | import es.unex.sextante.exceptions.UnsupportedOutputChannelException; |
||
61 | 332 | nbrodin | import es.unex.sextante.gui.algorithm.GeoAlgorithmParametersPanel; |
62 | 175 | cordinyana | import es.unex.sextante.outputs.OutputVectorLayer; |
63 | |||
64 | /**
|
||
65 | * Geoprocess that computes a buffer area around each feature's geometry of the
|
||
66 | * input layer. <br>
|
||
67 | * All the points interior to this buffer area has to be at a distance inferior
|
||
68 | * to "buffer distance" to the original geometry. This buffer distance could be
|
||
69 | * constant, or it could be a function of the value of a feature attribute.<br>
|
||
70 | *
|
||
71 | * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
|
||
72 | 191 | cordinyana | * @author gvSIG Team
|
73 | 175 | cordinyana | */
|
74 | 191 | cordinyana | public class BufferAlgorithm extends AbstractSextanteGeoProcess { |
75 | |||
76 | 244 | cordinyana | public static final String RESULT = "RESULT"; |
77 | public static final String LAYER = "LAYER"; |
||
78 | public static final String SELECTED_GEOM = "SELECTED_GEOM"; |
||
79 | public static final String DISTANCE = "DISTANCE"; |
||
80 | public static final String FIELD = "FIELD"; |
||
81 | public static final String DISSOLVE = "DISSOLVE"; |
||
82 | public static final String ROUND_BORDER = "ROUND_BORDER"; |
||
83 | public static final String AREA = "AREA"; |
||
84 | public static final String RING_NUMBER = "RING_NUMBER"; |
||
85 | 332 | nbrodin | public static String[] sOptions = { |
86 | GeoProcessLocator.getGeoProcessManager().getTranslation("poly_out"),
|
||
87 | GeoProcessLocator.getGeoProcessManager().getTranslation("poly_in"),
|
||
88 | GeoProcessLocator.getGeoProcessManager().getTranslation("poly_inandout")
|
||
89 | }; |
||
90 | 244 | cordinyana | |
91 | public void defineCharacteristics() { |
||
92 | setName(getTranslation("Buffer"));
|
||
93 | setGroup(getTranslation("basic_vect_algorithms"));
|
||
94 | 175 | cordinyana | // setGeneratesUserDefinedRasterOutput(false);
|
95 | 332 | nbrodin | |
96 | 244 | cordinyana | try {
|
97 | 272 | nbrodin | m_Parameters.addInputVectorLayer(LAYER, getTranslation("Input_layer"),
|
98 | IVectorLayer.SHAPE_TYPE_WRONG, true);
|
||
99 | m_Parameters.addBoolean(SELECTED_GEOM, getTranslation("Selected_geometries"), false); |
||
100 | m_Parameters.addNumericalValue(DISTANCE, getTranslation("area_distance"), 0, |
||
101 | 244 | cordinyana | AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE); |
102 | 264 | nbrodin | m_Parameters.addTableField(FIELD, getTranslation("area_field"), "LAYER"); |
103 | 272 | nbrodin | m_Parameters.addBoolean(DISSOLVE, getTranslation("Dissolve_entities"), false); |
104 | m_Parameters.addBoolean(ROUND_BORDER, getTranslation("Round_border"), true); |
||
105 | m_Parameters.addSelection(AREA, getTranslation("Builds_influence_area"), sOptions);
|
||
106 | m_Parameters.addSelection(RING_NUMBER, getTranslation("Number_of_rings"),
|
||
107 | 244 | cordinyana | new String[] { "1", "2", "3" }); |
108 | } catch (RepeatedParameterNameException e) {
|
||
109 | Sextante.addErrorToLog(e); |
||
110 | } catch (UndefinedParentParameterNameException e) {
|
||
111 | Sextante.addErrorToLog(e); |
||
112 | } catch (OptionalParentParameterException e) {
|
||
113 | Sextante.addErrorToLog(e); |
||
114 | } |
||
115 | addOutputVectorLayer(RESULT, getTranslation("Buffer"),
|
||
116 | OutputVectorLayer.SHAPE_TYPE_UNDEFINED); |
||
117 | } |
||
118 | 175 | cordinyana | |
119 | 244 | cordinyana | public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
120 | 271 | nbrodin | |
121 | if(existsOutPutFile(BufferAlgorithm.RESULT, 0)) { |
||
122 | throw new GeoAlgorithmExecutionException(getTranslation("file_exists")); |
||
123 | } |
||
124 | |||
125 | 244 | cordinyana | IVectorLayer layer = m_Parameters.getParameterValueAsVectorLayer(LAYER); |
126 | 264 | nbrodin | boolean selectedGeom = m_Parameters.getParameter(SELECTED_GEOM).getParameterValueAsBoolean();
|
127 | double dist = m_Parameters.getParameter(DISTANCE).getParameterValueAsDouble();
|
||
128 | 244 | cordinyana | int attributePosition = m_Parameters.getParameterValueAsInt(FIELD);
|
129 | // boolean dissolve =
|
||
130 | // m_Parameters.getParameter(DISSOLVE).getParameterValueAsBoolean();
|
||
131 | 264 | nbrodin | boolean round_border = m_Parameters.getParameter(ROUND_BORDER).getParameterValueAsBoolean();
|
132 | 244 | cordinyana | int inflArea = m_Parameters.getParameterValueAsInt(AREA);
|
133 | int rings = m_Parameters.getParameterValueAsInt(RING_NUMBER);
|
||
134 | 277 | nbrodin | boolean dissolve = m_Parameters.getParameter(DISSOLVE).getParameterValueAsBoolean();
|
135 | 175 | cordinyana | |
136 | 244 | cordinyana | if (layer.getShapeType() != IVectorLayer.SHAPE_TYPE_POLYGON
|
137 | && inflArea != 0) {
|
||
138 | JOptionPane.showMessageDialog(null, |
||
139 | getTranslation("Wrong_type_for_this_shapetype"), "Error", |
||
140 | JOptionPane.WARNING_MESSAGE);
|
||
141 | inflArea = 0;
|
||
142 | } |
||
143 | 175 | cordinyana | |
144 | 244 | cordinyana | FeatureStore storeLayer = null;
|
145 | if (layer instanceof FlyrVectIVectorLayer) |
||
146 | storeLayer = ((FlyrVectIVectorLayer) layer).getFeatureStore(); |
||
147 | else
|
||
148 | return false; |
||
149 | |||
150 | try {
|
||
151 | FeatureSet features = null;
|
||
152 | features = storeLayer.getFeatureSet(); |
||
153 | FeatureType featureType = features.getDefaultFeatureType(); |
||
154 | |||
155 | // Object to compute the distance
|
||
156 | IDistance distance = null;
|
||
157 | if (dist == 0) |
||
158 | distance = new FieldDistance(attributePosition);
|
||
159 | else
|
||
160 | distance = new ConstantDistance();
|
||
161 | |||
162 | // Object to compute the buffer operation
|
||
163 | BufferOperation operation = null;
|
||
164 | switch (inflArea) {
|
||
165 | case 0: |
||
166 | 289 | nbrodin | operation = new OutBufferOperation(distance, layer, dist, this); |
167 | 244 | cordinyana | break;
|
168 | case 1: |
||
169 | 289 | nbrodin | operation = new InBufferOperation(distance, layer, dist, this); |
170 | 244 | cordinyana | break;
|
171 | case 2: |
||
172 | 289 | nbrodin | operation = new InOutBufferOperation(distance, layer, dist, this); |
173 | 244 | cordinyana | break;
|
174 | } |
||
175 | operation.setTypeOfCap(round_border ? BufferOperation.CAP_ROUND |
||
176 | : BufferOperation.CAP_SQUARE); |
||
177 | operation.setNumberOfRadialBuffers(rings + 1);
|
||
178 | 288 | nbrodin | operation.setGeoProcess(this, 100); |
179 | |||
180 | 277 | nbrodin | // Builds the output FeatureStore
|
181 | FeatureStore outFeatStore = |
||
182 | buildOutPutStore(featureType, |
||
183 | org.gvsig.fmap.geom.Geometry.TYPES.SURFACE, |
||
184 | getTranslation("Buffer"), RESULT, inflArea);
|
||
185 | |||
186 | 290 | nbrodin | |
187 | if(dissolve && rings == 0) { //solo se disuelve si hay un anillo |
||
188 | 277 | nbrodin | FeatureStore outAuxFeatStore = null;
|
189 | try {
|
||
190 | 278 | nbrodin | String file = System.getProperty("java.io.tmpdir") + File.separator + System.currentTimeMillis() + ".shp"; |
191 | 277 | nbrodin | outAuxFeatStore = buildTemporalStore(featureType, |
192 | 278 | nbrodin | org.gvsig.fmap.geom.Geometry.TYPES.SURFACE, file, inflArea, |
193 | storeLayer.getDefaultFeatureType().getDefaultSRS()); |
||
194 | 244 | cordinyana | |
195 | 277 | nbrodin | operation.setTaskStatus(getStatus()); |
196 | operation.computesGeometryOperation(storeLayer, outAuxFeatStore, |
||
197 | attrNames, selectedGeom, true);
|
||
198 | |||
199 | 278 | nbrodin | outAuxFeatStore = open(file, storeLayer.getDefaultFeatureType().getDefaultSRS()); |
200 | 277 | nbrodin | FuseSpatiallyAlgorithm alg = new FuseSpatiallyAlgorithm();
|
201 | 288 | nbrodin | alg.setTaskMonitor(m_Task); |
202 | alg.setParentProcess(this);
|
||
203 | m_Task.setProgressText(getTranslation("fuse_spatially"));
|
||
204 | 278 | nbrodin | alg.execute(outAuxFeatStore, outFeatStore, IVectorLayer.SHAPE_TYPE_POLYGON, |
205 | false, getStatus(), "FID", false); |
||
206 | 277 | nbrodin | } catch (ValidateDataParametersException e) {
|
207 | Sextante.addErrorToLog(e); |
||
208 | } |
||
209 | 290 | nbrodin | } else {
|
210 | // Computes the operation
|
||
211 | operation.setTaskStatus(getStatus()); |
||
212 | operation.computesGeometryOperation(storeLayer, outFeatStore, |
||
213 | attrNames, selectedGeom, true);
|
||
214 | } |
||
215 | 244 | cordinyana | } catch (DataException e) {
|
216 | Sextante.addErrorToLog(e); |
||
217 | return false; |
||
218 | } |
||
219 | 321 | nbrodin | |
220 | if(getTaskMonitor().isCanceled())
|
||
221 | return false; |
||
222 | 175 | cordinyana | |
223 | 244 | cordinyana | return true; |
224 | } |
||
225 | 278 | nbrodin | |
226 | private FeatureStore open(String file, IProjection proj) throws InitializeException, ProviderNotRegisteredException, ValidateDataParametersException { |
||
227 | DataManager manager = DALLocator.getDataManager(); |
||
228 | DataStoreParameters params = manager.createStoreParameters("Shape");
|
||
229 | params.setDynValue("shpfile", file);
|
||
230 | params.setDynValue("crs", proj);
|
||
231 | FeatureStore featureStore = (FeatureStore) manager.openStore(params.getDataStoreName(), params); |
||
232 | return featureStore;
|
||
233 | } |
||
234 | 244 | cordinyana | |
235 | /**
|
||
236 | * Builds the output FeatureStore
|
||
237 | *
|
||
238 | * @param featureType
|
||
239 | * @return FeatureStore
|
||
240 | */
|
||
241 | protected FeatureStore buildOutPutStore(FeatureType featureType,
|
||
242 | int shapeType, String sextanteLayerName, String sextanteLayerLabel, |
||
243 | int infArea) {
|
||
244 | |||
245 | Class<?>[] types = null; |
||
246 | if (infArea == 2) { |
||
247 | types = new Class[] { Integer.class, Double.class, Double.class }; |
||
248 | attrNames = new String[] { "FID", "FROM", "TO" }; |
||
249 | } else {
|
||
250 | types = new Class[] { Integer.class, Double.class }; |
||
251 | attrNames = new String[] { "FID", "DIST" }; |
||
252 | } |
||
253 | |||
254 | try {
|
||
255 | IVectorLayer output = |
||
256 | getNewVectorLayer(sextanteLayerLabel, sextanteLayerName, |
||
257 | shapeType, types, attrNames); |
||
258 | return ((FlyrVectIVectorLayer) output).getFeatureStore();
|
||
259 | } catch (UnsupportedOutputChannelException e) {
|
||
260 | Sextante.addErrorToLog(e); |
||
261 | 175 | cordinyana | } catch (GeoAlgorithmExecutionException e) {
|
262 | Sextante.addErrorToLog(e); |
||
263 | } |
||
264 | 244 | cordinyana | return null; |
265 | } |
||
266 | 277 | nbrodin | |
267 | /**
|
||
268 | * Builds the output FeatureStore
|
||
269 | *
|
||
270 | * @param featureType
|
||
271 | * @return FeatureStore
|
||
272 | * @throws DataException
|
||
273 | * @throws ValidateDataParametersException
|
||
274 | */
|
||
275 | protected FeatureStore buildTemporalStore(FeatureType featureType,
|
||
276 | 278 | nbrodin | int shapeType, String file, |
277 | 277 | nbrodin | int infArea, IProjection crs) throws DataException, ValidateDataParametersException { |
278 | 175 | cordinyana | |
279 | 277 | nbrodin | int[] types = null; |
280 | if (infArea == 2) { |
||
281 | 278 | nbrodin | types = new int[] { Types.INTEGER, Types.DOUBLE, Types.DOUBLE }; |
282 | 277 | nbrodin | attrNames = new String[] { "FID", "FROM", "TO" }; |
283 | } else {
|
||
284 | 278 | nbrodin | types = new int[] { Types.INTEGER, Types.DOUBLE }; |
285 | 277 | nbrodin | attrNames = new String[] { "FID", "DIST" }; |
286 | } |
||
287 | |||
288 | 278 | nbrodin | return create(file, types, attrNames, crs);
|
289 | 277 | nbrodin | } |
290 | |||
291 | 290 | nbrodin | @SuppressWarnings("deprecation") |
292 | 277 | nbrodin | public FeatureStore create(String sFilename, |
293 | int[] types, String[] sFields, IProjection crs) { |
||
294 | try {
|
||
295 | DataManager manager = DALLocator.getDataManager(); |
||
296 | FilesystemServerExplorerParameters explorerParams = |
||
297 | (FilesystemServerExplorerParameters) manager.createServerExplorerParameters("FilesystemExplorer");
|
||
298 | explorerParams.setRoot(new File(sFilename).getParent()); |
||
299 | FilesystemServerExplorer explorer = (FilesystemServerExplorer) manager.createServerExplorer(explorerParams); |
||
300 | NewFeatureStoreParameters newParams = (NewFeatureStoreParameters) explorer.getAddParameters(new File(sFilename)); |
||
301 | |||
302 | EditableFeatureType ft = newParams.getDefaultFeatureType(); |
||
303 | for (int i = 0; i < attrNames.length; i++) { |
||
304 | 278 | nbrodin | ft.add(attrNames[i], types[i], 7);
|
305 | 277 | nbrodin | } |
306 | ft.add("GEOMETRY", DataTypes.GEOMETRY).setGeometryType(
|
||
307 | Geometry.TYPES.SURFACE).setGeometrySubType(Geometry.SUBTYPES.GEOM2D); |
||
308 | |||
309 | newParams.setDefaultFeatureType(ft); |
||
310 | newParams.setDynValue("CRS", crs);
|
||
311 | newParams.setDynValue("geometryType", Geometry.TYPES.SURFACE);
|
||
312 | |||
313 | manager.newStore("FilesystemExplorer",
|
||
314 | newParams.getDataStoreName(), newParams, true);
|
||
315 | |||
316 | FeatureStore featureStore = (FeatureStore) manager.openStore(newParams.getDataStoreName(), newParams); |
||
317 | featureStore.edit(FeatureStore.MODE_APPEND); |
||
318 | return featureStore;
|
||
319 | } catch (Exception e) { |
||
320 | Sextante.addErrorToLog(e); |
||
321 | } |
||
322 | return null; |
||
323 | } |
||
324 | |||
325 | |||
326 | 332 | nbrodin | @Override
|
327 | public Class<? extends GeoAlgorithmParametersPanel> getCustomParametersPanelClass() { |
||
328 | return BufferParametersPanel.class;
|
||
329 | } |
||
330 | 175 | cordinyana | } |