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 std::abs(position.x - this->xMin), // left border
57 std::abs(this->xMax - position.x), // right border
58 std::abs(position.y - this->yMin), // bottom border
59 std::abs(this->yMax - position.y), // top border
60 };
61 uint8_t flags = 0;
62 double minDist = std::numeric_limits<double>::max();
63 for (int i = 0; i < 4; i++)
64 {
65 if (distanceFromBorders[i] > minDist)
66 {
67 continue;
68 }
69 // In case we find a border closer to the position,
70 // we replace it and mark the flag
71 if (distanceFromBorders[i] < minDist)
72 {
73 minDist = distanceFromBorders[i];
74 flags = 0;
75 }
76 flags |= (0b1000 >> i);
77 }
78 NS_ASSERT(minDist != std::numeric_limits<double>::max());
79 Rectangle::Side side;
80 switch (flags)
81 {
82 // LRBT
83 case 0b1111:
84 // Every side is equally distant, so choose any
85 side = TOPSIDE;
86 break;
87 case 0b0011:
88 // Opposing sides are equally distant, so we need to check the other two
89 // We also need to check if we're inside or outside.
90 side = TOPSIDE;
91 if (!IsInside(position))
92 {
93 side = (distanceFromBorders[0] > distanceFromBorders[1]) ? RIGHTSIDE : LEFTSIDE;
94 }
95 break;
96 case 0b1100:
97 // Opposing sides are equally distant, so we need to check the other two
98 // We also need to check if we're inside or outside.
99 side = RIGHTSIDE;
100 if (!IsInside(position))
101 {
102 side = (distanceFromBorders[2] > distanceFromBorders[3]) ? TOPSIDE : BOTTOMSIDE;
103 }
104 break;
105 case 0b0001:
106 case 0b1101:
107 side = TOPSIDE;
108 break;
109 case 0b0010:
110 case 0b1110:
111 side = BOTTOMSIDE;
112 break;
113 case 0b0100:
114 case 0b0111:
115 side = RIGHTSIDE;
116 break;
117 case 0b0101:
118 side = TOPRIGHTCORNER;
119 break;
120 case 0b0110:
121 side = BOTTOMRIGHTCORNER;
122 break;
123 case 0b1000:
124 case 0b1011:
125 side = LEFTSIDE;
126 break;
127 case 0b1001:
128 side = TOPLEFTCORNER;
129 break;
130 case 0b1010:
131 side = BOTTOMLEFTCORNER;
132 break;
133 default:
134 NS_FATAL_ERROR("Impossible case");
135 break;
136 }
137 return side;
138}
139
140Vector
141Rectangle::CalculateIntersection(const Vector& current, const Vector& speed) const
142{
143 NS_ASSERT(IsInside(current));
144 double xMaxY = current.y + (this->xMax - current.x) / speed.x * speed.y;
145 double xMinY = current.y + (this->xMin - current.x) / speed.x * speed.y;
146 double yMaxX = current.x + (this->yMax - current.y) / speed.y * speed.x;
147 double yMinX = current.x + (this->yMin - current.y) / speed.y * speed.x;
148 bool xMaxYOk = (xMaxY <= this->yMax && xMaxY >= this->yMin);
149 bool xMinYOk = (xMinY <= this->yMax && xMinY >= this->yMin);
150 bool yMaxXOk = (yMaxX <= this->xMax && yMaxX >= this->xMin);
151 bool yMinXOk = (yMinX <= this->xMax && yMinX >= this->xMin);
152 if (xMaxYOk && speed.x >= 0)
153 {
154 return Vector(this->xMax, xMaxY, 0.0);
155 }
156 else if (xMinYOk && speed.x <= 0)
157 {
158 return Vector(this->xMin, xMinY, 0.0);
159 }
160 else if (yMaxXOk && speed.y >= 0)
161 {
162 return Vector(yMaxX, this->yMax, 0.0);
163 }
164 else if (yMinXOk && speed.y <= 0)
165 {
166 return Vector(yMinX, this->yMin, 0.0);
167 }
168 else
169 {
170 NS_ASSERT(false);
171 // quiet compiler
172 return Vector(0.0, 0.0, 0.0);
173 }
174}
175
177
178/**
179 * @brief Stream insertion operator.
180 *
181 * @param os the stream
182 * @param rectangle the rectangle
183 * @returns a reference to the stream
184 */
185std::ostream&
186operator<<(std::ostream& os, const Rectangle& rectangle)
187{
188 os << rectangle.xMin << "|" << rectangle.xMax << "|" << rectangle.yMin << "|" << rectangle.yMax;
189 return os;
190}
191
192/**
193 * @brief Stream extraction operator.
194 *
195 * @param is the stream
196 * @param rectangle the rectangle
197 * @returns a reference to the stream
198 */
199std::istream&
200operator>>(std::istream& is, Rectangle& rectangle)
201{
202 char c1;
203 char c2;
204 char c3;
205 is >> rectangle.xMin >> c1 >> rectangle.xMax >> c2 >> rectangle.yMin >> c3 >> rectangle.yMax;
206 if (c1 != '|' || c2 != '|' || c3 != '|')
207 {
208 is.setstate(std::ios_base::failbit);
209 }
210 return is;
211}
212
213/**
214 * @brief Stream insertion operator.
215 *
216 * @param os the stream
217 * @param side the rectangle side
218 * @returns a reference to the stream
219 */
220std::ostream&
221operator<<(std::ostream& os, const Rectangle::Side& side)
222{
223 switch (side)
224 {
226 os << "RIGHTSIDE";
227 break;
229 os << "LEFTSIDE";
230 break;
232 os << "TOPSIDE";
233 break;
235 os << "BOTTOMSIDE";
236 break;
238 os << "TOPRIGHTCORNER";
239 break;
241 os << "TOPLEFTCORNER";
242 break;
244 os << "BOTTOMRIGHTCORNER";
245 break;
247 os << "BOTTOMLEFTCORNER";
248 break;
249 }
250 return os;
251}
252
253} // 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:141
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