/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015 Mario Luzeiro * Copyright (C) 1992-2015 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 "CBBox.h" // openGL includes used for debug the bounding box #ifdef __WXMAC__ # ifdef __DARWIN__ # include # else # include # endif #else # include #endif CBBOX::CBBOX() { Reset(); } CBBOX::CBBOX( const S3D_VERTEX &aPbInit ) { m_min = aPbInit; m_max = aPbInit; m_initialized = true; } CBBOX::CBBOX( const S3D_VERTEX &aPbMin, const S3D_VERTEX &aPbMax ) { Set( aPbMin, aPbMax ); } CBBOX::~CBBOX() { } void CBBOX::Set( const S3D_VERTEX &aPbMin, const S3D_VERTEX &aPbMax ) { m_min.x = glm::min( aPbMin.x, aPbMax.x ); m_min.y = glm::min( aPbMin.y, aPbMax.y ); m_min.z = glm::min( aPbMin.z, aPbMax.z ); m_max.x = glm::max( aPbMin.x, aPbMax.x ); m_max.y = glm::max( aPbMin.y, aPbMax.y ); m_max.z = glm::max( aPbMin.z, aPbMax.z ); m_initialized = true; } bool CBBOX::IsInitialized() const { return m_initialized; } void CBBOX::Reset() { m_min = S3D_VERTEX( 0.0f, 0.0f, 0.0f ); m_max = S3D_VERTEX( 0.0f, 0.0f, 0.0f ); m_initialized = false; } void CBBOX::Union( const S3D_VERTEX &aPoint ) { if( !m_initialized ) { m_initialized = true; // Initialize the bounding box with the given point m_min = aPoint; m_max = aPoint; } else { // get the minimun value between the added point and the existent bounding box m_min.x = glm::min( m_min.x, aPoint.x ); m_min.y = glm::min( m_min.y, aPoint.y ); m_min.z = glm::min( m_min.z, aPoint.z ); // get the maximun value between the added point and the existent bounding box m_max.x = glm::max( m_max.x, aPoint.x ); m_max.y = glm::max( m_max.y, aPoint.y ); m_max.z = glm::max( m_max.z, aPoint.z ); } } void CBBOX::Union( const CBBOX &aBBox ) { if( aBBox.m_initialized == false ) return; if( !m_initialized ) { // Initialize the bounding box with the given bounding box m_initialized = true; m_min = aBBox.m_min; m_max = aBBox.m_max; } else { // get the minimun value between the added bounding box and the existent bounding box m_min.x = glm::min( m_min.x, aBBox.m_min.x ); m_min.y = glm::min( m_min.y, aBBox.m_min.y ); m_min.z = glm::min( m_min.z, aBBox.m_min.z ); // get the maximun value between the added bounding box and the existent bounding box m_max.x = glm::max( m_max.x, aBBox.m_max.x ); m_max.y = glm::max( m_max.y, aBBox.m_max.y ); m_max.z = glm::max( m_max.z, aBBox.m_max.z ); } } S3D_VERTEX CBBOX::GetCenter() const { return (m_max + m_min) * 0.5f; } S3D_VERTEX CBBOX::Min() const { return m_min; } S3D_VERTEX CBBOX::Max() const { return m_max; } void CBBOX::Scale( float aScale ) { if( m_initialized == false ) return; S3D_VERTEX scaleV = S3D_VERTEX( aScale, aScale, aScale ); S3D_VERTEX centerV = GetCenter(); m_min = (m_min - centerV) * scaleV + centerV; m_max = (m_max - centerV) * scaleV + centerV; } bool CBBOX::OverlapsBox( const CBBOX &aBBox ) const { if( aBBox.m_initialized == false ) return false; 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 S3D_VERTEX &aPoint ) const { if( m_initialized == false ) return false; 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 { if( m_initialized == false ) return 0.0f; S3D_VERTEX d = m_max - m_min; return d.x * d.y * d.z; } void CBBOX::ApplyTransformation( glm::mat4 aTransformMatrix ) { if( m_initialized == false ) return; S3D_VERTEX v1 = S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) ); S3D_VERTEX v2 = S3D_VERTEX( 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 ) { if( m_initialized == false ) return; // apply the transformation matrix for each of vertices of the bounding box // and make a union with all vertices CBBOX tmpBBox = CBBOX( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_min.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_min.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_max.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_max.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_min.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_max.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( 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::GLdebug() const { if( m_initialized == false ) return; glBegin( GL_LINE_LOOP ); glVertex3f( m_min.x, m_min.y, m_min.z ); glVertex3f( m_max.x, m_min.y, m_min.z ); glVertex3f( m_max.x, m_max.y, m_min.z ); glVertex3f( m_min.x, m_max.y, m_min.z ); glEnd(); glBegin( GL_LINE_LOOP ); glVertex3f( m_min.x, m_min.y, m_max.z ); glVertex3f( m_max.x, m_min.y, m_max.z ); glVertex3f( m_max.x, m_max.y, m_max.z ); glVertex3f( m_min.x, m_max.y, m_max.z ); glEnd(); glBegin( GL_LINE_STRIP ); glVertex3f( m_min.x, m_min.y, m_min.z ); glVertex3f( m_min.x, m_min.y, m_max.z ); glEnd(); glBegin( GL_LINE_STRIP ); glVertex3f( m_max.x, m_min.y, m_min.z ); glVertex3f( m_max.x, m_min.y, m_max.z ); glEnd(); glBegin( GL_LINE_STRIP ); glVertex3f( m_max.x, m_max.y, m_min.z ); glVertex3f( m_max.x, m_max.y, m_max.z ); glEnd(); glBegin( GL_LINE_STRIP ); glVertex3f( m_min.x, m_max.y, m_min.z ); glVertex3f( m_min.x, m_max.y, m_max.z ); glEnd(); }