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