CrossSectionGeometry.java
package org.opentrafficsim.road.network.lane;
import java.util.LinkedHashMap;
import java.util.Map;
import org.djutils.draw.curve.OffsetCurve2d;
import org.djutils.draw.curve.OffsetFlattener2d;
import org.djutils.draw.function.ContinuousPiecewiseLinearFunction;
import org.djutils.draw.line.PolyLine2d;
import org.djutils.draw.line.Polygon2d;
import org.djutils.draw.point.DirectedPoint2d;
import org.djutils.exceptions.Throw;
import org.djutils.math.functions.MathFunction.TupleSt;
import org.opentrafficsim.base.geometry.OtsLine2d;
import org.opentrafficsim.base.geometry.OtsShape;
/**
* Cross-section element geometry. A static method {@code of(...)} is available to generate geometry based on a design line and
* information on offset and width.
* <p>
* Copyright (c) 2024-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
* BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
* </p>
* @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
* @param centerLine center line
* @param absoluteContour contour
* @param offset offset
* @param width width
*/
public record CrossSectionGeometry(OtsLine2d centerLine, Polygon2d absoluteContour, ContinuousPiecewiseLinearFunction offset,
ContinuousPiecewiseLinearFunction width)
{
/**
* Constructor.
* @throws NullPointerException when centerLine, contour or slices is {@code null}
*/
public CrossSectionGeometry
{
Throw.whenNull(centerLine, "centerLine");
Throw.whenNull(absoluteContour, "absoluteContour");
Throw.whenNull(offset, "offset");
Throw.whenNull(width, "width");
}
/**
* Create geometry based on design line, flattener, offset and width information.
* @param designLine design line relative to which offsets are defined
* @param flattener flattener to flatten center line and contour
* @param offset offset information
* @param width offset information
* @return geometry for cross-section element
*/
public static CrossSectionGeometry of(final OffsetCurve2d designLine, final OffsetFlattener2d flattener,
final ContinuousPiecewiseLinearFunction offset, final ContinuousPiecewiseLinearFunction width)
{
PolyLine2d line = designLine.toPolyLine(flattener, offset);
Map<Double, Double> leftMap = new LinkedHashMap<>();
Map<Double, Double> rightMap = new LinkedHashMap<>();
for (TupleSt st : offset)
{
leftMap.put(st.s(), st.t() + .5 * width.get(st.s()));
rightMap.put(st.s(), st.t() - .5 * width.get(st.s()));
}
for (TupleSt st : width)
{
leftMap.put(st.s(), offset.get(st.s()) + .5 * width.get(st.s()));
rightMap.put(st.s(), offset.get(st.s()) - .5 * width.get(st.s()));
}
PolyLine2d left = designLine.toPolyLine(flattener, new ContinuousPiecewiseLinearFunction(leftMap));
PolyLine2d right = designLine.toPolyLine(flattener, new ContinuousPiecewiseLinearFunction(rightMap));
Polygon2d cont = LaneGeometryUtil.getContour(left, right);
return new CrossSectionGeometry(new OtsLine2d(line), cont, offset, width);
}
/**
* Returns the location.
* @return returns the location of this geometry
*/
public DirectedPoint2d getLocation()
{
return centerLine().getLocationFractionExtended(0.5);
}
/**
* Returns the relative contour.
* @return relative contour
*/
public Polygon2d getRelativeContour()
{
return new Polygon2d(OtsShape.toRelativeTransform(getLocation()).transform(absoluteContour().iterator()));
}
}