comparison gnv-artifacts/src/main/java/de/intevation/gnv/raster/JTSMultiLineStringProducer.java @ 1119:7c4f81f74c47

merged gnv-artifacts
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:00 +0200
parents f953c9a559d8
children
comparison
equal deleted inserted replaced
1027:fca4b5eb8d2f 1119:7c4f81f74c47
1 /*
2 * Copyright (c) 2010 by Intevation GmbH
3 *
4 * This program is free software under the LGPL (>=v2.1)
5 * Read the file LGPL.txt coming with the software for details
6 * or visit http://www.gnu.org/licenses/ if it does not exist.
7 */
8
9 package de.intevation.gnv.raster;
10
11 import com.vividsolutions.jts.geom.Coordinate;
12 import com.vividsolutions.jts.geom.Geometry;
13 import com.vividsolutions.jts.geom.GeometryFactory;
14 import com.vividsolutions.jts.geom.LineString;
15 import com.vividsolutions.jts.geom.MultiLineString;
16 import com.vividsolutions.jts.geom.Polygon;
17 import com.vividsolutions.jts.geom.TopologyException;
18
19 import de.intevation.gnv.math.IJKey;
20
21 import de.intevation.gnv.raster.Vectorizer.Edge;
22
23 import de.intevation.gnv.utils.Pair;
24
25 import gnu.trove.TIntObjectHashMap;
26
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import org.apache.log4j.Logger;
31
32 /**
33 * Vectorizer backend to generated iso lines in form of
34 * JTS multi linestrings.
35 *
36 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a>
37 */
38 public class JTSMultiLineStringProducer
39 extends IsoProducer
40 {
41 private static Logger log = Logger.getLogger(
42 JTSMultiLineStringProducer.class);
43
44 /**
45 * The JTS geometry factory of this producer.
46 */
47 protected GeometryFactory geometryFactory;
48
49 /**
50 * The polygon used to clip the produced multe line strings.
51 */
52 protected Polygon clip;
53
54 /**
55 * Constructor to create a JTSMultiLineStringProducer with
56 * a given clipping polygon and a world bounding box.
57 * @param clip The clipping polygon.
58 * @param minX Min x coord of the world.
59 * @param minY Min y coord of the world.
60 * @param maxX Max x coord of the world.
61 * @param maxY Max y coord of the world.
62 */
63 public JTSMultiLineStringProducer(
64 Polygon clip,
65 double minX, double minY,
66 double maxX, double maxY
67 ) {
68 this(
69 clip,
70 // XXX: Geotools crashes if only using a 2d packed data format!
71 JTSMultiPolygonProducer.createDefaultGeometryFactory(3),
72 minX, minY,
73 maxX, maxY);
74 }
75
76 /**
77 * Constructor to create a JTSMultiLineStringProducer with
78 * a given clipping polygon, a geometry factory
79 * and a world bounding box.
80 * @param clip The clipping polygon.
81 * @param geometryFactory The geometry factory.
82 * @param minX Min x coord of the world.
83 * @param minY Min y coord of the world.
84 * @param maxX Max x coord of the world.
85 * @param maxY Max y coord of the world.
86 */
87 public JTSMultiLineStringProducer(
88 Polygon clip,
89 GeometryFactory geometryFactory,
90 double minX, double minY,
91 double maxX, double maxY
92 ) {
93 super(minX, minY, maxX, maxY);
94 this.clip = clip;
95 this.geometryFactory = geometryFactory;
96 }
97
98 /**
99 * Clips a given line string against the clippin polygon. The
100 * result is stored in the given list of line strings.
101 * @param lineString The line string to be clipped.
102 * @param lineStrings The result line string list.
103 */
104 protected void clipLineString(
105 LineString lineString,
106 ArrayList<LineString> lineStrings
107 ) {
108 if (clip == null) {
109 lineStrings.add(lineString);
110 return;
111 }
112
113 if (!lineString.intersects(clip)) {
114 return;
115 }
116
117 try {
118 Geometry result = lineString.intersection(clip);
119
120 if (result instanceof LineString) {
121 lineStrings.add((LineString)result);
122 }
123 else if (result instanceof MultiLineString) {
124 MultiLineString mls = (MultiLineString)result;
125 for (int i = 0, N = mls.getNumGeometries(); i < N; ++i) {
126 Geometry g = mls.getGeometryN(i);
127 if (g instanceof LineString) {
128 lineStrings.add((LineString)g);
129 }
130 else {
131 log.warn("cannot handle geometry " + g.getClass());
132 }
133 }
134 }
135 else {
136 log.warn("cannot handle " + result.getClass());
137 }
138 }
139 catch (TopologyException te) {
140 log.error(te.getLocalizedMessage(), te);
141 lineStrings.add(lineString);
142 }
143 }
144
145 /**
146 * Returns a list of pairs attribute -&gt; multi line string.
147 * All line strings produced are grouped by there attribute
148 * which is generated with the given attribute generator.
149 * @param attributeGenerator The attribute generator.
150 * @return The list of attribute/multi line strings.
151 */
152 public List<Pair<Object, MultiLineString>> getMultiLineStrings(
153 AttributeGenerator attributeGenerator
154 ) {
155 ArrayList<Pair<Object, MultiLineString>> multiLineStrings =
156 new ArrayList<Pair<Object, MultiLineString>>();
157
158 double b1 = minX;
159 double m1 = width != 1
160 ? (maxX - minX)/(width-1)
161 : 0d;
162
163 double b2 = minY;
164 double m2 = height != 1
165 ? (maxY - minY)/(height-1)
166 : 0d;
167
168 ArrayList<Coordinate> coordinates = new ArrayList<Coordinate>();
169
170 for (IJKey key: joinPairs()) {
171 ArrayList<LineString> lineStrings = new ArrayList<LineString>();
172
173 // process complete
174 ArrayList<Edge> completeList = complete.get(key);
175 if (completeList != null) {
176 for (Edge head: completeList) {
177 Edge current = head;
178 do {
179 coordinates.add(new Coordinate(
180 m1*(current.a % width) + b1,
181 m2*(current.a / width) + b2));
182 }
183 while ((current = current.next) != head);
184 // add head again to close shape
185 coordinates.add(new Coordinate(
186 m1*(head.a % width) + b1,
187 m2*(head.a / width) + b2));
188
189 clipLineString(
190 geometryFactory.createLineString(
191 coordinates.toArray(
192 new Coordinate[coordinates.size()])),
193 lineStrings);
194
195 coordinates.clear();
196 }
197 }
198
199 // process open
200 TIntObjectHashMap map = commonOpen.get(key);
201
202 if (map != null) {
203 for (Edge head: headList(map)) {
204
205 head = Vectorizer.simplify(head, width);
206 Edge current = head, last = head;
207 do {
208 coordinates.add(new Coordinate(
209 m1*(current.a % width) + b1,
210 m2*(current.a / width) + b2));
211 last = current;
212 }
213 while ((current = current.next) != null);
214 // add b from tail
215 coordinates.add(new Coordinate(
216 m1*(last.b % width) + b1,
217 m2*(last.b / width) + b2));
218
219 clipLineString(
220 geometryFactory.createLineString(
221 coordinates.toArray(
222 new Coordinate[coordinates.size()])),
223 lineStrings);
224
225 coordinates.clear();
226 } // for all in common open
227 } // if map defined for key
228
229 if (!lineStrings.isEmpty()) {
230 MultiLineString multiLineString =
231 geometryFactory.createMultiLineString(
232 lineStrings.toArray(
233 new LineString[lineStrings.size()]));
234 lineStrings.clear();
235 Object attribute = attributeGenerator != null
236 ? attributeGenerator.generateAttribute(key.i, key.j)
237 : key;
238 multiLineStrings.add(new Pair<Object, MultiLineString>(
239 attribute,
240 multiLineString));
241 }
242 } // for all pairs
243
244 return multiLineStrings;
245 }
246 }
247 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org