View Javadoc
1   package org.opentrafficsim.road.network;
2   
3   import java.util.LinkedHashMap;
4   import java.util.Map;
5   
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.line.Polygon2d;
11  import org.djutils.draw.point.DirectedPoint2d;
12  import org.djutils.exceptions.Throw;
13  import org.djutils.math.functions.MathFunction.TupleSt;
14  import org.opentrafficsim.base.geometry.OtsLine2d;
15  import org.opentrafficsim.base.geometry.OtsShape;
16  
17  /**
18   * Cross-section element geometry. A static method {@code of(...)} is available to generate geometry based on a design line and
19   * information on offset and width.
20   * <p>
21   * Copyright (c) 2024-2026 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
22   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
23   * </p>
24   * @author Wouter Schakel
25   * @param centerLine center line
26   * @param absoluteContour contour
27   * @param offset offset
28   * @param width width
29   */
30  public record CrossSectionGeometry(OtsLine2d centerLine, Polygon2d absoluteContour, ContinuousPiecewiseLinearFunction offset,
31          ContinuousPiecewiseLinearFunction width)
32  {
33  
34      /**
35       * Constructor.
36       * @param centerLine center line
37       * @param absoluteContour contour
38       * @param offset offset
39       * @param width width@param centerLine center line
40       * @throws NullPointerException when centerLine, contour or slices is {@code null}
41       */
42      public CrossSectionGeometry
43  
44      {
45          Throw.whenNull(centerLine, "centerLine");
46          Throw.whenNull(absoluteContour, "absoluteContour");
47          Throw.whenNull(offset, "offset");
48          Throw.whenNull(width, "width");
49      }
50  
51      /**
52       * Create geometry based on design line, flattener, offset and width information.
53       * @param designLine design line relative to which offsets are defined
54       * @param flattener flattener to flatten center line and contour
55       * @param offset offset information
56       * @param width offset information
57       * @return geometry for cross-section element
58       */
59      public static CrossSectionGeometry of(final OffsetCurve2d designLine, final OffsetFlattener2d flattener,
60              final ContinuousPiecewiseLinearFunction offset, final ContinuousPiecewiseLinearFunction width)
61      {
62          PolyLine2d line = designLine.toPolyLine(flattener, offset);
63          Map<Double, Double> leftMap = new LinkedHashMap<>();
64          Map<Double, Double> rightMap = new LinkedHashMap<>();
65          for (TupleSt st : offset)
66          {
67              leftMap.put(st.s(), st.t() + .5 * width.get(st.s()));
68              rightMap.put(st.s(), st.t() - .5 * width.get(st.s()));
69          }
70          for (TupleSt st : width)
71          {
72              leftMap.put(st.s(), offset.get(st.s()) + .5 * width.get(st.s()));
73              rightMap.put(st.s(), offset.get(st.s()) - .5 * width.get(st.s()));
74          }
75          PolyLine2d left = designLine.toPolyLine(flattener, new ContinuousPiecewiseLinearFunction(leftMap));
76          PolyLine2d right = designLine.toPolyLine(flattener, new ContinuousPiecewiseLinearFunction(rightMap));
77          Polygon2d cont = LaneGeometryUtil.getContour(left, right);
78          return new CrossSectionGeometry(new OtsLine2d(line), cont, offset, width);
79      }
80  
81      /**
82       * Returns the location.
83       * @return returns the location of this geometry
84       */
85      public DirectedPoint2d getLocation()
86      {
87          return centerLine().getLocationFractionExtended(0.5);
88      }
89  
90      /**
91       * Returns the relative contour.
92       * @return relative contour
93       */
94      public Polygon2d getRelativeContour()
95      {
96          return new Polygon2d(0.0, OtsShape.toRelativeTransform(getLocation()).transform(absoluteContour().iterator()));
97      }
98  
99  }