A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
30namespace ns3
31{
32
33Box::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
53bool
54Box::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
61Box::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
107Vector
108Box::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
143bool
144Box::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
204/**
205 * \brief Stream insertion operator.
206 *
207 * \param os the stream
208 * \param box the box
209 * \returns a reference to the stream
210 */
211std::ostream&
212operator<<(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
219/**
220 * \brief Stream extraction operator.
221 *
222 * \param is the stream
223 * \param box the box
224 * \returns a reference to the stream
225 */
226std::istream&
227operator>>(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
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
#define ATTRIBUTE_HELPER_CPP(type)
Define the attribute value, accessor and checkers for class type
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