Statistics
| Revision:

root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / topology / checkLineDirectionCoherence / CheckLineDirectionCoherenceAlgorithm.java @ 194

History | View | Annotate | Download (9.15 KB)

1

    
2

    
3
package es.unex.sextante.topology.checkLineDirectionCoherence;
4

    
5
import java.util.ArrayList;
6
import java.util.BitSet;
7
import java.util.HashMap;
8
import java.util.Iterator;
9
import java.util.Set;
10

    
11
import org.slf4j.Logger;
12
import org.slf4j.LoggerFactory;
13

    
14
import com.vividsolutions.jts.geom.Coordinate;
15
import com.vividsolutions.jts.geom.Geometry;
16
import com.vividsolutions.jts.geom.GeometryFactory;
17

    
18
import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue;
19
import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer;
20
import es.unex.sextante.core.GeoAlgorithm;
21
import es.unex.sextante.core.Sextante;
22
import es.unex.sextante.dataObjects.IFeature;
23
import es.unex.sextante.dataObjects.IFeatureIterator;
24
import es.unex.sextante.dataObjects.IVectorLayer;
25
import es.unex.sextante.dataObjects.vectorFilters.BoundingBoxFilter;
26
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException;
27
import es.unex.sextante.exceptions.OptionalParentParameterException;
28
import es.unex.sextante.exceptions.RepeatedParameterNameException;
29
import es.unex.sextante.exceptions.UndefinedParentParameterNameException;
30
import es.unex.sextante.outputs.OutputVectorLayer;
31

    
32

    
33
public class CheckLineDirectionCoherenceAlgorithm
34
         extends
