summaryrefslogtreecommitdiffstats
path: root/kpovmodeler/pmsqe.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kpovmodeler/pmsqe.cpp')
-rw-r--r--kpovmodeler/pmsqe.cpp413
1 files changed, 413 insertions, 0 deletions
diff --git a/kpovmodeler/pmsqe.cpp b/kpovmodeler/pmsqe.cpp
new file mode 100644
index 00000000..051aac72
--- /dev/null
+++ b/kpovmodeler/pmsqe.cpp
@@ -0,0 +1,413 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+**************************************************************************
+
+**************************************************************************
+* *
+* 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( )
+{
+}
+
+QString PMSuperquadricEllipsoid::description( ) const
+{
+ return i18n( "superquadric ellipsoid" );
+}
+
+void PMSuperquadricEllipsoid::serialize( QDomElement& e, QDomDocument& 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( QWidget* 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( );
+}