/****************************************************************************/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 Position.h14/// @author Daniel Krajzewicz15/// @author Jakob Erdmann16/// @author Axel Wegener17/// @author Michael Behrisch18/// @date Sept 200219///20// A position in the 2D- or 3D-world21/****************************************************************************/22#pragma once23#include <config.h>24#include <iostream>25#include <cmath>2627#include <config.h>2829// ===========================================================================30// class definitions31// ===========================================================================32/**33* @class Position34* @brief A point in 2D or 3D with translation and scaling methods.35*/36class Position {37public:38/// @brief default constructor39Position() :40myX(0.0), myY(0.0), myZ(0.0) { }4142/// @brief Parametrised constructor (only for x-y)43Position(double x, double y) :44myX(x), myY(y), myZ(0) { }4546/// @brief Parametrised constructor47Position(double x, double y, double z) :48myX(x), myY(y), myZ(z) { }4950/// @brief Returns the x-position51inline double x() const {52return myX;53}5455/// @brief Returns the y-position56inline double y() const {57return myY;58}5960/// @brief Returns the z-position61inline double z() const {62return myZ;63}6465/// @brief set position x66void setx(double x) {67myX = x;68}6970/// @brief set position y71void sety(double y) {72myY = y;73}7475/// @brief set position z76void setz(double z) {77myZ = z;78}7980/// @brief set positions x and y81void set(double x, double y) {82myX = x;83myY = y;84}8586/// @brief set positions x, y and z87void set(double x, double y, double z) {88myX = x;89myY = y;90myZ = z;91}9293/// @brief set position with another position94void set(const Position& pos) {95myX = pos.myX;96myY = pos.myY;97myZ = pos.myZ;98}99100/// @brief Multiplies position with the given value101void mul(double val) {102myX *= val;103myY *= val;104myZ *= val;105}106107/// @brief Divides position with the given value108void div(double val) {109myX /= val;110myY /= val;111myZ /= val;112}113114/// @brief Multiplies position with the given values115void mul(double mx, double my) {116myX *= mx;117myY *= my;118}119120/// @brief Multiplies position with the given values121void mul(double mx, double my, double mz) {122myX *= mx;123myY *= my;124myZ *= mz;125}126127/// @brief Adds the given position to this one128void add(const Position& pos) {129myX += pos.myX;130myY += pos.myY;131myZ += pos.myZ;132}133134/// @brief Adds the given position to this one135void add(double dx, double dy) {136myX += dx;137myY += dy;138}139140/// @brief Adds the given position to this one141void add(double dx, double dy, double dz) {142myX += dx;143myY += dy;144myZ += dz;145}146147/// @brief Subtracts the given position from this one148void sub(double dx, double dy) {149myX -= dx;150myY -= dy;151}152153/// @brief Subtracts the given position from this one154void sub(double dx, double dy, double dz) {155myX -= dx;156myY -= dy;157myZ -= dz;158}159160/// @brief Subtracts the given position from this one161void sub(const Position& pos) {162myX -= pos.myX;163myY -= pos.myY;164myZ -= pos.myZ;165}166167/// @brief Computes the length of the given vector168inline double length() const {169return sqrt(myX * myX + myY * myY + myZ * myZ);170}171172/// @brief Computes the length of the given vector neglecting the z coordinate173inline double length2D() const {174return sqrt(myX * myX + myY * myY);175}176177/// @brief Normalizes the given vector178inline void norm2D() {179const double val = length2D();180if (val != 0.) {181myX /= val;182myY /= val;183}184}185186/// @brief output operator187friend std::ostream& operator<<(std::ostream& os, const Position& p) {188os << p.x() << "," << p.y();189if (p.z() != double(0.0)) {190os << "," << p.z();191}192return os;193}194195/// @brief add operator196Position operator+(const Position& p2) const {197return Position(myX + p2.myX, myY + p2.myY, myZ + p2.myZ);198}199200/// @brief sub operator201Position operator-(const Position& p2) const {202return Position(myX - p2.myX, myY - p2.myY, myZ - p2.myZ);203}204205/// @brief keep the direction but modify the length of the (location) vector to length * scalar206Position operator*(double scalar) const {207return Position(myX * scalar, myY * scalar, myZ * scalar);208}209210/// @brief keep the direction but modify the length of the (location) vector to length / scalar211Position operator/(double scalar) const {212return Position(myX / scalar, myY / scalar, myZ / scalar);213}214215/// @brief keep the direction but modify the length of the (location) vector to length + scalar216Position operator+(double offset) const {217const double length = distanceTo(Position(0, 0, 0));218if (length == 0) {219return *this;220}221const double scalar = (length + offset) / length;222return Position(myX * scalar, myY * scalar, myZ * scalar);223}224225/// @brief keep the direction but modify the length of the (location) vector to length - scalar226Position operator-(double offset) const {227const double length = distanceTo(Position(0, 0, 0));228if (length == 0) {229return *this;230}231const double scalar = (length - offset) / length;232return Position(myX * scalar, myY * scalar, myZ * scalar);233}234235/// @brief comparation operator236bool operator==(const Position& p2) const {237return myX == p2.myX && myY == p2.myY && myZ == p2.myZ;238}239240/// @brief difference operator241bool operator!=(const Position& p2) const {242return myX != p2.myX || myY != p2.myY || myZ != p2.myZ;243}244245/// @brief lexicographical sorting for use in maps and sets246bool operator<(const Position& p2) const {247if (myX != p2.myX) {248return myX < p2.myX;249}250if (myY != p2.myY) {251return myY < p2.myY;252}253return myZ < p2.myZ;254}255256/// @brief check whether the other position has a euclidean distance of less than maxDiv257bool almostSame(const Position& p2, double maxDiv = POSITION_EPS) const {258return distanceTo(p2) < maxDiv;259}260261/// @brief returns the euclidean distance in 3 dimensions262inline double distanceTo(const Position& p2) const {263return sqrt(distanceSquaredTo(p2));264}265266/// @brief returns the square of the distance to another position267inline double distanceSquaredTo(const Position& p2) const {268return (myX - p2.myX) * (myX - p2.myX) + (myY - p2.myY) * (myY - p2.myY) + (myZ - p2.myZ) * (myZ - p2.myZ);269}270271/// @brief returns the euclidean distance in the x-y-plane272inline double distanceTo2D(const Position& p2) const {273return sqrt(distanceSquaredTo2D(p2));274}275276/// @brief returns the square of the distance to another position (Only using x and y positions)277inline double distanceSquaredTo2D(const Position& p2) const {278return (myX - p2.myX) * (myX - p2.myX) + (myY - p2.myY) * (myY - p2.myY);279}280281/// @brief returns the angle in the plane of the vector pointing from here to the other position (in radians between -M_PI and M_PI)282inline double angleTo2D(const Position& other) const {283return atan2(other.myY - myY, other.myX - myX);284}285286/// @brief returns the slope of the vector pointing from here to the other position (in radians between -M_PI and M_PI)287inline double slopeTo2D(const Position& other) const {288return atan2(other.myZ - myZ, distanceTo2D(other));289}290291/// @brief returns the cross product between this point and the second one292Position crossProduct(const Position& pos) {293return Position(294myY * pos.myZ - myZ * pos.myY,295myZ * pos.myX - myX * pos.myZ,296myX * pos.myY - myY * pos.myX);297}298299/// @brief returns the dot product (scalar product) between this point and the second one300inline double dotProduct(const Position& pos) const {301return myX * pos.myX + myY * pos.myY + myZ * pos.myZ;302}303304/// @brief rotate this position by rad around origin and return the result305Position rotateAround2D(double rad, const Position& origin);306307/// @brief swap position X and Y308void swapXY() {309std::swap(myX, myY);310}311312/// @brief check if position is NAN313bool isNAN() const {314return (std::isnan(myX) || std::isnan(myY) || std::isnan(myZ));315}316317/// @brief round all coordinates to the given precision318void round(int precision);319320321/// @brief used to indicate that a position is valid322static const Position INVALID;323324private:325/// @brief The x-position326double myX;327328/// @brief The y-position329double myY;330331/// @brief The z-position332double myZ;333};334335336