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