KiCad PCB EDA Suite
Loading...
Searching...
No Matches
bbox_3d.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2017 Mario Luzeiro <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
25#include "3d_fastmath.h"
26
27#include "bbox_3d.h"
28#include "../ray.h"
29#include <wx/log.h>
30#include <wx/debug.h> // For the wxASSERT
31
32
34{
35 Reset();
36}
37
38
39BBOX_3D::BBOX_3D( const SFVEC3F& aPbInit )
40{
41 m_min = aPbInit;
42 m_max = aPbInit;
43}
44
45
46BBOX_3D::BBOX_3D( const SFVEC3F& aPbMin, const SFVEC3F& aPbMax )
47{
48 Set( aPbMin, aPbMax );
49}
50
51
55
56
57void BBOX_3D::Set( const SFVEC3F& aPoint )
58{
59 m_min = aPoint;
60 m_max = aPoint;
61}
62
63
64void BBOX_3D::Set( const SFVEC3F& aPbMin, const SFVEC3F& aPbMax )
65{
66 m_min.x = fminf( aPbMin.x, aPbMax.x );
67 m_min.y = fminf( aPbMin.y, aPbMax.y );
68 m_min.z = fminf( aPbMin.z, aPbMax.z );
69
70 m_max.x = fmaxf( aPbMin.x, aPbMax.x );
71 m_max.y = fmaxf( aPbMin.y, aPbMax.y );
72 m_max.z = fmaxf( aPbMin.z, aPbMax.z );
73}
74
75
76void BBOX_3D::Set( const BBOX_3D& aBBox )
77{
78 wxASSERT( aBBox.IsInitialized() );
79
80 Set( aBBox.Min(), aBBox.Max() );
81}
82
83
85{
86 return !( ( FLT_MAX == m_min.x ) || ( FLT_MAX == m_min.y ) || ( FLT_MAX == m_min.z )
87 || ( -FLT_MAX == m_max.x ) || ( -FLT_MAX == m_max.y ) || ( -FLT_MAX == m_max.z ) );
88}
89
90
92{
93 m_min = SFVEC3F( FLT_MAX, FLT_MAX, FLT_MAX );
94 m_max = SFVEC3F( -FLT_MAX, -FLT_MAX, -FLT_MAX );
95}
96
97
98void BBOX_3D::Union( const SFVEC3F& aPoint )
99{
100 // get the minimum value between the added point and the existent bounding box
101 m_min.x = fminf( m_min.x, aPoint.x );
102 m_min.y = fminf( m_min.y, aPoint.y );
103 m_min.z = fminf( m_min.z, aPoint.z );
104
105 // get the maximum value between the added point and the existent bounding box
106 m_max.x = fmaxf( m_max.x, aPoint.x );
107 m_max.y = fmaxf( m_max.y, aPoint.y );
108 m_max.z = fmaxf( m_max.z, aPoint.z );
109}
110
111
112void BBOX_3D::Union( const BBOX_3D& aBBox )
113{
114 wxASSERT( aBBox.IsInitialized() );
115
116 // get the minimum value between the added bounding box and the existent bounding box
117 m_min.x = fmin( m_min.x, aBBox.m_min.x );
118 m_min.y = fmin( m_min.y, aBBox.m_min.y );
119 m_min.z = fmin( m_min.z, aBBox.m_min.z );
120
121 // get the maximum value between the added bounding box and the existent bounding box
122 m_max.x = fmax( m_max.x, aBBox.m_max.x );
123 m_max.y = fmax( m_max.y, aBBox.m_max.y );
124 m_max.z = fmax( m_max.z, aBBox.m_max.z );
125}
126
127
129{
130 return ( m_max + m_min ) * 0.5f;
131}
132
133
134float BBOX_3D::GetCenter( unsigned int aAxis ) const
135{
136 wxASSERT( aAxis < 3 );
137 return ( m_max[aAxis] + m_min[aAxis] ) * 0.5f;
138}
139
140
142{
143 return m_max - m_min;
144}
145
146
147unsigned int BBOX_3D::MaxDimension() const
148{
149 unsigned int result = 0;
150
151 SFVEC3F extent = GetExtent();
152
153 if( extent.y > extent.x )
154 result = 1;
155
156 if( extent.z > extent.y )
157 result = 2;
158
159 return result;
160}
161
162
164{
165 SFVEC3F extent = GetExtent();
166 return std::max( std::max( extent.x, extent.y ), extent.z );
167}
168
169
171{
172 SFVEC3F extent = GetExtent();
173
174 return 2.0f * ( extent.x * extent.z + extent.x * extent.y + extent.y * extent.z );
175}
176
177
178void BBOX_3D::Scale( float aScale )
179{
180 wxASSERT( IsInitialized() );
181
182 SFVEC3F scaleV = SFVEC3F( aScale, aScale, aScale );
183 SFVEC3F centerV = GetCenter();
184
185 m_min = ( m_min - centerV ) * scaleV + centerV;
186 m_max = ( m_max - centerV ) * scaleV + centerV;
187}
188
189
191{
192 m_min.x = NextFloatDown( m_min.x );
193 m_min.y = NextFloatDown( m_min.y );
194 m_min.z = NextFloatDown( m_min.z );
195
196 m_max.x = NextFloatUp( m_max.x );
197 m_max.y = NextFloatUp( m_max.y );
198 m_max.z = NextFloatUp( m_max.z );
199}
200
201
203{
204 m_min.x = NextFloatUp( m_min.x );
205 m_min.y = NextFloatUp( m_min.y );
206 m_min.z = NextFloatUp( m_min.z );
207
208 m_max.x = NextFloatDown( m_max.x );
209 m_max.y = NextFloatDown( m_max.y );
210 m_max.z = NextFloatDown( m_max.z );
211}
212
213
214bool BBOX_3D::Intersects( const BBOX_3D& aBBox ) const
215{
216 wxASSERT( IsInitialized() );
217 wxASSERT( aBBox.IsInitialized() );
218
219 bool x = ( m_max.x >= aBBox.m_min.x ) && ( m_min.x <= aBBox.m_max.x );
220 bool y = ( m_max.y >= aBBox.m_min.y ) && ( m_min.y <= aBBox.m_max.y );
221 bool z = ( m_max.z >= aBBox.m_min.z ) && ( m_min.z <= aBBox.m_max.z );
222
223 return ( x && y && z );
224}
225
226
227bool BBOX_3D::Inside( const SFVEC3F& aPoint ) const
228{
229 wxASSERT( IsInitialized() );
230
231 return ( aPoint.x >= m_min.x ) && ( aPoint.x <= m_max.x ) &&
232 ( aPoint.y >= m_min.y ) && ( aPoint.y <= m_max.y ) &&
233 ( aPoint.z >= m_min.z ) && ( aPoint.z <= m_max.z );
234}
235
236
237bool BBOX_3D::Inside( const BBOX_3D& aBBox ) const
238{
239 wxASSERT( IsInitialized() );
240 wxASSERT( aBBox.IsInitialized() );
241
242 return Inside( aBBox.Min() ) &&
243 Inside( aBBox.Max() );
244}
245
246
247float BBOX_3D::Volume() const
248{
249 wxASSERT( IsInitialized() );
250
251 SFVEC3F extent = GetExtent();
252
253 return extent.x * extent.y * extent.z;
254}
255
256
258{
259 return (p - m_min) / (m_max - m_min);
260}
261
262
263// https://github.com/mmp/pbrt-v2/blob/master/src/accelerators/bvh.cpp#L126
264bool BBOX_3D::Intersect( const RAY& aRay, float* aOutHitt0, float* aOutHitt1 ) const
265{
266 wxASSERT( aOutHitt0 );
267 wxASSERT( aOutHitt1 );
268
269 const SFVEC3F bounds[2] = {m_min, m_max};
270
271 // Check for ray intersection against x and y slabs
272 float tmin = ( bounds[aRay.m_dirIsNeg[0]].x - aRay.m_Origin.x ) * aRay.m_InvDir.x;
273 float tmax = ( bounds[1 - aRay.m_dirIsNeg[0]].x - aRay.m_Origin.x ) * aRay.m_InvDir.x;
274 const float tymin = ( bounds[aRay.m_dirIsNeg[1]].y - aRay.m_Origin.y ) * aRay.m_InvDir.y;
275 const float tymax = ( bounds[1 - aRay.m_dirIsNeg[1]].y - aRay.m_Origin.y ) * aRay.m_InvDir.y;
276
277 if( ( tmin > tymax ) || ( tymin > tmax ) )
278 return false;
279
280 tmin = ( tymin > tmin ) ? tymin : tmin;
281 tmax = ( tymax < tmax ) ? tymax : tmax;
282
283 // Check for ray intersection against z slab
284 const float tzmin = ( bounds[aRay.m_dirIsNeg[2]].z - aRay.m_Origin.z ) * aRay.m_InvDir.z;
285 const float tzmax = ( bounds[1 - aRay.m_dirIsNeg[2]].z - aRay.m_Origin.z ) * aRay.m_InvDir.z;
286
287 if( ( tmin > tzmax ) || ( tzmin > tmax ) )
288 return false;
289
290 tmin = ( tzmin > tmin ) ? tzmin : tmin;
291 tmin = ( tmin < 0.0f ) ? 0.0f : tmin;
292
293 tmax = ( tzmax < tmax ) ? tzmax : tmax;
294
295 *aOutHitt0 = tmin;
296 *aOutHitt1 = tmax;
297
298 return true;
299}
300
301
302void BBOX_3D::ApplyTransformation( glm::mat4 aTransformMatrix )
303{
304 wxASSERT( IsInitialized() );
305
306 const SFVEC3F v1 = SFVEC3F( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) );
307
308 const SFVEC3F v2 = SFVEC3F( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) );
309
310 Reset();
311 Union( v1 );
312 Union( v2 );
313}
314
315
Defines math related functions.
float NextFloatDown(float v)
float NextFloatUp(float v)
Bounding Box class definition.
void ScaleNextUp()
Scale a bounding box to the next float representation making it larger.
Definition bbox_3d.cpp:190
BBOX_3D()
Create with default values a bounding box (not initialized)
Definition bbox_3d.cpp:33
const SFVEC3F GetExtent() const
Definition bbox_3d.cpp:141
bool Intersect(const RAY &aRay, float *t) const
void Union(const SFVEC3F &aPoint)
Recalculate the bounding box adding a point.
Definition bbox_3d.cpp:98
SFVEC3F m_min
(12) point of the lower position of the bounding box
Definition bbox_3d.h:233
SFVEC3F GetCenter() const
Return the center point of the bounding box.
Definition bbox_3d.cpp:128
const SFVEC3F & Min() const
Return the minimum vertex pointer.
Definition bbox_3d.h:188
SFVEC3F Offset(const SFVEC3F &p) const
Definition bbox_3d.cpp:257
SFVEC3F m_max
(12) point of the higher position of the bounding box
Definition bbox_3d.h:234
const SFVEC3F & Max() const
Return the maximum vertex pointer.
Definition bbox_3d.h:195
void Set(const SFVEC3F &aPbMin, const SFVEC3F &aPbMax)
Set bounding box with new parameters.
Definition bbox_3d.cpp:64
void Reset()
Reset the bounding box to zero and de-initialize it.
Definition bbox_3d.cpp:91
void ApplyTransformation(glm::mat4 aTransformMatrix)
Apply a transformation matrix to the box points.
Definition bbox_3d.cpp:302
unsigned int MaxDimension() const
Definition bbox_3d.cpp:147
bool Intersects(const BBOX_3D &aBBox) const
Test if a bounding box intersects this box.
Definition bbox_3d.cpp:214
float SurfaceArea() const
Definition bbox_3d.cpp:170
float Volume() const
Calculate the volume of a bounding box.
Definition bbox_3d.cpp:247
float GetMaxDimension() const
Definition bbox_3d.cpp:163
void ScaleNextDown()
Scale a bounding box to the next float representation making it smaller.
Definition bbox_3d.cpp:202
~BBOX_3D()
Definition bbox_3d.cpp:52
bool IsInitialized() const
Check if this bounding box is already initialized.
Definition bbox_3d.cpp:84
bool Inside(const SFVEC3F &aPoint) const
Check if a point is inside this bounding box.
Definition bbox_3d.cpp:227
void Scale(float aScale)
Scales a bounding box by its center.
Definition bbox_3d.cpp:178
Definition ray.h:59
unsigned int m_dirIsNeg[3]
Definition ray.h:71
SFVEC3F m_InvDir
Definition ray.h:66
SFVEC3F m_Origin
Definition ray.h:60
VECTOR3I v1(5, 5, 5)
wxString result
Test unit parsing edge cases and error handling.
VECTOR2I v2(1, 0)
glm::vec3 SFVEC3F
Definition xv3d_types.h:40