00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "arc_type.h"
00019
00020 #include "bogus_imp.h"
00021 #include "other_imp.h"
00022 #include "point_imp.h"
00023 #include "conic_imp.h"
00024 #include "line_imp.h"
00025 #include "locus_imp.h"
00026
00027 #include "../misc/common.h"
00028 #include "../misc/calcpaths.h"
00029 #include "../misc/goniometry.h"
00030 #include "../kig/kig_part.h"
00031 #include "../kig/kig_view.h"
00032 #include "../kig/kig_commands.h"
00033
00034 #include <functional>
00035 #include <algorithm>
00036 #include <cmath>
00037
00038 using std::find;
00039
00040 #include <qstringlist.h>
00041
00042
00043
00044
00045
00046 static const char constructarcstartingstat[] = I18N_NOOP( "Construct an arc starting at this point" );
00047
00048 static const ArgsParser::spec argsspecArcBTP[] =
00049 {
00050 { PointImp::stype(), constructarcstartingstat,
00051 I18N_NOOP( "Select the start point of the new arc..." ), true },
00052 { PointImp::stype(), I18N_NOOP( "Construct an arc through this point" ),
00053 I18N_NOOP( "Select a point for the new arc to go through..." ), true },
00054 { PointImp::stype(), I18N_NOOP( "Construct an arc ending at this point" ),
00055 I18N_NOOP( "Select the end point of the new arc..." ), true }
00056 };
00057
00058 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ArcBTPType )
00059
00060 ArcBTPType::ArcBTPType()
00061 : ArgsParserObjectType( "ArcBTP", argsspecArcBTP, 3 )
00062 {
00063 }
00064
00065 ArcBTPType::~ArcBTPType()
00066 {
00067 }
00068
00069 const ArcBTPType* ArcBTPType::instance()
00070 {
00071 static const ArcBTPType t;
00072 return &t;
00073 }
00074
00075 ObjectImp* ArcBTPType::calc( const Args& args, const KigDocument& ) const
00076 {
00077 if ( ! margsparser.checkArgs( args, 2 ) )
00078 return new InvalidImp;
00079
00080 const Coordinate a =
00081 static_cast<const PointImp*>( args[0] )->coordinate();
00082 const Coordinate b =
00083 static_cast<const PointImp*>( args[1] )->coordinate();
00084 Coordinate center;
00085 double angle = 0.;
00086 double startangle = 0.;
00087 if ( args.size() == 3 )
00088 {
00089 Coordinate c = static_cast<const PointImp*>( args[2] )->coordinate();
00090 center = calcCenter( a, b, c );
00091 if ( ! center.valid() )
00092 {
00093 if ( fabs( a.x - c.x ) > fabs( a.y - c.y ) )
00094 {
00095 if ( ( b.x - a.x)*(c.x - b.x) > 1e-12 ) return new SegmentImp(a, c);
00096 } else
00097 {
00098 if ( ( b.y - a.y)*(c.y - b.y) > 1e-12 ) return new SegmentImp(a, c);
00099 }
00100 return new InvalidImp;
00101 }
00102 Coordinate ad = a - center;
00103 Coordinate bd = b - center;
00104 Coordinate cd = c - center;
00105 double anglea = atan2( ad.y, ad.x );
00106 double angleb = atan2( bd.y, bd.x );
00107 double anglec = atan2( cd.y, cd.x );
00108
00109
00110 if ( anglea > anglec )
00111 {
00112 double t = anglea;
00113 anglea = anglec;
00114 anglec = t;
00115 };
00116 if ( angleb > anglec || angleb < anglea )
00117 {
00118 startangle = anglec;
00119 angle = 2 * M_PI + anglea - startangle;
00120 }
00121 else
00122 {
00123 startangle = anglea;
00124 angle = anglec - anglea;
00125 };
00126 }
00127 else
00128 {
00129
00130 center = (b+a)/2 + .6*(b-a).orthogonal();
00131 Coordinate bd = b - center;
00132 Coordinate ad = a - center;
00133 startangle = atan2( ad.y, ad.x );
00134 double halfangle = atan2( bd.y, bd.x ) - startangle;
00135 if ( halfangle < - M_PI ) halfangle += 2*M_PI;
00136 angle = 2 * halfangle;
00137 };
00138
00139 double radius = ( a - center ).length();
00140 return new ArcImp( center, radius, startangle, angle );
00141 }
00142
00143 const ObjectImpType* ArcBTPType::impRequirement( const ObjectImp*, const Args& ) const
00144 {
00145 return PointImp::stype();
00146 }
00147
00148 bool ArcBTPType::inherits( int type ) const
00149 {
00150 return Parent::inherits( type );
00151 }
00152
00153 const ObjectImpType* ArcBTPType::resultId() const
00154 {
00155 return ArcImp::stype();
00156 }
00157
00158
00159
00160
00161
00162 static const ArgsParser::spec argsspecArcBCPA[] =
00163 {
00164 { PointImp::stype(), I18N_NOOP( "Construct an arc with this center" ),
00165 I18N_NOOP( "Select the center of the new arc..." ), true },
00166 { PointImp::stype(), constructarcstartingstat,
00167 I18N_NOOP( "Select the start point of the new arc..." ), true },
00168 { AngleImp::stype(), I18N_NOOP( "Construct an arc with this angle" ),
00169 I18N_NOOP( "Select the angle of the new arc..." ), true }
00170 };
00171
00172 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ArcBCPAType )
00173
00174 ArcBCPAType::ArcBCPAType()
00175 : ArgsParserObjectType( "ArcBCPA", argsspecArcBCPA, 3 )
00176 {
00177 }
00178
00179 ArcBCPAType::~ArcBCPAType()
00180 {
00181 }
00182
00183 const ArcBCPAType* ArcBCPAType::instance()
00184 {
00185 static const ArcBCPAType t;
00186 return &t;
00187 }
00188
00189 ObjectImp* ArcBCPAType::calc( const Args& args, const KigDocument& ) const
00190 {
00191 if ( ! margsparser.checkArgs( args ) )
00192 return new InvalidImp;
00193
00194 const Coordinate center = static_cast<const PointImp*>( args[0] )->coordinate();
00195 const Coordinate p = static_cast<const PointImp*>( args[1] )->coordinate();
00196 const AngleImp* a = static_cast<const AngleImp*>( args[2] );
00197 const double angle = a->angle();
00198 const Coordinate dir = p - center;
00199 const double startangle = atan2( dir.y, dir.x );
00200 const double radius = center.distance( p );
00201
00202 return new ArcImp( center, radius, startangle, angle );
00203 }
00204
00205 const ObjectImpType* ArcBCPAType::impRequirement( const ObjectImp*, const Args& ) const
00206 {
00207 return PointImp::stype();
00208 }
00209
00210 bool ArcBCPAType::inherits( int type ) const
00211 {
00212 return Parent::inherits( type );
00213 }
00214
00215 const ObjectImpType* ArcBCPAType::resultId() const
00216 {
00217 return ArcImp::stype();
00218 }
00219
00220
00221
00222
00223
00224 static const char constructconicarcstartingstat[] = I18N_NOOP( "Construct a conic arc starting at this point" );
00225 static const char selectconicarcstartingstat[] = I18N_NOOP( "Select the start point of the new conic arc..." );
00226 static const char constructconicarcthrustat[] = I18N_NOOP( "Construct a conic arc through this point" );
00227 static const char selectconicarcthrustat[] = I18N_NOOP( "Select a point for the new conic arc to go through..." );
00228 static const char constructconicarcendingstat[] = I18N_NOOP( "Construct a conic arc ending at this point" );
00229 static const char selectconicarcendingstat[] = I18N_NOOP( "Select the end point of the new conic arc..." );
00230
00231 static const ArgsParser::spec argsspecConicArcBCTP[] =
00232 {
00233 { PointImp::stype(), I18N_NOOP( "Construct an conic arc with this center" ),
00234 I18N_NOOP( "Select the center of the new conic arc..." ), false },
00235 { PointImp::stype(), constructconicarcstartingstat,
00236 selectconicarcstartingstat, true },
00237 { PointImp::stype(), constructconicarcthrustat,
00238 selectconicarcthrustat, true },
00239 { PointImp::stype(), constructconicarcendingstat,
00240 selectconicarcendingstat, true }
00241 };
00242
00243 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicArcBCTPType )
00244
00245 ConicArcBCTPType::ConicArcBCTPType()
00246 : ArgsParserObjectType( "ConicArcBCTP", argsspecConicArcBCTP, 4 )
00247 {
00248 }
00249
00250 ConicArcBCTPType::~ConicArcBCTPType()
00251 {
00252 }
00253
00254 const ConicArcBCTPType* ConicArcBCTPType::instance()
00255 {
00256 static const ConicArcBCTPType t;
00257 return &t;
00258 }
00259
00260 ObjectImp* ConicArcBCTPType::calc( const Args& args, const KigDocument& ) const
00261 {
00262 if ( ! margsparser.checkArgs( args, 2 ) )
00263 return new InvalidImp;
00264
00265 const Coordinate center =
00266 static_cast<const PointImp*>( args[0] )->coordinate();
00267 const Coordinate a =
00268 static_cast<const PointImp*>( args[1] )->coordinate();
00269 const Coordinate d = 2*center - a;
00270 Coordinate b = center + (a-center).orthogonal();
00271 Coordinate e = 2*center - b;
00272 if ( args.size() >= 3 )
00273 {
00274 b = static_cast<const PointImp*>( args[2] )->coordinate();
00275 e = 2*center - b;
00276 }
00277 bool have_c = false;
00278 Coordinate c;
00279 if ( args.size() == 4 )
00280 {
00281 c = static_cast<const PointImp*>( args[3] )->coordinate();
00282 const Coordinate e = 2*center - c;
00283 have_c = true;
00284 }
00285
00286 std::vector<Coordinate> points;
00287 points.push_back( a );
00288 points.push_back( b );
00289 if (have_c) points.push_back( c );
00290 points.push_back( d );
00291 points.push_back( e );
00292 ConicCartesianData cart =
00293 calcConicThroughPoints( points, zerotilt, circleifzt, ysymmetry );
00294 if ( ! d.valid() )
00295 return new InvalidImp;
00296
00297 ConicArcImp *me = new ConicArcImp( cart, 0.0, 2*M_PI );
00298 double angle = 0.;
00299 double startangle = 0.;
00300 double anglea = 2*M_PI*me->getParam( a );
00301 double angleb = anglea + M_PI/2;
00302 angleb = 2*M_PI*me->getParam( b );
00303 double anglec = 2*angleb - anglea;
00304 if ( have_c ) anglec = 2*M_PI*me->getParam( c );
00305
00306
00307 if ( anglea > anglec )
00308 {
00309 double t = anglea;
00310 anglea = anglec;
00311 anglec = t;
00312 };
00313 if ( angleb > anglec || angleb < anglea )
00314 {
00315 startangle = anglec;
00316 angle = 2 * M_PI + anglea - startangle;
00317 }
00318 else
00319 {
00320 startangle = anglea;
00321 angle = anglec - anglea;
00322 };
00323
00324 me->setStartAngle( startangle );
00325 me->setAngle( angle );
00326 return me;
00327 }
00328
00329 const ObjectImpType* ConicArcBCTPType::resultId() const
00330 {
00331 return ConicArcImp::stype();
00332 }
00333
00334
00335
00336
00337
00338 static const ArgsParser::spec argsspecConicArcB5P[] =
00339 {
00340 { PointImp::stype(), constructconicarcstartingstat,
00341 selectconicarcstartingstat, true },
00342 { PointImp::stype(), constructconicarcthrustat,
00343 selectconicarcthrustat, true },
00344 { PointImp::stype(), constructconicarcthrustat,
00345 selectconicarcthrustat, true },
00346 { PointImp::stype(), constructconicarcthrustat,
00347 selectconicarcthrustat, true },
00348 { PointImp::stype(), constructconicarcendingstat,
00349 selectconicarcendingstat, true }
00350 };
00351
00352 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicArcB5PType )
00353
00354 ConicArcB5PType::ConicArcB5PType()
00355 : ArgsParserObjectType( "ConicArcB5P", argsspecConicArcB5P, 5 )
00356 {
00357 }
00358
00359 ConicArcB5PType::~ConicArcB5PType()
00360 {
00361 }
00362
00363 const ConicArcB5PType* ConicArcB5PType::instance()
00364 {
00365 static const ConicArcB5PType t;
00366 return &t;
00367 }
00368
00369 ObjectImp* ConicArcB5PType::calc( const Args& args, const KigDocument& ) const
00370 {
00371 if ( ! margsparser.checkArgs( args, 2 ) )
00372 return new InvalidImp;
00373
00374 const Coordinate a =
00375 static_cast<const PointImp*>( args[0] )->coordinate();
00376 const Coordinate b =
00377 static_cast<const PointImp*>( args[1] )->coordinate();
00378
00379 Coordinate c, d, e;
00380 bool have_c = false;
00381 bool have_d = false;
00382 bool have_e = false;
00383 if ( args.size() >= 3 )
00384 {
00385 c = static_cast<const PointImp*>( args[2] )->coordinate();
00386 have_c = true;
00387 }
00388 if ( args.size() >= 4 )
00389 {
00390 d = static_cast<const PointImp*>( args[3] )->coordinate();
00391 have_d = true;
00392 }
00393 if ( args.size() >= 5 )
00394 {
00395 e = static_cast<const PointImp*>( args[4] )->coordinate();
00396 have_e = true;
00397 }
00398
00399 std::vector<Coordinate> points;
00400 points.push_back( a );
00401 points.push_back( b );
00402 if (have_c) points.push_back( c );
00403 if (have_d) points.push_back( d );
00404 if (have_e) points.push_back( e );
00405 ConicCartesianData cart =
00406 calcConicThroughPoints( points, zerotilt, circleifzt, ysymmetry );
00407 if ( ! d.valid() )
00408 return new InvalidImp;
00409
00410 ConicArcImp *me = new ConicArcImp( cart, 0.0, 2*M_PI );
00411 double angle = 0.;
00412 double startangle = 0.;
00413 double anglea = 2*M_PI*me->getParam( a );
00414 double angleb = anglea + M_PI/2;
00415 angleb = 2*M_PI*me->getParam( b );
00416 if ( have_c ) angleb = 2*M_PI*me->getParam( c );
00417 double anglec = 2*angleb - anglea;
00418 if ( have_e ) anglec = 2*M_PI*me->getParam( e );
00419
00420
00421 if ( anglea > anglec )
00422 {
00423 double t = anglea;
00424 anglea = anglec;
00425 anglec = t;
00426 };
00427 if ( angleb > anglec || angleb < anglea )
00428 {
00429 startangle = anglec;
00430 angle = 2 * M_PI + anglea - startangle;
00431 }
00432 else
00433 {
00434 startangle = anglea;
00435 angle = anglec - anglea;
00436 };
00437
00438 me->setStartAngle( startangle );
00439 me->setAngle( angle );
00440 return me;
00441 }
00442
00443 const ObjectImpType* ConicArcB5PType::resultId() const
00444 {
00445 return ConicArcImp::stype();
00446 }
00447