svn-gvsig-desktop / branches / v2_0_0_prep / extensions / extEditing / src / org / gvsig / editing / gui / cad / tools / SplitGeometryCADTool.java @ 39578
History | View | Annotate | Download (22.5 KB)
1 | 37138 | cordinyana | /* gvSIG. Geographic Information System of the Valencian Government
|
---|---|---|---|
2 | 28070 | vcaballero | *
|
3 | 37138 | cordinyana | * Copyright (C) 2007-2008 Infrastructures and Transports Department
|
4 | * of the Valencian Government (CIT)
|
||
5 | *
|
||
6 | 28070 | vcaballero | * 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 | 37138 | cordinyana | *
|
11 | 28070 | vcaballero | * 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 | 37138 | cordinyana | *
|
16 | 28070 | vcaballero | * 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 | 37138 | cordinyana | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
19 | * MA 02110-1301, USA.
|
||
20 | *
|
||
21 | 28070 | vcaballero | */
|
22 | 29616 | jpiera | package org.gvsig.editing.gui.cad.tools; |
23 | 28070 | vcaballero | |
24 | 38539 | jldominguez | import java.awt.Color; |
25 | import java.awt.Component; |
||
26 | 28070 | vcaballero | import java.awt.Image; |
27 | import java.awt.event.InputEvent; |
||
28 | import java.awt.event.MouseEvent; |
||
29 | import java.awt.geom.Point2D; |
||
30 | import java.util.ArrayList; |
||
31 | import java.util.List; |
||
32 | |||
33 | 38539 | jldominguez | import javax.swing.JOptionPane; |
34 | |||
35 | 34696 | cordinyana | import com.vividsolutions.jts.geom.Coordinate; |
36 | import com.vividsolutions.jts.geom.Geometry; |
||
37 | import com.vividsolutions.jts.geom.GeometryCollection; |
||
38 | import com.vividsolutions.jts.geom.GeometryFactory; |
||
39 | import com.vividsolutions.jts.geom.LineString; |
||
40 | import com.vividsolutions.jts.geom.MultiLineString; |
||
41 | import com.vividsolutions.jts.geom.MultiPoint; |
||
42 | import com.vividsolutions.jts.geom.MultiPolygon; |
||
43 | import com.vividsolutions.jts.geom.Point; |
||
44 | import com.vividsolutions.jts.geom.Polygon; |
||
45 | import com.vividsolutions.jts.geom.PrecisionModel; |
||
46 | |||
47 | 38539 | jldominguez | import org.slf4j.Logger; |
48 | import org.slf4j.LoggerFactory; |
||
49 | |||
50 | 29756 | jpiera | import org.gvsig.andami.PluginServices; |
51 | 38539 | jldominguez | import org.gvsig.andami.ui.mdiManager.IWindow; |
52 | import org.gvsig.app.ApplicationLocator; |
||
53 | 29616 | jpiera | import org.gvsig.editing.gui.cad.DefaultCADTool; |
54 | import org.gvsig.editing.gui.cad.exception.CommandException; |
||
55 | import org.gvsig.editing.gui.cad.tools.smc.SplitGeometryCADToolContext; |
||
56 | import org.gvsig.editing.gui.cad.tools.split.SplitStrategy; |
||
57 | import org.gvsig.editing.layers.VectorialLayerEdited; |
||
58 | 29756 | jpiera | import org.gvsig.fmap.dal.exception.DataException; |
59 | 28070 | vcaballero | import org.gvsig.fmap.dal.feature.EditableFeature; |
60 | import org.gvsig.fmap.dal.feature.Feature; |
||
61 | import org.gvsig.fmap.dal.feature.FeatureStore; |
||
62 | import org.gvsig.fmap.geom.Geometry.SUBTYPES; |
||
63 | 34696 | cordinyana | import org.gvsig.fmap.geom.GeometryLocator; |
64 | 28070 | vcaballero | import org.gvsig.fmap.geom.exception.CreateGeometryException; |
65 | import org.gvsig.fmap.geom.operation.GeometryOperationException; |
||
66 | import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException; |
||
67 | import org.gvsig.fmap.geom.primitive.Envelope; |
||
68 | import org.gvsig.fmap.geom.primitive.GeneralPathX; |
||
69 | 37328 | cordinyana | import org.gvsig.fmap.geom.type.GeometryType; |
70 | 28070 | vcaballero | import org.gvsig.fmap.geom.util.Converter; |
71 | import org.gvsig.fmap.mapcontext.layers.SpatialCache; |
||
72 | import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect; |
||
73 | 38539 | jldominguez | import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol; |
74 | 30335 | jpiera | import org.gvsig.fmap.mapcontrol.MapControlDrawer; |
75 | 38539 | jldominguez | import org.gvsig.i18n.Messages; |
76 | import org.gvsig.symbology.SymbologyLocator; |
||
77 | import org.gvsig.symbology.SymbologyManager; |
||
78 | import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.ISimpleFillSymbol; |
||
79 | 31284 | cordinyana | import org.gvsig.tools.dispose.DisposableIterator; |
80 | import org.gvsig.tools.dispose.DisposeUtils; |
||
81 | 28070 | vcaballero | import org.gvsig.tools.locator.LocatorException; |
82 | |||
83 | import statemap.State; |
||
84 | 38539 | jldominguez | import statemap.StateUndefinedException; |
85 | 28070 | vcaballero | |
86 | /**
|
||
87 | * CAD Tool which splits the selected geometries of a vectorial editing
|
||
88 | * layer with a digitized polyline.
|
||
89 | 37138 | cordinyana | *
|
90 | *
|
||
91 | 28070 | vcaballero | * @author Alvaro Zabala
|
92 | 37138 | cordinyana | *
|
93 | 28070 | vcaballero | */
|
94 | public class SplitGeometryCADTool extends DefaultCADTool { |
||
95 | |||
96 | 38539 | jldominguez | private static Logger logger = |
97 | LoggerFactory.getLogger(SplitGeometryCADTool.class); |
||
98 | 37138 | cordinyana | /**
|
99 | * String representation of this tool (used for example to active the tool
|
||
100 | * in mapcontrol)
|
||
101 | */
|
||
102 | 38564 | jjdelcerro | public static final String SPLIT_GEOMETRY_ACTION_NAME = "layer-modify-split"; |
103 | 37138 | cordinyana | public static final String SPLIT_GEOMETRY_TOOL_NAME = "_split_geometry"; |
104 | 28070 | vcaballero | |
105 | 37138 | cordinyana | /**
|
106 | * finite state machine for this CAD tool
|
||
107 | */
|
||
108 | protected SplitGeometryCADToolContext _fsm;
|
||
109 | 28070 | vcaballero | |
110 | 37138 | cordinyana | /**
|
111 | * Flag to mark if the digitized line has been finished.
|
||
112 | */
|
||
113 | protected boolean digitizingFinished = false; |
||
114 | 28070 | vcaballero | |
115 | 37138 | cordinyana | /**
|
116 | * Collection of digitized geometries
|
||
117 | */
|
||
118 | protected List<Point2D> clickedPoints; |
||
119 | 28070 | vcaballero | |
120 | 37138 | cordinyana | /**
|
121 | 38539 | jldominguez | * used to draw helping rectangle (bbox)
|
122 | */
|
||
123 | protected ISymbol rectSymbol = null; |
||
124 | /**
|
||
125 | 37138 | cordinyana | * Initialization method.
|
126 | */
|
||
127 | public void init() { |
||
128 | digitizingFinished = false;
|
||
129 | _fsm = new SplitGeometryCADToolContext(this); |
||
130 | setNextTool(SplitGeometryCADTool.SPLIT_GEOMETRY_TOOL_NAME); |
||
131 | } |
||
132 | 28070 | vcaballero | |
133 | 37138 | cordinyana | public boolean isDigitizingFinished() { |
134 | return digitizingFinished;
|
||
135 | } |
||
136 | 28070 | vcaballero | |
137 | 37138 | cordinyana | public String toString() { |
138 | return SplitGeometryCADTool.SPLIT_GEOMETRY_TOOL_NAME;
|
||
139 | } |
||
140 | 28070 | vcaballero | |
141 | 37138 | cordinyana | public void finishDigitizedLine() { |
142 | } |
||
143 | 28070 | vcaballero | |
144 | 37138 | cordinyana | public Coordinate[] getPoint2DAsCoordinates(Point2D[] point2d) { |
145 | Coordinate[] solution = new Coordinate[point2d.length]; |
||
146 | for (int i = 0; i < point2d.length; i++) { |
||
147 | solution[i] = new Coordinate(point2d[i].getX(), point2d[i].getY());
|
||
148 | } |
||
149 | return solution;
|
||
150 | } |
||
151 | 28070 | vcaballero | |
152 | 37138 | cordinyana | public void splitSelectedGeometryWithDigitizedLine() { |
153 | 38539 | jldominguez | |
154 | // comprobar bucle, probar interseccion?
|
||
155 | 37138 | cordinyana | Point2D[] clickedPts = new Point2D[this.clickedPoints.size()]; |
156 | clickedPoints.toArray(clickedPts); |
||
157 | Coordinate[] digitizedCoords = getPoint2DAsCoordinates(clickedPts);
|
||
158 | LineString splittingLs = |
||
159 | new GeometryFactory(new PrecisionModel(10000)) |
||
160 | .createLineString(digitizedCoords); |
||
161 | DisposableIterator selected = null;
|
||
162 | try {
|
||
163 | VectorialLayerEdited vle = getVLE(); |
||
164 | FeatureStore store = vle.getFeatureStore(); |
||
165 | selected = store.getFeatureSelection().iterator(); |
||
166 | 28070 | vcaballero | |
167 | 37138 | cordinyana | getCadToolAdapter().getMapControl().getMapContext() |
168 | .beginAtomicEvent(); |
||
169 | store.beginEditingGroup(getName()); |
||
170 | while (selected.hasNext()) {
|
||
171 | Feature feature = (Feature) selected.next(); |
||
172 | org.gvsig.fmap.geom.Geometry ig = feature.getDefaultGeometry(); |
||
173 | 37776 | jpiera | Geometry jtsGeo = (Geometry)ig.invokeOperation("toJTS", null); |
174 | 37138 | cordinyana | if (jtsGeo == null) |
175 | return;
|
||
176 | Geometry splitGeo = SplitStrategy.splitOp(jtsGeo, splittingLs); |
||
177 | if (splitGeo instanceof GeometryCollection |
||
178 | && ((GeometryCollection) splitGeo).getNumGeometries() > 1) {
|
||
179 | 28070 | vcaballero | |
180 | 37138 | cordinyana | GeometryCollection gc = (GeometryCollection) splitGeo; |
181 | ArrayList<Geometry> geoms0 = new ArrayList<Geometry>(); |
||
182 | ArrayList<Geometry> geoms1 = new ArrayList<Geometry>(); |
||
183 | if (gc.getNumGeometries() > 2) { |
||
184 | Geometry[] splitGroups =
|
||
185 | createSplitGroups(jtsGeo, splittingLs); |
||
186 | 38539 | jldominguez | |
187 | if (splitGroups == null) { |
||
188 | |||
189 | String _tit = Messages.getText("split_geometry"); |
||
190 | String _msg = Messages.getText("_Split_line_must_start_and_end_outside_bbox"); |
||
191 | Component parent = getCurrentWindow();
|
||
192 | JOptionPane.showMessageDialog(
|
||
193 | parent, |
||
194 | _msg, |
||
195 | _tit, |
||
196 | JOptionPane.WARNING_MESSAGE);
|
||
197 | // cancel splitting
|
||
198 | break;
|
||
199 | } |
||
200 | |||
201 | 37138 | cordinyana | if (splitGroups.length == 0) { |
202 | continue;
|
||
203 | } |
||
204 | 28070 | vcaballero | |
205 | 37138 | cordinyana | for (int j = 0; j < gc.getNumGeometries(); j++) { |
206 | Geometry g = gc.getGeometryN(j); |
||
207 | 38539 | jldominguez | |
208 | if (isRatherInside(g, splitGroups[0])) { |
||
209 | geoms0.add(g); |
||
210 | } else {
|
||
211 | geoms1.add(g); |
||
212 | 37138 | cordinyana | } |
213 | } |
||
214 | 38539 | jldominguez | } else {
|
215 | 37138 | cordinyana | if (gc.getNumGeometries() == 2) { |
216 | geoms0.add(gc.getGeometryN(0));
|
||
217 | geoms1.add(gc.getGeometryN(1));
|
||
218 | } else {
|
||
219 | continue;
|
||
220 | } |
||
221 | 38539 | jldominguez | } |
222 | 37138 | cordinyana | GeometryCollection gc0 = |
223 | createMulti(geoms0, gc.getFactory()); |
||
224 | 28070 | vcaballero | |
225 | 37138 | cordinyana | // for(int j = 0; j < gc.getNumGeometries(); j++){
|
226 | // Geometry g = gc.getGeometryN(j);
|
||
227 | org.gvsig.fmap.geom.Geometry fmapGeo = |
||
228 | Converter.jtsToGeometry(gc0); |
||
229 | 28070 | vcaballero | |
230 | 37138 | cordinyana | // if (j==0){
|
231 | EditableFeature eFeature = feature.getEditable(); |
||
232 | eFeature.setGeometry(store.getDefaultFeatureType() |
||
233 | .getDefaultGeometryAttributeName(), fmapGeo); |
||
234 | store.update(eFeature); |
||
235 | // }else{
|
||
236 | GeometryCollection gc1 = |
||
237 | createMulti(geoms1, gc.getFactory()); |
||
238 | fmapGeo = Converter.jtsToGeometry(gc1); |
||
239 | 28070 | vcaballero | |
240 | 39578 | jjdelcerro | super.insertGeometry(fmapGeo,feature);
|
241 | // EditableFeature newFeature =
|
||
242 | // store.createNewFeature(store.getDefaultFeatureType(),
|
||
243 | // feature);
|
||
244 | // newFeature.setGeometry(store.getDefaultFeatureType()
|
||
245 | // .getDefaultGeometryAttributeName(), fmapGeo);
|
||
246 | // store.insert(newFeature);
|
||
247 | //
|
||
248 | // SpatialCache spatialCache =
|
||
249 | // ((FLyrVect) vle.getLayer()).getSpatialCache();
|
||
250 | // Envelope envelope = fmapGeo.getEnvelope();
|
||
251 | // spatialCache.insert(envelope, fmapGeo);
|
||
252 | |||
253 | 37138 | cordinyana | // }
|
254 | // }//for j
|
||
255 | }// if splitGeo
|
||
256 | 28070 | vcaballero | |
257 | 37138 | cordinyana | } |
258 | 28070 | vcaballero | |
259 | 37138 | cordinyana | store.endEditingGroup(); |
260 | 28070 | vcaballero | |
261 | 37138 | cordinyana | getCadToolAdapter().getMapControl().getMapContext() |
262 | .endAtomicEvent(); |
||
263 | } catch (Exception ex) { |
||
264 | PluginServices.getLogger().error("Error splitting geom", ex);
|
||
265 | } finally {
|
||
266 | DisposeUtils.dispose(selected); |
||
267 | } |
||
268 | } |
||
269 | 28070 | vcaballero | |
270 | 38539 | jldominguez | /**
|
271 | * @return
|
||
272 | */
|
||
273 | private Component getCurrentWindow() { |
||
274 | |||
275 | IWindow iw = PluginServices.getMDIManager().getActiveWindow(); |
||
276 | if (iw instanceof Component) { |
||
277 | return (Component) iw; |
||
278 | } else {
|
||
279 | return null; |
||
280 | } |
||
281 | } |
||
282 | |||
283 | 37138 | cordinyana | private GeometryCollection createMulti(ArrayList<Geometry> geoms, |
284 | GeometryFactory factory) { |
||
285 | if (geoms.size() == 0) |
||
286 | return null; |
||
287 | if (geoms.get(0) instanceof Polygon) { |
||
288 | return new MultiPolygon((Polygon[]) geoms.toArray(new Polygon[0]), |
||
289 | factory); |
||
290 | } else
|
||
291 | if (geoms.get(0) instanceof LineString) { |
||
292 | return new MultiLineString( |
||
293 | (LineString[]) geoms.toArray(new LineString[0]), factory); |
||
294 | } else
|
||
295 | if (geoms.get(0) instanceof Point) { |
||
296 | return new MultiPoint( |
||
297 | (Point[]) geoms.toArray(new Point[0]), factory); |
||
298 | } |
||
299 | return null; |
||
300 | } |
||
301 | 28070 | vcaballero | |
302 | 37138 | cordinyana | private Geometry[] createSplitGroups(Geometry splitGeo, |
303 | LineString splittingLs) { |
||
304 | try {
|
||
305 | Geometry[] geomsJTS = new Geometry[2]; |
||
306 | Geometry r = splitGeo.getEnvelope(); |
||
307 | Geometry splitG = SplitStrategy.splitOp(r, splittingLs); |
||
308 | if (splitG instanceof GeometryCollection |
||
309 | && ((GeometryCollection) splitG).getNumGeometries() > 1) {
|
||
310 | GeometryCollection gc = (GeometryCollection) splitG; |
||
311 | for (int j = 0; j < gc.getNumGeometries(); j++) { |
||
312 | geomsJTS[j] = gc.getGeometryN(j); |
||
313 | } |
||
314 | } |
||
315 | return geomsJTS;
|
||
316 | } catch (Exception e) { |
||
317 | 38539 | jldominguez | logger.info("Warning: Found split line which does not leave bbox. User will be prompted.");
|
318 | 37138 | cordinyana | } |
319 | return null; |
||
320 | } |
||
321 | 29724 | vcaballero | |
322 | 37138 | cordinyana | public void end() { |
323 | getCadToolAdapter().refreshEditedLayer(); |
||
324 | init(); |
||
325 | } |
||
326 | 29724 | vcaballero | |
327 | 37138 | cordinyana | public void addOption(String s) { |
328 | State actualState = _fsm.getPreviousState(); |
||
329 | String status = actualState.getName();
|
||
330 | if (s.equals(PluginServices.getText(this, "cancel"))) { |
||
331 | init(); |
||
332 | return;
|
||
333 | } |
||
334 | if (status.equals("TopologicalEdition.FirstPoint")) { |
||
335 | return;
|
||
336 | } |
||
337 | init(); |
||
338 | 29724 | vcaballero | |
339 | 37138 | cordinyana | } |
340 | 28070 | vcaballero | |
341 | 37138 | cordinyana | public void addPoint(double x, double y, InputEvent event) { |
342 | 28070 | vcaballero | |
343 | 37138 | cordinyana | State actualState = _fsm.getPreviousState(); |
344 | String status = actualState.getName();
|
||
345 | if (status.equals("SplitGeometry.FirstPoint")) { |
||
346 | clickedPoints = new ArrayList<Point2D>(); |
||
347 | clickedPoints.add(new Point2D.Double(x, y)); |
||
348 | } else
|
||
349 | if (status.equals("SplitGeometry.DigitizingLine")) { |
||
350 | clickedPoints.add(new Point2D.Double(x, y)); |
||
351 | if (event != null && ((MouseEvent) event).getClickCount() == 2) { |
||
352 | digitizingFinished = true;
|
||
353 | finishDigitizedLine(); |
||
354 | splitSelectedGeometryWithDigitizedLine(); |
||
355 | end(); |
||
356 | } |
||
357 | } |
||
358 | } |
||
359 | 28070 | vcaballero | |
360 | 37138 | cordinyana | public void addValue(double d) { |
361 | } |
||
362 | 28070 | vcaballero | |
363 | 37138 | cordinyana | /**
|
364 | * Draws a polyline with the clicked digitized points in the specified
|
||
365 | * graphics.
|
||
366 | *
|
||
367 | * @param g2
|
||
368 | * graphics on to draw the polyline
|
||
369 | * @param x
|
||
370 | * last x mouse pointer position
|
||
371 | * @param y
|
||
372 | * last y mouse pointer position
|
||
373 | */
|
||
374 | protected void drawPolyLine(MapControlDrawer renderer, double x, double y) { |
||
375 | GeneralPathX gpx = |
||
376 | new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, clickedPoints.size());
|
||
377 | Point2D firstPoint = clickedPoints.get(0); |
||
378 | gpx.moveTo(firstPoint.getX(), firstPoint.getY()); |
||
379 | for (int i = 1; i < clickedPoints.size(); i++) { |
||
380 | Point2D clickedPoint = clickedPoints.get(i);
|
||
381 | gpx.lineTo(clickedPoint.getX(), clickedPoint.getY()); |
||
382 | 28070 | vcaballero | |
383 | 37138 | cordinyana | } |
384 | gpx.lineTo(x, y); |
||
385 | org.gvsig.fmap.geom.Geometry geom; |
||
386 | try {
|
||
387 | geom = |
||
388 | GeometryLocator.getGeometryManager().createCurve(gpx, |
||
389 | SUBTYPES.GEOM2D); |
||
390 | renderer.draw(geom, mapControlManager.getGeometrySelectionSymbol()); |
||
391 | } catch (LocatorException e) {
|
||
392 | e.printStackTrace(); |
||
393 | } catch (CreateGeometryException e) {
|
||
394 | e.printStackTrace(); |
||
395 | } |
||
396 | } |
||
397 | 28070 | vcaballero | |
398 | 37138 | cordinyana | private void drawRectangleOfSplit(MapControlDrawer renderer) |
399 | throws GeometryOperationNotSupportedException,
|
||
400 | 38378 | jldominguez | GeometryOperationException, DataException, |
401 | CreateGeometryException { |
||
402 | 37138 | cordinyana | VectorialLayerEdited vle = getVLE(); |
403 | FeatureStore store = vle.getFeatureStore(); |
||
404 | DisposableIterator selected = null;
|
||
405 | 28070 | vcaballero | |
406 | 37138 | cordinyana | try {
|
407 | selected = store.getFeatureSelection().iterator(); |
||
408 | while (selected.hasNext()) {
|
||
409 | Feature feature = (Feature) selected.next(); |
||
410 | org.gvsig.fmap.geom.Geometry ig = feature.getDefaultGeometry(); |
||
411 | 37776 | jpiera | Geometry jtsG = (Geometry)ig.invokeOperation("toJTS", null); |
412 | 37138 | cordinyana | if (jtsG != null && jtsG instanceof GeometryCollection |
413 | && jtsG.getNumGeometries() > 1) {
|
||
414 | 38378 | jldominguez | |
415 | /*
|
||
416 | 37138 | cordinyana | org.gvsig.fmap.geom.Geometry r =
|
417 | ig.getEnvelope().getGeometry();
|
||
418 | 38378 | jldominguez | */
|
419 | // get perimeter of envelope to prevent
|
||
420 | // opaque rectangle
|
||
421 | org.gvsig.fmap.geom.Geometry geom = |
||
422 | GeometryLocator.getGeometryManager().createCurve( |
||
423 | ig.getEnvelope().getGeometry().getGeneralPath(), |
||
424 | SUBTYPES.GEOM2D); |
||
425 | |||
426 | 38539 | jldominguez | renderer.draw(geom, getRectangleOfSplitSymbol()); |
427 | 37138 | cordinyana | } |
428 | } |
||
429 | } finally {
|
||
430 | DisposeUtils.dispose(selected); |
||
431 | } |
||
432 | } |
||
433 | 28070 | vcaballero | |
434 | 38539 | jldominguez | /**
|
435 | * @return
|
||
436 | */
|
||
437 | private ISymbol getRectangleOfSplitSymbol() {
|
||
438 | |||
439 | if (rectSymbol == null) { |
||
440 | SymbologyManager sm = SymbologyLocator.getSymbologyManager(); |
||
441 | ISimpleFillSymbol resp = sm.createSimpleFillSymbol(); |
||
442 | resp.setColor(Color.RED);
|
||
443 | resp.setFillColor(new Color(0,0,0, 100)); |
||
444 | rectSymbol = resp; |
||
445 | } |
||
446 | return rectSymbol;
|
||
447 | } |
||
448 | |||
449 | 37138 | cordinyana | public void drawOperation(MapControlDrawer renderer, double x, double y) { |
450 | 38539 | jldominguez | |
451 | // decide whether user line must be drawn
|
||
452 | boolean draw_user_poly_line = false; |
||
453 | 29756 | jpiera | try {
|
454 | 38539 | jldominguez | State currentState = _fsm.getState(); |
455 | if (currentState != null) { |
||
456 | String status = currentState.getName();
|
||
457 | if (status != null && status.equals("SplitGeometry.DigitizingLine")) { |
||
458 | draw_user_poly_line = true;
|
||
459 | } |
||
460 | } |
||
461 | } catch (StateUndefinedException sue) {
|
||
462 | // this happens when state is null
|
||
463 | // because the line has been finished and we must not draw it
|
||
464 | draw_user_poly_line = false;
|
||
465 | } |
||
466 | |||
467 | // =======================================================
|
||
468 | |||
469 | try {
|
||
470 | 37138 | cordinyana | drawRectangleOfSplit(renderer); |
471 | 38539 | jldominguez | |
472 | // possibly draw splitting line
|
||
473 | if (draw_user_poly_line) {
|
||
474 | 37138 | cordinyana | drawPolyLine(renderer, x, y); |
475 | } |
||
476 | 28070 | vcaballero | |
477 | 29756 | jpiera | // draw selection
|
478 | 37138 | cordinyana | Image imgSel = getVLE().getSelectionImage();
|
479 | renderer.drawImage(imgSel, 0, 0); |
||
480 | 28070 | vcaballero | } catch (Exception e) { |
481 | 38539 | jldominguez | |
482 | logger.info("Error while drawing split tool.", e);
|
||
483 | ApplicationLocator.getManager().message( |
||
484 | Messages.getText("_Drawing_error") + e.getMessage(),
|
||
485 | JOptionPane.ERROR_MESSAGE);
|
||
486 | 28070 | vcaballero | } |
487 | 37138 | cordinyana | } |
488 | 28070 | vcaballero | |
489 | 37138 | cordinyana | public String getName() { |
490 | return PluginServices.getText(this, "split_geometry_shell"); |
||
491 | } |
||
492 | 28070 | vcaballero | |
493 | 37138 | cordinyana | public void transition(double x, double y, InputEvent event) { |
494 | try {
|
||
495 | _fsm.addPoint(x, y, event); |
||
496 | } catch (Exception e) { |
||
497 | init(); |
||
498 | } |
||
499 | 28070 | vcaballero | |
500 | 37138 | cordinyana | } |
501 | 28070 | vcaballero | |
502 | 37138 | cordinyana | public void transition(double d) { |
503 | _fsm.addValue(d); |
||
504 | } |
||
505 | 28070 | vcaballero | |
506 | 37138 | cordinyana | public void transition(String s) throws CommandException { |
507 | if (!super.changeCommand(s)) { |
||
508 | _fsm.addOption(s); |
||
509 | } |
||
510 | } |
||
511 | 28070 | vcaballero | |
512 | 37328 | cordinyana | @Override
|
513 | public boolean isApplicable(GeometryType geometryType) { |
||
514 | return true; |
||
515 | } |
||
516 | |||
517 | @Override
|
||
518 | protected int[] getSupportedGeometryTypes() { |
||
519 | return null; |
||
520 | } |
||
521 | 38539 | jldominguez | |
522 | /**
|
||
523 | * This method decides if geometrya is inside geometry b
|
||
524 | * by more than 50%. This is useful because it will be
|
||
525 | * used to assign each geometry to one of two possible containers
|
||
526 | *
|
||
527 | * @param a
|
||
528 | * @param b must be a multi(polygon)
|
||
529 | * @return
|
||
530 | */
|
||
531 | private static boolean isRatherInside(Geometry a, Geometry b) { |
||
532 | |||
533 | if (a instanceof Polygon || a instanceof MultiPolygon) { |
||
534 | return polygonIsRatherInside(a, b);
|
||
535 | } else {
|
||
536 | if (a instanceof LineString || a instanceof MultiLineString) { |
||
537 | return lineIsRatherInside(a, b);
|
||
538 | } else {
|
||
539 | if (a instanceof MultiPoint) { |
||
540 | |||
541 | MultiPoint mp = (MultiPoint) a; |
||
542 | int n = mp.getNumPoints();
|
||
543 | int inn = 0; |
||
544 | Geometry itemg = null;
|
||
545 | for (int i=0; i<n; i++) { |
||
546 | itemg = mp.getGeometryN(i); |
||
547 | if (isRatherInside(itemg, b)) {
|
||
548 | inn++; |
||
549 | } |
||
550 | } |
||
551 | return inn > (n/2); |
||
552 | } else {
|
||
553 | // last case: should be a point
|
||
554 | return b.contains(a);
|
||
555 | } |
||
556 | } |
||
557 | } |
||
558 | |||
559 | } |
||
560 | |||
561 | |||
562 | |||
563 | /**
|
||
564 | * This method decides if a polygon is inside another
|
||
565 | * by more than 50%. This is useful because it will be
|
||
566 | * used to assign each polygon to one of two possible containers
|
||
567 | *
|
||
568 | * @param a
|
||
569 | * @param b
|
||
570 | * @return whether a is 'rather' contained by b
|
||
571 | */
|
||
572 | private static boolean polygonIsRatherInside(Geometry a, Geometry b) { |
||
573 | |||
574 | if (a == null || b == null || a.isEmpty() || b.isEmpty()) { |
||
575 | return false; |
||
576 | } |
||
577 | |||
578 | double area_a = a.getArea();
|
||
579 | |||
580 | if (area_a == 0) { |
||
581 | return false; |
||
582 | } |
||
583 | |||
584 | Geometry a_inters_b = null;
|
||
585 | |||
586 | a_inters_b = a.intersection(b); |
||
587 | if (a_inters_b == null || a_inters_b.isEmpty()) { |
||
588 | return false; |
||
589 | } |
||
590 | |||
591 | double area_aib = a_inters_b.getArea();
|
||
592 | |||
593 | if (area_aib == 0) { |
||
594 | return false; |
||
595 | } |
||
596 | |||
597 | return area_aib > (0.5d * area_a); |
||
598 | } |
||
599 | |||
600 | /**
|
||
601 | *
|
||
602 | * @param a assumed to be a (multi)linestring
|
||
603 | * @param b the (possibly) containing polygon
|
||
604 | * @return
|
||
605 | */
|
||
606 | private static boolean lineIsRatherInside(Geometry a, Geometry b) { |
||
607 | |||
608 | if (a == null || b == null || a.isEmpty() || b.isEmpty()) { |
||
609 | return false; |
||
610 | } |
||
611 | |||
612 | double len_a = a.getLength();
|
||
613 | |||
614 | if (len_a == 0) { |
||
615 | return false; |
||
616 | } |
||
617 | |||
618 | Geometry a_inters_b = null;
|
||
619 | |||
620 | a_inters_b = a.intersection(b); |
||
621 | if (a_inters_b == null || a_inters_b.isEmpty()) { |
||
622 | return false; |
||
623 | } |
||
624 | |||
625 | double len_aib = a_inters_b.getLength();
|
||
626 | |||
627 | if (len_aib == 0) { |
||
628 | return false; |
||
629 | } |
||
630 | |||
631 | return len_aib > (0.5d * len_a); |
||
632 | } |
||
633 | 28070 | vcaballero | } |