00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "intersection_types.h"
00019
00020 #include "bogus_imp.h"
00021 #include "circle_imp.h"
00022 #include "conic_imp.h"
00023 #include "cubic_imp.h"
00024 #include "line_imp.h"
00025 #include "other_imp.h"
00026 #include "point_imp.h"
00027
00028 #include <klocale.h>
00029
00030 static const char intersectlinestat[] = I18N_NOOP( "Intersect with this line" );
00031
00032 static const ArgsParser::spec argsspecConicLineIntersection[] =
00033 {
00034 { ConicImp::stype(), I18N_NOOP( "Intersect with this conic" ),
00035 "SHOULD NOT BE SEEN", true },
00036 { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true },
00037 { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }
00038 };
00039
00040 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicLineIntersectionType )
00041
00042 ConicLineIntersectionType::ConicLineIntersectionType()
00043 : ArgsParserObjectType( "ConicLineIntersection",
00044 argsspecConicLineIntersection, 3 )
00045 {
00046 }
00047
00048 ConicLineIntersectionType::~ConicLineIntersectionType()
00049 {
00050 }
00051
00052 const ConicLineIntersectionType* ConicLineIntersectionType::instance()
00053 {
00054 static const ConicLineIntersectionType t;
00055 return &t;
00056 }
00057
00058 ObjectImp* ConicLineIntersectionType::calc( const Args& parents, const KigDocument& doc ) const
00059 {
00060 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
00061
00062 int side = static_cast<const IntImp*>( parents[2] )->data();
00063 assert( side == 1 || side == -1 );
00064 const AbstractLineImp* lineimp = static_cast<const AbstractLineImp*>( parents[1] );
00065 const LineData line = lineimp->data();
00066
00067 Coordinate ret;
00068 if ( parents[0]->inherits( CircleImp::stype() ) )
00069 {
00070
00071 const CircleImp* c = static_cast<const CircleImp*>( parents[0] );
00072 ret = calcCircleLineIntersect(
00073 c->center(), c->squareRadius(), line, side );
00074 }
00075 else
00076 {
00077
00078 ret = calcConicLineIntersect(
00079 static_cast<const ConicImp*>( parents[0] )->cartesianData(),
00080 line, 0.0, side );
00081 }
00082 if ( !ret.valid() ) return new InvalidImp;
00083 if ( !lineimp->containsPoint( ret, doc ) ) return new InvalidImp;
00084 return new PointImp( ret );
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 static const ArgsParser::spec argsspecConicLineOtherIntersection[] =
00098 {
00099 { ConicImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true },
00100 { AbstractLineImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true },
00101 { PointImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", false }
00102 };
00103
00104 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicLineOtherIntersectionType )
00105
00106 ConicLineOtherIntersectionType::ConicLineOtherIntersectionType()
00107 : ArgsParserObjectType( "ConicLineOtherIntersection",
00108 argsspecConicLineOtherIntersection, 3 )
00109 {
00110 }
00111
00112 ConicLineOtherIntersectionType::~ConicLineOtherIntersectionType()
00113 {
00114 }
00115
00116 const ConicLineOtherIntersectionType* ConicLineOtherIntersectionType::instance()
00117 {
00118 static const ConicLineOtherIntersectionType t;
00119 return &t;
00120 }
00121
00122 ObjectImp* ConicLineOtherIntersectionType::calc( const Args& parents, const KigDocument& doc ) const
00123 {
00124 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
00125
00126 Coordinate p = static_cast<const PointImp*>( parents[2] )->coordinate();
00127 const AbstractLineImp* line = static_cast<const AbstractLineImp*>( parents[1] );
00128 const ConicImp* conic = static_cast<const ConicImp*>( parents[0] );
00129 const LineData linedata = line->data();
00130
00131 if ( !line->containsPoint( p, doc ) || !conic->containsPoint( p, doc ) )
00132 {
00133 return new InvalidImp;
00134 }
00135
00136 Coordinate ret;
00137 double pax = p.x - linedata.a.x;
00138 double pay = p.y - linedata.a.y;
00139 double bax = linedata.b.x - linedata.a.x;
00140 double bay = linedata.b.y - linedata.a.y;
00141 double knownparam = (pax*bax + pay*bay)/(bax*bax + bay*bay);
00142 ret = calcConicLineIntersect(
00143 conic->cartesianData(),
00144 linedata, knownparam, 0 );
00145 if ( !ret.valid() ) return new InvalidImp;
00146 if ( !line->containsPoint( ret, doc ) ) return new InvalidImp;
00147 return new PointImp( ret );
00148 }
00149
00150
00151
00152
00153
00154
00155
00156 static const ArgsParser::spec argsspecCircleCircleOtherIntersection[] =
00157 {
00158 { CircleImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true },
00159 { CircleImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true },
00160 { PointImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", false }
00161 };
00162
00163 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleCircleOtherIntersectionType )
00164
00165 CircleCircleOtherIntersectionType::CircleCircleOtherIntersectionType()
00166 : ArgsParserObjectType( "CircleCircleOtherIntersection",
00167 argsspecCircleCircleOtherIntersection, 3 )
00168 {
00169 }
00170
00171 CircleCircleOtherIntersectionType::~CircleCircleOtherIntersectionType()
00172 {
00173 }
00174
00175 const CircleCircleOtherIntersectionType* CircleCircleOtherIntersectionType::instance()
00176 {
00177 static const CircleCircleOtherIntersectionType t;
00178 return &t;
00179 }
00180
00181 ObjectImp* CircleCircleOtherIntersectionType::calc( const Args& parents, const KigDocument& doc ) const
00182 {
00183 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
00184
00185 Coordinate p = static_cast<const PointImp*>( parents[2] )->coordinate();
00186 const CircleImp* circle1 = static_cast<const CircleImp*>( parents[0] );
00187 const CircleImp* circle2 = static_cast<const CircleImp*>( parents[1] );
00188
00189 if ( !circle1->containsPoint( p, doc ) || !circle2->containsPoint( p, doc ) )
00190 {
00191 return new InvalidImp;
00192 }
00193
00194 Coordinate c1 = circle1->center();
00195 Coordinate c1c2 = circle2->center() - c1;
00196 Coordinate c1p = p - c1;
00197 Coordinate w = Coordinate( -c1c2.y, c1c2.x );
00198 double wnormsq = w.x*w.x + w.y*w.y;
00199 if ( wnormsq < 1e-12 ) return new InvalidImp;
00200 double pc1c2dist = ( c1p.x*w.x + c1p.y*w.y )/wnormsq;
00201
00202 Coordinate ret = p - 2*pc1c2dist*w;
00203 return new PointImp( ret );
00204 }
00205
00206
00207
00208 static const ArgsParser::spec argsspecLineLineIntersection[] =
00209 {
00210 { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true },
00211 { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }
00212 };
00213
00214 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineLineIntersectionType )
00215
00216 LineLineIntersectionType::LineLineIntersectionType()
00217 : ArgsParserObjectType( "LineLineIntersection",
00218 argsspecLineLineIntersection, 2 )
00219 {
00220 }
00221
00222 LineLineIntersectionType::~LineLineIntersectionType()
00223 {
00224 }
00225
00226 const LineLineIntersectionType* LineLineIntersectionType::instance()
00227 {
00228 static const LineLineIntersectionType t;
00229 return &t;
00230 }
00231
00232 ObjectImp* LineLineIntersectionType::calc( const Args& parents, const KigDocument& d ) const
00233 {
00234 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
00235
00236 Coordinate p =
00237 calcIntersectionPoint(
00238 static_cast<const AbstractLineImp*>( parents[0] )->data(),
00239 static_cast<const AbstractLineImp*>( parents[1] )->data() );
00240 if ( static_cast<const AbstractLineImp*>( parents[0] )->containsPoint( p, d ) &&
00241 static_cast<const AbstractLineImp*>( parents[1] )->containsPoint( p, d ) )
00242 return new PointImp( p );
00243 else return new InvalidImp();
00244 }
00245
00246 static const ArgsParser::spec argsspecLineCubicIntersection[] =
00247 {
00248 { CubicImp::stype(), I18N_NOOP( "Intersect with this cubic curve" ),
00249 "SHOULD NOT BE SEEN", true },
00250 { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true },
00251 { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }
00252 };
00253
00254 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineCubicIntersectionType )
00255
00256 LineCubicIntersectionType::LineCubicIntersectionType()
00257 : ArgsParserObjectType( "LineCubicIntersection",
00258 argsspecLineCubicIntersection, 3 )
00259 {
00260 }
00261
00262 LineCubicIntersectionType::~LineCubicIntersectionType()
00263 {
00264 }
00265
00266 const LineCubicIntersectionType* LineCubicIntersectionType::instance()
00267 {
00268 static const LineCubicIntersectionType t;
00269 return &t;
00270 }
00271
00272 ObjectImp* LineCubicIntersectionType::calc( const Args& parents, const KigDocument& ) const
00273 {
00274 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
00275
00276 int which = static_cast<const IntImp*>( parents[2] )->data();
00277 bool valid = true;
00278 const Coordinate c = calcCubicLineIntersect(
00279 static_cast<const CubicImp*>( parents[0] )->data(),
00280 static_cast<const AbstractLineImp*>( parents[1] )->data(),
00281 which, valid );
00282 if ( valid ) return new PointImp( c );
00283 else return new InvalidImp;
00284 }
00285
00286 const ObjectImpType* ConicLineIntersectionType::resultId() const
00287 {
00288 return PointImp::stype();
00289 }
00290
00291 const ObjectImpType* ConicLineOtherIntersectionType::resultId() const
00292 {
00293 return PointImp::stype();
00294 }
00295
00296 const ObjectImpType* CircleCircleOtherIntersectionType::resultId() const
00297 {
00298 return PointImp::stype();
00299 }
00300
00301 const ObjectImpType* LineLineIntersectionType::resultId() const
00302 {
00303 return PointImp::stype();
00304 }
00305
00306 const ObjectImpType* LineCubicIntersectionType::resultId() const
00307 {
00308 return PointImp::stype();
00309 }
00310
00311 static const ArgsParser::spec argsspecCircleCircleIntersection[] =
00312 {
00313 { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ),
00314 "SHOULD NOT BE SEEN", true },
00315 { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ),
00316 "SHOULD NOT BE SEEN", true },
00317 { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }
00318 };
00319
00320 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleCircleIntersectionType )
00321
00322 CircleCircleIntersectionType::CircleCircleIntersectionType()
00323 : ArgsParserObjectType( "CircleCircleIntersection",
00324 argsspecCircleCircleIntersection, 3 )
00325 {
00326 }
00327
00328 CircleCircleIntersectionType::~CircleCircleIntersectionType()
00329 {
00330 }
00331
00332 const CircleCircleIntersectionType* CircleCircleIntersectionType::instance()
00333 {
00334 static const CircleCircleIntersectionType t;
00335 return &t;
00336 }
00337
00338 ObjectImp* CircleCircleIntersectionType::calc( const Args& parents, const KigDocument& ) const
00339 {
00340 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
00341
00342 int side = static_cast<const IntImp*>( parents[2] )->data();
00343 assert( side == 1 || side == -1 );
00344 const CircleImp* c1 = static_cast<const CircleImp*>( parents[0] );
00345 const CircleImp* c2 = static_cast<const CircleImp*>( parents[1] );
00346 const Coordinate o1 = c1->center();
00347 const Coordinate o2 = c2->center();
00348 const double r1sq = c1->squareRadius();
00349 const Coordinate a = calcCircleRadicalStartPoint(
00350 o1, o2, r1sq, c2->squareRadius()
00351 );
00352 const LineData line = LineData (a, Coordinate ( a.x -o2.y + o1.y, a.y + o2.x - o1.x ));
00353 Coordinate ret = calcCircleLineIntersect( o1, r1sq, line, side );
00354 if ( ret.valid() ) return new PointImp( ret );
00355 else return new InvalidImp;
00356 }
00357
00358 const ObjectImpType* CircleCircleIntersectionType::resultId() const
00359 {
00360 return PointImp::stype();
00361 }
00362
00363 static const ArgsParser::spec argsspecArcLineIntersection[] =
00364 {
00365 { ArcImp::stype(), I18N_NOOP( "Intersect with this arc" ),
00366 "SHOULD NOT BE SEEN", true },
00367 { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true },
00368 { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }
00369 };
00370
00371 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ArcLineIntersectionType )
00372
00373 ArcLineIntersectionType::ArcLineIntersectionType()
00374 : ArgsParserObjectType( "ArcLineIntersection",
00375 argsspecArcLineIntersection, 3 )
00376 {
00377 }
00378
00379 ArcLineIntersectionType::~ArcLineIntersectionType()
00380 {
00381 }
00382
00383 const ArcLineIntersectionType* ArcLineIntersectionType::instance()
00384 {
00385 static const ArcLineIntersectionType t;
00386 return &t;
00387 }
00388
00389 ObjectImp* ArcLineIntersectionType::calc( const Args& parents, const KigDocument& ) const
00390 {
00391 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
00392
00393 int side = static_cast<const IntImp*>( parents[2] )->data();
00394 assert( side == 1 || side == -1 );
00395 const LineData line = static_cast<const AbstractLineImp*>( parents[1] )->data();
00396
00397 const ArcImp* c = static_cast<const ArcImp*>( parents[0] );
00398 const double r = c->radius();
00399 Coordinate ret = calcArcLineIntersect( c->center(), r*r, c->startAngle(),
00400 c->angle(), line, side );
00401 if ( ret.valid() ) return new PointImp( ret );
00402 else return new InvalidImp;
00403 }
00404
00405 const ObjectImpType* ArcLineIntersectionType::resultId() const
00406 {
00407 return PointImp::stype();
00408 }