A Discrete-Event Network Simulator
API
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 
30 namespace ns3
31 {
32 
33 Rectangle::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 
49 bool
50 Rectangle::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 
56 bool
57 Rectangle::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 
64 Rectangle::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  }
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 
151 Vector
152 Rectangle::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 
196 std::ostream&
197 operator<<(std::ostream& os, const Rectangle& rectangle)
198 {
199  os << rectangle.xMin << "|" << rectangle.xMax << "|" << rectangle.yMin << "|" << rectangle.yMax;
200  return os;
201 }
202 
210 std::istream&
211 operator>>(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 
231 std::ostream&
232 operator<<(std::ostream& os, const Rectangle::Side& side)
233 {
234  switch (side)
235  {
237  os << "RIGHTSIDE";
238  break;
239  case Rectangle::LEFTSIDE:
240  os << "LEFTSIDE";
241  break;
242  case Rectangle::TOPSIDE:
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
#define max(a, b)
Definition: 80211b.c:42
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 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.
ATTRIBUTE_HELPER_CPP(ValueClassTest)
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:183
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159