/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file PositionVector.h14/// @author Daniel Krajzewicz15/// @author Jakob Erdmann16/// @author Michael Behrisch17/// @date Sept 200218///19// A list of positions20/****************************************************************************/21#pragma once22#include <config.h>2324#include <vector>25#include <limits>26#include "AbstractPoly.h"272829// ===========================================================================30// class declarations31// ===========================================================================3233class Boundary;3435// ===========================================================================36// class definitions37// ===========================================================================38/**39* @class PositionVector40* @brief A list of positions41*/42class PositionVector : public AbstractPoly, private std::vector<Position> {4344private:45/// @brief vector of position46typedef std::vector<Position> vp;4748public:49/// @brief Constructor. Creates an empty position vector50PositionVector();5152/// @brief Copy Constructor. Create a positionVector with the same elements as other positionVector53/// @param[in] v The vector to copy54PositionVector(const std::vector<Position>& v);5556/// @brief Parameter Constructor. Create a positionVector using a part of other positionVector57/// @param[in] beg The begin iterator for copy58/// @param[in] end The end iterator to copy59PositionVector(const std::vector<Position>::const_iterator beg, const std::vector<Position>::const_iterator end);6061/// @brief Parameter Constructor used for lines62/// @param[in] p1 the first position63/// @param[in] p2 the second position64PositionVector(const Position& p1, const Position& p2);6566/// @brief Destructor67~PositionVector();6869/// @brief empty Vector70static const PositionVector EMPTY;7172/// @name methode for iterate over PositionVector73/// @{74/// @brief iterator75using vp::iterator;7677/// @brief constant iterator78using vp::const_iterator;7980/// @brief contant reference81using vp::const_reference;8283/// @brief value type84using vp::value_type;8586/// @brief begin of position vector87using vp::begin;8889/// @brief end of position vector90using vp::end;9192/// @brief push a position in the back of position vector93using vp::push_back;9495/// @brief push a position in the front of position vector96using vp::pop_back;9798/// @brief clear all elements of position vector99using vp::clear;100101/// @brief returns size of position vector102using vp::size;103104/// @brief returns whether the position vector is empty105using vp::empty;106107/// @brief get the front element of position vector108using vp::front;109110/// @brief get back element of position vector111using vp::back;112113/// @brief get a reference of position vector114using vp::reference;115116/// @brief erase a position of position vector gived by iterator117using vp::erase;118119/// @brief insert a position in position vector gived by iterator120using vp::insert;121/// @}122123/// @brief Returns the information whether the position vector describes a polygon lying around the given point124/// @note The optional offset is added to the polygon's boundaries125bool around(const Position& p, double offset = 0) const;126127/// @brief Returns the information whether the given polygon overlaps with this128/// @note Again a boundary may be specified129bool overlapsWith(const AbstractPoly& poly, double offset = 0) const;130131/// @brief Returns the maximum overlaps between this and the given polygon (when not separated by at least zThreshold)132double getOverlapWith(const PositionVector& poly, double zThreshold) const;133134/// @brief Returns the information whether this list of points interesects the given line135bool intersects(const Position& p1, const Position& p2) const;136137/// @brief Returns the information whether this list of points interesects one the given lines138bool intersects(const PositionVector& v1) const;139140/// @brief Returns the position of the intersection141Position intersectionPosition2D(const Position& p1, const Position& p2, const double withinDist = 0.) const;142143/// @brief For all intersections between this vector and other, return the 2D-length of the subvector from this vectors start to the intersection144std::vector<double> intersectsAtLengths2D(const PositionVector& other) const;145146/// @brief For all intersections between this vector and line, return the 2D-length of the subvector from this vectors start to the intersection147std::vector<double> intersectsAtLengths2D(const Position& lp1, const Position& lp2) const;148149/// @brief Returns the position of the intersection150Position intersectionPosition2D(const PositionVector& v1) const;151152/// @brief open polygon153void openPolygon();154155/// @brief ensures that the last position equals the first156void closePolygon();157158/// @brief returns the constant position at the given index, negative indices are interpreted python style159/// @throws OutOfBoundsException if index >= size or index < -size160const Position& operator[](int index) const;161162/// @brief returns the position at the given index, negative indices are interpreted python style163/// @throws OutOfBoundsException if index >= size or index < -size164Position& operator[](int index);165166/// @brief Returns the position at the given length167Position positionAtOffset(double pos, double lateralOffset = 0) const;168169/// @brief Returns the position at the given length170Position positionAtOffset2D(double pos, double lateralOffset = 0, bool extrapolateBeyond = false) const;171172/* @brief Returns position similar to positionAtOffset but instead of applying the173* lateral offset orthogonal to the shape, apply it orthogonal to the given angle */174Position sidePositionAtAngle(double pos, double lateralOffset, double angle) const;175176/// @brief Returns the rotation at the given length177double rotationAtOffset(double pos) const;178179/// @brief Returns the rotation at the given length180double rotationDegreeAtOffset(double pos) const;181182/// @brief Returns the slope at the given length183double slopeDegreeAtOffset(double pos) const;184185/// @brief Returns the position between the two given point at the specified position186static Position positionAtOffset(const Position& p1, const Position& p2, double pos, double lateralOffset = 0.);187188/// Returns the position between the two given point at the specified position189static Position positionAtOffset2D(const Position& p1, const Position& p2, double pos, double lateralOffset = 0, bool extrapolateBeyond = false);190191/* @brief Returns position similar to positionAtOffset but instead of applying the192* lateral offset orthogonal to the shape, apply it orthogonal to the given angle */193static Position sidePositionAtAngle(const Position& p1, const Position& p2, double pos, double lateralOffset, double angle);194195/// @brief Returns a boundary enclosing this list of lines196Boundary getBoxBoundary() const;197198/// @brief Returns the arithmetic of all corner points199/// @note: this is different from the centroid!200Position getPolygonCenter() const;201202/// @brief Returns the centroid (closes the polygon if unclosed)203Position getCentroid() const;204205/// @brief enlarges/shrinks the polygon by a factor based at the centroid206void scaleRelative(double factor);207208/// @brief enlarges/shrinks the polygon by an absolute offset based at the centroid209void scaleAbsolute(double offset);210211/// @brief get line center212Position getLineCenter() const;213214/// @brief Returns the length215double length() const;216217/// @brief Returns the length218double length2D() const;219220/// @brief Returns the area (0 for non-closed)221double area() const;222223/// @brief Returns the information whether this polygon lies partially within the given polygon224bool partialWithin(const AbstractPoly& poly, double offset = 0) const;225226/// @brief Returns the two lists made when this list vector is splitted at the given point227std::pair<PositionVector, PositionVector> splitAt(double where, bool use2D = false) const;228229//// @brief Output operator230friend std::ostream& operator<<(std::ostream& os, const PositionVector& geom);231232//// @brief check if two positions crosses233bool crosses(const Position& p1, const Position& p2) const;234235//// @brief add an offset to all positions236void add(double xoff, double yoff, double zoff);237238//// @brief add an offset to all positions239void add(const Position& offset);240241//// @brief subtract an offset from all positions242void sub(const Position& offset);243244//// @brief adds a position without modifying the vector itself but returning the result245PositionVector added(const Position& offset) const;246247//// @brief mirror coordinates along the x-axis248void mirrorX();249250//// @brief rotate all points around (0,0) in the plane by the given angle251void rotate2D(double angle);252253//// @brief rotate all points around the given position in the plane by the given angle254void rotate2D(const Position& pos, double angle);255256//// @brief rotate all points around the first element257void rotateAroundFirstElement2D(double angle);258259//// @brief append the given vector to this one260void append(const PositionVector& v, double sameThreshold = 2.0);261262//// @brief prepend the given vector to this one263void prepend(const PositionVector& v, double sameThreshold = 2.0);264265/// @brief get subpart of a position vector266PositionVector getSubpart(double beginOffset, double endOffset) const;267268/// @brief get subpart of a position vector in two dimensions (Z is ignored)269PositionVector getSubpart2D(double beginOffset, double endOffset) const;270271/// @brief get subpart of a position vector using index and a cout272PositionVector getSubpartByIndex(int beginIndex, int count) const;273274/// @brief sort as polygon CW by angle275/// @remark this function works for non-convex polygons but won't possibly yield the desired polygon276void sortAsPolyCWByAngle();277278/// @brief sort by increasing X-Y Positions279void sortByIncreasingXY();280281/// @brief extrapolate position vector282void extrapolate(const double val, const bool onlyFirst = false, const bool onlyLast = false);283284/// @brief extrapolate position vector in two dimensions (Z is ignored)285void extrapolate2D(const double val, const bool onlyFirst = false);286287/// @brief reverse position vector288PositionVector reverse() const;289290/// @brief get a side position of position vector using a offset291static Position sideOffset(const Position& beg, const Position& end, const double amount);292293/// @brief move position vector to side using certain amount294void move2side(double amount, double maxExtension = 100);295296/// @brief move position vector to side using a custom offset for each geometry point297void move2sideCustom(std::vector<double> amount, double maxExtension = 100);298299/// @brief get angle in certain position of position vector (in radians between -M_PI and M_PI)300double angleAt2D(int pos) const;301302/**@brief inserts p between the two closest positions303* @param p position to be inserted304* @param interpolateZ flag to enable/disable interpolation of Z Value between the two closest positions305* @return the insertion index306*/307int insertAtClosest(const Position& p, bool interpolateZ);308309/// @brief removes the point closest to p and return the removal index310int removeClosest(const Position& p);311312/// @brief comparing operation313bool operator==(const PositionVector& v2) const;314315/// @brief comparing operation316bool operator!=(const PositionVector& v2) const;317318/// @brief subtracts two vectors (requires vectors of the same length)319PositionVector operator-(const PositionVector& v2) const;320321/// @brief adds two vectors (requires vectors of the same length)322PositionVector operator+(const PositionVector& v2) const;323324/// @brief class for CW Sorter325class as_poly_cw_sorter {326public:327/// @brief constructor328as_poly_cw_sorter();329330/// @brief comparing operation for sort331int operator()(const Position& p1, const Position& p2) const;332333private:334/// @brief computes the angle of the given vector, in the range $[0,2*\pi[$335double atAngle2D(const Position& p) const;336};337338/// @brief clase for increasing Sorter339class increasing_x_y_sorter {340public:341/// constructor342explicit increasing_x_y_sorter();343344/// comparing operation345int operator()(const Position& p1, const Position& p2) const;346};347348/// @brief get left349/// @note previously marked with "!!!"350double isLeft(const Position& P0, const Position& P1, const Position& P2) const;351352/// @brief returns the angle in radians of the line connecting the first and the last position353double beginEndAngle() const;354355/// @brief return the nearest offest to point 2D356double nearest_offset_to_point2D(const Position& p, bool perpendicular = true) const;357358/// @brief return the nearest offest to point 2D projected onto the 3D geometry359double nearest_offset_to_point25D(const Position& p, bool perpendicular = true) const;360361/** @brief return position p within the length-wise coordinate system362* defined by this position vector. The x value is the same as that returned363* by nearest_offset_to_point2D(p) and the y value is the perpendicular distance to this364* vector with the sign indicating the side (right is postive).365* if extend is true, the vector is extended on both sides and the366* x-coordinate of the result may be below 0 or above the length of the original vector367*/368Position transformToVectorCoordinates(const Position& p, bool extend = false) const;369370/* @brief index of the closest position to p371* @in twoD whether all positions should be projected onto the plan372@note: may only be called for a non-empty vector373*/374int indexOfClosest(const Position& p, bool twoD = false) const;375376/// @brief distances of all my points to s and all of s points to myself377/// @note if perpendicular is set to true, only the perpendicular distances are returned378std::vector<double> distances(const PositionVector& s, bool perpendicular = false) const;379380/// @brief closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector)381double distance2D(const Position& p, bool perpendicular = false) const;382383/// @brief insert in front a Position384void push_front(const Position& p);385386/// @brief pop first Position387void pop_front();388389/// @brief insert in back a non double position390void push_back_noDoublePos(const Position& p);391392/// @brief insert in front a non double position393void push_front_noDoublePos(const Position& p);394395/// @brief insert in front a non double position396void insert_noDoublePos(const std::vector<Position>::iterator& at, const Position& p);397398/// @brief check if PositionVector is closed399bool isClosed() const;400401/// @brief check if PositionVector is NAN402bool isNAN() const;403404/// @brief round all coordinates to the given precision405void round(int precision);406407/** @brief Removes positions if too near408* @param[in] minDist The minimum accepted distance; default: POSITION_EPS409* @param[in] assertLength Whether the result must at least contain two points (be a line); default: false, to ensure original behaviour410*/411void removeDoublePoints(double minDist = POSITION_EPS, bool assertLength = false, int beginOffset = 0, int endOffset = 0, bool resample = false);412413/// @brief return whether two positions differ in z-coordinate414bool hasElevation() const;415416/// @brief return the same shape with intermediate colinear points removed417PositionVector simplified() const;418// test implementation of an alternative check419const PositionVector simplified2(const bool closed, const double eps = NUMERICAL_EPS) const;420421/** @brief return orthogonal through p (extending this vector if necessary)422* @param[in] p The point through which to draw the orthogonal423* @param[in] extend how long to extend this vector for finding an orthogonal424* @param[in] front Whether to take the segment before or after the base point in case of ambiguity425* @param[in] length the length of the orthogonal426* @param[in] deg the rotation angle relative to the shape direction427*/428PositionVector getOrthogonal(const Position& p, double extend, bool before, double length = 1.0, double deg = 90) const;429430/// @brief returned vector that is smoothed at the front (within dist)431PositionVector smoothedZFront(double dist = std::numeric_limits<double>::max()) const;432433/// @brief returned vector that varies z smoothly over its length434PositionVector interpolateZ(double zStart, double zEnd) const;435436/**@brief resample shape (i.e. transform to segments, equal spacing)437* @param[in] maxLength length of every segment438* @param[in] adjustEnd enable or disable adjust end (i.e. result has the same original length, last segment could be short)439*/440PositionVector resample(double maxLength, const bool adjustEnd) const;441442/// @brief return the offset at the given index443double offsetAtIndex2D(int index) const;444445/* @brief return the maximum grade of all segments as a fraction of zRange/length2D446* @param[out] maxJump The maximum vertical jump (with grade infinity)447*/448double getMaxGrade(double& maxJump) const;449450/// @brief return minimum z-coordinate451double getMinZ() const;452453/// @brief check if the two vectors have the same length and pairwise similar positions454bool almostSame(const PositionVector& v2, double maxDiv = POSITION_EPS) const;455456/// @brief return a bezier interpolation457PositionVector bezier(int numPoints);458459static double localAngle(const Position& from, const Position& pos, const Position& to);460461/* @brief checks if the polygon represented by the PositionVector is clockwise-oriented462@remark this function works for non-convex polygons463*/464bool isClockwiseOriented(void);465466private:467/// @brief return whether the line segments defined by Line p11,p12 and Line p21,p22 intersect468static bool intersects(const Position& p11, const Position& p12, const Position& p21, const Position& p22, const double withinDist = 0., double* x = 0, double* y = 0, double* mu = 0);469};470471472