View Javadoc
1   package org.opentrafficsim.road.network.lane;
2   
3   import java.util.LinkedHashMap;
4   import java.util.Map;
5   
6   import org.djutils.draw.line.PolyLine2d;
7   import org.djutils.draw.line.Polygon2d;
8   import org.djutils.exceptions.Throw;
9   import org.opentrafficsim.base.geometry.OtsLine2d;
10  import org.opentrafficsim.core.geometry.ContinuousLine;
11  import org.opentrafficsim.core.geometry.ContinuousLine.ContinuousDoubleFunction;
12  import org.opentrafficsim.core.geometry.Flattener;
13  import org.opentrafficsim.core.geometry.FractionalLengthData;
14  
15  /**
16   * Cross-section element geometry. A static method {@code of(...)} is available to generate geometry based on a design line and
17   * information on offset and width.
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   * @param centerLine center line
24   * @param contour contour
25   * @param offset offset
26   * @param width width
27   */
28  @SuppressWarnings("javadoc")
29  public record CrossSectionGeometry(OtsLine2d centerLine, Polygon2d contour, ContinuousDoubleFunction offset,
30          ContinuousDoubleFunction width)
31  {
32  
33      /**
34       * Constructor.
35       * @throws NullPointerException when centerLine, contour or slices is {@code null}
36       */
37      public CrossSectionGeometry
38  
39      {
40          Throw.whenNull(centerLine, "Center line may not be null.");
41          Throw.whenNull(contour, "Contour may not be null.");
42          Throw.whenNull(offset, "Offset may not be null.");
43          Throw.whenNull(width, "Width may not be null.");
44      }
45  
46      /**
47       * Create geometry based on design line, flattener, offset and width information.
48       * @param designLine design line relative to which offsets are defined
49       * @param flattener flattener to flatten center line and contour
50       * @param offset offset information
51       * @param width offset information
52       * @return geometry for cross-section element
53       */
54      public static CrossSectionGeometry of(final ContinuousLine designLine, final Flattener flattener,
55              final ContinuousDoubleFunction offset, final ContinuousDoubleFunction width)
56      {
57          PolyLine2d line = designLine.flattenOffset(offset, flattener);
58          Map<Double, Double> leftMap = new LinkedHashMap<>();
59          Map<Double, Double> rightMap = new LinkedHashMap<>();
60          for (double f : offset.getKnots())
61          {
62              leftMap.put(f, offset.apply(f) + .5 * width.apply(f));
63              rightMap.put(f, offset.apply(f) - .5 * width.apply(f));
64          }
65          for (double f : width.getKnots())
66          {
67              leftMap.put(f, offset.apply(f) + .5 * width.apply(f));
68              rightMap.put(f, offset.apply(f) - .5 * width.apply(f));
69          }
70          PolyLine2d left = designLine.flattenOffset(new FractionalLengthData(leftMap), flattener);
71          PolyLine2d right = designLine.flattenOffset(new FractionalLengthData(rightMap), flattener);
72          Polygon2d cont = LaneGeometryUtil.getContour(left, right);
73          return new CrossSectionGeometry(new OtsLine2d(line), cont, offset, width);
74      }
75  
76  }