// Copyright (C) 2003 Dominique Devriese // Copyright (C) 2004 Pino Toscano // 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 "angle_type.h" #include "bogus_imp.h" #include "other_imp.h" #include "point_imp.h" #include "../misc/calcpaths.h" #include "../misc/common.h" #include "../misc/goniometry.h" #include "../misc/kiginputdialog.h" #include "../kig/kig_commands.h" #include "../kig/kig_part.h" #include "../kig/kig_view.h" #include #include #include #include static const char* constructanglethroughpoint = I18N_NOOP( "Construct an angle through this point" ); static const ArgsParser::spec argsspecAngle[] = { { PointImp::stype(), constructanglethroughpoint, I18N_NOOP( "Select a point that the first half-line of the angle should go through..." ), true }, { PointImp::stype(), I18N_NOOP( "Construct an angle at this point" ), I18N_NOOP( "Select the point to construct the angle in..." ), true }, { PointImp::stype(), constructanglethroughpoint, I18N_NOOP( "Select a point that the second half-line of the angle should go through..." ), true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AngleType ) AngleType::AngleType() : ArgsParserObjectType( "Angle", argsspecAngle, 3 ) { } AngleType::~AngleType() { } const AngleType* AngleType::instance() { static const AngleType t; return &t; } ObjectImp* AngleType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; std::vector points; for ( uint i = 0; i < parents.size(); ++i ) points.push_back( static_cast( parents[i] )->coordinate() ); Coordinate lvect = points[0] - points[1]; Coordinate rvect; if ( points.size() == 3 ) rvect = points[2] - points[1]; else { rvect = lvect.orthogonal(); } double startangle = atan2( lvect.y, lvect.x ); double endangle = atan2( rvect.y, rvect.x ); double anglelength = endangle - startangle; if ( anglelength < 0 ) anglelength += 2* M_PI; if ( startangle < 0 ) startangle += 2*M_PI; return new AngleImp( points[1], startangle, anglelength ); } const ObjectImpType* AngleType::resultId() const { return AngleImp::stype(); } TQStringList AngleType::specialActions() const { TQStringList ret; ret << i18n( "Set Si&ze" ); return ret; } void AngleType::executeAction( int i, ObjectHolder&, ObjectTypeCalcer& t, KigPart& d, KigWidget& w, NormalMode& ) const { assert( i == 0 ); // pretend to use this var.. (void) i; std::vector parents = t.parents(); assert( margsparser.checkArgs( parents ) ); Coordinate a = static_cast( parents[0]->imp() )->coordinate(); Coordinate b = static_cast( parents[1]->imp() )->coordinate(); Coordinate c = static_cast( parents[2]->imp() )->coordinate(); Coordinate lvect = a - b; Coordinate rvect = c - b; double startangle = atan2( lvect.y, lvect.x ); double endangle = atan2( rvect.y, rvect.x ); double anglelength = endangle - startangle; if ( anglelength < 0 ) anglelength += 2* M_PI; if ( startangle < 0 ) startangle += 2*M_PI; Goniometry go( anglelength, Goniometry::Rad ); go.convertTo( Goniometry::Deg ); bool ok; Goniometry newsize = KigInputDialog::getAngle( &w, &ok, go ); if ( !ok ) return; newsize.convertTo( Goniometry::Rad ); double newcangle = startangle + newsize.value(); Coordinate cdir( cos( newcangle ), sin( newcangle ) ); Coordinate nc = b + cdir.normalize( rvect.length() ); MonitorDataObjects mon( getAllParents( parents ) ); parents[2]->move( nc, d.document() ); KigCommand* kc = new KigCommand( d, i18n( "Resize Angle" ) ); mon.finish( kc ); d.history()->addCommand( kc ); } KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HalfAngleType ) HalfAngleType::HalfAngleType() : ArgsParserObjectType( "HalfAngle", argsspecAngle, 3 ) { } HalfAngleType::~HalfAngleType() { } const HalfAngleType* HalfAngleType::instance() { static const HalfAngleType t; return &t; } ObjectImp* HalfAngleType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; std::vector points; for ( uint i = 0; i < parents.size(); ++i ) points.push_back( static_cast( parents[i] )->coordinate() ); Coordinate lvect = points[0] - points[1]; Coordinate rvect; if ( points.size() == 3 ) rvect = points[2] - points[1]; else { rvect = lvect.orthogonal(); } double startangle = atan2( lvect.y, lvect.x ); double endangle = atan2( rvect.y, rvect.x ); double anglelength = endangle - startangle; if ( anglelength < 0 ) anglelength += 2 * M_PI; if ( startangle < 0 ) startangle += 2 * M_PI; if ( anglelength > M_PI ) { startangle += anglelength; anglelength = 2 * M_PI - anglelength; if ( startangle > 2 * M_PI ) startangle -= 2 * M_PI; if ( anglelength < 0 ) anglelength += 2 * M_PI; } return new AngleImp( points[1], startangle, anglelength ); } const ObjectImpType* HalfAngleType::resultId() const { return AngleImp::stype(); }