// Copyright (C) 2003 Dominique Devriese // 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 "conic_types.h" #include "bogus_imp.h" #include "conic_imp.h" #include "point_imp.h" #include "circle_imp.h" #include "line_imp.h" #include "object_calcer.h" #include "../misc/conic-common.h" #include "../misc/common.h" #include "../kig/kig_commands.h" #include "../kig/kig_part.h" #include static const char conic_constructstatement[] = I18N_NOOP( "Construct a conic through this point" ); static const struct ArgsParser::spec argsspecConicB5P[] = { { PointImp::stype(), conic_constructstatement, I18N_NOOP( "Select a point for the new conic to go through..." ), true }, { PointImp::stype(), conic_constructstatement, I18N_NOOP( "Select a point for the new conic to go through..." ), true }, { PointImp::stype(), conic_constructstatement, I18N_NOOP( "Select a point for the new conic to go through..." ), true }, { PointImp::stype(), conic_constructstatement, I18N_NOOP( "Select a point for the new conic to go through..." ), true }, { PointImp::stype(), conic_constructstatement, I18N_NOOP( "Select a point for the new conic to go through..." ),true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicB5PType ) ConicB5PType::ConicB5PType() : ArgsParserObjectType( "ConicB5P", argsspecConicB5P, 5 ) { } ConicB5PType::~ConicB5PType() { } ObjectImp* ConicB5PType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents, 1 ) ) return new InvalidImp; std::vector points; for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) points.push_back( static_cast( *i )->coordinate() ); ConicCartesianData d = calcConicThroughPoints( points, zerotilt, parabolaifzt, ysymmetry ); if ( d.valid() ) return new ConicImpCart( d ); else return new InvalidImp; } const ConicB5PType* ConicB5PType::instance() { static const ConicB5PType t; return &t; } static const ArgsParser::spec argsspecConicBAAP[] = { { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this asymptote" ), I18N_NOOP( "Select the first asymptote of the new conic..." ), false }, { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this asymptote" ), I18N_NOOP( "Select the second asymptote of the new conic..." ), false }, { PointImp::stype(), I18N_NOOP( "Construct a conic through this point" ), I18N_NOOP( "Select a point for the new conic to go through..." ), true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicBAAPType ) ConicBAAPType::ConicBAAPType() : ArgsParserObjectType( "ConicBAAP", argsspecConicBAAP, 3 ) { } ConicBAAPType::~ConicBAAPType() { } const ConicBAAPType* ConicBAAPType::instance() { static const ConicBAAPType t; return &t; } ObjectImp* ConicBAAPType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; const LineData la = static_cast( parents[0] )->data(); const LineData lb = static_cast( parents[1] )->data(); const Coordinate c = static_cast( parents[2] )->coordinate(); return new ConicImpCart( calcConicByAsymptotes( la, lb, c ) ); } ObjectImp* ConicBFFPType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; std::vector cs; for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) cs.push_back( static_cast( *i )->coordinate() ); return new ConicImpPolar( calcConicBFFP( cs, type() ) ); } ConicBFFPType::ConicBFFPType( const char* fullname, const ArgsParser::spec* spec, int n ) : ArgsParserObjectType( fullname, spec, n ) { } ConicBFFPType::~ConicBFFPType() { } static const char constructellipsewithfocusstat[] = I18N_NOOP( "Construct an ellipse with this focus" ); static const ArgsParser::spec argsspecEllipseBFFP[] = { { PointImp::stype(), constructellipsewithfocusstat, I18N_NOOP( "Select the first focus of the new ellipse..." ), false }, { PointImp::stype(), constructellipsewithfocusstat, I18N_NOOP( "Select the second focus of the new ellipse..." ), false }, { PointImp::stype(), I18N_NOOP( "Construct an ellipse through this point" ), I18N_NOOP( "Select a point for the new ellipse to go through..." ), true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( EllipseBFFPType ) EllipseBFFPType::EllipseBFFPType() : ConicBFFPType( "EllipseBFFP", argsspecEllipseBFFP, 3 ) { } EllipseBFFPType::~EllipseBFFPType() { } int EllipseBFFPType::type() const { return 1; } const EllipseBFFPType* EllipseBFFPType::instance() { static const EllipseBFFPType t; return &t; } static const char constructhyperbolawithfocusstat[] = I18N_NOOP( "Construct a hyperbola with this focus" ); static const ArgsParser::spec argsspecHyperbolaBFFP[] = { { PointImp::stype(), constructhyperbolawithfocusstat, I18N_NOOP( "Select the first focus of the new hyperbola..." ), false }, { PointImp::stype(), constructhyperbolawithfocusstat, I18N_NOOP( "Select the second focus of the new hyperbola..." ), false }, { PointImp::stype(), I18N_NOOP( "Construct a hyperbola through this point" ), I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HyperbolaBFFPType ) HyperbolaBFFPType::HyperbolaBFFPType() : ConicBFFPType( "HyperbolaBFFP", argsspecHyperbolaBFFP, 3 ) { } HyperbolaBFFPType::~HyperbolaBFFPType() { } const HyperbolaBFFPType* HyperbolaBFFPType::instance() { static const HyperbolaBFFPType t; return &t; } int HyperbolaBFFPType::type() const { return -1; } const ConicBDFPType* ConicBDFPType::instance() { static const ConicBDFPType t; return &t; } static const struct ArgsParser::spec argsspecConicBDFP[] = { { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this line as directrix" ), I18N_NOOP( "Select the directrix of the new conic..." ), false }, { PointImp::stype(), I18N_NOOP( "Construct a conic with this point as focus" ), I18N_NOOP( "Select the focus of the new conic..." ), false }, { PointImp::stype(), I18N_NOOP( "Construct a conic through this point" ), I18N_NOOP( "Select a point for the new conic to go through..." ), true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicBDFPType ) ConicBDFPType::ConicBDFPType() : ArgsParserObjectType( "ConicBDFP", argsspecConicBDFP, 3 ) { } ConicBDFPType::~ConicBDFPType() { } ObjectImp* ConicBDFPType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; const LineData line = static_cast( parents[0] )->data(); const Coordinate focus = static_cast( parents[1] )->coordinate(); Coordinate point; if ( parents.size() == 3 ) point = static_cast( parents[2] )->coordinate(); else { /* !!!! costruisci point come punto medio dell'altezza tra fuoco e d. */ Coordinate ba = line.dir(); Coordinate fa = focus - line.b; double balsq = ba.x*ba.x + ba.y*ba.y; double scal = (fa.x*ba.x + fa.y*ba.y)/balsq; point = 0.5*(line.a + focus + scal*ba); }; return new ConicImpPolar( calcConicBDFP( line, focus, point ) ); } static const char constructparabolathroughpointstat[] = I18N_NOOP( "Construct a parabola through this point" ); static const ArgsParser::spec argsspecParabolaBTP[] = { { PointImp::stype(), constructparabolathroughpointstat, I18N_NOOP( "Select a point for the new parabola to go through..." ), true }, { PointImp::stype(), constructparabolathroughpointstat, I18N_NOOP( "Select a point for the new parabola to go through..." ), true }, { PointImp::stype(), constructparabolathroughpointstat, I18N_NOOP( "Select a point for the new parabola to go through..." ), true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ParabolaBTPType ) ParabolaBTPType::ParabolaBTPType() : ArgsParserObjectType( "ParabolaBTP", argsspecParabolaBTP, 3 ) { } ParabolaBTPType::~ParabolaBTPType() { } const ParabolaBTPType* ParabolaBTPType::instance() { static const ParabolaBTPType t; return &t; } ObjectImp* ParabolaBTPType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; std::vector points; for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) points.push_back( static_cast( *i )->coordinate() ); ConicCartesianData d = calcConicThroughPoints( points, zerotilt, parabolaifzt, ysymmetry ); if ( d.valid() ) return new ConicImpCart( d ); else return new InvalidImp; } static const ArgsParser::spec argsspecConicPolarPoint[] = { { ConicImp::stype(), I18N_NOOP( "Construct a polar point wrt. this conic" ), I18N_NOOP( "Select the conic wrt. which you want to construct a polar point..." ), false }, { AbstractLineImp::stype(), I18N_NOOP( "Construct the polar point of this line" ), I18N_NOOP( "Select the line of which you want to construct the polar point..." ), false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicPolarPointType ) ConicPolarPointType::ConicPolarPointType() : ArgsParserObjectType( "ConicPolarPoint", argsspecConicPolarPoint, 2 ) { } ConicPolarPointType::~ConicPolarPointType() { } const ConicPolarPointType* ConicPolarPointType::instance() { static const ConicPolarPointType t; return &t; } ObjectImp* ConicPolarPointType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; const ConicCartesianData c = static_cast( parents[0] )->cartesianData(); const LineData l = static_cast( parents[1] )->data(); const Coordinate p = calcConicPolarPoint( c, l ); if ( p.valid() ) return new PointImp( p ); else return new InvalidImp; } static const ArgsParser::spec argsspecConicPolarLine[] = { { ConicImp::stype(), I18N_NOOP( "Construct a polar line wrt. this conic" ), I18N_NOOP( "Select the conic wrt. which you want to construct a polar point..." ), false }, { PointImp::stype(), I18N_NOOP( "Construct the polar line of this point" ), I18N_NOOP( "Select the line of which you want to construct the polar point..." ), false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicPolarLineType ) ConicPolarLineType::ConicPolarLineType() : ArgsParserObjectType( "ConicPolarLine", argsspecConicPolarLine, 2 ) { } ConicPolarLineType::~ConicPolarLineType() { } const ConicPolarLineType* ConicPolarLineType::instance() { static const ConicPolarLineType t; return &t; } ObjectImp* ConicPolarLineType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; const ConicCartesianData c = static_cast( parents[0] )->cartesianData(); const Coordinate p = static_cast( parents[1] )->coordinate(); bool valid = true; const LineData l = calcConicPolarLine( c, p, valid ); if ( valid ) return new LineImp( l ); else return new InvalidImp; } static const ArgsParser::spec argsspecConicDirectrix[] = { { ConicImp::stype(), I18N_NOOP( "Construct the directrix of this conic" ), I18N_NOOP( "Select the conic of which you want to construct the directrix..." ), false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicDirectrixType ) ConicDirectrixType::ConicDirectrixType() : ArgsParserObjectType( "ConicDirectrix", argsspecConicDirectrix, 1 ) { } ConicDirectrixType::~ConicDirectrixType() { } const ConicDirectrixType* ConicDirectrixType::instance() { static const ConicDirectrixType t; return &t; } ObjectImp* ConicDirectrixType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; const ConicPolarData data = static_cast( parents[0] )->polarData(); double ec = data.ecostheta0; double es = data.esintheta0; double eccsq = ec*ec + es*es; Coordinate a = data.focus1 - data.pdimen/eccsq*Coordinate(ec,es); Coordinate b = a + Coordinate(-es,ec); return new LineImp( a, b ); } static const char hyperbolatpstatement[] = I18N_NOOP( "Construct a hyperbola through this point" ); static const ArgsParser::spec argsspecHyperbolaB4P[] = { { PointImp::stype(), hyperbolatpstatement, I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true }, { PointImp::stype(), hyperbolatpstatement, I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true }, { PointImp::stype(), hyperbolatpstatement, I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true }, { PointImp::stype(), hyperbolatpstatement, I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( EquilateralHyperbolaB4PType ) EquilateralHyperbolaB4PType::EquilateralHyperbolaB4PType() : ArgsParserObjectType( "EquilateralHyperbolaB4P", argsspecHyperbolaB4P, 4 ) { } EquilateralHyperbolaB4PType::~EquilateralHyperbolaB4PType() { } const EquilateralHyperbolaB4PType* EquilateralHyperbolaB4PType::instance() { static const EquilateralHyperbolaB4PType t; return &t; } ObjectImp* EquilateralHyperbolaB4PType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents, 1 ) ) return new InvalidImp; std::vector pts; for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) pts.push_back( static_cast( *i )->coordinate() ); ConicCartesianData d = calcConicThroughPoints( pts, equilateral ); if ( d.valid() ) return new ConicImpCart( d ); else return new InvalidImp; } static const ArgsParser::spec argsspecParabolaBDP[] = { { AbstractLineImp::stype(), I18N_NOOP( "Construct a parabola with this directrix" ), I18N_NOOP( "Select the directrix of the new parabola..." ), false }, { PointImp::stype(), I18N_NOOP( "Construct a parabola with this focus" ), I18N_NOOP( "Select the focus of the new parabola..." ), true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ParabolaBDPType ) ParabolaBDPType::ParabolaBDPType() : ObjectLPType( "ParabolaBDP", argsspecParabolaBDP, 2 ) { } ParabolaBDPType::~ParabolaBDPType() { } const ParabolaBDPType* ParabolaBDPType::instance() { static const ParabolaBDPType t; return &t; } ObjectImp* ParabolaBDPType::calc( const LineData& l, const Coordinate& c ) const { ConicPolarData ret; Coordinate ldir = l.dir(); ldir = ldir.normalize(); ret.focus1 = c; ret.ecostheta0 = - ldir.y; ret.esintheta0 = ldir.x; Coordinate fa = c - l.a; ret.pdimen = fa.y*ldir.x - fa.x*ldir.y; ConicImpPolar* r = new ConicImpPolar( ret ); kdDebug() << k_funcinfo << r->conicTypeString() << endl; return r; } static const ArgsParser::spec argsspecConicAsymptote[] = { { ConicImp::stype(), I18N_NOOP( "Construct the asymptotes of this conic" ), I18N_NOOP( "Select the conic of which you want to construct the asymptotes..." ), false }, { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicAsymptoteType ) ConicAsymptoteType::ConicAsymptoteType() : ArgsParserObjectType( "ConicAsymptote", argsspecConicAsymptote, 2 ) { } ConicAsymptoteType::~ConicAsymptoteType() { } const ConicAsymptoteType* ConicAsymptoteType::instance() { static const ConicAsymptoteType t; return &t; } ObjectImp* ConicAsymptoteType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; bool valid = true; const LineData ret = calcConicAsymptote( static_cast( parents[0] )->cartesianData(), static_cast( parents[1] )->data(), valid ); if ( valid ) return new LineImp( ret ); else return new InvalidImp; } static const char radicallinesstatement[] = I18N_NOOP( "Construct the radical lines of this conic" ); static const ArgsParser::spec argsspecConicRadical[] = { { ConicImp::stype(), radicallinesstatement, I18N_NOOP( "Select the first of the two conics of which you want to construct the radical line..." ), false }, { ConicImp::stype(), radicallinesstatement, I18N_NOOP( "Select the other of the two conic of which you want to construct the radical line..." ), false }, { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }, { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicRadicalType ) ConicRadicalType::ConicRadicalType() : ArgsParserObjectType( "ConicRadical", argsspecConicRadical, 4 ) { } const ConicRadicalType* ConicRadicalType::instance() { static const ConicRadicalType t; return &t; } ObjectImp* ConicRadicalType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; if ( parents[0]->inherits( CircleImp::stype() ) && parents[1]->inherits( CircleImp::stype() ) ) { if( static_cast( parents[2] )->data() != 1 ) return new InvalidImp; else { const CircleImp* c1 = static_cast( parents[0] ); const CircleImp* c2 = static_cast( parents[1] ); const Coordinate a = calcCircleRadicalStartPoint( c1->center(), c2->center(), c1->squareRadius(), c2->squareRadius() ); return new LineImp( a, calcPointOnPerpend( LineData( c1->center(), c2->center() ), a ) ); }; } else { bool valid = true; const LineData l = calcConicRadical( static_cast( parents[0] )->cartesianData(), static_cast( parents[1] )->cartesianData(), static_cast( parents[2] )->data(), static_cast( parents[3] )->data(), valid ); if ( valid ) return new LineImp( l ); else return new InvalidImp; }; } ConicRadicalType::~ConicRadicalType() { } const ObjectImpType* ConicB5PType::resultId() const { return ConicImp::stype(); } const ObjectImpType* ConicBAAPType::resultId() const { return ConicImp::stype(); } const ObjectImpType* ConicBFFPType::resultId() const { return ConicImp::stype(); } const ObjectImpType* ConicBDFPType::resultId() const { return ConicImp::stype(); } const ObjectImpType* ParabolaBTPType::resultId() const { return ConicImp::stype(); } const ObjectImpType* EquilateralHyperbolaB4PType::resultId() const { return ConicImp::stype(); } const ObjectImpType* ConicPolarPointType::resultId() const { return PointImp::stype(); } const ObjectImpType* ConicPolarLineType::resultId() const { return LineImp::stype(); } const ObjectImpType* ConicDirectrixType::resultId() const { return LineImp::stype(); } const ObjectImpType* ParabolaBDPType::resultId() const { return ConicImp::stype(); } const ObjectImpType* ConicAsymptoteType::resultId() const { return LineImp::stype(); } const ObjectImpType* ConicRadicalType::resultId() const { return LineImp::stype(); } TQStringList ConicRadicalType::specialActions() const { TQStringList ret; ret << i18n( "Switch Radical Lines" ); return ret; } void ConicRadicalType::executeAction( int i, ObjectHolder&, ObjectTypeCalcer& t, KigPart& d, KigWidget&, NormalMode& ) const { assert( i == 0 ); std::vector parents = t.parents(); assert( dynamic_cast( parents[3] ) ); ObjectConstCalcer* zeroindexo = static_cast( parents[3] ); MonitorDataObjects mon( zeroindexo ); assert( zeroindexo->imp()->inherits( IntImp::stype() ) ); int oldzeroindex = static_cast( zeroindexo->imp() )->data(); int newzeroindex = oldzeroindex % 3 + 1; zeroindexo->setImp( new IntImp( newzeroindex ) ); KigCommand* kc = new KigCommand( d, "Switch Conic Radical Lines" ); mon.finish( kc ); d.history()->addCommand( kc ); }