View Javadoc
1   package org.opentrafficsim.core.geometry;
2   
3   import java.util.List;
4   
5   import org.djutils.draw.curve.Flattener2d;
6   import org.djutils.draw.curve.OffsetCurve2d;
7   import org.djutils.draw.curve.OffsetFlattener2d;
8   import org.djutils.draw.function.ContinuousPiecewiseLinearFunction;
9   import org.djutils.draw.line.PolyLine2d;
10  import org.djutils.draw.point.DirectedPoint2d;
11  import org.djutils.draw.point.Point2d;
12  import org.djutils.exceptions.Throw;
13  import org.djutils.math.functions.MathFunction.TupleSt;
14  import org.opentrafficsim.base.geometry.OtsGeometryUtil;
15  
16  /**
17   * Curve based on a poly line implementing all the features of {@link OffsetCurve2d}.
18   * <p>
19   * Copyright (c) 2024-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
20   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
21   * </p>
22   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
23   */
24  public class PolyLineCurve2d implements OffsetCurve2d
25  {
26  
27      /** Poly line. */
28      private final PolyLine2d line;
29  
30      /** Start direction. */
31      private final double startDirection;
32  
33      /** End direction. */
34      private final double endDirection;
35  
36      /**
37       * Constructor.
38       * @param line poly line
39       * @param startDirection start direction
40       * @param endDirection end direction
41       */
42      public PolyLineCurve2d(final PolyLine2d line, final double startDirection, final double endDirection)
43      {
44          this.line = line;
45          this.startDirection = startDirection;
46          this.endDirection = endDirection;
47      }
48  
49      @Override
50      public Double getDirection(final double fraction)
51      {
52          return fraction == 0.0 ? this.startDirection
53                  : (fraction == 1.0 ? this.endDirection : this.line.getLocation(fraction).dirZ);
54      }
55  
56      @Override
57      public double getDirection(final double fraction, final ContinuousPiecewiseLinearFunction of)
58      {
59          return getDirection(fraction) + of.getDerivative(fraction);
60      }
61  
62      @Override
63      public DirectedPoint2d getPoint(final double fraction)
64      {
65          return this.line.getLocationFraction(fraction);
66      }
67  
68      @Override
69      public DirectedPoint2d getPoint(final double fraction, final ContinuousPiecewiseLinearFunction of)
70      {
71          DirectedPoint2d offsetPoint = OtsGeometryUtil.offsetPoint(getPoint(fraction), of.get(fraction));
72          return new DirectedPoint2d(offsetPoint.x, offsetPoint.y, offsetPoint.dirZ + of.getDerivative(fraction));
73      }
74  
75      @Override
76      public double getLength()
77      {
78          return this.line.getLength();
79      }
80  
81      @Override
82      public PolyLine2d toPolyLine(final Flattener2d flattener)
83      {
84          return this.line;
85      }
86  
87      @Override
88      public PolyLine2d toPolyLine(final OffsetFlattener2d flattener, final ContinuousPiecewiseLinearFunction offsets)
89      {
90          Throw.whenNull(offsets, "Offsets may not be null.");
91          double[] knots = new double[offsets.size()];
92          double[] knotOffset = new double[offsets.size()];
93          int i = 0;
94          for (TupleSt st : offsets)
95          {
96              knots[i] = st.s();
97              knotOffset[i] = st.t();
98              i++;
99          }
100         PolyLine2d offsetLine = OtsGeometryUtil.offsetLine(this.line, knots, knotOffset);
101         Point2d start = OtsGeometryUtil.offsetPoint(getStartPoint(), offsets.get(0.0));
102         Point2d end = OtsGeometryUtil.offsetPoint(getEndPoint(), offsets.get(1.0));
103         List<Point2d> points = offsetLine.getPointList();
104         points.set(0, start);
105         points.set(points.size() - 1, end);
106         return new PolyLine2d(points);
107     }
108 
109 }