You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
470 lines
13 KiB
470 lines
13 KiB
/*
|
|
**************************************************************************
|
|
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 <tdelocale.h>
|
|
|
|
const PMHeightField::HeightFieldType c_defaultType = PMHeightField::HFgif;
|
|
const TQString c_defaultTypeText = TQString( "gif" );
|
|
const TQString c_defaultFileName = TQString( "" );
|
|
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;
|
|
}
|
|
|
|
TQString PMHeightField::description( ) const
|
|
{
|
|
return i18n( "height field" );
|
|
}
|
|
|
|
void PMHeightField::serialize( TQDomElement& e, TQDomDocument& 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 TQString& 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( TQWidget* 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;
|
|
}
|
|
|
|
TQString PMHeightField::typeToString( PMHeightField::HeightFieldType t )
|
|
{
|
|
TQString s;
|
|
switch( t )
|
|
{
|
|
case HFgif:
|
|
s = TQString( "gif" );
|
|
break;
|
|
case HFtga:
|
|
s = TQString( "tga" );
|
|
break;
|
|
case HFpot:
|
|
s = TQString( "pot" );
|
|
break;
|
|
case HFpng:
|
|
s = TQString( "png" );
|
|
break;
|
|
case HFpgm:
|
|
s = TQString( "pgm" );
|
|
break;
|
|
case HFppm:
|
|
s = TQString( "ppm" );
|
|
break;
|
|
case HFsys:
|
|
s = TQString( "sys" );
|
|
break;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
PMHeightField::HeightFieldType PMHeightField::stringToType( const TQString &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( );
|
|
}
|