Statistics
| Revision:

root / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / es / unex / sextante / vectorTools / snapPoints / SnapPointsAlgorithm.java @ 15

History | View | Annotate | Download (5.43 KB)

1

    
2

    
3
package es.unex.sextante.vectorTools.snapPoints;
4

    
5
import java.util.List;
6

    
7
import com.vividsolutions.jts.geom.Coordinate;
8
import com.vividsolutions.jts.geom.Geometry;
9
import com.vividsolutions.jts.geom.GeometryFactory;
10
import com.vividsolutions.jts.geom.LineSegment;
11
import com.vividsolutions.jts.geom.Point;
12

    
13
import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue;
14
import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer;
15
import es.unex.sextante.core.GeoAlgorithm;
16
import es.unex.sextante.core.Sextante;
17
import es.unex.sextante.dataObjects.IFeature;
18
import es.unex.sextante.dataObjects.IFeatureIterator;
19
import es.unex.sextante.dataObjects.IVectorLayer;
20
import es.unex.sextante.dataObjects.vectorFilters.BoundingBoxFilter;
21
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException;
22
import es.unex.sextante.exceptions.RepeatedParameterNameException;
23
import es.unex.sextante.outputs.OutputVectorLayer;
24

    
25

    
26
public class SnapPointsAlgorithm
27
         extends
28
            GeoAlgorithm {
29

    
30
   public static final String     SNAPTO    = "SNAPTO";
31
   public static final String     LAYER     = "LAYER";
32
   public static final String     TOLERANCE = "TOLERANCE";
33
   public static final String     RESULT    = "RESULT";
34

    
35
   private IVectorLayer           m_Layer;
36
   private IVectorLayer           m_SnapTo;
37
   private IVectorLayer           m_Output;
38
   private double                 m_dTolerance;
39
   private NearestNeighbourFinder m_NNF;
40

    
41

    
42
   @Override
43
   public void defineCharacteristics() {
44

    
45
      setName(Sextante.getText("Snap_points_to_layer"));
46
      setGroup(Sextante.getText("Tools_for_point_layers"));
47
      setUserCanDefineAnalysisExtent(true);
48

    
49
      try {
50
         m_Parameters.addInputVectorLayer(LAYER, Sextante.getText("Points_layer"), AdditionalInfoVectorLayer.SHAPE_TYPE_POINT,
51
                  true);
52
         m_Parameters.addInputVectorLayer(SNAPTO, Sextante.getText("Capa_ajuste"), AdditionalInfoVectorLayer.SHAPE_TYPE_ANY,
53
                  true);
54
         m_Parameters.addNumericalValue(TOLERANCE, Sextante.getText("Tolerance"),
55
                  AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE, 10, 0, Double.MAX_VALUE);
56
         addOutputVectorLayer(RESULT, Sextante.getText("Snapped_points"), OutputVectorLayer.SHAPE_TYPE_POINT);
57
      }
58
      catch (final RepeatedParameterNameException e) {
59
         Sextante.addErrorToLog(e);
60
      }
61

    
62
   }
63

    
64

    
65
   @Override
66
   public boolean processAlgorithm() throws GeoAlgorithmExecutionException {
67

    
68
      int i;
69
      int iShapeCount;
70

    
71
      m_Layer = m_Parameters.getParameterValueAsVectorLayer(LAYER);
72
      m_SnapTo = m_Parameters.getParameterValueAsVectorLayer(SNAPTO);
73
      m_dTolerance = m_Parameters.getParameterValueAsDouble(TOLERANCE);
74

    
75
      if (!m_bIsAutoExtent) {
76
         m_Layer.addFilter(new BoundingBoxFilter(m_AnalysisExtent));
77
         m_SnapTo.addFilter(new BoundingBoxFilter(m_AnalysisExtent));
78
      }
79

    
80
      m_NNF = new NearestNeighbourFinder(m_SnapTo, m_Task);
81

    
82
      m_Output = getNewVectorLayer(RESULT, Sextante.getText("Snapped_points"), m_Layer.getShapeType(), m_Layer.getFieldTypes(),
83
               m_Layer.getFieldNames());
84

    
85
      i = 0;
86
      iShapeCount = m_Layer.getShapesCount();
87
      final IFeatureIterator iter = m_Layer.iterator();
88
      while (iter.hasNext() && setProgress(i, iShapeCount)) {
89
         final IFeature feature = iter.next();
90
         final Geometry geom = feature.getGeometry();
91
         final Coordinate coord = geom.getCoordinate();
92
         addPoint(coord.x, coord.y, feature.getRecord().getValues());
93
         i++;
94
      }
95

    
96
      iter.close();
97

    
98
      return !m_Task.isCanceled();
99

    
100
   }
101

    
102

    
103
   private void addPoint(final double x,
104
                         final double y,
105
                         final Object[] values) {
106

    
107
      final Point pt = getSnappedPoint(x, y);
108
      m_Output.addFeature(pt, values);
109

    
110
   }
111

    
112

    
113
   private Point getSnappedPoint(final double x,
114
                   final double y) {
115

    
116
           final GeometryFactory gf = new GeometryFactory();
117
           final Coordinate c = new Coordinate(x, y);
118
           Coordinate closestPoint = new Coordinate(x, y);
119
           Coordinate closestPointToThisLine;
120
           double minDist = m_dTolerance;
121

    
122
           try {
123
                   final List<Geometry> list = m_NNF.getClosestGeometries(c, m_dTolerance);
124
                   for (int iGeom = 0; iGeom < list.size(); iGeom++) {
125
                           final Geometry geom = list.get(iGeom);
126
                           final int iNumGeom = geom.getNumGeometries();
127
                           for (int i = 0; i < iNumGeom; i++) {
128
                                   final Geometry subGeom = geom.getGeometryN(i);
129
                                   final Coordinate[] coords = subGeom.getCoordinates();
130
                                   if (coords.length == 1) {
131
                                           //When snapping to point layer
132
                                           final double dist = c.distance(coords[0]);
133
                                           if ((dist < minDist)) {
134
                                                   minDist = dist;
135
                                                   closestPoint = coords[0];
136
                                           }
137
                                   } else {
138
                                           // When snapping to linestring or polygon layer
139
                                           for (int j = 0; j < coords.length - 1; j++) {
140
                                                   final LineSegment line = new LineSegment(coords[j], coords[j + 1]);
141
                                                   closestPointToThisLine = line.closestPoint(c);
142
                                                   final double dist = c.distance(closestPointToThisLine);
143
                                                   if ((dist < minDist)) {
144
                                                           minDist = dist;
145
                                                           closestPoint = closestPointToThisLine;
146
                                                   }
147
                                           }
148
                                   }
149
                           }
150
                   }
151
           } catch (final Exception e) {
152
                   // will return closest point so far
153
           }
154

    
155
           return gf.createPoint(closestPoint);
156

    
157
   }
158

    
159
}