|
|
|
/*
|
|
|
|
**************************************************************************
|
|
|
|
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 "pmsqe.h"
|
|
|
|
|
|
|
|
#include "pmxmlhelper.h"
|
|
|
|
#include "pmsqeedit.h"
|
|
|
|
#include "pmmemento.h"
|
|
|
|
#include "pmviewstructure.h"
|
|
|
|
#include "pmdefaults.h"
|
|
|
|
#include "pmmath.h"
|
|
|
|
|
|
|
|
#include <klocale.h>
|
|
|
|
|
|
|
|
const double c_defaultEastWestExponent = 1.0;
|
|
|
|
const double c_defaultNorthSouthExponent = 1.0;
|
|
|
|
|
|
|
|
PMViewStructure* PMSuperquadricEllipsoid::s_pDefaultViewStructure = 0;
|
|
|
|
int PMSuperquadricEllipsoid::s_vStep = c_defaultSuperquadricEllipsoidVSteps;
|
|
|
|
int PMSuperquadricEllipsoid::s_uStep = c_defaultSuperquadricEllipsoidUSteps;
|
|
|
|
int PMSuperquadricEllipsoid::s_parameterKey = 0;
|
|
|
|
|
|
|
|
PMDefinePropertyClass( PMSuperquadricEllipsoid, PMSuperquadricEllipsoidProperty );
|
|
|
|
|
|
|
|
PMMetaObject* PMSuperquadricEllipsoid::s_pMetaObject = 0;
|
|
|
|
PMObject* createNewSuperquadricEllipsoid( PMPart* part )
|
|
|
|
{
|
|
|
|
return new PMSuperquadricEllipsoid( part );
|
|
|
|
}
|
|
|
|
|
|
|
|
PMSuperquadricEllipsoid::PMSuperquadricEllipsoid( PMPart* part )
|
|
|
|
: Base( part )
|
|
|
|
{
|
|
|
|
m_eastWestExponent = c_defaultEastWestExponent;
|
|
|
|
m_northSouthExponent = c_defaultNorthSouthExponent;
|
|
|
|
}
|
|
|
|
|
|
|
|
PMSuperquadricEllipsoid::PMSuperquadricEllipsoid( const PMSuperquadricEllipsoid& s )
|
|
|
|
: Base( s )
|
|
|
|
{
|
|
|
|
m_eastWestExponent = s.m_eastWestExponent;
|
|
|
|
m_northSouthExponent = s.m_northSouthExponent;
|
|
|
|
}
|
|
|
|
|
|
|
|
PMSuperquadricEllipsoid::~PMSuperquadricEllipsoid( )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString PMSuperquadricEllipsoid::description( ) const
|
|
|
|
{
|
|
|
|
return i18n( "superquadric ellipsoid" );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMSuperquadricEllipsoid::serialize( TQDomElement& e, TQDomDocument& doc ) const
|
|
|
|
{
|
|
|
|
e.setAttribute( "value_e", m_eastWestExponent );
|
|
|
|
e.setAttribute( "value_n", m_northSouthExponent );
|
|
|
|
Base::serialize( e, doc );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMSuperquadricEllipsoid::readAttributes( const PMXMLHelper& h )
|
|
|
|
{
|
|
|
|
m_eastWestExponent = h.doubleAttribute( "value_e", c_defaultEastWestExponent );
|
|
|
|
m_northSouthExponent = h.doubleAttribute( "value_n", c_defaultNorthSouthExponent );
|
|
|
|
Base::readAttributes( h );
|
|
|
|
}
|
|
|
|
|
|
|
|
PMMetaObject* PMSuperquadricEllipsoid::metaObject( ) const
|
|
|
|
{
|
|
|
|
if( !s_pMetaObject )
|
|
|
|
{
|
|
|
|
s_pMetaObject = new PMMetaObject( "SuperquadricEllipsoid", Base::metaObject( ),
|
|
|
|
createNewSuperquadricEllipsoid );
|
|
|
|
s_pMetaObject->addProperty(
|
|
|
|
new PMSuperquadricEllipsoidProperty( "eastWestExponent",
|
|
|
|
&PMSuperquadricEllipsoid::setEastWestExponent,
|
|
|
|
&PMSuperquadricEllipsoid::eastWestExponent ) );
|
|
|
|
s_pMetaObject->addProperty(
|
|
|
|
new PMSuperquadricEllipsoidProperty( "northSouthExponent",
|
|
|
|
&PMSuperquadricEllipsoid::setNorthSouthExponent,
|
|
|
|
&PMSuperquadricEllipsoid::northSouthExponent ) );
|
|
|
|
}
|
|
|
|
return s_pMetaObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMSuperquadricEllipsoid::setEastWestExponent( double e )
|
|
|
|
{
|
|
|
|
if( e != m_eastWestExponent )
|
|
|
|
{
|
|
|
|
if( m_pMemento )
|
|
|
|
m_pMemento->addData( s_pMetaObject, PMEastWestExponentID,
|
|
|
|
m_eastWestExponent );
|
|
|
|
if( e < 0.001 )
|
|
|
|
{
|
|
|
|
kdError( PMArea ) << "EastWestExponent < 0.001 in PMSuperquadricEllipsoid::setEastWestExponent\n";
|
|
|
|
e = 0.001;
|
|
|
|
}
|
|
|
|
m_eastWestExponent = e;
|
|
|
|
setViewStructureChanged( );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMSuperquadricEllipsoid::setNorthSouthExponent( double n )
|
|
|
|
{
|
|
|
|
if( n != m_northSouthExponent )
|
|
|
|
{
|
|
|
|
if( m_pMemento )
|
|
|
|
m_pMemento->addData( s_pMetaObject, PMNorthSouthExponentID,
|
|
|
|
m_northSouthExponent );
|
|
|
|
if( n < 0.001 )
|
|
|
|
{
|
|
|
|
kdError( PMArea ) << "NorthSouthExponent < 0.001 in PMSuperquadricEllipsoid::setNorthSouthExponent\n";
|
|
|
|
n = 0.001;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_northSouthExponent = n;
|
|
|
|
setViewStructureChanged( );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PMDialogEditBase* PMSuperquadricEllipsoid::editWidget( TQWidget* parent ) const
|
|
|
|
{
|
|
|
|
return new PMSuperquadricEllipsoidEdit( parent );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMSuperquadricEllipsoid::restoreMemento( PMMemento* s )
|
|
|
|
{
|
|
|
|
PMMementoDataIterator it( s );
|
|
|
|
PMMementoData* data;
|
|
|
|
|
|
|
|
for( ; it.current( ); ++it )
|
|
|
|
{
|
|
|
|
data = it.current( );
|
|
|
|
if( data->objectType( ) == s_pMetaObject )
|
|
|
|
{
|
|
|
|
switch( data->valueID( ) )
|
|
|
|
{
|
|
|
|
case PMEastWestExponentID:
|
|
|
|
setEastWestExponent( data->doubleData( ) );
|
|
|
|
break;
|
|
|
|
case PMNorthSouthExponentID:
|
|
|
|
setNorthSouthExponent( data->doubleData( ) );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
kdError( PMArea ) << "Wrong ID in PMSuperquadricEllipsoid::restoreMemento\n";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Base::restoreMemento( s );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool PMSuperquadricEllipsoid::isDefault( )
|
|
|
|
{
|
|
|
|
if( ( m_eastWestExponent == c_defaultEastWestExponent ) &&
|
|
|
|
( m_northSouthExponent == c_defaultNorthSouthExponent )
|
|
|
|
&& globalDetail( ) )
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMSuperquadricEllipsoid::createViewStructure( )
|
|
|
|
{
|
|
|
|
if( !m_pViewStructure )
|
|
|
|
{
|
|
|
|
m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
|
|
|
|
m_pViewStructure->points( ).detach( );
|
|
|
|
}
|
|
|
|
|
|
|
|
int uStep = (int)( ( (float)s_uStep / 2 ) * ( displayDetail( ) + 1 ) );
|
|
|
|
int vStep = (int)( ( (float)s_vStep / 2 ) * ( displayDetail( ) + 1 ) );
|
|
|
|
int uStep2 = uStep * 4;
|
|
|
|
int vStep2 = vStep * 8;
|
|
|
|
unsigned ptsSize = vStep2 * ( uStep2 - 1 ) + 2;
|
|
|
|
unsigned lineSize = vStep2 * ( uStep2 - 1 ) * 2 + vStep2;
|
|
|
|
|
|
|
|
if( ptsSize != m_pViewStructure->points( ).size( ) )
|
|
|
|
m_pViewStructure->points( ).resize( ptsSize );
|
|
|
|
|
|
|
|
createPoints( m_pViewStructure->points( ), m_eastWestExponent,
|
|
|
|
m_northSouthExponent, uStep, vStep );
|
|
|
|
|
|
|
|
if( lineSize != m_pViewStructure->lines( ).size( ) )
|
|
|
|
{
|
|
|
|
m_pViewStructure->lines( ).detach( );
|
|
|
|
m_pViewStructure->lines( ).resize( lineSize );
|
|
|
|
createLines( m_pViewStructure->lines( ), uStep2, vStep2 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PMViewStructure* PMSuperquadricEllipsoid::defaultViewStructure( ) const
|
|
|
|
{
|
|
|
|
if( !s_pDefaultViewStructure || s_pDefaultViewStructure->parameterKey( ) != viewStructureParameterKey( ) )
|
|
|
|
{
|
|
|
|
delete s_pDefaultViewStructure;
|
|
|
|
s_pDefaultViewStructure = 0;
|
|
|
|
int uStep = (int)( ( (float)s_uStep / 2 ) * ( globalDetailLevel( ) + 1 ) );
|
|
|
|
int vStep = (int)( ( (float)s_vStep / 2 ) * ( globalDetailLevel( ) + 1 ) );
|
|
|
|
|
|
|
|
// transform u and v steps to sphere u/v steps
|
|
|
|
int uStep2 = uStep * 4;
|
|
|
|
int vStep2 = vStep * 8;
|
|
|
|
|
|
|
|
s_pDefaultViewStructure =
|
|
|
|
new PMViewStructure( vStep2 * ( uStep2 - 1 ) + 2,
|
|
|
|
vStep2 * ( uStep2 - 1 ) * 2 + vStep2 );
|
|
|
|
|
|
|
|
// points
|
|
|
|
createPoints( s_pDefaultViewStructure->points( ),
|
|
|
|
c_defaultEastWestExponent, c_defaultNorthSouthExponent, uStep, vStep );
|
|
|
|
|
|
|
|
createLines( s_pDefaultViewStructure->lines( ), uStep2, vStep2 );
|
|
|
|
}
|
|
|
|
return s_pDefaultViewStructure;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMSuperquadricEllipsoid::createLines( PMLineArray& lines, int uStep, int vStep )
|
|
|
|
{
|
|
|
|
int u, v;
|
|
|
|
int offset = 0;
|
|
|
|
|
|
|
|
// horizontal lines
|
|
|
|
for( u = 0; u < ( uStep - 1 ); u++ )
|
|
|
|
{
|
|
|
|
for( v = 0; v < ( vStep - 1 ); v++ )
|
|
|
|
lines[offset + v] =
|
|
|
|
PMLine( u * vStep + v + 1, u * vStep + v + 2 );
|
|
|
|
lines[offset + vStep - 1] =
|
|
|
|
PMLine( u * vStep + 1, u * vStep + vStep );
|
|
|
|
|
|
|
|
offset += vStep;
|
|
|
|
}
|
|
|
|
|
|
|
|
// vertical lines
|
|
|
|
// lines at the "north pole"
|
|
|
|
for( v = 0; v < vStep; v++ )
|
|
|
|
lines[offset + v] = PMLine( 0, v + 1 );
|
|
|
|
offset += vStep;
|
|
|
|
|
|
|
|
for( v = 0; v < vStep; v++ )
|
|
|
|
{
|
|
|
|
for( u = 0; u < ( uStep - 2 ); u++ )
|
|
|
|
{
|
|
|
|
lines[offset + u] =
|
|
|
|
PMLine( u * vStep + v + 1, ( u + 1 ) * vStep + v + 1 );
|
|
|
|
}
|
|
|
|
offset += ( uStep - 2 );
|
|
|
|
}
|
|
|
|
// lines at the "south pole"
|
|
|
|
for( v = 0; v < vStep; v++ )
|
|
|
|
lines[offset + v] = PMLine( ( uStep - 2 ) * vStep + v + 1,
|
|
|
|
( uStep - 1 ) * vStep + 1 );
|
|
|
|
// offset += vStep;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMSuperquadricEllipsoid::createPoints( PMPointArray& points,
|
|
|
|
double e, double n, int uStep, int vStep )
|
|
|
|
{
|
|
|
|
int u, v;
|
|
|
|
int zi;
|
|
|
|
int pbase = 0, pref = 0;
|
|
|
|
|
|
|
|
if( e <= 0.001 )
|
|
|
|
e = 0.001;
|
|
|
|
if( n <= 0.001 )
|
|
|
|
n = 0.001;
|
|
|
|
|
|
|
|
double c2_e = 2.0 / e;
|
|
|
|
double c2_n = 2.0 / n;
|
|
|
|
double cn_2 = n / 2.0;
|
|
|
|
double ce_2 = e / 2.0;
|
|
|
|
double cn_e = n / e;
|
|
|
|
// double ce_n = e / n;
|
|
|
|
double z = 0.0, c = 0.0, a = 0.0, a2 = 0.0, x = 0.0, y = 0.0;
|
|
|
|
double k = 0.0, k2 = 0.0, du = 0.0, dv = 0.0;
|
|
|
|
PMPoint p;
|
|
|
|
|
|
|
|
points[0] = PMPoint( 0, 0, 1 );
|
|
|
|
pbase++;
|
|
|
|
|
|
|
|
for( zi = 0; zi < 2; zi++ )
|
|
|
|
{
|
|
|
|
for( u = 0; u < uStep; u++ )
|
|
|
|
{
|
|
|
|
du = ( double ) ( u + 1 ) / ( double ) uStep;
|
|
|
|
if( zi == 1 )
|
|
|
|
du = 1.0 - du;
|
|
|
|
k = tan( M_PI / 4.0 * pow( du, n < 1.0 ? n : sqrt( n ) ) );
|
|
|
|
k2 = 1 / ( pow( k, c2_n ) + 1 );
|
|
|
|
z = pow( k2, cn_2 );
|
|
|
|
if( zi == 1 )
|
|
|
|
z *= k;
|
|
|
|
c = pow( 1 - pow( z, c2_n ), cn_e );
|
|
|
|
|
|
|
|
for( v = 0; v < ( vStep + 1 ); v++ )
|
|
|
|
{
|
|
|
|
dv = ( double ) v / ( double ) vStep;
|
|
|
|
a = tan( M_PI / 4.0 * pow( dv, e < 1.0 ? e : sqrt( e ) ) );
|
|
|
|
a2 = 1 + pow( a, c2_e );
|
|
|
|
x = pow( c / a2, ce_2 );
|
|
|
|
y = x * a;
|
|
|
|
|
|
|
|
points[pbase+v] = PMPoint( x, y, z );
|
|
|
|
}
|
|
|
|
// 1/8
|
|
|
|
|
|
|
|
pref = pbase + 2 * vStep;
|
|
|
|
for( v = 0; v < vStep; v++, pref-- )
|
|
|
|
{
|
|
|
|
p = points[pbase+v];
|
|
|
|
x = p[0];
|
|
|
|
p[0] = p[1];
|
|
|
|
p[1] = x;
|
|
|
|
points[pref] = p;
|
|
|
|
}
|
|
|
|
// 1/4
|
|
|
|
|
|
|
|
pref = pbase + 4 * vStep;
|
|
|
|
for( v = 0; v < ( 2 * vStep ); v++, pref-- )
|
|
|
|
{
|
|
|
|
p = points[pbase+v];
|
|
|
|
p[0] = -p[0];
|
|
|
|
points[pref] = p;
|
|
|
|
}
|
|
|
|
// 1/2
|
|
|
|
|
|
|
|
pref = pbase + 8 * vStep - 1;
|
|
|
|
for( v = 1; v < ( 4 * vStep ); v++, pref-- )
|
|
|
|
{
|
|
|
|
p = points[pbase+v];
|
|
|
|
p[1] = -p[1];
|
|
|
|
points[pref] = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
pbase += 8 * vStep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for( u = 0; u < ( uStep * 2 - 1 ); u++ )
|
|
|
|
{
|
|
|
|
pbase = 1 + u * vStep * 8;
|
|
|
|
pref = 1 + ( uStep * 4 - 2 - u ) * vStep * 8;
|
|
|
|
|
|
|
|
for( v = 0; v < ( vStep * 8 ); v++, pref++ )
|
|
|
|
{
|
|
|
|
p = points[pbase + v];
|
|
|
|
p[2] = -p[2];
|
|
|
|
points[pref] = p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
points[ vStep * 8 * ( uStep * 4 - 1 ) + 1 ] = PMPoint( 0, 0, -1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMSuperquadricEllipsoid::setUSteps( int u )
|
|
|
|
{
|
|
|
|
if( u >= 2 )
|
|
|
|
{
|
|
|
|
s_uStep = u;
|
|
|
|
if( s_pDefaultViewStructure )
|
|
|
|
{
|
|
|
|
delete s_pDefaultViewStructure;
|
|
|
|
s_pDefaultViewStructure = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
kdDebug( PMArea ) << "PMSuperquadricEllipsoid::setUSteps: U must be greater than 1\n";
|
|
|
|
s_parameterKey++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMSuperquadricEllipsoid::setVSteps( int v )
|
|
|
|
{
|
|
|
|
if( v >= 2 )
|
|
|
|
{
|
|
|
|
s_vStep = v;
|
|
|
|
if( s_pDefaultViewStructure )
|
|
|
|
{
|
|
|
|
delete s_pDefaultViewStructure;
|
|
|
|
s_pDefaultViewStructure = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
kdDebug( PMArea ) << "PMSuperquadricEllipsoid::setVSteps: V must be greater than 1\n";
|
|
|
|
s_parameterKey++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMSuperquadricEllipsoid::cleanUp( ) const
|
|
|
|
{
|
|
|
|
if( s_pDefaultViewStructure )
|
|
|
|
delete s_pDefaultViewStructure;
|
|
|
|
s_pDefaultViewStructure = 0;
|
|
|
|
if( s_pMetaObject )
|
|
|
|
{
|
|
|
|
delete s_pMetaObject;
|
|
|
|
s_pMetaObject = 0;
|
|
|
|
}
|
|
|
|
Base::cleanUp( );
|
|
|
|
}
|