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.
tdeedu/kig/objects/angle_type.cc

209 lines
5.8 KiB

// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
// Copyright (C) 2004 Pino Toscano <toscano.pino@tiscali.it>
// 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 <functional>
#include <algorithm>
#include <cmath>
#include <tqstringlist.h>
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<Coordinate> points;
for ( uint i = 0; i < parents.size(); ++i )
points.push_back(
static_cast<const PointImp*>( 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<ObjectCalcer*> parents = t.parents();
assert( margsparser.checkArgs( parents ) );
Coordinate a = static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
Coordinate b = static_cast<const PointImp*>( parents[1]->imp() )->coordinate();
Coordinate c = static_cast<const PointImp*>( 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<Coordinate> points;
for ( uint i = 0; i < parents.size(); ++i )
points.push_back(
static_cast<const PointImp*>( 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();
}