View Javadoc
1   package org.opentrafficsim.core.geometry;
2   
3   import java.util.List;
4   
5   import org.djutils.draw.line.PolyLine2d;
6   import org.djutils.draw.line.Ray2d;
7   import org.djutils.draw.point.OrientedPoint2d;
8   import org.djutils.draw.point.Point2d;
9   import org.djutils.exceptions.Throw;
10  import org.djutils.exceptions.Try;
11  
12  /**
13   * Continuous definition of a PolyLine. Naive approaches are applied for offsets, since polylines have no exact information for
14   * this.
15   * <p>
16   * Copyright (c) 2023-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
17   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
18   * </p>
19   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
20   */
21  public class ContinuousPolyLine implements ContinuousLine
22  {
23  
24      /** Line. */
25      private final PolyLine2d line;
26  
27      /** Start point. */
28      private final OrientedPoint2d startPoint;
29  
30      /** End points. */
31      private final OrientedPoint2d endPoint;
32  
33      /**
34       * Define continuous line from polyline. Start and end point direction are derived from the line.
35       * @param line OtsLine2d; line.
36       */
37      public ContinuousPolyLine(final PolyLine2d line)
38      {
39          Throw.whenNull(line, "Line may not be null.");
40          this.line = line;
41          Ray2d startRay = line.getLocationFractionExtended(0.0);
42          Ray2d endRay = line.getLocationFractionExtended(1.0);
43          this.startPoint = new OrientedPoint2d(startRay.x, startRay.y, startRay.phi);
44          this.endPoint = new OrientedPoint2d(endRay.x, endRay.y, endRay.phi);
45      }
46  
47      /**
48       * Define continuous line from polyline. Start and end point are given and may alter the direction at the endpoints
49       * (slightly).
50       * @param line OtsLine2d; line.
51       * @param startPoint OrientedPoint2d; start point.
52       * @param endPoint OrientedPoint2d; end point.
53       */
54      public ContinuousPolyLine(final PolyLine2d line, final OrientedPoint2d startPoint, final OrientedPoint2d endPoint)
55      {
56          Throw.whenNull(line, "Line may not be null.");
57          this.line = line;
58          this.startPoint = startPoint;
59          this.endPoint = endPoint;
60      }
61  
62      /** {@inheritDoc} */
63      @Override
64      public OrientedPoint2d getStartPoint()
65      {
66          return this.startPoint;
67      }
68  
69      /** {@inheritDoc} */
70      @Override
71      public OrientedPoint2d getEndPoint()
72      {
73          return this.endPoint;
74      }
75  
76      /** {@inheritDoc} */
77      @Override
78      public double getStartCurvature()
79      {
80          return 1.0 / getStartRadius();
81      }
82  
83      /** {@inheritDoc} */
84      @Override
85      public double getEndCurvature()
86      {
87          return 1.0 / getEndRadius();
88      }
89  
90      /** {@inheritDoc} */
91      @Override
92      public double getStartRadius()
93      {
94          return Try.assign(() -> new OtsLine2d(this.line).getProjectedRadius(0.0).si, "0.0 should be in range.");
95      }
96  
97      /** {@inheritDoc} */
98      @Override
99      public double getEndRadius()
100     {
101         return Try.assign(() -> new OtsLine2d(this.line).getProjectedRadius(1.0).si, "0.0 should be in range.");
102     }
103 
104     /**
105      * Polyline from continuous line. Returns the line as is.
106      * @return PolyLine2d; polyline.
107      */
108     public PolyLine2d flatten()
109     {
110         return this.line;
111     }
112     
113     /**
114      * Returns the line as is. Flattener is ignored.
115      * @param flattener Flattener; flattener (ignored).
116      * @return PolyLine2d; flattened line.
117      */
118     @Override
119     public PolyLine2d flatten(final Flattener flattener)
120     {
121         return this.line;
122     }
123 
124     /**
125      * Returns an offset line. This is a regular offset line, with start and end points moved to be perpendicular to end point
126      * directions.
127      * @param offsets FractionalLengthData; offset data.
128      * @return PolyLine2d; flattened line.
129      */
130     public PolyLine2d offset(final FractionalLengthData offsets)
131     {
132         Throw.whenNull(offsets, "Offsets may not be null.");
133         PolyLine2d offsetLine = Try.assign(
134                 () -> OtsGeometryUtil.offsetLine(this.line, offsets.getFractionalLengthsAsArray(), offsets.getValuesAsArray()),
135                 "Unexpected exception while creating offset line.");
136         Point2d start = OtsGeometryUtil.offsetPoint(this.startPoint, offsets.get(0.0));
137         Point2d end = OtsGeometryUtil.offsetPoint(this.endPoint, offsets.get(1.0));
138         List<Point2d> points = offsetLine.getPointList();
139         points.set(0, start);
140         points.set(points.size() - 1, end);
141         return new PolyLine2d(points);
142     }
143 
144     /**
145      * Returns the regular offset. Flattener is ignored.
146      * @param offsets FractionalLengthData; offset data.
147      * @param flattener Flattener; flattener (ignored).
148      * @return PolyLine2d; flattened line.
149      */
150     @Override
151     public PolyLine2d flattenOffset(final FractionalLengthData offsets, final Flattener flattener)
152     {
153         return offset(offsets);
154     }
155 
156     /** {@inheritDoc} */
157     @Override
158     public double getLength()
159     {
160         return this.line.getLength();
161     }
162 
163     /** {@inheritDoc} */
164     @Override
165     public String toString()
166     {
167         return "ContinuousPolyLine [startPoint=" + this.startPoint + ", endPoint=" + this.endPoint + "]";
168     }
169 
170 }