A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
rectangle.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8#include "rectangle.h"
9
10#include "ns3/assert.h"
11#include "ns3/fatal-error.h"
12#include "ns3/vector.h"
13
14#include <algorithm>
15#include <array>
16#include <cmath>
17#include <sstream>
18
19namespace ns3
20{
21
22Rectangle::Rectangle(double _xMin, double _xMax, double _yMin, double _yMax)
23 : xMin(_xMin),
24 xMax(_xMax),
25 yMin(_yMin),
26 yMax(_yMax)
27{
28}
29
31 : xMin(0.0),
32 xMax(0.0),
33 yMin(0.0),
34 yMax(0.0)
35{
36}
37
38bool
39Rectangle::IsInside(const Vector& position) const
40{
41 return position.x <= this->xMax && position.x >= this->xMin && position.y <= this->yMax &&
42 position.y >= this->yMin;
43}
44
45bool
46Rectangle::IsOnTheBorder(const Vector& position) const
47{
48 return position.x == this->xMax || position.x == this->xMin || position.y == this->yMax ||
49 position.y == this->yMin;
50}
51
53Rectangle::GetClosestSideOrCorner(const Vector& position) const
54{
55 std::array<double, 4> distanceFromBorders;
56
57 if (IsInside(position))
58 {
59 distanceFromBorders = {
60 std::abs(position.x - this->xMin), // left border
61 std::abs(this->xMax - position.x), // right border
62 std::abs(position.y - this->yMin), // bottom border
63 std::abs(this->yMax - position.y) // top border
64 };
65 }
66 else
67 {
68 const auto yMid = (yMax + yMin) / 2;
69 const auto xMid = (xMax + xMin) / 2;
70 distanceFromBorders = {
71 CalculateDistance(position, Vector(xMin, yMid, position.z)), // left border
72 CalculateDistance(position, Vector(xMax, yMid, position.z)), // right border
73 CalculateDistance(position, Vector(xMid, yMin, position.z)), // bottom border
74 CalculateDistance(position, Vector(xMid, yMax, position.z)) // top border
75 };
76 }
77 uint8_t flags = 0;
78 double minDist = std::numeric_limits<double>::max();
79 for (int i = 0; i < 4; i++)
80 {
81 if (distanceFromBorders[i] > minDist)
82 {
83 continue;
84 }
85 // In case we find a border closer to the position,
86 // we replace it and mark the flag
87 if (distanceFromBorders[i] < minDist)
88 {
89 minDist = distanceFromBorders[i];
90 flags = 0;
91 }
92 flags |= (0b1000 >> i);
93 }
94 NS_ASSERT(minDist != std::numeric_limits<double>::max());
95 Rectangle::Side side;
96 switch (flags)
97 {
98 // LRBT
99 case 0b1111: // Equidistant to all sides, so we choose top
100 case 0b1101: // Equidistant to top, left and right, so we choose top
101 case 0b0011: // Opposing sides are equally distant, so we choose top
102 case 0b0001: // Closer to top
103 side = TOPSIDE;
104 break;
105 case 0b0010:
106 case 0b1110:
107 side = BOTTOMSIDE;
108 break;
109 case 0b1100: // Opposing sides are equally distant, so choose right
110 case 0b0100:
111 case 0b0111:
112 side = RIGHTSIDE;
113 break;
114 case 0b0101:
115 side = TOPRIGHTCORNER;
116 break;
117 case 0b0110:
118 side = BOTTOMRIGHTCORNER;
119 break;
120 case 0b1000:
121 case 0b1011:
122 side = LEFTSIDE;
123 break;
124 case 0b1001:
125 side = TOPLEFTCORNER;
126 break;
127 case 0b1010:
128 side = BOTTOMLEFTCORNER;
129 break;
130 default:
131 NS_FATAL_ERROR("Impossible case");
132 break;
133 }
134 return side;
135}
136
137Vector
138Rectangle::CalculateIntersection(const Vector& current, const Vector& speed) const
139{
140 NS_ASSERT(IsInside(current));
141 double xMaxY = current.y + (this->xMax - current.x) / speed.x * speed.y;
142 double xMinY = current.y + (this->xMin - current.x) / speed.x * speed.y;
143 double yMaxX = current.x + (this->yMax - current.y) / speed.y * speed.x;
144 double yMinX = current.x + (this->yMin - current.y) / speed.y * speed.x;
145 bool xMaxYOk = (xMaxY <= this->yMax && xMaxY >= this->yMin);
146 bool xMinYOk = (xMinY <= this->yMax && xMinY >= this->yMin);
147 bool yMaxXOk = (yMaxX <= this->xMax && yMaxX >= this->xMin);
148 bool yMinXOk = (yMinX <= this->xMax && yMinX >= this->xMin);
149 if (xMaxYOk && speed.x >= 0)
150 {
151 return Vector(this->xMax, xMaxY, 0.0);
152 }
153 else if (xMinYOk && speed.x <= 0)
154 {
155 return Vector(this->xMin, xMinY, 0.0);
156 }
157 else if (yMaxXOk && speed.y >= 0)
158 {
159 return Vector(yMaxX, this->yMax, 0.0);
160 }
161 else if (yMinXOk && speed.y <= 0)
162 {
163 return Vector(yMinX, this->yMin, 0.0);
164 }
165 else
166 {
167 NS_ASSERT(false);
168 // quiet compiler
169 return Vector(0.0, 0.0, 0.0);
170 }
171}
172
174
175/**
176 * @brief Stream insertion operator.
177 *
178 * @param os the stream
179 * @param rectangle the rectangle
180 * @returns a reference to the stream
181 */
182std::ostream&
183operator<<(std::ostream& os, const Rectangle& rectangle)
184{
185 os << rectangle.xMin << "|" << rectangle.xMax << "|" << rectangle.yMin << "|" << rectangle.yMax;
186 return os;
187}
188
189/**
190 * @brief Stream extraction operator.
191 *
192 * @param is the stream
193 * @param rectangle the rectangle
194 * @returns a reference to the stream
195 */
196std::istream&
197operator>>(std::istream& is, Rectangle& rectangle)
198{
199 char c1;
200 char c2;
201 char c3;
202 is >> rectangle.xMin >> c1 >> rectangle.xMax >> c2 >> rectangle.yMin >> c3 >> rectangle.yMax;
203 if (c1 != '|' || c2 != '|' || c3 != '|')
204 {
205 is.setstate(std::ios_base::failbit);
206 }
207 return is;
208}
209
210/**
211 * @brief Stream insertion operator.
212 *
213 * @param os the stream
214 * @param side the rectangle side
215 * @returns a reference to the stream
216 */
217std::ostream&
218operator<<(std::ostream& os, const Rectangle::Side& side)
219{
220 switch (side)
221 {
223 os << "RIGHTSIDE";
224 break;
226 os << "LEFTSIDE";
227 break;
229 os << "TOPSIDE";
230 break;
232 os << "BOTTOMSIDE";
233 break;
235 os << "TOPRIGHTCORNER";
236 break;
238 os << "TOPLEFTCORNER";
239 break;
241 os << "BOTTOMRIGHTCORNER";
242 break;
244 os << "BOTTOMLEFTCORNER";
245 break;
246 }
247 return os;
248}
249
250} // namespace ns3
a 2d rectangle
Definition rectangle.h:24
double yMax
The y coordinate of the top bound of the rectangle.
Definition rectangle.h:107
Side GetClosestSideOrCorner(const Vector &position) const
Definition rectangle.cc:53
bool IsInside(const Vector &position) const
Definition rectangle.cc:39
bool IsOnTheBorder(const Vector &position) const
Definition rectangle.cc:46
double xMax
The x coordinate of the right bound of the rectangle.
Definition rectangle.h:105
Vector CalculateIntersection(const Vector &current, const Vector &speed) const
Definition rectangle.cc:138
Side
enum for naming sides
Definition rectangle.h:30
double xMin
The x coordinate of the left bound of the rectangle.
Definition rectangle.h:104
Rectangle()
Create a zero-sized rectangle located at coordinates (0.0,0.0)
Definition rectangle.cc:30
double yMin
The y coordinate of the bottom bound of the rectangle.
Definition rectangle.h:106
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define ATTRIBUTE_HELPER_CPP(type)
Define the attribute value, accessor and checkers for class type
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
std::istream & operator>>(std::istream &is, Angles &a)
Definition angles.cc:172
double CalculateDistance(const Vector3D &a, const Vector3D &b)
Definition vector.cc:98