Wayne Stambaugh ede39780e2 Remove all debugging output that cannot be disabled.
The use of printf, wxLogDebug, and std::err/std::out causes excessive
debugging output which makes finding specific debugging messages more
difficult than it needs to be.

There is still some debugging output in test code that really needs to
be moved into a unit test.

Add debugging output section to the coding policy regarding debugging
output.
2020-08-18 10:17:36 -04:00

401 lines
10 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015-2017 Mario Luzeiro <mrluzeiro@ua.pt>
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file cbbox.cpp
* @brief Bounding Box class implementation
*/
#include "3d_fastmath.h"
#include "cbbox.h"
#include <cstdio>
#include <wx/debug.h> // For the wxASSERT
CBBOX::CBBOX()
{
Reset();
}
CBBOX::CBBOX( const SFVEC3F &aPbInit )
{
m_min = aPbInit;
m_max = aPbInit;
}
CBBOX::CBBOX( const SFVEC3F &aPbMin, const SFVEC3F &aPbMax )
{
Set( aPbMin, aPbMax );
}
CBBOX::~CBBOX()
{
}
void CBBOX::Set( const SFVEC3F &aPoint )
{
m_min = aPoint;
m_max = aPoint;
}
void CBBOX::Set( const SFVEC3F &aPbMin, const SFVEC3F &aPbMax )
{
m_min.x = fminf( aPbMin.x, aPbMax.x );
m_min.y = fminf( aPbMin.y, aPbMax.y );
m_min.z = fminf( aPbMin.z, aPbMax.z );
m_max.x = fmaxf( aPbMin.x, aPbMax.x );
m_max.y = fmaxf( aPbMin.y, aPbMax.y );
m_max.z = fmaxf( aPbMin.z, aPbMax.z );
}
void CBBOX::Set( const CBBOX &aBBox )
{
wxASSERT( aBBox.IsInitialized() );
Set( aBBox.Min(), aBBox.Max() );
}
bool CBBOX::IsInitialized() const
{
return !( ( FLT_MAX == m_min.x) ||
( FLT_MAX == m_min.y) ||
( FLT_MAX == m_min.z) ||
(-FLT_MAX == m_max.x) ||
(-FLT_MAX == m_max.y) ||
(-FLT_MAX == m_max.z) );
}
void CBBOX::Reset()
{
m_min = SFVEC3F( FLT_MAX, FLT_MAX, FLT_MAX );
m_max = SFVEC3F(-FLT_MAX,-FLT_MAX,-FLT_MAX );
}
void CBBOX::Union( const SFVEC3F &aPoint )
{
// get the minimun value between the added point and the existent bounding box
m_min.x = fminf( m_min.x, aPoint.x );
m_min.y = fminf( m_min.y, aPoint.y );
m_min.z = fminf( m_min.z, aPoint.z );
// get the maximun value between the added point and the existent bounding box
m_max.x = fmaxf( m_max.x, aPoint.x );
m_max.y = fmaxf( m_max.y, aPoint.y );
m_max.z = fmaxf( m_max.z, aPoint.z );
}
void CBBOX::Union( const CBBOX &aBBox )
{
wxASSERT( aBBox.IsInitialized() );
// get the minimun value between the added bounding box and the existent bounding box
m_min.x = fmin( m_min.x, aBBox.m_min.x );
m_min.y = fmin( m_min.y, aBBox.m_min.y );
m_min.z = fmin( m_min.z, aBBox.m_min.z );
// get the maximun value between the added bounding box and the existent bounding box
m_max.x = fmax( m_max.x, aBBox.m_max.x );
m_max.y = fmax( m_max.y, aBBox.m_max.y );
m_max.z = fmax( m_max.z, aBBox.m_max.z );
}
SFVEC3F CBBOX::GetCenter() const
{
return (m_max + m_min) * 0.5f;
}
float CBBOX::GetCenter( unsigned int aAxis ) const
{
wxASSERT( aAxis < 3 );
return (m_max[aAxis] + m_min[aAxis]) * 0.5f;
}
const SFVEC3F CBBOX::GetExtent() const
{
return m_max - m_min;
}
unsigned int CBBOX::MaxDimension() const
{
unsigned int result = 0;
SFVEC3F extent = GetExtent();
if( extent.y > extent.x )
result = 1;
if( extent.z > extent.y )
result = 2;
return result;
}
float CBBOX::GetMaxDimension() const
{
unsigned int max_dimensions_idx = 0;
SFVEC3F extent = GetExtent();
if( extent.y > extent.x )
max_dimensions_idx = 1;
if( extent.z > extent.y )
max_dimensions_idx = 2;
return extent[max_dimensions_idx];
}
float CBBOX::SurfaceArea() const
{
SFVEC3F extent = GetExtent();
return 2.0f * ( extent.x * extent.z +
extent.x * extent.y +
extent.y * extent.z );
}
void CBBOX::Scale( float aScale )
{
wxASSERT( IsInitialized() );
SFVEC3F scaleV = SFVEC3F( aScale, aScale, aScale );
SFVEC3F centerV = GetCenter();
m_min = (m_min - centerV) * scaleV + centerV;
m_max = (m_max - centerV) * scaleV + centerV;
}
void CBBOX::ScaleNextUp()
{
m_min.x = NextFloatDown( m_min.x );
m_min.y = NextFloatDown( m_min.y );
m_min.z = NextFloatDown( m_min.z );
m_max.x = NextFloatUp( m_max.x );
m_max.y = NextFloatUp( m_max.y );
m_max.z = NextFloatUp( m_max.z );
}
void CBBOX::ScaleNextDown()
{
m_min.x = NextFloatUp( m_min.x );
m_min.y = NextFloatUp( m_min.y );
m_min.z = NextFloatUp( m_min.z );
m_max.x = NextFloatDown( m_max.x );
m_max.y = NextFloatDown( m_max.y );
m_max.z = NextFloatDown( m_max.z );
}
bool CBBOX::Intersects( const CBBOX &aBBox ) const
{
wxASSERT( IsInitialized() );
wxASSERT( aBBox.IsInitialized() );
bool x = ( m_max.x >= aBBox.m_min.x ) && ( m_min.x <= aBBox.m_max.x );
bool y = ( m_max.y >= aBBox.m_min.y ) && ( m_min.y <= aBBox.m_max.y );
bool z = ( m_max.z >= aBBox.m_min.z ) && ( m_min.z <= aBBox.m_max.z );
return ( x && y && z );
}
bool CBBOX::Inside( const SFVEC3F &aPoint ) const
{
wxASSERT( IsInitialized() );
return (( aPoint.x >= m_min.x ) && ( aPoint.x <= m_max.x ) &&
( aPoint.y >= m_min.y ) && ( aPoint.y <= m_max.y ) &&
( aPoint.z >= m_min.z ) && ( aPoint.z <= m_max.z ));
}
float CBBOX::Volume() const
{
wxASSERT( IsInitialized() );
SFVEC3F extent = GetExtent();
return extent.x * extent.y * extent.z;
}
SFVEC3F CBBOX::Offset( const SFVEC3F &p ) const
{
return (p - m_min) / (m_max - m_min);
}
// Intersection code based on the book:
// "Physical Based Ray Tracing" (by Matt Pharr and Greg Humphrey)
// https://github.com/mmp/pbrt-v2/blob/master/src/core/geometry.cpp#L68
// /////////////////////////////////////////////////////////////////////////
#if 0
bool CBBOX::Intersect( const RAY &aRay, float *aOutHitt0, float *aOutHitt1 ) const
{
float t0 = 0.0f;
float t1 = FLT_MAX;
for( unsigned int i = 0; i < 3; ++i )
{
// Update interval for _i_th bounding box slab
float tNear = (m_min[i] - aRay.m_Origin[i]) * aRay.m_InvDir[i];
float tFar = (m_max[i] - aRay.m_Origin[i]) * aRay.m_InvDir[i];
// Update parametric interval from slab intersection
if( tNear > tFar )
{
// Swap
float ftemp = tNear;
tNear = tFar;
tFar = ftemp;
}
t0 = tNear > t0 ? tNear : t0;
t1 = tFar < t1 ? tFar : t1;
if( t0 > t1 )
return false;
}
if( aOutHitt0 )
*aOutHitt0 = t0;
if( aOutHitt1 )
*aOutHitt1 = t1;
return true;
}
#else
// https://github.com/mmp/pbrt-v2/blob/master/src/accelerators/bvh.cpp#L126
bool CBBOX::Intersect( const RAY &aRay,
float *aOutHitt0,
float *aOutHitt1 ) const
{
wxASSERT( aOutHitt0 );
wxASSERT( aOutHitt1 );
const SFVEC3F bounds[2] = {m_min, m_max};
// Check for ray intersection against x and y slabs
float tmin = (bounds[ aRay.m_dirIsNeg[0]].x - aRay.m_Origin.x) * aRay.m_InvDir.x;
float tmax = (bounds[1 - aRay.m_dirIsNeg[0]].x - aRay.m_Origin.x) * aRay.m_InvDir.x;
const float tymin = (bounds[ aRay.m_dirIsNeg[1]].y - aRay.m_Origin.y) * aRay.m_InvDir.y;
const float tymax = (bounds[1 - aRay.m_dirIsNeg[1]].y - aRay.m_Origin.y) * aRay.m_InvDir.y;
if( (tmin > tymax) || (tymin > tmax) )
return false;
tmin = (tymin > tmin)? tymin : tmin;
tmax = (tymax < tmax)? tymax : tmax;
// Check for ray intersection against z slab
const float tzmin = (bounds[ aRay.m_dirIsNeg[2]].z - aRay.m_Origin.z) * aRay.m_InvDir.z;
const float tzmax = (bounds[1 - aRay.m_dirIsNeg[2]].z - aRay.m_Origin.z) * aRay.m_InvDir.z;
if( (tmin > tzmax) || (tzmin > tmax) )
return false;
tmin = (tzmin > tmin)? tzmin : tmin;
tmin = ( tmin < 0.0f)? 0.0f : tmin;
tmax = (tzmax < tmax)? tzmax : tmax;
*aOutHitt0 = tmin;
*aOutHitt1 = tmax;
return true;
}
#endif
void CBBOX::ApplyTransformation( glm::mat4 aTransformMatrix )
{
wxASSERT( IsInitialized() );
const SFVEC3F v1 = SFVEC3F( aTransformMatrix *
glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) );
const SFVEC3F v2 = SFVEC3F( aTransformMatrix *
glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) );
Reset();
Union( v1 );
Union( v2 );
}
void CBBOX::ApplyTransformationAA( glm::mat4 aTransformMatrix )
{
wxASSERT( IsInitialized() );
// apply the transformation matrix for each of vertices of the bounding box
// and make a union with all vertices
CBBOX tmpBBox = CBBOX(
SFVEC3F( aTransformMatrix *
glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) ) );
tmpBBox.Union( SFVEC3F( aTransformMatrix *
glm::vec4( m_max.x, m_min.y, m_min.z, 1.0f ) ) );
tmpBBox.Union( SFVEC3F( aTransformMatrix *
glm::vec4( m_min.x, m_max.y, m_min.z, 1.0f ) ) );
tmpBBox.Union( SFVEC3F( aTransformMatrix *
glm::vec4( m_min.x, m_min.y, m_max.z, 1.0f ) ) );
tmpBBox.Union( SFVEC3F( aTransformMatrix *
glm::vec4( m_min.x, m_max.y, m_max.z, 1.0f ) ) );
tmpBBox.Union( SFVEC3F( aTransformMatrix *
glm::vec4( m_max.x, m_max.y, m_min.z, 1.0f ) ) );
tmpBBox.Union( SFVEC3F( aTransformMatrix *
glm::vec4( m_max.x, m_min.y, m_max.z, 1.0f ) ) );
tmpBBox.Union( SFVEC3F( aTransformMatrix *
glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) ) );
m_min = tmpBBox.m_min;
m_max = tmpBBox.m_max;
}
void CBBOX::debug() const
{
wxLogDebug( "min(%f, %f, %f) - max(%f, %f, %f)\n", m_min.x, m_min.y, m_min.z,
m_max.x, m_max.y, m_max.z );
}