A Discrete-Event Network Simulator
API
box.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 Dan Broyles
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: Dan Broyles <dbroyl01@ku.edu>
18  */
19 
20 #include "box.h"
21 
22 #include "ns3/assert.h"
23 #include "ns3/fatal-error.h"
24 #include "ns3/vector.h"
25 
26 #include <algorithm>
27 #include <cmath>
28 #include <sstream>
29 
30 namespace ns3
31 {
32 
33 Box::Box(double _xMin, double _xMax, double _yMin, double _yMax, double _zMin, double _zMax)
34  : xMin(_xMin),
35  xMax(_xMax),
36  yMin(_yMin),
37  yMax(_yMax),
38  zMin(_zMin),
39  zMax(_zMax)
40 {
41 }
42 
44  : xMin(0.0),
45  xMax(0.0),
46  yMin(0.0),
47  yMax(0.0),
48  zMin(0.0),
49  zMax(0.0)
50 {
51 }
52 
53 bool
54 Box::IsInside(const Vector& position) const
55 {
56  return position.x <= this->xMax && position.x >= this->xMin && position.y <= this->yMax &&
57  position.y >= this->yMin && position.z <= this->zMax && position.z >= this->zMin;
58 }
59 
61 Box::GetClosestSide(const Vector& position) const
62 {
63  double xMinDist = std::abs(position.x - this->xMin);
64  double xMaxDist = std::abs(this->xMax - position.x);
65  double yMinDist = std::abs(position.y - this->yMin);
66  double yMaxDist = std::abs(this->yMax - position.y);
67  double zMinDist = std::abs(position.z - this->zMin);
68  double zMaxDist = std::abs(this->zMax - position.z);
69  double minX = std::min(xMinDist, xMaxDist);
70  double minY = std::min(yMinDist, yMaxDist);
71  double minZ = std::min(zMinDist, zMaxDist);
72  if (minX < minY && minX < minZ)
73  {
74  if (xMinDist < xMaxDist)
75  {
76  return LEFT;
77  }
78  else
79  {
80  return RIGHT;
81  }
82  }
83  else if (minY < minZ)
84  {
85  if (yMinDist < yMaxDist)
86  {
87  return BOTTOM;
88  }
89  else
90  {
91  return TOP;
92  }
93  }
94  else
95  {
96  if (zMinDist < zMaxDist)
97  {
98  return DOWN;
99  }
100  else
101  {
102  return UP;
103  }
104  }
105 }
106 
107 Vector
108 Box::CalculateIntersection(const Vector& current, const Vector& speed) const
109 {
110  NS_ASSERT(IsInside(current));
111  double xMaxY = current.y + (this->xMax - current.x) / speed.x * speed.y;
112  double xMinY = current.y + (this->xMin - current.x) / speed.x * speed.y;
113  double yMaxX = current.x + (this->yMax - current.y) / speed.y * speed.x;
114  double yMinX = current.x + (this->yMin - current.y) / speed.y * speed.x;
115  bool xMaxYOk = (xMaxY <= this->yMax && xMaxY >= this->yMin);
116  bool xMinYOk = (xMinY <= this->yMax && xMinY >= this->yMin);
117  bool yMaxXOk = (yMaxX <= this->xMax && yMaxX >= this->xMin);
118  bool yMinXOk = (yMinX <= this->xMax && yMinX >= this->xMin);
119  if (xMaxYOk && speed.x >= 0)
120  {
121  return Vector(this->xMax, xMaxY, 0.0);
122  }
123  else if (xMinYOk && speed.x <= 0)
124  {
125  return Vector(this->xMin, xMinY, 0.0);
126  }
127  else if (yMaxXOk && speed.y >= 0)
128  {
129  return Vector(yMaxX, this->yMax, 0.0);
130  }
131  else if (yMinXOk && speed.y <= 0)
132  {
133  return Vector(yMinX, this->yMin, 0.0);
134  }
135  else
136  {
137  NS_ASSERT(false);
138  // quiet compiler
139  return Vector(0.0, 0.0, 0.0);
140  }
141 }
142 
143 bool
144 Box::IsIntersect(const Vector& l1, const Vector& l2) const
145 {
146  // If any of the position falls inside the box,
147  // return true.
148  if (IsInside(l1) || IsInside(l2))
149  {
150  return true;
151  }
152 
153  Vector boxSize(0.5 * (this->xMax - this->xMin),
154  0.5 * (this->yMax - this->yMin),
155  0.5 * (this->zMax - this->zMin));
156  Vector boxCenter(this->xMin + boxSize.x, this->yMin + boxSize.y, this->zMin + boxSize.z);
157 
158  // Put line-segment in box space
159  Vector lB1(l1.x - boxCenter.x, l1.y - boxCenter.y, l1.z - boxCenter.z);
160  Vector lB2(l2.x - boxCenter.x, l2.y - boxCenter.y, l2.z - boxCenter.z);
161 
162  // Get line-segment midpoint and extent
163  Vector lMid(0.5 * (lB1.x + lB2.x), 0.5 * (lB1.y + lB2.y), 0.5 * (lB1.z + lB2.z));
164  Vector l(lB1.x - lMid.x, lB1.y - lMid.y, lB1.z - lMid.z);
165  Vector lExt(std::abs(l.x), std::abs(l.y), std::abs(l.z));
166 
167  // Use Separating Axis Test
168  // Separation vector from box center to line-segment center is lMid, since the
169  // line is in box space, if any dimension of the line-segment did not intersect
170  // the box, return false, which means the whole line-segment didn't
171  // intersect the box.
172  if (std::abs(lMid.x) > boxSize.x + lExt.x)
173  {
174  return false;
175  }
176  if (std::abs(lMid.y) > boxSize.y + lExt.y)
177  {
178  return false;
179  }
180  if (std::abs(lMid.z) > boxSize.z + lExt.z)
181  {
182  return false;
183  }
184  // Cross-products of line and each axis
185  if (std::abs(lMid.y * l.z - lMid.z * l.y) > (boxSize.y * lExt.z + boxSize.z * lExt.y))
186  {
187  return false;
188  }
189  if (std::abs(lMid.x * l.z - lMid.z * l.x) > (boxSize.x * lExt.z + boxSize.z * lExt.x))
190  {
191  return false;
192  }
193  if (std::abs(lMid.x * l.y - lMid.y * l.x) > (boxSize.x * lExt.y + boxSize.y * lExt.x))
194  {
195  return false;
196  }
197 
198  // No separating axis, the line-segment intersect this box, return true.
199  return true;
200 }
201 
203 
211 std::ostream&
212 operator<<(std::ostream& os, const Box& box)
213 {
214  os << box.xMin << "|" << box.xMax << "|" << box.yMin << "|" << box.yMax << "|" << box.zMin
215  << "|" << box.zMax;
216  return os;
217 }
218 
226 std::istream&
227 operator>>(std::istream& is, Box& box)
228 {
229  char c1;
230  char c2;
231  char c3;
232  char c4;
233  char c5;
234  is >> box.xMin >> c1 >> box.xMax >> c2 >> box.yMin >> c3 >> box.yMax >> c4 >> box.zMin >> c5 >>
235  box.zMax;
236  if (c1 != '|' || c2 != '|' || c3 != '|' || c4 != '|' || c5 != '|')
237  {
238  is.setstate(std::ios_base::failbit);
239  }
240  return is;
241 }
242 
243 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:41
a 3d box
Definition: box.h:35
double yMax
The y coordinate of the top bound of the box.
Definition: box.h:116
bool IsInside(const Vector &position) const
Definition: box.cc:54
double xMin
The x coordinate of the left bound of the box.
Definition: box.h:110
Side
Enum class to specify sides of a box.
Definition: box.h:41
@ RIGHT
Definition: box.h:42
@ UP
Definition: box.h:46
@ DOWN
Definition: box.h:47
@ BOTTOM
Definition: box.h:45
@ LEFT
Definition: box.h:43
@ TOP
Definition: box.h:44
double yMin
The y coordinate of the bottom bound of the box.
Definition: box.h:114
double xMax
The x coordinate of the right bound of the box.
Definition: box.h:112
Vector CalculateIntersection(const Vector &current, const Vector &speed) const
Definition: box.cc:108
double zMin
The z coordinate of the down bound of the box.
Definition: box.h:118
bool IsIntersect(const Vector &l1, const Vector &l2) const
Checks if a line-segment between position l1 and position l2 intersects a box.
Definition: box.cc:144
Side GetClosestSide(const Vector &position) const
Definition: box.cc:61
Box()
Create a zero-sized box located at coordinates (0.0,0.0,0.0)
Definition: box.cc:43
double zMax
The z coordinate of the up bound of the box.
Definition: box.h:120
#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
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