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.
949 lines
24 KiB
949 lines
24 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 "pmlathe.h"
|
|
|
|
#include "pmxmlhelper.h"
|
|
#include "pmlatheedit.h"
|
|
#include "pmmemento.h"
|
|
#include "pmviewstructure.h"
|
|
#include "pm2dcontrolpoint.h"
|
|
#include "pmsplinememento.h"
|
|
#include "pmsplinesegment.h"
|
|
#include "pmdefaults.h"
|
|
#include "pmenumproperty.h"
|
|
#include "pmobjectaction.h"
|
|
|
|
#include <tdelocale.h>
|
|
|
|
const int defaultNumberOfPoints = 4;
|
|
const PMVector defaultPoint[defaultNumberOfPoints] =
|
|
{
|
|
PMVector( 0.0, 1.0 ),
|
|
PMVector( 0.5, 0.7 ),
|
|
PMVector( 0.5, 0.3 ),
|
|
PMVector( 0.0, 0.0 )
|
|
};
|
|
|
|
const bool defaultSturm = false;
|
|
const PMLathe::SplineType defaultSplineType = PMLathe::LinearSpline;
|
|
|
|
PMDefinePropertyClass( PMLathe, PMLatheProperty );
|
|
PMDefineEnumPropertyClass( PMLathe, PMLathe::SplineType, PMSplineTypeProperty );
|
|
|
|
PMMetaObject* PMLathe::s_pMetaObject = 0;
|
|
PMObject* createNewLathe( PMPart* part )
|
|
{
|
|
return new PMLathe( part );
|
|
}
|
|
|
|
class PMPointProperty : public PMPropertyBase
|
|
{
|
|
public:
|
|
PMPointProperty( )
|
|
: PMPropertyBase( "splinePoints", PMVariant::Vector )
|
|
{
|
|
m_index = 0;
|
|
}
|
|
virtual int dimensions( ) const { return 1; }
|
|
virtual void setIndex( int /*dimension*/, int index )
|
|
{
|
|
m_index = index;
|
|
}
|
|
virtual int size( PMObject* object, int /*dimension*/ ) const
|
|
{
|
|
return ( ( PMLathe* ) object )->numberOfPoints( );
|
|
}
|
|
protected:
|
|
virtual bool setProtected( PMObject* obj, const PMVariant& var )
|
|
{
|
|
PMLathe* p = ( PMLathe* ) obj;
|
|
TQValueList<PMVector> list = p->points( );
|
|
TQValueList<PMVector>::Iterator it = list.begin( );
|
|
int i;
|
|
PMVector v = var.vectorData( );
|
|
v.resize( 2 );
|
|
|
|
for( i = 0; i < m_index && it != list.end( ); ++i )
|
|
++it;
|
|
// expand the list if necessary
|
|
for( ; i < m_index; ++i )
|
|
list.insert( it, v );
|
|
if( it == list.end( ) )
|
|
it = list.insert( it, v );
|
|
else
|
|
*it = v;
|
|
|
|
p->setPoints( list );
|
|
return true;
|
|
}
|
|
virtual PMVariant getProtected( const PMObject* obj )
|
|
{
|
|
PMLathe* p = ( PMLathe* ) obj;
|
|
TQValueList<PMVector> list = p->points( );
|
|
TQValueList<PMVector>::ConstIterator it = list.at( m_index );
|
|
|
|
if( it == list.end( ) )
|
|
{
|
|
kdError( PMArea ) << "Range error in PMLathe::PointProperty::get" << endl;
|
|
return PMVariant( );
|
|
}
|
|
|
|
return PMVariant( *it );
|
|
}
|
|
|
|
private:
|
|
int m_index;
|
|
};
|
|
|
|
|
|
int PMLathe::s_rSteps = c_defaultLatheRSteps;
|
|
int PMLathe::s_sSteps = c_defaultLatheSSteps;
|
|
int PMLathe::s_parameterKey = 0;
|
|
|
|
PMLathe::PMLathe( PMPart* part )
|
|
: Base( part )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < defaultNumberOfPoints; ++i )
|
|
m_points.append( defaultPoint[i] );
|
|
m_splineType = defaultSplineType;
|
|
m_sturm = defaultSturm;
|
|
}
|
|
|
|
PMLathe::PMLathe( const PMLathe& l )
|
|
: Base( l )
|
|
{
|
|
m_points = l.m_points;
|
|
m_splineType = l.m_splineType;
|
|
m_sturm = l.m_sturm;
|
|
}
|
|
|
|
PMLathe::~PMLathe( )
|
|
{
|
|
}
|
|
|
|
TQString PMLathe::description( ) const
|
|
{
|
|
return i18n( "lathe" );
|
|
}
|
|
|
|
void PMLathe::serialize( TQDomElement& e, TQDomDocument& doc ) const
|
|
{
|
|
TQDomElement data = doc.createElement( "extra_data" );
|
|
TQDomElement p;
|
|
|
|
e.setAttribute( "spline_type", m_splineType );
|
|
e.setAttribute( "sturm", m_sturm );
|
|
|
|
TQValueList<PMVector>::ConstIterator it;
|
|
for( it = m_points.begin( ); it != m_points.end( ); ++it )
|
|
{
|
|
p = doc.createElement( "point" );
|
|
p.setAttribute( "vector", ( *it ).serializeXML( ) );
|
|
data.appendChild( p );
|
|
}
|
|
|
|
e.appendChild( data );
|
|
Base::serialize( e, doc );
|
|
}
|
|
|
|
void PMLathe::readAttributes( const PMXMLHelper& h )
|
|
{
|
|
m_splineType = ( SplineType ) h.intAttribute( "spline_type", defaultSplineType );
|
|
m_sturm = h.boolAttribute( "sturm", defaultSturm );
|
|
|
|
m_points.clear( );
|
|
PMVector v( 2 );
|
|
|
|
TQDomElement e = h.extraData( );
|
|
if( !e.isNull( ) )
|
|
{
|
|
TQDomNode c = e.firstChild( );
|
|
while( !c.isNull( ) )
|
|
{
|
|
if( c.isElement( ) )
|
|
{
|
|
TQDomElement ce = c.toElement( );
|
|
if( ce.tagName( ) == "point" )
|
|
{
|
|
TQString str = ce.attribute( "vector" );
|
|
if( !str.isNull( ) )
|
|
{
|
|
v.loadXML( str );
|
|
m_points.append( v );
|
|
}
|
|
}
|
|
}
|
|
c = c.nextSibling( );
|
|
}
|
|
}
|
|
|
|
Base::readAttributes( h );
|
|
}
|
|
|
|
PMMetaObject* PMLathe::metaObject( ) const
|
|
{
|
|
if( !s_pMetaObject )
|
|
{
|
|
s_pMetaObject = new PMMetaObject( "Lathe", Base::metaObject( ),
|
|
createNewLathe );
|
|
s_pMetaObject->addProperty(
|
|
new PMLatheProperty( "sturm", &PMLathe::setSturm, &PMLathe::sturm ) );
|
|
PMSplineTypeProperty* p = new PMSplineTypeProperty(
|
|
"splineType", &PMLathe::setSplineType, &PMLathe::splineType );
|
|
p->addEnumValue( "LinearSpline", LinearSpline );
|
|
p->addEnumValue( "QuadraticSpline", QuadraticSpline );
|
|
p->addEnumValue( "CubicSpline", CubicSpline );
|
|
p->addEnumValue( "BezierSpline", BezierSpline );
|
|
s_pMetaObject->addProperty( p );
|
|
s_pMetaObject->addProperty( new PMPointProperty( ) );
|
|
}
|
|
return s_pMetaObject;
|
|
}
|
|
|
|
void PMLathe::cleanUp( ) const
|
|
{
|
|
if( s_pMetaObject )
|
|
{
|
|
delete s_pMetaObject;
|
|
s_pMetaObject = 0;
|
|
}
|
|
Base::cleanUp( );
|
|
}
|
|
|
|
void PMLathe::setSplineType( PMLathe::SplineType t )
|
|
{
|
|
if( m_splineType != t )
|
|
{
|
|
if( m_pMemento )
|
|
m_pMemento->addData( s_pMetaObject, PMSplineTypeID, ( int ) m_splineType );
|
|
setViewStructureChanged( );
|
|
m_splineType = t;
|
|
}
|
|
}
|
|
|
|
void PMLathe::setSturm( bool s )
|
|
{
|
|
if( m_sturm != s )
|
|
{
|
|
if( m_pMemento )
|
|
m_pMemento->addData( s_pMetaObject, PMSturmID, m_sturm );
|
|
m_sturm = s;
|
|
}
|
|
}
|
|
|
|
void PMLathe::setPoints( const TQValueList<PMVector>& points )
|
|
{
|
|
if( m_points != points )
|
|
{
|
|
if( m_pMemento )
|
|
( ( PMSplineMemento* ) m_pMemento )->setSplinePoints( m_points );
|
|
|
|
setViewStructureChanged( );
|
|
m_points = points;
|
|
}
|
|
}
|
|
|
|
PMDialogEditBase* PMLathe::editWidget( TQWidget* parent ) const
|
|
{
|
|
return new PMLatheEdit( parent );
|
|
}
|
|
|
|
void PMLathe::createMemento( )
|
|
{
|
|
if( m_pMemento )
|
|
delete m_pMemento;
|
|
m_pMemento = new PMSplineMemento( this );
|
|
}
|
|
|
|
void PMLathe::restoreMemento( PMMemento* s )
|
|
{
|
|
PMSplineMemento* m = ( PMSplineMemento* ) s;
|
|
PMMementoDataIterator it( s );
|
|
PMMementoData* data;
|
|
|
|
for( ; it.current( ); ++it )
|
|
{
|
|
data = it.current( );
|
|
if( data->objectType( ) == s_pMetaObject )
|
|
{
|
|
switch( data->valueID( ) )
|
|
{
|
|
case PMSplineTypeID:
|
|
setSplineType( ( SplineType ) data->intData( ) );
|
|
break;
|
|
case PMSturmID:
|
|
setSturm( data->boolData( ) );
|
|
break;
|
|
default:
|
|
kdError( PMArea ) << "Wrong ID in PMLathe::restoreMemento\n";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if( m->splinePointsSaved( ) )
|
|
setPoints( m->splinePoints( ) );
|
|
|
|
Base::restoreMemento( s );
|
|
}
|
|
|
|
|
|
void PMLathe::createViewStructure( )
|
|
{
|
|
if( s_sSteps == 0 )
|
|
s_sSteps = c_defaultLatheSSteps;
|
|
if( s_rSteps == 0 )
|
|
s_rSteps = c_defaultLatheRSteps;
|
|
|
|
int rSteps = (int)( ( (float)s_rSteps / 2 ) * ( displayDetail( ) + 1 ) );
|
|
int sSteps = (int)( ( (float)s_sSteps / 2 ) * ( displayDetail( ) + 1 ) );
|
|
|
|
int np = m_points.count( );
|
|
int ns = 0;
|
|
int i, j, r, si;
|
|
|
|
// calculate number of segments
|
|
switch( m_splineType )
|
|
{
|
|
case LinearSpline:
|
|
ns = np - 1;
|
|
break;
|
|
case QuadraticSpline:
|
|
ns = np - 2;
|
|
break;
|
|
case CubicSpline:
|
|
ns = np - 3;
|
|
break;
|
|
case BezierSpline:
|
|
ns = np / 4;
|
|
break;
|
|
}
|
|
|
|
// calculate number of points and lines of the view structure
|
|
int vsp = 0;
|
|
if( m_splineType != BezierSpline )
|
|
vsp = ns * sSteps + 1;
|
|
else
|
|
vsp = ns * ( sSteps + 1 );
|
|
|
|
int vsl = 0;
|
|
if( m_splineType != BezierSpline )
|
|
vsl = ( 2 * vsp - 1 ) * rSteps;
|
|
else
|
|
vsl = ns * ( ( 2 * sSteps + 1 ) * rSteps );
|
|
|
|
vsp *= rSteps;
|
|
|
|
if( m_pViewStructure )
|
|
{
|
|
if( m_pViewStructure->points( ).size( ) != ( unsigned ) vsp )
|
|
m_pViewStructure->points( ).resize( vsp );
|
|
if( m_pViewStructure->lines( ).size( ) != ( unsigned ) vsl )
|
|
m_pViewStructure->lines( ).resize( vsl );
|
|
}
|
|
else
|
|
m_pViewStructure = new PMViewStructure( vsp, vsl );
|
|
|
|
|
|
// calculate the spline segments
|
|
TQValueList<PMSplineSegment> segments;
|
|
TQValueList<PMVector>::Iterator it1, it2, it3, it4;
|
|
it1 = m_points.begin( );
|
|
it2 = it1; ++it2;
|
|
it3 = it2; ++it3;
|
|
it4 = it3; ++it4;
|
|
PMSplineSegment s;
|
|
|
|
for( i = 0; i < ns; ++i )
|
|
{
|
|
switch( m_splineType )
|
|
{
|
|
case LinearSpline:
|
|
s.calculateLinear( *it1, *it2 );
|
|
++it1;
|
|
++it2;
|
|
break;
|
|
case QuadraticSpline:
|
|
s.calculateQuadratic( *it1, *it2, *it3 );
|
|
++it1;
|
|
++it2;
|
|
++it3;
|
|
break;
|
|
case CubicSpline:
|
|
s.calculateCubic( *it1, *it2, *it3, *it4 );
|
|
++it1;
|
|
++it2;
|
|
++it3;
|
|
++it4;
|
|
break;
|
|
case BezierSpline:
|
|
s.calculateBezier( *it1, *it2, *it3, *it4 );
|
|
for( j = 0; j < 4; ++j )
|
|
{
|
|
++it1;
|
|
++it2;
|
|
++it3;
|
|
++it4;
|
|
}
|
|
break;
|
|
}
|
|
segments.append( s );
|
|
}
|
|
|
|
// create the line array
|
|
if( m_splineType != BezierSpline )
|
|
{
|
|
PMLineArray& lines = m_pViewStructure->lines( );
|
|
int vl = ns * sSteps;
|
|
int lb = 0;
|
|
for( i = 0; i < vl + 1; ++i )
|
|
{
|
|
for( j = 0; j < rSteps - 1; ++j )
|
|
lines[lb+j] = PMLine( lb + j, lb + j + 1 );
|
|
lines[lb+rSteps-1] = PMLine( lb, lb + rSteps - 1 );
|
|
lb += rSteps;
|
|
}
|
|
int pi = 0;
|
|
for( i = 0; i < vl; ++i )
|
|
{
|
|
for( j = 0; j < rSteps; ++j )
|
|
{
|
|
lines[lb] = PMLine( pi, pi + rSteps );
|
|
++pi;
|
|
++lb;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PMLineArray& lines = m_pViewStructure->lines( );
|
|
int lb = 0;
|
|
int pi = 0;
|
|
|
|
for( si = 0; si < ns; ++si )
|
|
{
|
|
for( i = 0; i < sSteps + 1; ++i )
|
|
{
|
|
for( j = 0; j < rSteps - 1; ++j )
|
|
lines[lb+j] = PMLine( lb + j, lb + j + 1 );
|
|
lines[lb+rSteps-1] = PMLine( lb, lb + rSteps - 1 );
|
|
lb += rSteps;
|
|
}
|
|
}
|
|
for( si = 0; si < ns; ++si )
|
|
{
|
|
for( i = 0; i < sSteps; ++i )
|
|
{
|
|
for( j = 0; j < rSteps; ++j )
|
|
{
|
|
lines[lb] = PMLine( pi, pi + rSteps );
|
|
++pi;
|
|
++lb;
|
|
}
|
|
}
|
|
pi += rSteps;
|
|
}
|
|
}
|
|
// calculate the points
|
|
PMVector point2, point3;
|
|
TQValueList<PMSplineSegment>::Iterator sit = segments.begin( );
|
|
int pi = 0;
|
|
|
|
double poffset = 1.0 / sSteps;
|
|
PMMatrix rot = PMMatrix::rotation( 0.0, M_PI * 2.0 / rSteps, 0.0 );
|
|
PMPointArray& points = m_pViewStructure->points( );
|
|
|
|
if( m_splineType != BezierSpline )
|
|
{
|
|
for( i = 0; i < ns; ++i, ++sit )
|
|
{
|
|
for( j = 0; j < sSteps; ++j )
|
|
{
|
|
point2 = ( *sit ).point( poffset * j );
|
|
point3[0] = point2[0];
|
|
point3[1] = point2[1];
|
|
point3[2] = 0.0;
|
|
|
|
for( r = 0; r < rSteps; ++r )
|
|
{
|
|
points[pi] = PMPoint( point3 );
|
|
if( r != rSteps - 1 )
|
|
point3.transform( rot );
|
|
++pi;
|
|
}
|
|
}
|
|
if( i == ns - 1 )
|
|
{
|
|
point2 = ( *sit ).point( 1.0 );
|
|
point3[0] = point2[0];
|
|
point3[1] = point2[1];
|
|
point3[2] = 0.0;
|
|
|
|
for( r = 0; r < rSteps; ++r )
|
|
{
|
|
points[pi] = PMPoint( point3 );
|
|
if( r != rSteps - 1 )
|
|
point3.transform( rot );
|
|
++pi;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( i = 0; i < ns; ++i, ++sit )
|
|
{
|
|
for( j = 0; j < sSteps + 1; ++j )
|
|
{
|
|
point2 = ( *sit ).point( poffset * j );
|
|
point3[0] = point2[0];
|
|
point3[1] = point2[1];
|
|
point3[2] = 0.0;
|
|
|
|
for( r = 0; r < rSteps; ++r )
|
|
{
|
|
points[pi] = PMPoint( point3 );
|
|
if( r != rSteps - 1 )
|
|
point3.transform( rot );
|
|
++pi;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PMLathe::controlPoints( PMControlPointList& list )
|
|
{
|
|
TQValueList<PMVector>::Iterator it;
|
|
int i, d;
|
|
|
|
PM2DControlPoint* cp = 0;
|
|
TQPtrList<PM2DControlPoint> tmp[2];
|
|
|
|
for( d = 0; d < 2; ++d )
|
|
{
|
|
if( m_splineType != BezierSpline )
|
|
{
|
|
PM2DControlPoint* firstPoint = 0;
|
|
PM2DControlPoint* lastPoint = 0;
|
|
|
|
for( it = m_points.begin( ), i = 0; it != m_points.end( ); ++it, ++i )
|
|
{
|
|
lastPoint = cp;
|
|
if( d == 0 )
|
|
cp = new PM2DControlPoint( *it, PM2DControlPoint::PM2DXY, i,
|
|
i18n( "Point %1 (xy)" ).arg( i + 1 ) );
|
|
else
|
|
cp = new PM2DControlPoint( *it, PM2DControlPoint::PM2DZY, i,
|
|
i18n( "Point %1 (xy)" ).arg( i + 1 ) );
|
|
|
|
if( i == 0 )
|
|
firstPoint = cp;
|
|
if( ( i == 1 ) && ( m_splineType != LinearSpline ) )
|
|
firstPoint->setBasePoint( cp );
|
|
|
|
tmp[d].append( cp );
|
|
}
|
|
if( m_splineType == CubicSpline )
|
|
cp->setBasePoint( lastPoint );
|
|
}
|
|
else
|
|
{
|
|
PM2DControlPoint* helpPoint = 0;
|
|
|
|
for( it = m_points.begin( ), i = 0; it != m_points.end( ); ++it, ++i )
|
|
{
|
|
int imod4 = i % 4;
|
|
if( d == 0 )
|
|
cp = new PM2DControlPoint( *it, PM2DControlPoint::PM2DXY, i,
|
|
i18n( "Point %1 (xy)" ).arg( i + 1 ) );
|
|
else
|
|
cp = new PM2DControlPoint( *it, PM2DControlPoint::PM2DZY, i,
|
|
i18n( "Point %1 (xy)" ).arg( i + 1 ) );
|
|
switch( imod4 )
|
|
{
|
|
case 0:
|
|
helpPoint = cp;
|
|
break;
|
|
case 1:
|
|
cp->setBasePoint( helpPoint );
|
|
break;
|
|
case 2:
|
|
helpPoint = cp;
|
|
break;
|
|
case 3:
|
|
helpPoint->setBasePoint( cp );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
tmp[d].append( cp );
|
|
}
|
|
}
|
|
}
|
|
|
|
TQPtrListIterator<PM2DControlPoint> cit1( tmp[0] ), cit2( tmp[1] );
|
|
|
|
for( ; cit1.current( ) && cit2.current( ); ++cit1, ++cit2 )
|
|
{
|
|
( *cit1 )->setLatheLink( *cit2 );
|
|
( *cit2 )->setLatheLink( *cit1 );
|
|
}
|
|
for( cit1.toFirst( ); cit1.current( ); ++cit1 )
|
|
list.append( *cit1 );
|
|
for( cit2.toFirst( ); cit2.current( ); ++cit2 )
|
|
list.append( *cit2 );
|
|
}
|
|
|
|
void PMLathe::controlPointsChanged( PMControlPointList& list )
|
|
{
|
|
PMControlPointListIterator it1( list ), it2( list );
|
|
TQValueList<PMVector>::Iterator pit = m_points.begin( );
|
|
PM2DControlPoint* p1;
|
|
PM2DControlPoint* p2;
|
|
bool firstChange = true;
|
|
|
|
for( it2 += list.count( ) / 2; it2.current( ); ++it1, ++it2, ++pit )
|
|
{
|
|
p1 = ( PM2DControlPoint* ) it1.current( );
|
|
p2 = ( PM2DControlPoint* ) it2.current( );
|
|
|
|
if( p1->changed( ) )
|
|
{
|
|
if( firstChange )
|
|
{
|
|
if( m_pMemento )
|
|
{
|
|
PMSplineMemento* m = ( PMSplineMemento* ) m_pMemento;
|
|
if( !m->splinePointsSaved( ) )
|
|
m->setSplinePoints( m_points );
|
|
}
|
|
firstChange = false;
|
|
setViewStructureChanged( );
|
|
}
|
|
p2->setPoint( p1->point( ) );
|
|
( *pit ) = p1->point( );
|
|
}
|
|
else if( p2->changed( ) )
|
|
{
|
|
if( firstChange )
|
|
{
|
|
if( m_pMemento )
|
|
{
|
|
PMSplineMemento* m = ( PMSplineMemento* ) m_pMemento;
|
|
if( !m->splinePointsSaved( ) )
|
|
m->setSplinePoints( m_points );
|
|
}
|
|
firstChange = false;
|
|
setViewStructureChanged( );
|
|
}
|
|
p1->setPoint( p2->point( ) );
|
|
( *pit ) = p2->point( );
|
|
}
|
|
}
|
|
}
|
|
|
|
void PMLathe::addObjectActions( const PMControlPointList& /*cp*/,
|
|
TQPtrList<PMObjectAction>& actions )
|
|
{
|
|
PMObjectAction* a;
|
|
|
|
a = new PMObjectAction( s_pMetaObject, PMSplitSegmentID,
|
|
i18n( "Add Point" ) );
|
|
actions.append( a );
|
|
|
|
a = new PMObjectAction( s_pMetaObject, PMJoinSegmentsID,
|
|
i18n( "Remove Point" ) );
|
|
int np = m_points.count( );
|
|
int minp = 3;
|
|
switch( m_splineType )
|
|
{
|
|
case LinearSpline:
|
|
minp = 3;
|
|
break;
|
|
case QuadraticSpline:
|
|
minp = 4;
|
|
break;
|
|
case CubicSpline:
|
|
minp = 5;
|
|
break;
|
|
case BezierSpline:
|
|
minp = 8;
|
|
break;
|
|
}
|
|
|
|
if( np < minp )
|
|
a->setEnabled( false );
|
|
actions.append( a );
|
|
}
|
|
|
|
void PMLathe::objectActionCalled( const PMObjectAction* action,
|
|
const PMControlPointList& cp,
|
|
const TQPtrList<PMVector>& cpViewPosition,
|
|
const PMVector& clickPosition )
|
|
{
|
|
if( action->objectType( ) == s_pMetaObject )
|
|
{
|
|
switch( action->actionID( ) )
|
|
{
|
|
case PMSplitSegmentID:
|
|
splitSegment( cp, cpViewPosition, clickPosition );
|
|
break;
|
|
case PMJoinSegmentsID:
|
|
joinSegments( cp, cpViewPosition, clickPosition );
|
|
break;
|
|
default:
|
|
kdError( PMArea ) << "Wrong ID in PMLathe::objectActionCalled\n";
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
Base::objectActionCalled( action, cp, cpViewPosition, clickPosition );
|
|
}
|
|
|
|
void PMLathe::splitSegment( const PMControlPointList& /*cp*/,
|
|
const TQPtrList<PMVector>& cpViewPosition,
|
|
const PMVector& clickPosition )
|
|
{
|
|
// find nearest segment
|
|
int nump = cpViewPosition.count( ) / 2 - 1;
|
|
double abs = 0.0, minabs = 1e10;
|
|
int ns = -1;
|
|
int i, j;
|
|
PMVector mid( 3 ), dist( 2 );
|
|
|
|
TQPtrListIterator<PMVector> it1( cpViewPosition );
|
|
TQPtrListIterator<PMVector> it2( cpViewPosition );
|
|
++it2;
|
|
|
|
for( j = 0; j < 2; ++j )
|
|
{
|
|
for( i = 0; i < nump; ++i )
|
|
{
|
|
bool skip = false;
|
|
switch( m_splineType )
|
|
{
|
|
case LinearSpline:
|
|
case BezierSpline:
|
|
break;
|
|
case QuadraticSpline:
|
|
if( i == 0 )
|
|
skip = true;
|
|
break;
|
|
case CubicSpline:
|
|
if( ( i == 0 ) || ( i == ( nump - 1 ) ) )
|
|
skip = true;
|
|
break;
|
|
}
|
|
|
|
if( !skip )
|
|
{
|
|
mid = ( **it1 + **it2 ) / 2.0;
|
|
dist[0] = mid[0];
|
|
dist[1] = mid[1];
|
|
dist -= clickPosition;
|
|
abs = dist.abs( );
|
|
|
|
if( ( minabs > abs ) || ( ns < 0 ) )
|
|
{
|
|
minabs = abs;
|
|
ns = i;
|
|
}
|
|
}
|
|
++it1;
|
|
++it2;
|
|
}
|
|
++it1;
|
|
++it2;
|
|
}
|
|
|
|
// add a new segment
|
|
TQValueList<PMVector> newPoints = m_points;
|
|
|
|
if( m_splineType == BezierSpline )
|
|
{
|
|
ns /= 4;
|
|
ns *= 4;
|
|
}
|
|
TQValueList<PMVector>::Iterator it = newPoints.at( ( unsigned ) ns );
|
|
PMVector p[4];
|
|
TQValueList<PMVector>::Iterator hit = it;
|
|
|
|
// calculate the spline segment
|
|
PMSplineSegment segment;
|
|
switch( m_splineType )
|
|
{
|
|
case LinearSpline:
|
|
for( i = 0; i < 2; ++i, ++hit )
|
|
p[i] = *hit;
|
|
segment.calculateLinear( p[0], p[1] );
|
|
break;
|
|
case QuadraticSpline:
|
|
--hit;
|
|
for( i = 0; i < 3; ++i, ++hit )
|
|
p[i] = *hit;
|
|
segment.calculateQuadratic( p[0], p[1], p[2] );
|
|
break;
|
|
case CubicSpline:
|
|
--hit;
|
|
for( i = 0; i < 4; ++i, ++hit )
|
|
p[i] = *hit;
|
|
segment.calculateCubic( p[0], p[1], p[2], p[3] );
|
|
break;
|
|
case BezierSpline:
|
|
for( i = 0; i < 4; ++i, ++hit )
|
|
p[i] = *hit;
|
|
segment.calculateBezier( p[0], p[1], p[2], p[3] );
|
|
break;
|
|
}
|
|
|
|
mid = segment.point( 0.5 );
|
|
if( m_splineType != BezierSpline )
|
|
{
|
|
++it;
|
|
newPoints.insert( it, mid );
|
|
}
|
|
else
|
|
{
|
|
PMVector end = *it;
|
|
++it;
|
|
*it = end + ( *it - end ) / 2.0;
|
|
++it;
|
|
|
|
PMVector grad = segment.gradient( 0.5 ) / 4.0;
|
|
|
|
newPoints.insert( it, mid - grad );
|
|
newPoints.insert( it, mid );
|
|
newPoints.insert( it, mid );
|
|
newPoints.insert( it, mid + grad );
|
|
|
|
++it;
|
|
end = *it;
|
|
--it;
|
|
*it = end + ( *it - end ) / 2.0;
|
|
}
|
|
setPoints( newPoints );
|
|
}
|
|
|
|
void PMLathe::joinSegments( const PMControlPointList& /*cp*/,
|
|
const TQPtrList<PMVector>& cpViewPosition,
|
|
const PMVector& clickPosition )
|
|
{
|
|
// find nearest point
|
|
int nump = cpViewPosition.count( ) / 2;
|
|
int minp = 0;
|
|
|
|
switch( m_splineType )
|
|
{
|
|
case LinearSpline:
|
|
minp = 3;
|
|
break;
|
|
case QuadraticSpline:
|
|
minp = 4;
|
|
break;
|
|
case CubicSpline:
|
|
minp = 5;
|
|
break;
|
|
case BezierSpline:
|
|
minp = 8;
|
|
break;
|
|
}
|
|
|
|
if( nump < minp )
|
|
{
|
|
kdError( PMArea ) << "Not enough points in PMLathe::joinSegments\n";
|
|
return;
|
|
}
|
|
|
|
double abs = 0.0, minabs = 1e10;
|
|
int ns = -1;
|
|
int i, j;
|
|
PMVector* p;
|
|
PMVector dist( 2 );
|
|
|
|
TQPtrListIterator<PMVector> it1( cpViewPosition );
|
|
|
|
for( j = 0; j < 2; ++j )
|
|
{
|
|
for( i = 0; i < nump; ++i )
|
|
{
|
|
p = *it1;
|
|
dist[0] = (*p)[0];
|
|
dist[1] = (*p)[1];
|
|
dist -= clickPosition;
|
|
abs = dist.abs( );
|
|
|
|
if( ( minabs > abs ) || ( ns < 0 ) )
|
|
{
|
|
minabs = abs;
|
|
ns = i;
|
|
}
|
|
++it1;
|
|
}
|
|
}
|
|
|
|
// join two segments
|
|
TQValueList<PMVector> newPoints = m_points;
|
|
TQValueList<PMVector>::Iterator it;
|
|
|
|
if( m_splineType != BezierSpline )
|
|
{
|
|
// never remove the first or last point
|
|
if( ns == 0 )
|
|
++ns;
|
|
if( ns == ( nump - 1 ) )
|
|
--ns;
|
|
it = newPoints.at( ns );
|
|
newPoints.remove( it );
|
|
}
|
|
else
|
|
{
|
|
ns = ( ns - 2 ) / 4;
|
|
if( ns < 0 )
|
|
ns = 0;
|
|
if( ns >= ( nump / 4 - 1 ) )
|
|
ns = nump / 4 - 2;
|
|
|
|
it = newPoints.at( ns * 4 + 2 );
|
|
for( i = 0; i < 4; ++i )
|
|
it = newPoints.remove( it );
|
|
}
|
|
setPoints( newPoints );
|
|
}
|
|
|
|
void PMLathe::setRSteps( int r )
|
|
{
|
|
if( r >= 4 )
|
|
s_rSteps = r;
|
|
else
|
|
kdDebug( PMArea ) << "PMLathe::setRSteps: R must be greater than 3\n";
|
|
++s_parameterKey;
|
|
}
|
|
|
|
void PMLathe::setSSteps( int s )
|
|
{
|
|
if( s >= 1 )
|
|
s_sSteps = s;
|
|
else
|
|
kdDebug( PMArea ) << "PMLathe::setSSteps: S must be greater than 0\n";
|
|
++s_parameterKey;
|
|
}
|