diff options
Diffstat (limited to 'kig/objects/cubic_imp.cc')
-rw-r--r-- | kig/objects/cubic_imp.cc | 437 |
1 files changed, 0 insertions, 437 deletions
diff --git a/kig/objects/cubic_imp.cc b/kig/objects/cubic_imp.cc deleted file mode 100644 index 7fb5ec63..00000000 --- a/kig/objects/cubic_imp.cc +++ /dev/null @@ -1,437 +0,0 @@ -// 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 "cubic_imp.h" - -#include "bogus_imp.h" - -#include "../misc/kigpainter.h" -#include "../misc/screeninfo.h" -#include "../misc/kignumerics.h" -#include "../misc/common.h" -#include "../kig/kig_view.h" - -#include <math.h> -#include <tdelocale.h> - -CubicImp::CubicImp( const CubicCartesianData& data ) - : CurveImp(), mdata( data ) -{ -} - -CubicImp::~CubicImp() -{ -} - -ObjectImp* CubicImp::transform( const Transformation& t ) const -{ - bool valid = true; - CubicCartesianData d = calcCubicTransformation( data(), t, valid ); - if ( valid ) return new CubicImp( d ); - else return new InvalidImp; -} - -void CubicImp::draw( KigPainter& p ) const -{ - p.drawCurve( this ); -} - -bool CubicImp::contains( const Coordinate& o, int width, const KigWidget& w ) const -{ - return internalContainsPoint( o, w.screenInfo().normalMiss( width ) ); -} - -bool CubicImp::inRect( const Rect&, int, const KigWidget& ) const -{ - // TODO ? - return false; -} - -CubicImp* CubicImp::copy() const -{ - return new CubicImp( mdata ); -} - -double CubicImp::getParam( const Coordinate& p, const KigDocument& ) const -{ - double x = p.x; - double y = p.y; - double t; - - double a000 = mdata.coeffs[0]; - double a001 = mdata.coeffs[1]; - double a002 = mdata.coeffs[2]; - double a011 = mdata.coeffs[3]; - double a012 = mdata.coeffs[4]; - double a022 = mdata.coeffs[5]; - double a111 = mdata.coeffs[6]; - double a112 = mdata.coeffs[7]; - double a122 = mdata.coeffs[8]; - double a222 = mdata.coeffs[9]; - - /* - * first project p onto the cubic. This is done by computing the - * line through p in the direction of the gradient - */ - - double f = a000 + a001*x + a002*y + a011*x*x + a012*x*y + a022*y*y + - a111*x*x*x + a112*x*x*y + a122*x*y*y + a222*y*y*y; - if ( f != 0 ) - { - double fx = a001 + 2*a011*x + a012*y + 3*a111*x*x + 2*a112*x*y + a122*y*y; - double fy = a002 + 2*a022*y + a012*x + 3*a222*y*y + 2*a122*x*y + a112*x*x; - Coordinate v = Coordinate (fx, fy); - if ( f < 0 ) v = -v; // the line points away from the intersection - double a, b, c, d; - calcCubicLineRestriction ( mdata, p, v, a, b, c, d ); - if ( a < 0 ) - { - a *= -1; - b *= -1; - c *= -1; - d *= -1; - } - - // computing the coefficients of the Sturm sequence - double p1a = 2*b*b - 6*a*c; - double p1b = b*c - 9*a*d; - double p0a = c*p1a*p1a + p1b*(3*a*p1b - 2*b*p1a); - // compute the number of roots for negative lambda - int variations = calcCubicVariations ( 0, a, b, c, d, p1a, p1b, p0a ); - bool valid; - int numroots; - double lambda = calcCubicRoot ( -1e10, 1e10, a, b, c, d, variations, valid, - numroots ); - if ( valid ) - { - Coordinate pnew = p + lambda*v; - x = pnew.x; - y = pnew.y; - } - } - - if (x > 0) t = x/(1+x); - else t = x/(1-x); - t = 0.5*(t + 1); - t /= 3; - - Coordinate p1 = getPoint ( t ); - Coordinate p2 = getPoint ( t + 1.0/3.0 ); - Coordinate p3 = getPoint ( t + 2.0/3.0 ); - - double mint = t; - double mindist = p1.valid() ? fabs ( y - p1.y ) : double_inf; - if ( p2.valid() && fabs ( y - p2.y ) < mindist ) - { - mint = t + 1.0/3.0; - mindist = fabs ( y - p2.y ); - } - if ( p3.valid() && fabs ( y - p3.y ) < mindist ) - { - mint = t + 2.0/3.0; - } - - return mint; -} - -const Coordinate CubicImp::getPoint( double p, const KigDocument& ) const -{ - return getPoint( p ); -} - -const Coordinate CubicImp::getPoint( double p ) const -{ - /* - * this isn't really elegant... - * the magnitude of p tells which one of the maximum 3 intersections - * of the vertical line with the cubic to take. - */ - - p *= 3; - int root = (int) p; - assert ( root >= 0 ); - assert ( root <= 3 ); - if ( root == 3 ) root = 2; - - p -= root; - - assert ( 0 <= p && p <= 1 ); - if ( p <= 0. ) p = 1e-6; - if ( p >= 1. ) p = 1 - 1e-6; - root++; - p = 2*p - 1; - double x; - if (p > 0) x = p/(1 - p); - else x = p/(1 + p); - - // calc the third degree polynomial: - // compute the third degree polinomial: -// double a000 = mdata.coeffs[0]; -// double a001 = mdata.coeffs[1]; -// double a002 = mdata.coeffs[2]; -// double a011 = mdata.coeffs[3]; -// double a012 = mdata.coeffs[4]; -// double a022 = mdata.coeffs[5]; -// double a111 = mdata.coeffs[6]; -// double a112 = mdata.coeffs[7]; -// double a122 = mdata.coeffs[8]; -// double a222 = mdata.coeffs[9]; -// -// // first the y^3 coefficient, it coming only from a222: -// double a = a222; -// // next the y^2 coefficient (from a122 and a022): -// double b = a122*x + a022; -// // next the y coefficient (from a112, a012 and a002): -// double c = a112*x*x + a012*x + a002; -// // finally the constant coefficient (from a111, a011, a001 and a000): -// double d = a111*x*x*x + a011*x*x + a001*x + a000; - -// commented out, since the bound is already computed when passing a huge -// interval; the normalization is not needed also - - // renormalize: positive a -// if ( a < 0 ) -// { -// a *= -1; -// b *= -1; -// c *= -1; -// d *= -1; -// } -// -// const double small = 1e-7; -// int degree = 3; -// if ( fabs(a) < small*fabs(b) || -// fabs(a) < small*fabs(c) || -// fabs(a) < small*fabs(d) ) -// { -// degree = 2; -// if ( fabs(b) < small*fabs(c) || -// fabs(b) < small*fabs(d) ) -// { -// degree = 1; -// } -// } - -// and a bound for all the real roots: - -// double bound; -// switch (degree) -// { -// case 3: -// bound = fabs(d/a); -// if ( fabs(c/a) + 1 > bound ) bound = fabs(c/a) + 1; -// if ( fabs(b/a) + 1 > bound ) bound = fabs(b/a) + 1; -// break; -// -// case 2: -// bound = fabs(d/b); -// if ( fabs(c/b) + 1 > bound ) bound = fabs(c/b) + 1; -// break; -// -// case 1: -// default: -// bound = fabs(d/c) + 1; -// break; -// } - - int numroots; - bool valid = true; - double y = calcCubicYvalue ( x, -double_inf, double_inf, root, mdata, valid, - numroots ); - if ( ! valid ) return Coordinate::invalidCoord(); - else return Coordinate(x,y); -// if ( valid ) return Coordinate(x,y); -// root--; if ( root <= 0) root += 3; -// y = calcCubicYvalue ( x, -bound, bound, root, mdata, valid, -// numroots ); -// if ( valid ) return Coordinate(x,y); -// root--; if ( root <= 0) root += 3; -// y = calcCubicYvalue ( x, -bound, bound, root, mdata, valid, -// numroots ); -// assert ( valid ); -// return Coordinate(x,y); -} - -const uint CubicImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 1; -} - -const QCStringList CubicImp::propertiesInternalNames() const -{ - QCStringList l = Parent::propertiesInternalNames(); - l << "cartesian-equation"; - assert( l.size() == CubicImp::numberOfProperties() ); - return l; - -} - -/* - * cartesian equation property contributed by Carlo Sardi - */ - -const QCStringList CubicImp::properties() const -{ - QCStringList l = Parent::properties(); - l << I18N_NOOP( "Cartesian Equation" ); - assert( l.size() == CubicImp::numberOfProperties() ); - return l; - -} - -const ObjectImpType* CubicImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else return CubicImp::stype(); -} - -const char* CubicImp::iconForProperty( uint which ) const -{ - int pnum = 0; - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - if ( which == Parent::numberOfProperties() + pnum++ ) - return "kig_text"; // cartesian equation string - else - assert( false ); - return ""; -} - -ObjectImp* CubicImp::property( uint which, const KigDocument& w ) const -{ - int pnum = 0; - - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, w ); - if ( which == Parent::numberOfProperties() + pnum++ ) - return new StringImp( cartesianEquationString( w ) ); - else - assert( false ); - return new InvalidImp; -} - -const CubicCartesianData CubicImp::data() const -{ - return mdata; -} - -void CubicImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -bool CubicImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( CubicImp::stype() ) && - static_cast<const CubicImp&>( rhs ).data() == data(); -} - -const ObjectImpType* CubicImp::type() const -{ - return CubicImp::stype(); -} - -const ObjectImpType* CubicImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "cubic", - I18N_NOOP( "cubic curve" ), - I18N_NOOP( "Select this cubic curve" ), - I18N_NOOP( "Select cubic curve %1" ), - I18N_NOOP( "Remove a Cubic Curve" ), - I18N_NOOP( "Add a Cubic Curve" ), - I18N_NOOP( "Move a Cubic Curve" ), - I18N_NOOP( "Attach to this cubic curve" ), - I18N_NOOP( "Show a Cubic Curve" ), - I18N_NOOP( "Hide a Cubic Curve" ) - ); - return &t; -} - -bool CubicImp::containsPoint( const Coordinate& p, const KigDocument& ) const -{ - return internalContainsPoint( p, test_threshold ); -} - -bool CubicImp::internalContainsPoint( const Coordinate& p, double threshold ) const -{ - double a000 = mdata.coeffs[0]; - double a001 = mdata.coeffs[1]; - double a002 = mdata.coeffs[2]; - double a011 = mdata.coeffs[3]; - double a012 = mdata.coeffs[4]; - double a022 = mdata.coeffs[5]; - double a111 = mdata.coeffs[6]; - double a112 = mdata.coeffs[7]; - double a122 = mdata.coeffs[8]; - double a222 = mdata.coeffs[9]; - - double x = p.x; - double y = p.y; - - double f = a000 + a001*x + a002*y + a011*x*x + a012*x*y + a022*y*y + - a111*x*x*x + a112*x*x*y + a122*x*y*y + a222*y*y*y; - double fx = a001 + 2*a011*x + a012*y + 3*a111*x*x + 2*a112*x*y + a122*y*y; - double fy = a002 + a012*x + 2*a022*y + a112*x*x + 2*a122*x*y + 3*a222*y*y; - - double dist = fabs(f)/(fabs(fx) + fabs(fy)); - - return dist <= threshold; -} - -bool CubicImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - return Parent::isPropertyDefinedOnOrThroughThisImp( which ); -} - -Rect CubicImp::surroundingRect() const -{ - // it's probably possible to calculate this if it exists, but for - // now we don't. - return Rect::invalidRect(); -} - -TQString CubicImp::cartesianEquationString( const KigDocument& ) const -{ - /* - * unfortunately TQStrings.arg method is limited to %1, %9, so we cannot - * treat all 10 arguments! Let's split the equation in two parts... - * Now this ends up also in the translation machinery, is this really - * necessary? Otherwise we could do a little bit of tidy up on the - * the equation (removal of zeros, avoid " ... + -1234 x ", etc.) - */ - - TQString ret = i18n( "%6 x³ + %9 y³ + %7 x²y + %8 xy² + %5 y² + %3 x² + %4 xy + %1 x + %2 y" ); - ret = ret.arg( mdata.coeffs[1], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[2], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[3], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[4], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[5], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[6], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[7], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[8], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[9], 0, 'g', 3 ); - - ret.append( i18n( " + %1 = 0" ) ); - ret = ret.arg( mdata.coeffs[0], 0, 'g', 3 ); - - // we should find a common place to do this... - ret.replace( "+ -", "- " ); - ret.replace( "+-", "-" ); - return ret; -} |