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 | 59 | nbrodin | |
---|---|---|---|
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 | 194 | fdiaz | import org.slf4j.Logger; |
12 | import org.slf4j.LoggerFactory; |
||
13 | |||
14 | 59 | nbrodin | 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 | 194 | fdiaz | import es.unex.sextante.exceptions.OptionalParentParameterException; |
28 | 59 | nbrodin | import es.unex.sextante.exceptions.RepeatedParameterNameException; |
29 | 194 | fdiaz | import es.unex.sextante.exceptions.UndefinedParentParameterNameException; |
30 | 59 | nbrodin | import es.unex.sextante.outputs.OutputVectorLayer; |
31 | |||
32 | |||
33 | public class CheckLineDirectionCoherenceAlgorithm |
||
34 | extends
|
||
35 | GeoAlgorithm { |
||
36 | |||
37 | 194 | fdiaz | private static final Logger LOG = |
38 | LoggerFactory.getLogger(CheckLineDirectionCoherenceAlgorithm.class); |
||
39 | |||
40 | 59 | nbrodin | 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 | 194 | fdiaz | m_Parameters.addTableField(FIELD, Sextante.getText("Field"), LINES);
|
61 | 59 | nbrodin | 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 | 194 | fdiaz | } 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 | 59 | nbrodin | } |
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 | 194 | fdiaz | while (bitset.cardinality() != bitset.length() || bitset.isEmpty()) {
|
130 | 59 | nbrodin | final IFeature line = getExtremeLine(lines, bitset);
|
131 | m_Output.addFeature(line); |
||
132 | followLine(line, lines, bitset); |
||
133 | } |
||
134 | 194 | fdiaz | 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 | 59 | nbrodin | } |
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 | 194 | fdiaz | IFeature feature2 = lines.get(j); |
154 | final Geometry line2 = feature2.getGeometry();
|
||
155 | 59 | nbrodin | final Coordinate[] coords2 = line2.getCoordinates(); |
156 | 194 | fdiaz | 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 | 59 | nbrodin | } |
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 | 194 | fdiaz | IFeature feature2 = lines.get(j); |
169 | final Geometry line2 = feature2.getGeometry();
|
||
170 | 59 | nbrodin | final Coordinate[] coords2 = line2.getCoordinates(); |
171 | 194 | fdiaz | if (!bitset.get(j) && !line.equals(line2) && coords2[coords2.length - 1].distance(coords[coords.length - 1]) < m_dTolerance) { |
172 | 59 | nbrodin | final Geometry inverted = invertDirection(feature.getGeometry());
|
173 | 194 | fdiaz | m_Output.addFeature(inverted, feature2.getRecord().getValues()); |
174 | bitset.set(j); |
||
175 | followLine(lines.get(j), lines, bitset); |
||
176 | 59 | nbrodin | } |
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 | 194 | fdiaz | final BitSet bitset) { |
200 | 59 | nbrodin | |
201 | 194 | fdiaz | 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 | 59 | nbrodin | } |
231 | 194 | fdiaz | } |
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 | 59 | nbrodin | } |
238 | 194 | fdiaz | } |
239 | 59 | nbrodin | |
240 | 194 | fdiaz | return null; |
241 | 59 | nbrodin | |
242 | 194 | fdiaz | } |
243 | 59 | nbrodin | |
244 | } |