35
            GeoAlgorithm {
36

    
37
    private static final Logger LOG =
38
        LoggerFactory.getLogger(CheckLineDirectionCoherenceAlgorithm.class);
39

    
40
   public static final String  RESULT    = "RESULT";
41
   public static final String  LINES     = "LINES";
42
   public static final String  FIELD     = "FIELD";
43
   private static final String TOLERANCE = "TOLERANCE";
44

    
45
   private IVectorLayer        m_Lines;
46
   private IVectorLayer        m_Output;
47

    
48
   private double              m_dTolerance;
49

    
50

    
51
   @Override
52
   public void defineCharacteristics() {
53

    
54
      setName(Sextante.getText("CheckLineDirectionCoherence"));
55
      setGroup(Sextante.getText("Tools_for_line_layers"));
56
      setUserCanDefineAnalysisExtent(true);
57

    
58
      try {
59
         m_Parameters.addInputVectorLayer(LINES, Sextante.getText("Lines_layer"), AdditionalInfoVectorLayer.SHAPE_TYPE_LINE, true);
60
         m_Parameters.addTableField(FIELD, Sextante.getText("Field"), LINES);
61
         m_Parameters.addNumericalValue(TOLERANCE, Sextante.getText("Tolerance"),
62
                  AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE, 1, 0, Double.MAX_VALUE);
63
         addOutputVectorLayer(RESULT, Sextante.getText("Result"), OutputVectorLayer.SHAPE_TYPE_LINE);
64
      } catch (final RepeatedParameterNameException e) {
65
          LOG.error("Repeated parameter name", e);
66
          return;
67
      } catch (UndefinedParentParameterNameException e) {
68
          LOG.error("Undefined parameter name", e);
69
          return;
70
      } catch (OptionalParentParameterException e) {
71
          LOG.error("Optional parent parameter", e);
72
          return;
73
      }
74
   }
75

    
76

    
77
   @Override
78
   public boolean processAlgorithm() throws GeoAlgorithmExecutionException {
79

    
80
      int i = 0;
81
      int iShapesCount;
82
      final HashMap map = new HashMap();
83
      final HashMap<String, ArrayList<IFeature>> classes = new HashMap<String, ArrayList<IFeature>>();
84

    
85
      m_Lines = m_Parameters.getParameterValueAsVectorLayer(LINES);
86
      if (!m_bIsAutoExtent) {
87
         m_Lines.addFilter(new BoundingBoxFilter(m_AnalysisExtent));
88
      }
89

    
90
      final int iField = m_Parameters.getParameterValueAsInt(FIELD);
91
      m_dTolerance = m_Parameters.getParameterValueAsDouble(TOLERANCE);
92

    
93
      m_Output = getNewVectorLayer(RESULT, m_Lines.getName(), m_Lines.getShapeType(), m_Lines.getFieldTypes(),
94
               m_Lines.getFieldNames());
95

    
96
      //this is a naive approach. Might not work with very large layers...
97
      iShapesCount = m_Lines.getShapesCount();
98
      final IFeatureIterator iter = m_Lines.iterator();
99
      while (iter.hasNext() && setProgress(i, iShapesCount)) {
100
         final IFeature feature = iter.next();
101
         final String sClass = feature.getRecord().getValue(iField).toString();
102
         ArrayList<IFeature> features = classes.get(sClass);
103
         if (features == null) {
104
            features = new ArrayList<IFeature>();
105
            classes.put(sClass, features);
106
         }
107
         features.add(feature);
108
         i++;
109
      }
110
      iter.close();
111

    
112
      final Set set = classes.keySet();
113
      final Iterator keys = set.iterator();
114
      i = 0;
115
      while (keys.hasNext() && setProgress(i, classes.size())) {
116
         final Object sClass = keys.next();
117
         final ArrayList<IFeature> lines = classes.get(sClass);
118
         processLines(lines);
119
      }
120

    
121
      return !m_Task.isCanceled();
122

    
123
   }
124

    
125

    
126
   private void processLines(final ArrayList<IFeature> lines) {
127

    
128
      final BitSet bitset = new BitSet(lines.size());
129
      while (bitset.cardinality() != bitset.length() || bitset.isEmpty()) {
130
         final IFeature line = getExtremeLine(lines, bitset);
131
         m_Output.addFeature(line);
132
         followLine(line, lines, bitset);
133
      }
134
      for (int i = 0; i < lines.size(); i++) {
135
          if(!bitset.get(i)){
136
              IFeature line = lines.get(i);
137
              m_Output.addFeature(line);
138
          }
139
      }
140
   }
141

    
142

    
143
   private void followLine(final IFeature feature,
144
                           final ArrayList<IFeature> lines,
145
                           final BitSet bitset) {
146

    
147

    
148
      final Geometry line = feature.getGeometry();
149
      for (int i = 0; i < lines.size(); i++) {
150
         if (!bitset.get(i)) {
151
            final Coordinate[] coords = line.getCoordinates();
152
            for (int j = 0; j < lines.size(); j++) {
153
                IFeature feature2 = lines.get(j);
154
                final Geometry line2 = feature2.getGeometry();
155
               final Coordinate[] coords2 = line2.getCoordinates();
156
               if (!bitset.get(j) && !line.equals(line2) && coords2[0].distance(coords[coords.length - 1]) < m_dTolerance) {
157
                  m_Output.addFeature(feature2);
158
                  bitset.set(j);
159
                  followLine(feature2, lines, bitset);
160
               }
161
            }
162
         }
163
      }
164
      for (int i = 0; i < lines.size(); i++) {
165
         if (!bitset.get(i)) {
166
            final Coordinate[] coords = line.getCoordinates();
167
            for (int j = 0; j < lines.size(); j++) {
168
                IFeature feature2 = lines.get(j);
169
                final Geometry line2 = feature2.getGeometry();
170
               final Coordinate[] coords2 = line2.getCoordinates();
171
               if (!bitset.get(j) && !line.equals(line2) && coords2[coords2.length - 1].distance(coords[coords.length - 1]) < m_dTolerance) {
172
                  final Geometry inverted = invertDirection(feature.getGeometry());
173
                  m_Output.addFeature(inverted, feature2.getRecord().getValues());
174
                  bitset.set(j);
175
                  followLine(lines.get(j), lines, bitset);
176
               }
177
            }
178
         }
179
      }
180

    
181

    
182
   }
183

    
184

    
185
   private Geometry invertDirection(final Geometry geometry) {
186

    
187
      final Coordinate[] coords = geometry.getCoordinates();
188
      final Coordinate[] newCoords = new Coordinate[coords.length];
189
      for (int i = 0; i < coords.length; i++) {
190
         newCoords[i] = coords[coords.length - i - 1];
191
      }
192
      final GeometryFactory gf = new GeometryFactory();
193
      return gf.createLineString(newCoords);
194

    
195
   }
196

    
197

    
198
   private IFeature getExtremeLine(final ArrayList<IFeature> lines,
199
 final BitSet bitset) {
200

    
201
        for (int i = 0; i < lines.size(); i++) {
202
            if (!bitset.get(i)) {
203
                final Geometry line = lines.get(i).getGeometry();
204
                final Coordinate[] coords = line.getCoordinates();
205
                boolean bHasContiguousLineOnStart = false;
206
                for (int j = 0; j < lines.size(); j++) {
207
                    final Geometry line2 = lines.get(j).getGeometry();
208

    
209
                    final Coordinate[] coords2 = line2.getCoordinates();
210
                    if (i!=j && ((coords2[0].distance(coords[0]) < m_dTolerance)
211
                        || (coords2[coords2.length - 1].distance(coords[0]) < m_dTolerance))) {
212
                        bHasContiguousLineOnStart = true;
213
                        break;
214
                    }
215
                }
216
                boolean bHasContiguousLineOnEnd = false;
217
                for (int j = 0; j < lines.size(); j++) {
218
                    final Geometry line2 = lines.get(j).getGeometry();
219
                    final Coordinate[] coords2 = line2.getCoordinates();
220
                    if (i!=j && ((coords2[0].distance(coords[coords.length - 1]) < m_dTolerance)
221
                        || (coords2[coords2.length - 1].distance(coords[coords.length - 1]) < m_dTolerance))) {
222
                        bHasContiguousLineOnEnd = true;
223
                        break;
224
                    }
225
                }
226
                if (bHasContiguousLineOnEnd != bHasContiguousLineOnStart) {
227
                    bitset.set(i);
228
                    return lines.get(i);
229
                }
230
            }
231
        }
232

    
233
        for (int i = 0; i < lines.size(); i++) {
234
            if (!bitset.get(i)) {
235
                bitset.set(i);
236
                return lines.get(i);
237
            }
238
        }
239

    
240
        return null;
241

    
242
    }
243

    
244
}