1 package org.opentrafficsim.core.network.geotools;
2
3 import java.io.Serializable;
4
5 import org.geotools.geometry.DirectPosition2D;
6 import org.geotools.referencing.CRS;
7 import org.geotools.referencing.GeodeticCalculator;
8 import org.opengis.geometry.DirectPosition;
9 import org.opengis.geometry.coordinate.PointArray;
10 import org.opengis.referencing.crs.CoordinateReferenceSystem;
11 import org.opengis.referencing.operation.TransformException;
12 import org.opentrafficsim.core.network.NetworkException;
13 import org.opentrafficsim.core.unit.LengthUnit;
14 import org.opentrafficsim.core.value.vdouble.scalar.DoubleScalar;
15
16 import com.vividsolutions.jts.geom.Coordinate;
17 import com.vividsolutions.jts.geom.CoordinateSequence;
18 import com.vividsolutions.jts.geom.GeometryFactory;
19 import com.vividsolutions.jts.geom.LineString;
20 import com.vividsolutions.jts.geom.Point;
21 import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
22
23
24
25
26
27
28
29
30
31
32
33
34 public class LinearGeometry implements Serializable
35 {
36
37 private static final long serialVersionUID = 20141008L;
38
39
40 private final LinkGeotools<?, ?> link;
41
42
43 private final LineString line;
44
45
46 private final CoordinateReferenceSystem crs;
47
48
49 private final DoubleScalar.Rel<LengthUnit> length;
50
51
52
53
54
55
56 public LinearGeometry(final LinkGeotools<?, ?> link, final PointArray pointArray) throws NetworkException
57 {
58 super();
59 this.link = link;
60 this.crs = pointArray.getCoordinateReferenceSystem();
61 double len = 0.0;
62 GeodeticCalculator calc = new GeodeticCalculator(this.crs);
63 Coordinate[] coords = new Coordinate[pointArray.size()];
64 DirectPosition prevPos = null;
65 for (int i = 0; i < pointArray.size(); i++)
66 {
67 DirectPosition p = pointArray.get(i).getDirectPosition();
68 double x = p.getOrdinate(0);
69 double y = p.getDimension() > 1 ? p.getOrdinate(1) : 0;
70 double z = p.getDimension() > 2 ? p.getOrdinate(2) : 0;
71 coords[i] = new Coordinate(x, y, z);
72 if (i > 0)
73 {
74 try
75 {
76 calc.setStartingPosition(prevPos);
77 calc.setDestinationPosition(p);
78 len += calc.getOrthodromicDistance();
79 }
80 catch (TransformException te)
81 {
82 throw new NetworkException("When constructing LinearGeometry for link=" + link.toString()
83 + ": transformation for distance calculation failed in CRS=" + this.crs.toWKT(), te);
84 }
85 }
86 prevPos = p;
87 }
88 CoordinateSequence points = new CoordinateArraySequence(coords);
89 GeometryFactory factory = new GeometryFactory();
90 this.line = new LineString(points, factory);
91 this.length = new DoubleScalar.Rel<LengthUnit>(len, LengthUnit.METER);
92 link.setGeometry(this);
93 }
94
95
96
97
98
99
100
101 public LinearGeometry(final LinkGeotools<?, ?> link, final LineString lineString, final CoordinateReferenceSystem crs)
102 throws NetworkException
103 {
104 super();
105 this.link = link;
106 this.crs = crs;
107 double len = 0.0;
108 DirectPosition prevPos = null;
109 GeodeticCalculator calc = null;
110 if (CRS.getEllipsoid(this.crs) != null)
111 {
112 calc = new GeodeticCalculator(this.crs);
113 }
114 for (int i = 0; i < lineString.getNumPoints(); i++)
115 {
116 Point point = lineString.getPointN(i);
117 DirectPosition pos = new DirectPosition2D(this.crs, point.getX(), point.getY());
118 if (i > 0)
119 {
120 try
121 {
122 if (calc != null)
123 {
124 calc.setStartingPosition(prevPos);
125 calc.setDestinationPosition(pos);
126 len += calc.getOrthodromicDistance();
127 }
128 else
129 {
130
131 double dx =
132 prevPos.getDirectPosition().getCoordinate()[0] - pos.getDirectPosition().getCoordinate()[0];
133 double dy =
134 prevPos.getDirectPosition().getCoordinate()[1] - pos.getDirectPosition().getCoordinate()[1];
135 len += Math.sqrt(dx * dx + dy * dy);
136 }
137 }
138 catch (TransformException te)
139 {
140 throw new NetworkException("When constructing LinearGeometry for link=" + link.toString()
141 + ": transformation for distance calculation failed in CRS=" + this.crs.toWKT(), te);
142 }
143 }
144 prevPos = pos;
145 }
146 this.line = lineString;
147 this.length = new DoubleScalar.Rel<LengthUnit>(len, LengthUnit.METER);
148 link.setGeometry(this);
149 }
150
151
152
153
154
155
156 public final LinkGeotools<?, ?> getLink()
157 {
158 return this.link;
159 }
160
161
162
163
164 public final LineString getLineString()
165 {
166 return this.line;
167 }
168
169
170
171
172 public final CoordinateReferenceSystem getCRS()
173 {
174 return this.crs;
175 }
176
177
178
179
180 public final DoubleScalar.Rel<LengthUnit> getLineLength()
181 {
182 return this.length;
183 }
184 }