A Discrete-Event Network Simulator
API
box.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2009 Dan Broyles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Dan Broyles <dbroyl01@ku.edu>
19 */
20
21#include "box.h"
22#include "ns3/vector.h"
23#include "ns3/assert.h"
24#include "ns3/fatal-error.h"
25#include <cmath>
26#include <algorithm>
27#include <sstream>
28
29namespace ns3 {
30
31Box::Box (double _xMin, double _xMax,
32 double _yMin, double _yMax,
33 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
57 position.x <= this->xMax && position.x >= this->xMin &&
58 position.y <= this->yMax && position.y >= this->yMin &&
59 position.z <= this->zMax && position.z >= this->zMin;
60}
61
63Box::GetClosestSide (const Vector &position) const
64{
65 double xMinDist = std::abs (position.x - this->xMin);
66 double xMaxDist = std::abs (this->xMax - position.x);
67 double yMinDist = std::abs (position.y - this->yMin);
68 double yMaxDist = std::abs (this->yMax - position.y);
69 double zMinDist = std::abs (position.z - this->zMin);
70 double zMaxDist = std::abs (this->zMax - position.z);
71 double minX = std::min (xMinDist, xMaxDist);
72 double minY = std::min (yMinDist, yMaxDist);
73 double minZ = std::min (zMinDist, zMaxDist);
74 if (minX < minY && minX < minZ)
75 {
76 if (xMinDist < xMaxDist)
77 {
78 return LEFT;
79 }
80 else
81 {
82 return RIGHT;
83 }
84 }
85 else if (minY < minZ)
86 {
87 if (yMinDist < yMaxDist)
88 {
89 return BOTTOM;
90 }
91 else
92 {
93 return TOP;
94 }
95 }
96 else
97 {
98 if (zMinDist < zMaxDist)
99 {
100 return DOWN;
101 }
102 else
103 {
104 return UP;
105 }
106 }
107}
108
109Vector
110Box::CalculateIntersection (const Vector &current, const Vector &speed) const
111{
112 NS_ASSERT (IsInside (current));
113 double xMaxY = current.y + (this->xMax - current.x) / speed.x * speed.y;
114 double xMinY = current.y + (this->xMin - current.x) / speed.x * speed.y;
115 double yMaxX = current.x + (this->yMax - current.y) / speed.y * speed.x;
116 double yMinX = current.x + (this->yMin - current.y) / speed.y * speed.x;
117 bool xMaxYOk = (xMaxY <= this->yMax && xMaxY >= this->yMin);
118 bool xMinYOk = (xMinY <= this->yMax && xMinY >= this->yMin);
119 bool yMaxXOk = (yMaxX <= this->xMax && yMaxX >= this->xMin);
120 bool yMinXOk = (yMinX <= this->xMax && yMinX >= this->xMin);
121 if (xMaxYOk && speed.x >= 0)
122 {
123 return Vector (this->xMax, xMaxY, 0.0);
124 }
125 else if (xMinYOk && speed.x <= 0)
126 {
127 return Vector (this->xMin, xMinY, 0.0);
128 }
129 else if (yMaxXOk && speed.y >= 0)
130 {
131 return Vector (yMaxX, this->yMax, 0.0);
132 }
133 else if (yMinXOk && speed.y <= 0)
134 {
135 return Vector (yMinX, this->yMin, 0.0);
136 }
137 else
138 {
139 NS_ASSERT (false);
140 // quiet compiler
141 return Vector (0.0, 0.0, 0.0);
142 }
143
144}
145
146bool
147Box::IsIntersect (const Vector &l1, const Vector &l2) const
148{
149 // If any of the position falls inside the box,
150 // return true.
151 if ((IsInside (l1) || IsInside (l2)))
152 {
153 return true;
154 }
155
156 Vector boxSize (0.5 * (this->xMax - this->xMin),
157 0.5 * (this->yMax - this->yMin),
158 0.5 * (this->zMax - this->zMin));
159 Vector boxCenter (this->xMin + boxSize.x,
160 this->yMin + boxSize.y,
161 this->zMin + boxSize.z);
162
163 // Put line-segment in box space
164 Vector lB1 (l1.x - boxCenter.x, l1.y - boxCenter.y, l1.z - boxCenter.z);
165 Vector lB2 (l2.x - boxCenter.x, l2.y - boxCenter.y, l2.z - boxCenter.z);
166
167 // Get line-segment midpoint and extent
168 Vector lMid (0.5 * (lB1.x + lB2.x), 0.5 * (lB1.y + lB2.y), 0.5 * (lB1.z + lB2.z));
169 Vector l (lB1.x - lMid.x, lB1.y - lMid.y, lB1.z - lMid.z);
170 Vector lExt (std::abs (l.x), std::abs (l.y), std::abs (l.z));
171
172 // Use Separating Axis Test
173 // Separation vector from box center to line-segment center is lMid, since the
174 // line is in box space, if any dimension of the line-segment did not intersect
175 // the box, return false, which means the whole line-segment didn't
176 // intersect the box.
177 if (std::abs (lMid.x) > boxSize.x + lExt.x)
178 {
179 return false;
180 }
181 if (std::abs (lMid.y) > boxSize.y + lExt.y)
182 {
183 return false;
184 }
185 if (std::abs (lMid.z) > boxSize.z + lExt.z)
186 {
187 return false;
188 }
189 // Cross-products of line and each axis
190 if (std::abs (lMid.y * l.z - lMid.z * l.y) > (boxSize.y * lExt.z + boxSize.z * lExt.y))
191 {
192 return false;
193 }
194 if (std::abs (lMid.x * l.z - lMid.z * l.x) > (boxSize.x * lExt.z + boxSize.z * lExt.x))
195 {
196 return false;
197 }
198 if (std::abs (lMid.x * l.y - lMid.y * l.x) > (boxSize.x * lExt.y + boxSize.y * lExt.x))
199 {
200 return false;
201 }
202
203 // No separating axis, the line-segment intersect this box, return true.
204 return true;
205}
206
208
216std::ostream &
217operator << (std::ostream &os, const Box &box)
218{
219 os << box.xMin << "|" << box.xMax << "|" << box.yMin << "|" << box.yMax << "|" << box.zMin << "|" << box.zMax;
220 return os;
221}
229std::istream &
230operator >> (std::istream &is, Box &box)
231{
232 char c1, c2, c3, c4, c5;
233 is >> box.xMin >> c1 >> box.xMax >> c2 >> box.yMin >> c3 >> box.yMax >> c4 >> box.zMin >> c5 >> box.zMax;
234 if (c1 != '|' ||
235 c2 != '|' ||
236 c3 != '|' ||
237 c4 != '|' ||
238 c5 != '|')
239 {
240 is.setstate (std::ios_base::failbit);
241 }
242 return is;
243}
244
245
246} // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
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:40
@ RIGHT
Definition: box.h:41
@ UP
Definition: box.h:45
@ DOWN
Definition: box.h:46
@ BOTTOM
Definition: box.h:44
@ LEFT
Definition: box.h:42
@ TOP
Definition: box.h:43
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:110
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:147
Side GetClosestSide(const Vector &position) const
Definition: box.cc:63
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:67
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:139
ATTRIBUTE_HELPER_CPP(Length)
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:162