1   
2   
3   
4   package org.opentrafficsim.road.network.factory.shape;
5   
6   import com.vividsolutions.jts.geom.Coordinate;
7   import com.vividsolutions.jts.geom.CoordinateList;
8   import com.vividsolutions.jts.geom.LineSegment;
9   import com.vividsolutions.jts.geom.LineString;
10  import com.vividsolutions.jts.util.Assert;
11  
12  
13  
14  
15  public class SubstringLine
16  {
17      
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29      
30  
31  
32  
33  
34  
35      public static LineString getSubstring(LineString line, double startLength, double endLength)
36      {
37          SubstringLine ls = new SubstringLine(line);
38          return ls.getSubstring(startLength, endLength);
39      }
40  
41      private LineString line;
42  
43      public SubstringLine(LineString line)
44      {
45          this.line = line;
46      }
47  
48      public LineString getSubstring(double startDistance, double endDistance)
49      {
50          
51          Assert.isTrue(startDistance <= endDistance, "inverted distances not currently supported");
52  
53          Coordinate[] coordinates = line.getCoordinates();
54          
55          if (endDistance <= 0.0)
56          {
57              return line.getFactory().createLineString(new Coordinate[] { coordinates[0], coordinates[0] });
58          }
59          if (startDistance >= line.getLength())
60          {
61              return line.getFactory().createLineString(
62                      new Coordinate[] { coordinates[coordinates.length - 1], coordinates[coordinates.length - 1] });
63          }
64          if (startDistance < 0.0)
65          {
66              startDistance = 0.0;
67          }
68          return computeSubstring(startDistance, endDistance);
69      }
70  
71      
72  
73  
74  
75  
76  
77      private LineString computeSubstring(double startDistance, double endDistance)
78      {
79          Coordinate[] coordinates = line.getCoordinates();
80          CoordinateList newCoordinates = new CoordinateList();
81          double segmentStartDistance = 0.0;
82          double segmentEndDistance = 0.0;
83          boolean started = false;
84          int i = 0;
85          LineSegment segment = new LineSegment();
86          while (i < coordinates.length - 1 && endDistance > segmentEndDistance)
87          {
88              segment.p0 = coordinates[i];
89              segment.p1 = coordinates[i + 1];
90              i++;
91              segmentStartDistance = segmentEndDistance;
92              segmentEndDistance = segmentStartDistance + segment.getLength();
93  
94              if (startDistance > segmentEndDistance)
95              {
96                  continue;
97              }
98              if (startDistance >= segmentStartDistance && startDistance < segmentEndDistance)
99              {
100                 newCoordinates.add(LocatePoint.pointAlongSegment(segment.p0, segment.p1, startDistance - segmentStartDistance),
101                         false);
102             }
103             
104 
105 
106 
107             if (endDistance >= segmentEndDistance)
108             {
109                 newCoordinates.add(new Coordinate(segment.p1), false);
110             }
111             if (endDistance >= segmentStartDistance && endDistance < segmentEndDistance)
112             {
113                 newCoordinates.add(LocatePoint.pointAlongSegment(segment.p0, segment.p1, endDistance - segmentStartDistance),
114                         false);
115             }
116         }
117         Coordinate[] newCoordinateArray = newCoordinates.toCoordinateArray();
118         
119 
120 
121 
122         if (newCoordinateArray.length <= 1)
123         {
124             newCoordinateArray = new Coordinate[] { newCoordinateArray[0], newCoordinateArray[0] };
125         }
126         return line.getFactory().createLineString(newCoordinateArray);
127     }
128 }