• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdeedu
  • Sitemap
  • Contact Us
 

kig

intersection_types.cc

Go to the documentation of this file.
00001 // Copyright (C)  2003  Dominique Devriese <devriese@kde.org>
00002 
00003 // This program is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU General Public License
00005 // as published by the Free Software Foundation; either version 2
00006 // of the License, or (at your option) any later version.
00007 
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software
00015 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00016 // 02110-1301, USA.
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     // easy case..
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     // harder case..
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  * This construction is authomatically invoked when the user 
00089  * intersects a line with a conic with one of the intersections
00090  * already present.  There are two positive side effects:
00091  * 1. The production of coincident points is greatly reduced
00092  * 2. The "other" intersection will remain the "other" one also
00093  * when dynamically moving the construction, which is what the
00094  * user expects
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  * This construction is authomatically invoked when the user 
00152  * intersects two circles with one of the intersections
00153  * already present, see above...
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 );   /* w is normal to the line through the centers */
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 /* LineLineIntersection */
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 }

kig

Skip menu "kig"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

kdeedu

Skip menu "kdeedu"
  • kalzium
  • kanagram
  • kig
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  •   docs
  •   src
  • parley
Generated for kdeedu by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal