/* * Copyright (C) 2010, 2011, 2012 by Arne Kesting, Martin Treiber, Ralph Germ, Martin Budden * <movsim.org@gmail.com> * ----------------------------------------------------------------------------------------- * * This file is part of * * MovSim - the multi-model open-source vehicular-traffic simulator. * * MovSim is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MovSim is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MovSim. If not, see <http://www.gnu.org/licenses/> * or <http://www.movsim.org>. * * ----------------------------------------------------------------------------------------- */ package org.movsim.roadmappings; import org.movsim.network.autogen.opendrive.OpenDRIVE.Road.PlanView.Geometry; /** * Maps a road segment onto an arc of a circle. Angles are interpreted as in the Argand diagram, that is 0 is at the 3 * o'clock position. A positive angle indicates a counter-clockwise rotation while a negative angle indicates a * clockwise rotation. */ public class RoadMappingArc extends RoadMappingCircle { protected double startAngle; protected double arcAngle; public static RoadMappingArc create(int laneCount, Geometry geometry, double laneWidth) { return new RoadMappingArc(laneCount, geometry.getS(), geometry.getX(), geometry.getY(), geometry.getHdg(), geometry.getLength(), geometry.getArc().getCurvature(), laneWidth); } /** * The arc begins at startAngle and extends for arcAngle radians. * * @param laneCount * number of lanes * @param x0 * start of arc, x coordinate * @param y0 * start of arc, y coordinate * @param radius * radius of arc * @param startAngle * start direction of arc, ie angle subtended at center + PI/2 * @param arcAngle */ RoadMappingArc(int laneCount, double x0, double y0, double radius, double startAngle, double arcAngle) { super(laneCount, x0, y0, radius, arcAngle < 0.0); this.startAngle = startAngle; this.arcAngle = arcAngle; // direction of travel on ramps when vehicles drive on the right roadLength = Math.abs(arcAngle) * radius; centerX = x0 - radius * Math.cos(startAngle - 0.5 * Math.PI) * (clockwise ? -1 : 1); centerY = y0 + radius * Math.sin(startAngle - 0.5 * Math.PI) * (clockwise ? -1 : 1); } /** * The arc begins at startAngle and extends for arcAngle radians. * * @param laneCount * number of lanes * @param s * @param x0 * start of arc, x coordinate * @param y0 * start of arc, y coordinate * @param startAngle * start direction of arc, ie angle subtended at center + PI/2 * @param length * length of arc * @param curvature * curvature of arc */ RoadMappingArc(int laneCount, double s, double x0, double y0, double startAngle, double length, double curvature) { super(laneCount, x0, y0, 1.0 / Math.abs(curvature), curvature < 0.0); roadLength = length; this.startAngle = startAngle; arcAngle = roadLength * curvature; centerX = x0 - radius * Math.cos(startAngle - 0.5 * Math.PI) * (clockwise ? -1 : 1); centerY = y0 + radius * Math.sin(startAngle - 0.5 * Math.PI) * (clockwise ? -1 : 1); } RoadMappingArc(int laneCount, double x0, double y0, double radius, boolean clockwise) { super(laneCount, x0, y0, radius, clockwise); } RoadMappingArc(int laneCount, double s, double x, double y, double hdg, double length, double curvature, double laneWidth) { this(laneCount, s, x, y, hdg, length, curvature); this.laneWidth = laneWidth; this.roadWidth = laneWidth * laneCount; } @Override public PosTheta map(double roadPos, double lateralOffset) { // tangent to arc (road direction) final double theta = clockwise ? startAngle - roadPos / radius : startAngle + roadPos / radius; // final double theta = clockwise ? startAngle + roadPos * curvature : startAngle - roadPos * curvature; // angle arc subtends at center final double arcTheta = theta - 0.5 * Math.PI; posTheta.cosTheta = Math.cos(theta); posTheta.sinTheta = Math.sin(theta); // lateralOffset is perpendicular to road final double r = radius + lateralOffset * (clockwise ? -1 : 1); posTheta.x = centerX + r * Math.cos(arcTheta) * (clockwise ? -1 : 1); posTheta.y = centerY - r * Math.sin(arcTheta) * (clockwise ? -1 : 1); return posTheta; } /** * Returns the start angle of the arc. * * @return the start angle of the arc, radians */ public double startAngle() { return startAngle; } /** * Returns the sweep angle of the arc. * * @return sweep angle of the arc, radians */ public double arcAngle() { return arcAngle; } }