1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    GeomHelper.h
11 /// @author  Daniel Krajzewicz
12 /// @author  Friedemann Wesner
13 /// @author  Jakob Erdmann
14 /// @author  Michael Behrisch
15 /// @date    Sept 2002
16 /// @version $Id$
17 ///
18 // Some static methods performing geometrical operations
19 /****************************************************************************/
20 #ifndef GeomHelper_h
21 #define GeomHelper_h
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #include <config.h>
28 
29 #include <cmath>
30 #include "Position.h"
31 #include "PositionVector.h"
32 #include <utils/common/UtilExceptions.h>
33 
34 #ifndef M_PI
35 #define M_PI 3.1415926535897932384626433832795
36 #endif
37 
38 #define DEG2RAD(x) static_cast<double>((x) * M_PI / 180.)
39 #define RAD2DEG(x) static_cast<double>((x) * 180. / M_PI)
40 
41 
42 // ===========================================================================
43 // class definitions
44 // ===========================================================================
45 /** @class GeomHelper
46  * @brief Some static methods performing geometrical operations
47  */
48 class GeomHelper {
49 
50 public:
51     /// @brief a value to signify offsets outside the range of [0, Line.length()]
52     static const double INVALID_OFFSET;
53 
54     /** @brief Returns the positions the given circle is crossed by the given line
55      * @param[in] c The center position of the circle
56      * @param[in] radius The radius of the circle
57      * @param[in] p1 The begin of the line
58      * @param[in] p2 The end of the line
59      * @param[filled] into The list of crossing positions (0-1 along the line's length)
60      * @see http://blog.csharphelper.com/2010/03/28/determine-where-a-line-intersects-a-circle-in-c.aspx
61      * @see http://gamedev.stackexchange.com/questions/18333/circle-line-collision-detection-problem (jazzdawg)
62      */
63     static void findLineCircleIntersections(const Position& c, double radius, const Position& p1, const Position& p2,
64                                             std::vector<double>& into);
65 
66 
67     /** @brief Returns the angle between two vectors on a plane
68        The angle is from vector 1 to vector 2, positive anticlockwise
69        The result is between -pi and pi
70     */
71     static double angle2D(const Position& p1, const Position& p2);
72 
73     static double nearest_offset_on_line_to_point2D(
74         const Position& lineStart, const Position& lineEnd,
75         const Position& p, bool perpendicular = true);
76 
77     static double nearest_offset_on_line_to_point25D(
78         const Position& lineStart, const Position& lineEnd,
79         const Position& p, bool perpendicular = true);
80 
81     static Position crossPoint(const Boundary& b,
82                                const PositionVector& v);
83 
84     /** @brief Returns the distance of second angle from first angle counter-clockwise
85      * @param[in] angle1 The first angle
86      * @param[in] angle2 The second angle
87      * @return Angle (counter-clockwise) starting from first to second angle
88      */
89     static double getCCWAngleDiff(double angle1, double angle2);
90 
91 
92     /** @brief Returns the distance of second angle from first angle clockwise
93      * @param[in] angle1 The first angle
94      * @param[in] angle2 The second angle
95      * @return Angle (clockwise) starting from first to second angle
96      */
97     static double getCWAngleDiff(double angle1, double angle2);
98 
99 
100     /** @brief Returns the minimum distance (clockwise/counter-clockwise) between both angles
101      * @param[in] angle1 The first angle
102      * @param[in] angle2 The second angle
103      * @return The minimum distance between both angles
104      */
105     static double getMinAngleDiff(double angle1, double angle2);
106 
107 
108     /** @brief Returns the difference of the second angle to the first angle in radiants
109      *
110      * The results are always between -pi and pi.
111      * Positive values denote that the second angle is counter clockwise closer, negative values mean
112      * it is clockwise closer.
113      * @param[in] angle1 The first angle
114      * @param[in] angle2 The second angle
115      * @return angle starting from first to second angle
116      */
117     static double angleDiff(const double angle1, const double angle2);
118 
119 
120     /** Converts an angle from mathematical radians where 0 is to the right and positive angles
121      *  are counterclockwise to navigational degrees where 0 is up and positive means clockwise.
122      *  The result is always in the range [0, 360).
123      * @param[in] angle The angle in radians to convert
124      * @return the angle in degrees
125      */
126     static double naviDegree(const double angle);
127 
128     /** Converts an angle from navigational degrees to mathematical radians.
129      * @see naviDegree
130      * @param[in] angle The angle in degree to convert
131      * @return the angle in radians
132      */
133     static double fromNaviDegree(const double angle);
134 
135     /** Converts an angle from mathematical radians where 0 is to the right and positive angles
136      *  are counterclockwise to the legacy degrees used in sumo where 0 is down and positive means clockwise.
137      *  If positive is true the result is in the range [0, 360), otherwise in the range [-180, 180).
138      * @param[in] angle The angle in radians to convert
139      * @return the angle in degrees
140      */
141     static double legacyDegree(const double angle, const bool positive = false);
142 
143     /** Creates a circular polygon
144      * @param[in] radius Radius of the circle
145      * @param[in] center Position of the circle's center
146      * @param[in] nPoints Number of points of the circle (Polygon's shape will have noPoints+1 points), must be >=3
147      * @return the polygon approximating the circle
148      */
149     static PositionVector makeCircle(const double radius, const Position& center, unsigned int nPoints);
150 
151     /** Creates a circular polygon
152      * @param[in] radius1 Inner radius of the ring
153      * @param[in] radius2 Outer radius of the ring
154      * @param[in] center Position of the circle's center
155      * @param[in] nPoints Number of points of the circle (Polygon's shape will have noPoints+1 points), must be >=3
156      * @return the polygon approximating the circle
157      */
158     static PositionVector makeRing(const double radius1, const double radius2, const Position& center, unsigned int nPoints);
159 
160 };
161 
162 
163 #endif
164 
165 /****************************************************************************/
166