001: package com.vividsolutions.jump.workbench.ui.cursortool;
002:
003: import java.awt.Color;
004: import java.awt.event.MouseEvent;
005: import java.awt.geom.NoninvertibleTransformException;
006: import java.awt.geom.Point2D;
007: import java.util.Collection;
008: import java.util.Iterator;
009:
010: import javax.swing.Icon;
011:
012: import com.vividsolutions.jts.geom.Coordinate;
013: import com.vividsolutions.jts.geom.Geometry;
014: import com.vividsolutions.jts.geom.LineString;
015: import com.vividsolutions.jts.geom.Point;
016: import com.vividsolutions.jts.operation.distance.DistanceOp;
017: import com.vividsolutions.jump.I18N;
018: import com.vividsolutions.jump.feature.Feature;
019: import com.vividsolutions.jump.util.CollectionUtil;
020: import com.vividsolutions.jump.workbench.model.Layer;
021: import com.vividsolutions.jump.workbench.ui.images.IconLoader;
022: import com.vividsolutions.jump.workbench.ui.snap.SnapManager;
023:
024: public class SplitLineStringTool extends
025: AbstractClickSelectedLineStringsTool {
026:
027: Coordinate snapCoord = null;
028:
029: public String getName() {
030: return I18N
031: .get("com.vividsolutions.jump.workbench.ui.cursortool.SplitLineStringTool.Split-LinesStrings");
032: }
033:
034: protected void gestureFinished(Collection nearbyLineStringFeatures)
035: throws NoninvertibleTransformException {
036: Feature closestFeature = closest(nearbyLineStringFeatures,
037: getModelClickPoint());
038: LineString lineString = (LineString) closestFeature
039: .getGeometry();
040: if (CollectionUtil.list(
041: lineString.getStartPoint().getCoordinate(),
042: lineString.getEndPoint().getCoordinate()).contains(
043: DistanceOp.closestPoints(lineString,
044: getModelClickPoint())[0])) {
045: getWorkbench().getFrame().warnUser(
046: NO_SELECTED_LINESTRINGS_HERE_MESSAGE);
047: return;
048: }
049: if (!layer(closestFeature, layerToSpecifiedFeaturesMap())
050: .isEditable()) {
051: warnLayerNotEditable(layer(closestFeature,
052: layerToSpecifiedFeaturesMap()));
053: return;
054: }
055: //-- [sstein] replaced Model destination by point to snap
056: if (this .snapCoord != null) {
057: split(closestFeature, this .snapCoord, layer(closestFeature,
058: layerToSpecifiedFeaturesMap()));
059: } else {
060: split(closestFeature, getModelDestination(), layer(
061: closestFeature, layerToSpecifiedFeaturesMap()));
062: }
063: }
064:
065: private void split(Feature feature, Coordinate coordinate,
066: Layer layer) {
067: new SplitLineStringsOp(Color.blue).addSplit(feature,
068: coordinate, layer, false).execute(getName(),
069: isRollingBackInvalidEdits(), getPanel());
070: }
071:
072: private Feature closest(Collection features, Point point) {
073: Feature closestFeature = null;
074: this .snapCoord = null;
075: //-- [sstein: 20.11.2005] : make snap working
076: double tol = SnapManager.getToleranceInPixels(this
077: .getWorkbench().getBlackboard())
078: / this .getPanel().getViewport().getScale();
079: //double closestDistance = Double.MAX_VALUE;
080: double closestDistance = tol;
081: for (Iterator i = features.iterator(); i.hasNext();) {
082: Feature feature = (Feature) i.next();
083: double distance = feature.getGeometry().distance(point);
084: if (distance < closestDistance) {
085: closestFeature = feature;
086: closestDistance = distance;
087: }
088: }
089: //-- [sstein]: get snap point
090: this .snapCoord = this .getVertexToSnap(closestFeature
091: .getGeometry(), point, tol);
092: return closestFeature;
093: }
094:
095: public Icon getIcon() {
096: return IconLoader.icon("SplitLinestring.gif");
097: }
098:
099: //[sstein: 20.11.2005] added
100: private Coordinate getVertexToSnap(Geometry g, Point p,
101: double tolerance) {
102: Coordinate coord = null;
103: if (g instanceof LineString) {
104: LineString ls = (LineString) g;
105: double minDist = tolerance;
106: for (int i = 0; i < ls.getNumPoints(); i++) {
107: Point pT = ls.getPointN(i);
108: double dist = pT.distance(p);
109: if (dist < minDist) {
110: minDist = dist;
111: coord = (Coordinate) pT.getCoordinate().clone();
112: }
113: }
114: }
115: return coord;
116: }
117: }
|