Shoulder.java
package org.opentrafficsim.road.network.lane;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import org.djunits.value.vdouble.scalar.Speed;
import org.djutils.draw.line.Polygon2d;
import org.opentrafficsim.core.geometry.OtsLine2d;
import org.opentrafficsim.core.gtu.GtuType;
import org.opentrafficsim.core.network.LateralDirectionality;
import org.opentrafficsim.core.network.NetworkException;
import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
/**
* This class is mostly the same as a Lane. But as a shoulder it can be recognized by algorithms and models to be responded to
* differently.
* <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>
*/
public class Shoulder extends Lane
{
/** */
private static final long serialVersionUID = 20240507L;
/**
* Constructor specifying geometry.
* @param link CrossSectionLink; link.
* @param id String; the id of this lane within the link; should be unique within the link.
* @param centerLine OtsLine2d; center line.
* @param contour Polygon2d; contour shape.
* @param crossSectionSlices List<CrossSectionSlice>; cross-section slices.
* @param laneType LaneType; lane type.
* @throws NetworkException when no cross-section slice is defined.
*/
public Shoulder(final CrossSectionLink link, final String id, final OtsLine2d centerLine, final Polygon2d contour,
final List<CrossSectionSlice> crossSectionSlices, final LaneType laneType) throws NetworkException
{
super(link, id, centerLine, contour, crossSectionSlices, laneType, new LinkedHashMap<>());
}
/**
* Returns one adjacent lane.
* @param laneChangeDirection LateralDirectionality; lane change direction
* @param gtuType GtuType; GTU type.
* @return Lane; adjacent lane, {@code null} if none
*/
@Override
public Lane getAdjacentLane(final LateralDirectionality laneChangeDirection, final GtuType gtuType)
{
Set<Lane> adjLanes = accessibleAdjacentLanesPhysical(laneChangeDirection, gtuType);
if (!adjLanes.isEmpty())
{
return adjLanes.iterator().next();
}
return null;
}
/** {@inheritDoc} */
@Override
public double getZ()
{
return -0.00005;
}
/** {@inheritDoc} */
@Override
public Speed getSpeedLimit(final GtuType gtuType) throws NetworkException
{
LateralDirectionality[] lats = getLink().getLaneKeepingPolicy().equals(LaneKeepingPolicy.KEEPRIGHT)
? new LateralDirectionality[] {LateralDirectionality.RIGHT, LateralDirectionality.LEFT}
: new LateralDirectionality[] {LateralDirectionality.LEFT, LateralDirectionality.RIGHT};
for (LateralDirectionality lat : lats)
{
Lane adjacentLane = getAdjacentLane(lat, gtuType);
if (adjacentLane != null)
{
return adjacentLane.getSpeedLimit(gtuType);
}
}
return Speed.ZERO;
}
}