kig
angle_type.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "angle_type.h"
00020
00021 #include "bogus_imp.h"
00022 #include "other_imp.h"
00023 #include "point_imp.h"
00024 #include "../misc/calcpaths.h"
00025 #include "../misc/common.h"
00026 #include "../misc/goniometry.h"
00027 #include "../misc/kiginputdialog.h"
00028 #include "../kig/kig_commands.h"
00029 #include "../kig/kig_part.h"
00030 #include "../kig/kig_view.h"
00031
00032 #include <functional>
00033 #include <algorithm>
00034 #include <cmath>
00035
00036 #include <qstringlist.h>
00037
00038 static const char* constructanglethroughpoint =
00039 I18N_NOOP( "Construct an angle through this point" );
00040
00041 static const ArgsParser::spec argsspecAngle[] =
00042 {
00043 { PointImp::stype(), constructanglethroughpoint,
00044 I18N_NOOP( "Select a point that the first half-line of the angle should go through..." ), true },
00045 { PointImp::stype(), I18N_NOOP( "Construct an angle at this point" ),
00046 I18N_NOOP( "Select the point to construct the angle in..." ), true },
00047 { PointImp::stype(), constructanglethroughpoint,
00048 I18N_NOOP( "Select a point that the second half-line of the angle should go through..." ), true }
00049 };
00050
00051 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AngleType )
00052
00053 AngleType::AngleType()
00054 : ArgsParserObjectType( "Angle", argsspecAngle, 3 )
00055 {
00056 }
00057
00058 AngleType::~AngleType()
00059 {
00060 }
00061
00062 const AngleType* AngleType::instance()
00063 {
00064 static const AngleType t;
00065 return &t;
00066 }
00067
00068 ObjectImp* AngleType::calc( const Args& parents, const KigDocument& ) const
00069 {
00070 if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp;
00071
00072 std::vector<Coordinate> points;
00073 for ( uint i = 0; i < parents.size(); ++i )
00074 points.push_back(
00075 static_cast<const PointImp*>( parents[i] )->coordinate() );
00076
00077 Coordinate lvect = points[0] - points[1];
00078 Coordinate rvect;
00079 if ( points.size() == 3 )
00080 rvect = points[2] - points[1];
00081 else
00082 {
00083 rvect = lvect.orthogonal();
00084 }
00085
00086 double startangle = atan2( lvect.y, lvect.x );
00087 double endangle = atan2( rvect.y, rvect.x );
00088 double anglelength = endangle - startangle;
00089 if ( anglelength < 0 ) anglelength += 2* M_PI;
00090 if ( startangle < 0 ) startangle += 2*M_PI;
00091
00092 return new AngleImp( points[1], startangle, anglelength );
00093 }
00094
00095 const ObjectImpType* AngleType::resultId() const
00096 {
00097 return AngleImp::stype();
00098 }
00099
00100 QStringList AngleType::specialActions() const
00101 {
00102 QStringList ret;
00103 ret << i18n( "Set Si&ze" );
00104 return ret;
00105 }
00106
00107 void AngleType::executeAction(
00108 int i, ObjectHolder&, ObjectTypeCalcer& t,
00109 KigPart& d, KigWidget& w, NormalMode& ) const
00110 {
00111 assert( i == 0 );
00112
00113 (void) i;
00114
00115 std::vector<ObjectCalcer*> parents = t.parents();
00116
00117 assert( margsparser.checkArgs( parents ) );
00118
00119 Coordinate a = static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
00120 Coordinate b = static_cast<const PointImp*>( parents[1]->imp() )->coordinate();
00121 Coordinate c = static_cast<const PointImp*>( parents[2]->imp() )->coordinate();
00122
00123 Coordinate lvect = a - b;
00124 Coordinate rvect = c - b;
00125
00126 double startangle = atan2( lvect.y, lvect.x );
00127 double endangle = atan2( rvect.y, rvect.x );
00128 double anglelength = endangle - startangle;
00129 if ( anglelength < 0 ) anglelength += 2* M_PI;
00130 if ( startangle < 0 ) startangle += 2*M_PI;
00131
00132 Goniometry go( anglelength, Goniometry::Rad );
00133 go.convertTo( Goniometry::Deg );
00134
00135 bool ok;
00136 Goniometry newsize = KigInputDialog::getAngle( &w, &ok, go );
00137 if ( !ok )
00138 return;
00139 newsize.convertTo( Goniometry::Rad );
00140
00141 double newcangle = startangle + newsize.value();
00142 Coordinate cdir( cos( newcangle ), sin( newcangle ) );
00143 Coordinate nc = b + cdir.normalize( rvect.length() );
00144
00145 MonitorDataObjects mon( getAllParents( parents ) );
00146 parents[2]->move( nc, d.document() );
00147 KigCommand* kc = new KigCommand( d, i18n( "Resize Angle" ) );
00148 mon.finish( kc );
00149 d.history()->push( kc );
00150 }
00151
00152 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HalfAngleType )
00153
00154 HalfAngleType::HalfAngleType()
00155 : ArgsParserObjectType( "HalfAngle", argsspecAngle, 3 )
00156 {
00157 }
00158
00159 HalfAngleType::~HalfAngleType()
00160 {
00161 }
00162
00163 const HalfAngleType* HalfAngleType::instance()
00164 {
00165 static const HalfAngleType t;
00166 return &t;
00167 }
00168
00169 ObjectImp* HalfAngleType::calc( const Args& parents, const KigDocument& ) const
00170 {
00171 if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp;
00172
00173 std::vector<Coordinate> points;
00174 for ( uint i = 0; i < parents.size(); ++i )
00175 points.push_back(
00176 static_cast<const PointImp*>( parents[i] )->coordinate() );
00177
00178 Coordinate lvect = points[0] - points[1];
00179 Coordinate rvect;
00180 if ( points.size() == 3 )
00181 rvect = points[2] - points[1];
00182 else
00183 {
00184 rvect = lvect.orthogonal();
00185 }
00186
00187 double startangle = atan2( lvect.y, lvect.x );
00188 double endangle = atan2( rvect.y, rvect.x );
00189 double anglelength = endangle - startangle;
00190 if ( anglelength < 0 ) anglelength += 2 * M_PI;
00191 if ( startangle < 0 ) startangle += 2 * M_PI;
00192
00193 if ( anglelength > M_PI )
00194 {
00195 startangle += anglelength;
00196 anglelength = 2 * M_PI - anglelength;
00197 if ( startangle > 2 * M_PI ) startangle -= 2 * M_PI;
00198 if ( anglelength < 0 ) anglelength += 2 * M_PI;
00199 }
00200
00201 return new AngleImp( points[1], startangle, anglelength );
00202 }
00203
00204 const ObjectImpType* HalfAngleType::resultId() const
00205 {
00206 return AngleImp::stype();
00207 }
00208