All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentrafficsim.draw.road.StripeAnimation Maven / Gradle / Ivy

The newest version!
package org.opentrafficsim.draw.road;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Path2D;
import java.awt.image.ImageObserver;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.naming.NamingException;

import org.djunits.value.vdouble.scalar.Length;
import org.djutils.draw.line.PolyLine2d;
import org.djutils.draw.line.Polygon2d;
import org.djutils.draw.point.OrientedPoint2d;
import org.djutils.draw.point.Point2d;
import org.opentrafficsim.base.geometry.OtsLocatable;
import org.opentrafficsim.base.geometry.OtsRenderable;
import org.opentrafficsim.draw.DrawLevel;
import org.opentrafficsim.draw.PaintPolygons;
import org.opentrafficsim.draw.road.StripeAnimation.StripeData;

import nl.tudelft.simulation.naming.context.Contextualized;

/**
 * Draw road stripes.
 * 

* Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License. *

* @author Alexander Verbraeck * @author Wouter Schakel */ public class StripeAnimation extends OtsRenderable { /** */ private static final long serialVersionUID = 20141017L; /** Drawable paths. */ private final Set paths; /** * @param source StripeData; stripe data * @param contextualized Contextualized; context provider * @throws NamingException ne * @throws RemoteException on communication failure */ public StripeAnimation(final StripeData source, final Contextualized contextualized) throws NamingException, RemoteException { super(source, contextualized); List list = makePoints(source); if (!list.isEmpty()) { this.paths = PaintPolygons.getPaths(getSource().getLocation(), list); } else { // no dash within length this.paths = null; } } /** * Generate the drawing commands for a dash pattern. * @param center PolyLine2d; the design line of the striped pattern * @param width double; width of the stripes in meters * @param startOffset double; shift the starting point in the pattern by this length in meters * @param onOffLengths double[]; one or more lengths of the dashes and the gaps between those dashes. If the number of * values in onOffLengths is odd, the pattern repeats inverted. The first value in * onOffLengths is the length of a dash. * @return ArrayList<Coordinate>; the coordinates of the dashes separated and terminated by a NEWPATH * Coordinate */ private ArrayList makeDashes(final PolyLine2d center, final double width, final double startOffset, final double[] onOffLengths) { double period = 0; for (double length : onOffLengths) { if (length < 0) { throw new Error("Bad pattern - on or off length is < 0"); } period += length; } if (period <= 0) { throw new Error("Bad pattern - repeat period length is 0"); } double length = center.getLength(); double position = -startOffset; int phase = 0; ArrayList result = new ArrayList<>(); while (position < length) { double nextBoundary = position + onOffLengths[phase++ % onOffLengths.length]; if (nextBoundary > 0) // Skip this one; this entire dash lies within the startOffset { if (position < 0) { position = 0; // Draw a partial dash, starting at 0 (begin of the center line) } double endPosition = nextBoundary; if (endPosition > length) { endPosition = length; // Draw a partial dash, ending at length (end of the center line) } PolyLine2d dashCenter; dashCenter = center.extract(position, endPosition); dashCenter.offsetLine(width / 2).getPoints().forEachRemaining(result::add); dashCenter.offsetLine(-width / 2).reverse().getPoints().forEachRemaining(result::add); result.add(PaintPolygons.NEWPATH); } position = nextBoundary + onOffLengths[phase++ % onOffLengths.length]; } return result; } /** * Generate the points needed to draw the stripe pattern. * @param stripe StripeData; the stripe * @return Coordinate[]; array of Coordinate * @throws NamingException when type is not supported */ private List makePoints(final StripeData stripe) throws NamingException { double width = stripe.getWidth().si; switch (stripe.getType()) { case DASHED:// ¦ - Draw a 3-9 dash pattern on the center line return makeDashes(stripe.getCenterLine(), width, 3.0, new double[] {3, 9}); case BLOCK:// : - Draw a 1-3 dash pattern on the center line return makeDashes(stripe.getCenterLine(), width, 1.0, new double[] {1, 3}); case DOUBLE:// ||- Draw two solid lines { PolyLine2d centerLine = stripe.getCenterLine(); List result = new ArrayList<>(centerLine.size() * 4 + 1); centerLine.offsetLine(width / 2).getPoints().forEachRemaining(result::add); centerLine.offsetLine(width / 6).reverse().getPoints().forEachRemaining(result::add); result.add(PaintPolygons.NEWPATH); centerLine.offsetLine(-width / 2).getPoints().forEachRemaining(result::add); centerLine.offsetLine(-width / 6).reverse().getPoints().forEachRemaining(result::add); return result; } case LEFT: // |¦ - Draw left solid, right 3-9 dashed { PolyLine2d centerLine = stripe.getCenterLine(); List result = makeDashes(centerLine.offsetLine(-width / 3), width / 3, 0.0, new double[] {3, 9}); result.add(PaintPolygons.NEWPATH); centerLine.offsetLine(width / 2).getPoints().forEachRemaining(result::add); centerLine.offsetLine(width / 6).reverse().getPoints().forEachRemaining(result::add); return result; } case RIGHT: // ¦| - Draw left 3-9 dashed, right solid { PolyLine2d centerLine = stripe.getCenterLine(); ArrayList result = makeDashes(centerLine.offsetLine(width / 3), width / 3, 0.0, new double[] {3, 9}); result.add(PaintPolygons.NEWPATH); centerLine.offsetLine(-width / 2).getPoints().forEachRemaining(result::add); centerLine.offsetLine(-width / 6).reverse().getPoints().forEachRemaining(result::add); return result; } case SOLID: // | - Draw single solid line PolyLine2d centerLine = stripe.getCenterLine(); PolyLine2d leftEdge = centerLine.offsetLine(stripe.getWidth().si / 2.0); PolyLine2d rightEdge = centerLine.offsetLine(-stripe.getWidth().si / 2.0); List list = leftEdge.getPointList(); list.addAll(rightEdge.reverse().getPointList()); List result = new Polygon2d(list).getPointList(); return result; default: throw new NamingException("Unsupported stripe type: " + stripe.getType()); } } /** {@inheritDoc} */ @Override public final void paint(final Graphics2D graphics, final ImageObserver observer) { if (this.paths != null) { setRendering(graphics); graphics.setStroke(new BasicStroke(2.0f)); PaintPolygons.paintPaths(graphics, Color.WHITE, this.paths, true); resetRendering(graphics); } } /** {@inheritDoc} */ @Override public final String toString() { return "StripeAnimation [source = " + getSource().toString() + ", paths=" + this.paths + "]"; } /** * StripeData provides the information required to draw a stripe. *

* Copyright (c) 2023-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. *
* BSD-style license. See OpenTrafficSim License. *

* @author Wouter Schakel */ public interface StripeData extends OtsLocatable { /** {@inheritDoc} */ @Override OrientedPoint2d getLocation(); /** * Returns the center line. * @return PolyLine2d; center line. */ PolyLine2d getCenterLine(); /** * Returns the stripe type. * @return Type; stripe type. */ Type getType(); /** * Returns the line width. * @return Length; line width. */ Length getWidth(); /** {@inheritDoc} */ @Override default double getZ() { return DrawLevel.MARKING.getZ(); } /** * Stripe type (same fields as org.opentrafficsim.road.network.lane.Stripe.Type). *

* Copyright (c) 2023-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights * reserved.
* BSD-style license. See OpenTrafficSim License. *

* @author Wouter Schakel */ public enum Type { /** Single solid line. */ SOLID, /** Line |¦ allow to go to left, but not to right. */ LEFT, /** Line ¦| allow to go to right, but not to left. */ RIGHT, /** Dashes ¦ allow to cross in both directions. */ DASHED, /** Double solid line ||, don't cross. */ DOUBLE, /** Block : allow to cross in both directions. */ BLOCK; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy