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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19#include "rectangle.h"
20
21#include "ns3/assert.h"
22#include "ns3/fatal-error.h"
23#include "ns3/vector.h"
24
25#include <algorithm>
26#include <array>
27#include <cmath>
28#include <sstream>
29
30namespace ns3
31{
32
33Rectangle::Rectangle(double _xMin, double _xMax, double _yMin, double _yMax)
34 : xMin(_xMin),
35 xMax(_xMax),
36 yMin(_yMin),
37 yMax(_yMax)
38{
39}
40
42 : xMin(0.0),
43 xMax(0.0),
44 yMin(0.0),
45 yMax(0.0)
46{
47}
48
49bool
50Rectangle::IsInside(const Vector& position) const
51{
52 return position.x <= this->xMax && position.x >= this->xMin && position.y <= this->yMax &&
53 position.y >= this->yMin;
54}
55
56bool
57Rectangle::IsOnTheBorder(const Vector& position) const
58{
59 return position.x == this->xMax || position.x == this->xMin || position.y == this->yMax ||
60 position.y == this->yMin;
61}
62
64Rectangle::GetClosestSideOrCorner(const Vector& position) const
65{
66 std::array<double, 4> distanceFromBorders{
67 std::abs(position.x - this->xMin), // left border
68 std::abs(this->xMax - position.x), // right border
69 std::abs(position.y - this->yMin), // bottom border
70 std::abs(this->yMax - position.y), // top border
71 };
72 uint8_t flags = 0;
73 double minDist = std::numeric_limits<double>::max();
74 for (int i = 0; i < 4; i++)
75 {
76 if (distanceFromBorders[i] > minDist)
77 {
78 continue;
79 }
80 // In case we find a border closer to the position,
81 // we replace it and mark the flag
82 if (distanceFromBorders[i] < minDist)
83 {
84 minDist = distanceFromBorders[i];
85 flags = 0;
86 }
87 flags |= (0b1000 >> i);
88 }
89 NS_ASSERT(minDist != std::numeric_limits<double>::max());
90 Rectangle::Side side;
91 switch (flags)
92 {
93 // LRBT
94 case 0b1111:
95 // Every side is equally distant, so choose any
96 side = TOPSIDE;
97 break;
98 case 0b0011:
99 // Opposing sides are equally distant, so we need to check the other two
100 // We also need to check if we're inside or outside.
101 side = TOPSIDE;
102 if (!IsInside(position))
103 {
104 side = (distanceFromBorders[0] > distanceFromBorders[1]) ? RIGHTSIDE : LEFTSIDE;
105 }
106 break;
107 case 0b1100:
108 // Opposing sides are equally distant, so we need to check the other two
109 // We also need to check if we're inside or outside.
110 side = RIGHTSIDE;
111 if (!IsInside(position))
112 {
113 side = (distanceFromBorders[2] > distanceFromBorders[3]) ? TOPSIDE : BOTTOMSIDE;
114 }
115 break;
116 case 0b0001:
117 case 0b1101:
118 side = TOPSIDE;
119 break;
120 case 0b0010:
121 case 0b1110:
122 side = BOTTOMSIDE;
123 break;
124 case 0b0100:
125 case 0b0111:
126 side = RIGHTSIDE;
127 break;
128 case 0b0101:
129 side = TOPRIGHTCORNER;
130 break;
131 case 0b0110:
132 side = BOTTOMRIGHTCORNER;
133 break;
134 case 0b1000:
135 case 0b1011:
136 side = LEFTSIDE;
137 break;
138 case 0b1001:
139 side = TOPLEFTCORNER;
140 break;
141 case 0b1010:
142 side = BOTTOMLEFTCORNER;
143 break;
144 default:
145 NS_FATAL_ERROR("Impossible case");
146 break;
147 }
148 return side;
149}
150
151Vector
152Rectangle::CalculateIntersection(const Vector& current, const Vector& speed) const
153{
154 NS_ASSERT(IsInside(current));
155 double xMaxY = current.y + (this->xMax - current.x) / speed.x * speed.y;
156 double xMinY = current.y + (this->xMin - current.x) / speed.x * speed.y;
157 double yMaxX = current.x + (this->yMax - current.y) / speed.y * speed.x;
158 double yMinX = current.x + (this->yMin - current.y) / speed.y * speed.x;
159 bool xMaxYOk = (xMaxY <= this->yMax && xMaxY >= this->yMin);
160 bool xMinYOk = (xMinY <= this->yMax && xMinY >= this->yMin);
161 bool yMaxXOk = (yMaxX <= this->xMax && yMaxX >= this->xMin);
162 bool yMinXOk = (yMinX <= this->xMax && yMinX >= this->xMin);
163 if (xMaxYOk && speed.x >= 0)
164 {
165 return Vector(this->xMax, xMaxY, 0.0);
166 }
167 else if (xMinYOk && speed.x <= 0)
168 {
169 return Vector(this->xMin, xMinY, 0.0);
170 }
171 else if (yMaxXOk && speed.y >= 0)
172 {
173 return Vector(yMaxX, this->yMax, 0.0);
174 }
175 else if (yMinXOk && speed.y <= 0)
176 {
177 return Vector(yMinX, this->yMin, 0.0);
178 }
179 else
180 {
181 NS_ASSERT(false);
182 // quiet compiler
183 return Vector(0.0, 0.0, 0.0);
184 }
185}
186
188
189/**
190 * \brief Stream insertion operator.
191 *
192 * \param os the stream
193 * \param rectangle the rectangle
194 * \returns a reference to the stream
195 */
196std::ostream&
197operator<<(std::ostream& os, const Rectangle& rectangle)
198{
199 os << rectangle.xMin << "|" << rectangle.xMax << "|" << rectangle.yMin << "|" << rectangle.yMax;
200 return os;
201}
202
203/**
204 * \brief Stream extraction operator.
205 *
206 * \param is the stream
207 * \param rectangle the rectangle
208 * \returns a reference to the stream
209 */
210std::istream&
211operator>>(std::istream& is, Rectangle& rectangle)
212{
213 char c1;
214 char c2;
215 char c3;
216 is >> rectangle.xMin >> c1 >> rectangle.xMax >> c2 >> rectangle.yMin >> c3 >> rectangle.yMax;
217 if (c1 != '|' || c2 != '|' || c3 != '|')
218 {
219 is.setstate(std::ios_base::failbit);
220 }
221 return is;
222}
223
224/**
225 * \brief Stream insertion operator.
226 *
227 * \param os the stream
228 * \param side the rectangle side
229 * \returns a reference to the stream
230 */
231std::ostream&
232operator<<(std::ostream& os, const Rectangle::Side& side)
233{
234 switch (side)
235 {
237 os << "RIGHTSIDE";
238 break;
240 os << "LEFTSIDE";
241 break;
243 os << "TOPSIDE";
244 break;
246 os << "BOTTOMSIDE";
247 break;
249 os << "TOPRIGHTCORNER";
250 break;
252 os << "TOPLEFTCORNER";
253 break;
255 os << "BOTTOMRIGHTCORNER";
256 break;
258 os << "BOTTOMLEFTCORNER";
259 break;
260 }
261 return os;
262}
263
264} // namespace ns3
a 2d rectangle
Definition: rectangle.h:35
double yMax
The y coordinate of the top bound of the rectangle.
Definition: rectangle.h:118
Side GetClosestSideOrCorner(const Vector &position) const
Definition: rectangle.cc:64
bool IsInside(const Vector &position) const
Definition: rectangle.cc:50
bool IsOnTheBorder(const Vector &position) const
Definition: rectangle.cc:57
double xMax
The x coordinate of the right bound of the rectangle.
Definition: rectangle.h:116
Vector CalculateIntersection(const Vector &current, const Vector &speed) const
Definition: rectangle.cc:152
Side
enum for naming sides
Definition: rectangle.h:41
double xMin
The x coordinate of the left bound of the rectangle.
Definition: rectangle.h:115
Rectangle()
Create a zero-sized rectangle located at coordinates (0.0,0.0)
Definition: rectangle.cc:41
double yMin
The y coordinate of the bottom bound of the rectangle.
Definition: rectangle.h:117
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#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.
Definition: fatal-error.h:179
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:159
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:183