/* $Id: areaitem.cpp,v 1.6 2005/12/10 15:59:12 chfreund Exp $ */ #include "areaitem.hpp" #include "global.hpp" /**********************************************************/ // setting attributes #define SATTR (Setting::COMMA_SEPARATED | \ Setting::EXPLICIT_ASSIGNMENT | \ Setting::CONFIG_FILE_ONLY) #define SATTRM (SATTR | Setting::MANDATORY) /**********************************************************/ const SettingDef AreaItem::m_SettingDef[NUM_AREAS+1] = { SettingDef("rectangles", NULL, Setting::STRING, 4, -1, SATTR), SettingDef("circles", NULL, Setting::STRING, 3, -1, SATTR), SettingDef() }; const char* AreaItem::m_IDStrings[NUM_AREAS] = { "RECTANGLE", "CIRCLE" }; /**********************************************************/ AreaItem::AreaItem() : m_AreaID(INVALID_AREA), m_x(0), m_y(0), m_width(0), m_height(0), m_radius(0) {} /**********************************************************/ AreaItem::AreaItem( const AreaItem &item ) : m_AreaID(item.m_AreaID), m_x(item.m_x), m_y(item.m_y), m_width(item.m_width), m_height(item.m_height), m_radius(item.m_radius) { } /**********************************************************/ AreaItem::AreaItem( const Sint32 ID, const Sint32 x, const Sint32 y, const Sint32 w, const Sint32 h ) : m_AreaID(ID), m_x(x), m_y(y), m_width(w), m_height(h), m_radius(0) {} /**********************************************************/ AreaItem::AreaItem( const Sint32 ID, const Sint32 x, const Sint32 y, const Sint32 r ) : m_AreaID(ID), m_x(x), m_y(y), m_width(0), m_height(0), m_radius(r) {} /**********************************************************/ AreaItem::~AreaItem() {} /**********************************************************/ real AreaItem::getContent() const { switch( m_AreaID ) { case RECTANGLE : return m_width * m_height; case CIRCLE : return M_PI * m_radius * m_radius; default : return 0; } } /**********************************************************/ void AreaItem::shift( const Sint32 dx, const Sint32 dy ) { m_x += dx; m_y += dy; } /**********************************************************/ bool AreaItem::isInside( const Sint32 x, const Sint32 y ) const { switch( m_AreaID ) { ////////////////////////////////////////// // RECTANGLE case RECTANGLE: { return m_x <= x && x <= m_x + m_width && m_y <= y && y <= m_y + m_height; } ////////////////////////////////////////// // CIRCLE case CIRCLE: { const Sint32 dx = x - m_x, dy = y - m_y; return dx*dx + dy*dy <= m_radius*m_radius; } } return false; } /**********************************************************/ bool AreaItem::touchesRect( const Sint32 x, const Sint32 y, const Sint32 w, const Sint32 h ) const { switch( m_AreaID ) { ////////////////////////////////////////// // RECTANGLE case RECTANGLE: { const Sint32 dx = x - m_x, dy = y - m_y; // THIS rectangle is on the right of the passed one if( dx >= 0 ) { if( dx >= m_width ) return false; // THIS rectangle is below the passed one if( dy <= 0 ) { if( -dy >= m_height ) return false; } else { if( dy >= h ) return false; } // THIS rectangle is on the left of the passed one } else { if( -dx >= w ) return false; // THIS rectangle is below the passed one if( dy <= 0 ) { if( -dy >= m_height ) return false; } else { if( dy >= h ) return false; } } return true; } ////////////////////////////////////////// // CIRCLE case CIRCLE: { Sint32 dx = 0, dy = 0; if( m_x <= x ) { dx = x - m_x; } else if( x + w <= m_x ) { dx = m_x - w - x; } // NOTE that in the third case (mx < x + w ) dx // would be 0, but this is the initial value of dx if( m_y >= y ) { dy = m_y - y; } else if( m_y <= y - h ) { dy = y - h - m_y; } return dx*dx + dy*dy <= m_radius * m_radius; } } // satisfy the compiler return false; } /**********************************************************/ bool AreaItem::readFromSettings( SettingDataBase &settings, Sint32 &pos ) { const char fn[] = "AreaItem::readFromSettings:"; Setting *setting = 0x0; // find the setting belonging to the position index "pos" Sint32 numParams = 0; m_AreaID = INVALID_AREA+1; while( m_AreaID < NUM_AREAS ) { setting = settings.getSetting( m_SettingDef[m_AreaID].m_IDString ); if( setting ) numParams += setting->getNumParameters(); if( pos < numParams ) break; m_AreaID++; } // should never happen, but we are paranoid DBG(1) ASSERT( INVALID_AREA < m_AreaID && m_AreaID < NUM_AREAS, "%s: could not map position %d to area ID\n", fn, pos ); // realPos is the current position in the current setting Sint32 realPos = pos - (numParams - setting->getNumParameters()); // load data. depending on the area type switch( m_AreaID ) { ////////////////////////////////////////// // RECTANGLE ////////////////////////////////////////// case RECTANGLE: { DBG(1) { ASSERT( realPos+4 <= setting->getNumParameters(), "%s only %d parameters left for a rectangle " "starting at position %d\n", fn, setting->getNumParameters() - realPos - 1, realPos ); } // read data m_x = atoi( setting->getString(realPos++) ); m_y = atoi( setting->getString(realPos++) ); m_width = atoi( setting->getString(realPos++) ); m_height = atoi( setting->getString(realPos++) ); pos += 4; break; } ////////////////////////////////////////// //// CIRCLE ////////////////////////////////////////// case CIRCLE: { DBG(1) { ASSERT( realPos+3 <= setting->getNumParameters(), "%s only %d parameters left for a circle " "starting at position %d\n", fn, setting->getNumParameters() - realPos - 1, realPos ); } // read data m_x = atoi( setting->getString(realPos++) ); m_y = atoi( setting->getString(realPos++) ); m_radius = atoi( setting->getString(realPos++) ); pos += 3; break; } default: ASSERT( false, "%s \"a thought occurs\", this should " "not happen\n", fn ); break; } LOG(4) INFO( "%s read area:\n %s: x:%d, y:%d, width:%d, " "height:%d, radius:%d\n", fn, getIDString(), m_x, m_y, m_width, m_height, m_radius ); // all areas from settings read? if( realPos >= setting->getNumParameters() ) { for( Sint32 i = m_AreaID+1; i < NUM_AREAS; i++ ) { if( settings.getSetting(m_SettingDef[i].m_IDString) ) { return true; } } pos = -1; } return true; } /**********************************************************/