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