diff options
Diffstat (limited to 'kig/objects/circle_imp.cpp')
-rw-r--r-- | kig/objects/circle_imp.cpp | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/kig/objects/circle_imp.cpp b/kig/objects/circle_imp.cpp new file mode 100644 index 00000000..16b3a5b7 --- /dev/null +++ b/kig/objects/circle_imp.cpp @@ -0,0 +1,356 @@ +// Copyright (C) 2003 Dominique Devriese <devriese@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. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include "circle_imp.h" + +#include "bogus_imp.h" +#include "point_imp.h" + +#include "../misc/kigtransform.h" +#include "../misc/kigpainter.h" +#include "../misc/coordinate_system.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_view.h" + +#include <tdelocale.h> + +#include <math.h> + +CircleImp::CircleImp( const Coordinate& center, double radius ) + : mcenter( center ), mradius( radius ) +{ +} + +CircleImp::~CircleImp() +{ +} + +ObjectImp* CircleImp::transform( const Transformation& t ) const +{ + if ( t.isHomothetic() ) + { + Coordinate nc = t.apply( mcenter ); + double nr = t.apply( mradius ); + if ( nc.valid() ) + return new CircleImp( nc, nr ); + else return new InvalidImp; + } + else + { + // domi: i should return a ConicImp here, but i don't know how to + // calculate it.. + return Parent::transform( t ); + }; +} + +void CircleImp::draw( KigPainter& p ) const +{ + p.drawCircle( mcenter, mradius ); +} + +bool CircleImp::contains( const Coordinate& p, int width, const KigWidget& w ) const +{ + return fabs((mcenter - p).length() - mradius) <= w.screenInfo().normalMiss( width ); +} + +bool CircleImp::inRect( const Rect& r, int width, const KigWidget& w ) const +{ + // first we check if the rect contains at least one of the + // north/south/east/west points of the circle + if ( r.contains( mcenter + Coordinate( 0, -mradius ) ) ) return true; + if ( r.contains( mcenter + Coordinate( mradius, 0 ) ) ) return true; + if ( r.contains( mcenter + Coordinate( 0, mradius ) ) ) return true; + if ( r.contains( mcenter + Coordinate( -mradius, 0 ) ) ) return true; + + // we allow a miss of some pixels .. + double miss = w.screenInfo().normalMiss( width ); + double bigradius = mradius + miss; + bigradius *= bigradius; + double smallradius = mradius - miss; + smallradius *= smallradius; + + const int in = -1; + const int undecided = 0; + const int out = 1; + + int inorout = undecided; + + Coordinate coords[4]; + coords[0] = r.topLeft(); + coords[1] = r.topRight(); + coords[2] = r.bottomRight(); + coords[3] = r.bottomLeft(); + + // we check if the corners of the rect are either + for ( Coordinate* i = coords; i < coords + 4; ++i ) + { + double t = ( *i - mcenter ).squareLength(); + if ( t >= bigradius ) + { + if ( inorout == in ) return true; + inorout = out; + } + else if ( t <= smallradius ) + { + if ( inorout == out ) return true; + inorout = in; + } + } + return inorout == undecided; +} + +bool CircleImp::valid() const +{ + return true; +} + +const uint CircleImp::numberOfProperties() const +{ + // We _intentionally_ do not use the Conic properties.. + return CurveImp::numberOfProperties() + 7; +} + +const QCStringList CircleImp::propertiesInternalNames() const +{ + QCStringList l = CurveImp::propertiesInternalNames(); + l << "surface"; + l << "circumference"; + l << "radius"; + l << "center"; + l << "cartesian-equation"; + l << "simply-cartesian-equation"; + l << "polar-equation"; + assert( l.size() == CircleImp::numberOfProperties() ); + return l; +} + +const QCStringList CircleImp::properties() const +{ + QCStringList l = CurveImp::properties(); + l << I18N_NOOP( "Surface" ); + l << I18N_NOOP( "Circumference" ); + l << I18N_NOOP( "Radius" ); + l << I18N_NOOP( "Center" ); + l << I18N_NOOP( "Expanded Cartesian Equation" ); + l << I18N_NOOP( "Cartesian Equation" ); + l << I18N_NOOP( "Polar Equation" ); + assert( l.size() == CircleImp::numberOfProperties() ); + return l; +} + +const ObjectImpType* CircleImp::impRequirementForProperty( uint which ) const +{ + if ( which < CurveImp::numberOfProperties() ) + return CurveImp::impRequirementForProperty( which ); + else return CircleImp::stype(); +} + +const char* CircleImp::iconForProperty( uint which ) const +{ + assert( which < CircleImp::numberOfProperties() ); + if ( which < CurveImp::numberOfProperties() ) + return CurveImp::iconForProperty( which ); + else if ( which == CurveImp::numberOfProperties() ) + return "areaCircle"; // surface + else if ( which == CurveImp::numberOfProperties() + 1 ) + return "circumference"; // circumference + else if ( which == CurveImp::numberOfProperties() + 2 ) + return ""; //radius + else if ( which == CurveImp::numberOfProperties() + 3 ) + return "baseCircle"; // circle center + else if ( which == CurveImp::numberOfProperties() + 4 ) + return "kig_text"; // cartesian equation + else if ( which == CurveImp::numberOfProperties() + 5 ) + return "kig_text"; // simply cartesian equation + else if ( which == CurveImp::numberOfProperties() + 6 ) + return "kig_text"; // polar equation + else assert( false ); + return ""; +} + +ObjectImp* CircleImp::property( uint which, const KigDocument& w ) const +{ + assert( which < CircleImp::numberOfProperties() ); + if ( which < CurveImp::numberOfProperties() ) + return CurveImp::property( which, w ); + if ( which == CurveImp::numberOfProperties() ) + return new DoubleImp( surface() ); + else if ( which == CurveImp::numberOfProperties() + 1 ) + return new DoubleImp( circumference() ); + else if ( which == CurveImp::numberOfProperties() + 2 ) + return new DoubleImp( radius() ); + else if ( which == CurveImp::numberOfProperties() + 3 ) + return new PointImp( center() ); + else if ( which == CurveImp::numberOfProperties() + 4 ) + return new StringImp( cartesianEquationString( w ) ); + else if ( which == CurveImp::numberOfProperties() + 5 ) + return new StringImp( simplyCartesianEquationString( w ) ); + else if ( which == CurveImp::numberOfProperties() + 6 ) + return new StringImp( polarEquationString( w ) ); + else assert( false ); + return new InvalidImp; +} + +const Coordinate CircleImp::center() const +{ + return mcenter; +} + +double CircleImp::radius() const +{ + return mradius; +} + +double CircleImp::surface() const +{ + return M_PI * squareRadius(); +} + +double CircleImp::squareRadius() const +{ + return mradius * mradius; +} + +double CircleImp::circumference() const +{ + return 2 * M_PI * radius(); +} + +TQString CircleImp::polarEquationString( const KigDocument& w ) const +{ + TQString ret = i18n( "rho = %1 [centered at %2]" ); + ConicPolarData data = polarData(); + ret = ret.arg( data.pdimen, 0, 'g', 3 ); + ret = ret.arg( w.coordinateSystem().fromScreen( data.focus1, w ) ); + return ret; +} + +TQString CircleImp::cartesianEquationString( const KigDocument& ) const +{ + TQString ret = i18n( "x² + y² + %1 x + %2 y + %3 = 0" ); + ConicCartesianData data = cartesianData(); + ret = ret.arg( data.coeffs[3], 0, 'g', 3 ); + ret = ret.arg( data.coeffs[4], 0, 'g', 3 ); + ret = ret.arg( data.coeffs[5], 0, 'g', 3 ); + return ret; +} + +TQString CircleImp::simplyCartesianEquationString( const KigDocument& ) const +{ + TQString ret = i18n( "( x - %1 )² + ( y - %2 )² = %3" ); + ret = ret.arg( mcenter.x, 0, 'g', 3 ); + ret = ret.arg( mcenter.y, 0, 'g', 3 ); + ret = ret.arg( mradius * mradius, 0, 'g', 3 ); + return ret; +} + +Coordinate CircleImp::focus1() const +{ + return center(); +} + +Coordinate CircleImp::focus2() const +{ + return center(); +} + +int CircleImp::conicType() const +{ + return 1; +} + +const ConicCartesianData CircleImp::cartesianData() const +{ + Coordinate c = center(); + double sqr = squareRadius(); + ConicCartesianData data( + 1.0, 1.0, 0.0, -2*c.x, -2*c.y, + c.x*c.x + c.y*c.y - sqr ); + return data; +} + +const ConicPolarData CircleImp::polarData() const +{ + return ConicPolarData( center(), radius(), 0, 0 ); +} + +CircleImp* CircleImp::copy() const +{ + return new CircleImp( mcenter, mradius ); +} + +double CircleImp::getParam( const Coordinate& point, const KigDocument& ) const +{ + Coordinate tmp = point - mcenter; + double ret = atan2(tmp.y, tmp.x) / ( 2 * M_PI ); + if ( ret > 0 ) return ret; + else return ret + 1; +} + +const Coordinate CircleImp::getPoint( double p, const KigDocument& ) const +{ + return mcenter + Coordinate (cos(p * 2 * M_PI), sin(p * 2 * M_PI)) * mradius; +} + +void CircleImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +bool CircleImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( CircleImp::stype() ) && + static_cast<const CircleImp&>( rhs ).center() == center() && + static_cast<const CircleImp&>( rhs ).radius() == radius(); +} + +const ObjectImpType* CircleImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "circle", + I18N_NOOP( "circle" ), + I18N_NOOP( "Select this circle" ), + I18N_NOOP( "Select circle %1" ), + I18N_NOOP( "Remove a Circle" ), + I18N_NOOP( "Add a Circle" ), + I18N_NOOP( "Move a Circle" ), + I18N_NOOP( "Attach to this circle" ), + I18N_NOOP( "Show a Circle" ), + I18N_NOOP( "Hide a Circle" ) + ); + return &t; +} + +const ObjectImpType* CircleImp::type() const +{ + return CircleImp::stype(); +} + +bool CircleImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + assert( which < CircleImp::numberOfProperties() ); + if ( which < CurveImp::numberOfProperties() ) + return CurveImp::isPropertyDefinedOnOrThroughThisImp( which ); + return false; +} + +Rect CircleImp::surroundingRect() const +{ + Coordinate d( mradius, mradius ); + return Rect( mcenter - d, mcenter + d ); +} |