//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see .
//
//---------------------------------------------------------------------------
#include
#include "WQuadTree.h"
#include "WQuadNode.h"
const size_t WQuadNode::vX[] = {0, 1, 0, 1};
const size_t WQuadNode::vY[] = {0, 0, 1, 1};
WQuadNode::WQuadNode( double centerX, double centerY, double radius )
{
m_pointCount = 0;
m_id = 0;
m_xMin = m_xMax = m_yMin = m_yMax = m_valueMin = m_valueMax = 0;
m_center[0] = centerX;
m_center[1] = centerY;
this->m_radius = radius;
for ( size_t index = 0; index < 4; index++ )
m_child[index] = 0;
}
WQuadNode::~WQuadNode()
{
m_pointCount = 0;
for( size_t index = 0; index < 4; index++ )
delete m_child[index];
}
WQuadNode* WQuadNode::getChild( size_t drawer )
{
return m_child[ drawer ];
}
bool WQuadNode::fitsIn( double x, double y )
{
if ( x < m_center[0]-m_radius || x >= m_center[0]+m_radius )
return false;
if ( y < m_center[1]-m_radius || y >= m_center[1]+m_radius )
return false;
return true;
}
size_t WQuadNode::getFittingCase( double x, double y )
{
if ( !fitsIn( x, y ) )
return false;
size_t caseX = x < m_center[0] ?0 :1;
size_t caseY = y < m_center[1] ?0 :1;
size_t quad = 0;
while ( vX[quad] != caseX || vY[quad] != caseY )
quad++;
return quad;
}
void WQuadNode::expand()
{
for ( size_t quad = 0; quad < 4; quad++ )
{
if ( m_child[quad] != 0 )
{
size_t newCase = 0;
while ( vX[newCase] == vX[quad] || vY[newCase] == vY[quad] )
newCase++;
double centerX = ( static_cast( vX[quad] )*2.0 - 1.0 ) * m_radius + m_center[0];
double centerY = ( static_cast( vY[quad] )*2.0 - 1.0 ) * m_radius + m_center[1];
WQuadNode* newChild = new WQuadNode( centerX, centerY, m_radius );
newChild->setChild( m_child[quad], newCase );
setChild( newChild, quad );
}
}
m_radius *= 2.0;
}
void WQuadNode::touchNode( size_t drawer )
{
if ( m_child[drawer] == 0 )
{
double centerX = m_center[0] - m_radius*0.5 + static_cast( vX[drawer] )*m_radius;
double centerY = m_center[1] - m_radius*0.5 + static_cast( vY[drawer] )*m_radius;
m_child[drawer] = new WQuadNode( centerX, centerY, m_radius * 0.5 );
}
}
double WQuadNode::getRadius()
{
return m_radius;
}
double WQuadNode::getCenter( size_t dimension )
{
return m_center[dimension];
}
void WQuadNode::updateMinMax( double x, double y, double value )
{
if( !( m_pointCount > 0 ) )
{
m_xMin = m_xMax = x;
m_yMin = m_yMax = y;
m_valueMin = m_valueMax = value;
}
if( x < m_xMin ) m_xMin = x;
if( x > m_xMax ) m_xMax = x;
if( y < m_yMin ) m_yMin = y;
if( y > m_yMax ) m_yMax = y;
if( value < m_valueMin ) m_valueMin = value;
if( value > m_valueMax ) m_valueMax = value;
m_pointCount++;
}
void WQuadNode::setChild( WQuadNode* child, size_t drawer )
{
m_child[drawer] = child;
}
size_t WQuadNode::getPointCount()
{
return m_pointCount;
}
double WQuadNode::getXMin()
{
return m_xMin;
}
double WQuadNode::getXMax()
{
return m_xMax;
}
double WQuadNode::getYMin()
{
return m_yMin;
}
double WQuadNode::getYMax()
{
return m_yMax;
}
double WQuadNode::getValueMin()
{
return m_valueMin;
}
double WQuadNode::getValueMax()
{
return m_valueMax;
}
size_t WQuadNode::getID()
{
return m_id;
}
void WQuadNode::setID( size_t id )
{
m_id = id;
}