diff options
Diffstat (limited to 'kpovmodeler/pmheightfield.cpp')
-rw-r--r-- | kpovmodeler/pmheightfield.cpp | 469 |
1 files changed, 469 insertions, 0 deletions
diff --git a/kpovmodeler/pmheightfield.cpp b/kpovmodeler/pmheightfield.cpp new file mode 100644 index 00000000..e729282a --- /dev/null +++ b/kpovmodeler/pmheightfield.cpp @@ -0,0 +1,469 @@ +/* +************************************************************************** + description + -------------------- + copyright : (C) 2002 by Andreas Zehender + email : zehender@kde.org +************************************************************************** + +************************************************************************** +* * +* 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. * +* * +**************************************************************************/ + + +#include "pmheightfield.h" + +#include "pmxmlhelper.h" +#include "pmheightfieldedit.h" +#include "pmheightfieldroam.h" +#include "pmmemento.h" +#include "pmviewstructure.h" +#include "pmenumproperty.h" +#include "pmdefaults.h" + +#include <klocale.h> + +const PMHeightField::HeightFieldType c_defaultType = PMHeightField::HFgif; +const QString c_defaultTypeText = QString( "gif" ); +const QString c_defaultFileName = QString( "" ); +const bool c_defaultHierarchy = true; +const bool c_defaultSmooth = false; +const double c_defaultWaterLevel = 0.0; + +PMDefinePropertyClass( PMHeightField, PMHeightFieldProperty ); +PMDefineEnumPropertyClass( PMHeightField, PMHeightField::HeightFieldType, + PMHeightFieldTypeProperty ); + + +int PMHeightField::s_variance = c_defaultHeightFieldVariance; +int PMHeightField::s_parameterKey = 0; + +PMViewStructure* PMHeightField::s_pDefaultViewStructure = 0; +PMMetaObject* PMHeightField::s_pMetaObject = 0; + +PMObject* createNewHeightField( PMPart* part ) +{ + return new PMHeightField( part ); +} + +PMHeightField::PMHeightField( PMPart* part ) + : Base( part ) +{ + m_hfType = c_defaultType; + m_fileName = c_defaultFileName; + m_hierarchy = c_defaultHierarchy; + m_smooth = c_defaultSmooth; + m_waterLevel = c_defaultWaterLevel; + + m_modMap = true; + m_pROAM = 0; +} + +PMHeightField::PMHeightField( const PMHeightField& f ) + : Base( f ) +{ + m_hfType = f.m_hfType; + m_fileName = f.m_fileName; + m_hierarchy = f.m_hierarchy; + m_smooth = f.m_smooth; + m_waterLevel = f.m_waterLevel; + + m_modMap = true; + m_pROAM = 0; +} + +PMHeightField::~PMHeightField( ) +{ + delete m_pROAM; +} + +QString PMHeightField::description( ) const +{ + return i18n( "height field" ); +} + +void PMHeightField::serialize( QDomElement& e, QDomDocument& doc ) const +{ + e.setAttribute( "hf_type", typeToString( m_hfType ) ); + e.setAttribute( "file_name", m_fileName ); + e.setAttribute( "hierarchy", m_hierarchy ); + e.setAttribute( "smooth", m_smooth ); + e.setAttribute( "water_level", m_waterLevel ); + Base::serialize( e, doc ); +} + +void PMHeightField::readAttributes( const PMXMLHelper& h ) +{ + m_hfType = stringToType( h.stringAttribute( "hf_type", c_defaultTypeText ) ); + m_fileName = h.stringAttribute( "file_name", c_defaultFileName ); + m_hierarchy = h.boolAttribute( "hierarchy", c_defaultHierarchy ); + m_smooth = h.boolAttribute( "smooth", c_defaultSmooth ); + m_waterLevel = h.doubleAttribute( "water_level", c_defaultWaterLevel ); + Base::readAttributes( h ); +} + +PMMetaObject* PMHeightField::metaObject( ) const +{ + if( !s_pMetaObject ) + { + s_pMetaObject = new PMMetaObject( "HeightField", Base::metaObject( ), + createNewHeightField ); + s_pMetaObject->addProperty( + new PMHeightFieldProperty( "fileName", &PMHeightField::setFileName, &PMHeightField::fileName ) ); + s_pMetaObject->addProperty( + new PMHeightFieldProperty( "hierarchy", &PMHeightField::setHierarchy, &PMHeightField::hierarchy ) ); + s_pMetaObject->addProperty( + new PMHeightFieldProperty( "smooth", &PMHeightField::setSmooth, &PMHeightField::smooth ) ); + s_pMetaObject->addProperty( + new PMHeightFieldProperty( "waterLevel", &PMHeightField::setWaterLevel, &PMHeightField::waterLevel ) ); + PMHeightFieldTypeProperty* p = + new PMHeightFieldTypeProperty( "heightFieldType", &PMHeightField::setHeightFieldType, + &PMHeightField::heightFieldType ); + p->addEnumValue( "Gif", HFgif ); + p->addEnumValue( "Tga", HFtga ); + p->addEnumValue( "Pot", HFpot ); + p->addEnumValue( "Png", HFpng ); + p->addEnumValue( "Pgm", HFpgm ); + p->addEnumValue( "Ppm", HFppm ); + p->addEnumValue( "Sys", HFsys ); + s_pMetaObject->addProperty( p ); + } + return s_pMetaObject; +} + +void PMHeightField::setHeightFieldType( PMHeightField::HeightFieldType t ) +{ + if( t != m_hfType ) + { + if( m_pMemento ) + m_pMemento->addData( s_pMetaObject, PMHeightFieldTypeID, m_hfType ); + m_hfType = t; + } +} + +void PMHeightField::setFileName( const QString& f ) +{ + if( f != m_fileName ) + { + if( m_pMemento ) + m_pMemento->addData( s_pMetaObject, PMFileNameID, m_fileName ); + m_fileName = f; + m_modMap = true; + setViewStructureChanged( ); + } +} + +void PMHeightField::setHierarchy( bool h ) +{ + if( h != m_hierarchy ) + { + if( m_pMemento ) + m_pMemento->addData( s_pMetaObject, PMHierarchyID, m_hierarchy ); + m_hierarchy = h; + } +} + +void PMHeightField::setSmooth( bool s ) +{ + if( s != m_smooth ) + { + if( m_pMemento ) + m_pMemento->addData( s_pMetaObject, PMSmoothID, m_smooth ); + m_smooth = s; + } +} + +void PMHeightField::setWaterLevel( double wl ) +{ + if( wl < 0.0 ) + { + kdError( PMArea ) << "Water level < 0.0 in PMHeightField::setWaterLevel\n"; + wl = 0.0; + } + if( wl > 1.0 ) + { + kdError( PMArea ) << "Water level > 1.0 in PMHeightField::setWaterLevel\n"; + wl = 1.0; + } + + if( wl != m_waterLevel ) + { + if( m_pMemento ) + m_pMemento->addData( s_pMetaObject, PMWaterLevelID, m_waterLevel ); + m_waterLevel = wl; + setViewStructureChanged( ); + } +} + +PMDialogEditBase* PMHeightField::editWidget( QWidget* parent ) const +{ + return new PMHeightFieldEdit( parent ); +} + +void PMHeightField::restoreMemento( PMMemento* s ) +{ + PMMementoDataIterator it( s ); + PMMementoData* data; + + for( ; it.current( ); ++it ) + { + data = it.current( ); + if( data->objectType( ) == s_pMetaObject ) + { + switch( data->valueID( ) ) + { + case PMHeightFieldTypeID: + m_hfType = ( HeightFieldType ) data->intData( ); + break; + case PMFileNameID: + m_fileName = data->stringData( ); + break; + case PMHierarchyID: + m_hierarchy = data->boolData( ); + break; + case PMSmoothID: + m_smooth = data->boolData( ); + break; + case PMWaterLevelID: + m_waterLevel = data->doubleData( ); + break; + default: + kdError( PMArea ) << "Wrong ID in PMHeightField::restoreMemento\n"; + break; + } + } + } + Base::restoreMemento( s ); +} + + +bool PMHeightField::isDefault( ) +{ + return ( m_waterLevel == c_defaultWaterLevel && m_fileName.isEmpty( ) ); +} + +void PMHeightField::createViewStructure( ) +{ + int detail = 65200 - ( ( s_variance * 163 ) * ( displayDetail( ) * displayDetail( ) ) ); + if ( m_modMap ) + { + m_modMap = false; + + if ( m_pROAM ) + { + delete m_pROAM; + m_pROAM = 0; + } + + if ( !m_fileName.isEmpty( ) ) + { + m_pROAM = new PMHeightFieldROAM( m_fileName ); + + if ( m_pROAM->isFailed( ) ) + { + delete m_pROAM; + m_pROAM = 0; + } + } + } + + if ( m_pROAM ) + { + m_pROAM->setDisplayDetail( detail ); + m_pROAM->setWaterLevel( m_waterLevel ); + m_pROAM->updateModel( ); + roamViewStructure( ); + return; + } + + if ( !m_pViewStructure ) + { + m_pViewStructure = new PMViewStructure( defaultViewStructure( ) ); + m_pViewStructure->points( ).detach( ); + m_pViewStructure->lines( ).detach( ); + } + else + { + m_pViewStructure->points( ).resize( + defaultViewStructure( )->points( ).size( ) ); + m_pViewStructure->lines( ).resize( + defaultViewStructure( )->lines( ).size( ) ); + } + + PMPointArray& points = m_pViewStructure->points( ); + + points[4][1] = m_waterLevel; + points[5][1] = m_waterLevel; + points[6][1] = m_waterLevel; + points[7][1] = m_waterLevel; +} + +void PMHeightField::roamViewStructure( ) +{ + if ( !m_pViewStructure ) + { + m_pViewStructure = new PMViewStructure( defaultViewStructure( ) ); + m_pViewStructure->points( ).detach( ); + m_pViewStructure->lines( ).detach( ); + } + + int x, z, i, pts; + int size = m_pROAM->size( ); + int currentLine = defaultViewStructure( )->lines( ).size( ); + int defPointsNum = defaultViewStructure( )->points( ).size( ); + double dx, dy, dz; + double sizeM1 = size - 1.0; + + m_pViewStructure->points( ).resize( m_pROAM->usedPoints( ) + defPointsNum ); + m_pViewStructure->lines( ).resize( m_pROAM->numLines( ) + currentLine ); + + PMPointArray& points = m_pViewStructure->points( ); + PMLineArray& lines = m_pViewStructure->lines( ); + + points[4][1] = m_waterLevel; + points[5][1] = m_waterLevel; + points[6][1] = m_waterLevel; + points[7][1] = m_waterLevel; + + for ( x = 0; x < size; ++x ) + { + dx = x / sizeM1; + for ( z = 0; z < size; ++z ) + { + dz = z / sizeM1; + if ( m_pROAM->usedPoint( x, z ) ) + { + pts = m_pROAM->posPoint( x, z ) + defPointsNum; + dy = m_pROAM->height( x, z, true ) / 65535.0; + points[ pts ] = PMPoint( dx, dy, dz ); + + for ( i = 0; m_pROAM->lineExist( x, z, i ) && i < 8; ++i ) + { + lines[ currentLine++ ] = + PMLine( pts, m_pROAM->endPoint( x, z, i ) + defPointsNum ); + } + } + } + } +} + +PMViewStructure* PMHeightField::defaultViewStructure( ) const +{ + if( !s_pDefaultViewStructure ) + { + s_pDefaultViewStructure = new PMViewStructure( 12, 16 ); + PMPointArray& points = s_pDefaultViewStructure->points( ); + PMLineArray& lines = s_pDefaultViewStructure->lines( ); + + points[ 0] = PMPoint( 0.0, 0.0, 0.0 ); + points[ 1] = PMPoint( 1.0, 0.0, 0.0 ); + points[ 2] = PMPoint( 1.0, 0.0, 1.0 ); + points[ 3] = PMPoint( 0.0, 0.0, 1.0 ); + points[ 4] = PMPoint( 0.0, c_defaultWaterLevel, 0.0 ); + points[ 5] = PMPoint( 1.0, c_defaultWaterLevel, 0.0 ); + points[ 6] = PMPoint( 1.0, c_defaultWaterLevel, 1.0 ); + points[ 7] = PMPoint( 0.0, c_defaultWaterLevel, 1.0 ); + points[ 8] = PMPoint( 0.0, 1.0, 0.0 ); + points[ 9] = PMPoint( 1.0, 1.0, 0.0 ); + points[10] = PMPoint( 1.0, 1.0, 1.0 ); + points[11] = PMPoint( 0.0, 1.0, 1.0 ); + + lines[ 0] = PMLine( 0, 1 ); + lines[ 1] = PMLine( 1, 2 ); + lines[ 2] = PMLine( 2, 3 ); + lines[ 3] = PMLine( 0, 3 ); + + lines[ 4] = PMLine( 0, 8 ); + lines[ 5] = PMLine( 1, 9 ); + lines[ 6] = PMLine( 2, 10 ); + lines[ 7] = PMLine( 3, 11 ); + + lines[ 8] = PMLine( 4, 5 ); + lines[ 9] = PMLine( 5, 6 ); + lines[10] = PMLine( 6, 7 ); + lines[11] = PMLine( 4, 7 ); + + lines[12] = PMLine( 8, 9 ); + lines[13] = PMLine( 9, 10 ); + lines[14] = PMLine( 10, 11 ); + lines[15] = PMLine( 8, 11 ); + } + return s_pDefaultViewStructure; +} + +QString PMHeightField::typeToString( PMHeightField::HeightFieldType t ) +{ + QString s; + switch( t ) + { + case HFgif: + s = QString( "gif" ); + break; + case HFtga: + s = QString( "tga" ); + break; + case HFpot: + s = QString( "pot" ); + break; + case HFpng: + s = QString( "png" ); + break; + case HFpgm: + s = QString( "pgm" ); + break; + case HFppm: + s = QString( "ppm" ); + break; + case HFsys: + s = QString( "sys" ); + break; + } + return s; +} + +PMHeightField::HeightFieldType PMHeightField::stringToType( const QString &str ) +{ + HeightFieldType t = HFgif; + if( str == "gif" ) + t = HFgif; + else if( str == "tga" ) + t = HFtga; + else if( str == "pot" ) + t = HFpot; + else if( str == "png" ) + t = HFpng; + else if( str == "pgm" ) + t = HFpgm; + else if( str == "ppm" ) + t = HFppm; + else if( str == "sys" ) + t = HFsys; + return t; +} + +void PMHeightField::setVariance( int v ) +{ + if( v < 52 && v > 0 ) + s_variance = v; + else + kdDebug( PMArea ) << "PMHeightField::setVariance: V must be less than 52 & greater than 0\n"; + s_parameterKey++; +} + +void PMHeightField::cleanUp( ) const +{ + if( s_pDefaultViewStructure ) + delete s_pDefaultViewStructure; + s_pDefaultViewStructure = 0; + if( s_pMetaObject ) + { + delete s_pMetaObject; + s_pMetaObject = 0; + } + Base::cleanUp( ); +} |