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

kig

conic_imp.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 "conic_imp.h"
00019 
00020 #include <math.h>
00021 
00022 #include "bogus_imp.h"
00023 #include "point_imp.h"
00024 
00025 #include "../misc/kigpainter.h"
00026 #include "../misc/common.h"
00027 #include "../misc/coordinate_system.h"
00028 
00029 #include "../kig/kig_document.h"
00030 #include "../kig/kig_view.h"
00031 
00032 #include <klocale.h>
00033 
00034 ObjectImp* ConicImp::transform( const Transformation& t ) const
00035 {
00036   bool valid = true;
00037   ConicCartesianData d = calcConicTransformation( cartesianData(), t, valid );
00038   if ( ! valid ) return new InvalidImp;
00039   else return new ConicImpCart( d );
00040 }
00041 
00042 void ConicImp::draw( KigPainter& p ) const
00043 {
00044   p.drawCurve( this );
00045 }
00046 
00047 bool ConicImp::valid() const
00048 {
00049   return true;
00050 }
00051 
00052 bool ConicImp::contains( const Coordinate& o, int width, const KigWidget& w ) const
00053 {
00054   return internalContainsPoint( o, w.screenInfo().normalMiss( width ) );
00055 }
00056 
00057 bool ConicImp::inRect( const Rect&, int, const KigWidget& ) const
00058 {
00059   // TODO
00060   return false;
00061 }
00062 
00063 int ConicImp::numberOfProperties() const
00064 {
00065   return Parent::numberOfProperties() + 6;
00066 }
00067 
00068 const QByteArrayList ConicImp::propertiesInternalNames() const
00069 {
00070   QByteArrayList l = Parent::propertiesInternalNames();
00071   l << "type";
00072   l << "center";
00073   l << "first-focus";
00074   l << "second-focus";
00075   l << "cartesian-equation";
00076   l << "polar-equation";
00077   assert( l.size() == ConicImp::numberOfProperties() );
00078   return l;
00079 }
00080 
00081 const QByteArrayList ConicImp::properties() const
00082 {
00083   QByteArrayList l = Parent::properties();
00084   l << I18N_NOOP( "Conic Type" );
00085   l << I18N_NOOP( "Center" );
00086   l << I18N_NOOP( "First Focus" );
00087   l << I18N_NOOP( "Second Focus" );
00088   l << I18N_NOOP( "Cartesian Equation" );
00089   l << I18N_NOOP( "Polar Equation" );
00090   assert( l.size() == ConicImp::numberOfProperties() );
00091   return l;
00092 }
00093 
00094 const ObjectImpType* ConicImp::impRequirementForProperty( int which ) const
00095 {
00096   if ( which < Parent::numberOfProperties() )
00097     return Parent::impRequirementForProperty( which );
00098   else return ConicImp::stype();
00099 }
00100 
00101 const char* ConicImp::iconForProperty( int which ) const
00102 {
00103   int pnum = 0;
00104   if ( which < Parent::numberOfProperties() )
00105     return Parent::iconForProperty( which );
00106   if ( which == Parent::numberOfProperties() + pnum++ )
00107     return "kig_text"; // conic type string
00108   else if ( which == Parent::numberOfProperties() + pnum++ )
00109     return ""; // center
00110   else if ( which == Parent::numberOfProperties() + pnum++ )
00111     return ""; // focus1
00112   else if ( which == Parent::numberOfProperties() + pnum++ )
00113     return ""; // focus2
00114   else if ( which == Parent::numberOfProperties() + pnum++ )
00115     return "kig_text"; // cartesian equation string
00116   else if ( which == Parent::numberOfProperties() + pnum++ )
00117     return "kig_text"; // polar equation string
00118   else assert( false );
00119   return "";
00120 }
00121 
00122 ObjectImp* ConicImp::property( int which, const KigDocument& w ) const
00123 {
00124   int pnum = 0;
00125 
00126   if ( which < Parent::numberOfProperties() )
00127     return Parent::property( which, w );
00128   if ( which == Parent::numberOfProperties() + pnum++ )
00129     return new StringImp( conicTypeString() );
00130   else if ( which == Parent::numberOfProperties() + pnum++ )
00131     return new PointImp( coniccenter() );
00132   else if ( which == Parent::numberOfProperties() + pnum++ )
00133     return new PointImp( focus1() );
00134   else if ( which == Parent::numberOfProperties() + pnum++ )
00135     return new PointImp( focus2() );
00136   else if ( which == Parent::numberOfProperties() + pnum++ )
00137     return new StringImp( cartesianEquationString( w ) );
00138   else if ( which == Parent::numberOfProperties() + pnum++ )
00139     return new StringImp( polarEquationString( w ) );
00140   else assert( false );
00141   return new InvalidImp;
00142 }
00143 
00144 double ConicImp::getParam( const Coordinate& p, const KigDocument& ) const
00145 {
00146   return getParam( p );
00147 }
00148 
00149 double ConicImp::getParam( const Coordinate& p ) const
00150 {
00151   const ConicPolarData d = polarData();
00152   Coordinate tmp = p - d.focus1;
00153   double l = tmp.length();
00154   double theta = atan2(tmp.y, tmp.x);
00155   double costheta = cos(theta);
00156   double sintheta = sin(theta);
00157   double ecosthetamtheta0 = costheta*d.ecostheta0 + sintheta*d.esintheta0;
00158   double esinthetamtheta0 = sintheta*d.ecostheta0 - costheta*d.esintheta0;
00159   double oneplus = 1.0 + d.ecostheta0*d.ecostheta0 + d.esintheta0*d.esintheta0;
00160   double fact = esinthetamtheta0*(1.0 - ecosthetamtheta0)/(oneplus - 2*ecosthetamtheta0);
00161 // fact is sin(a)*cos(a) where a is the angle between the ray from the first
00162 // focus and the normal to the conic.  We need it in order to adjust the
00163 // angle according to the projection onto the conic of our point
00164   double rho1 = d.pdimen / (1 - ecosthetamtheta0);
00165   double rho2 = - d.pdimen / (1 + ecosthetamtheta0);
00166   if (fabs(rho1 - l) < fabs(rho2 - l))
00167   {
00168     theta += (rho1 - l)*fact/rho1;
00169     return fmod(theta / ( 2 * M_PI ) + 1, 1);
00170   } else {
00171     theta += (rho2 - l)*fact/rho2;
00172     return fmod(theta / ( 2 * M_PI ) + 0.5, 1);
00173   }
00174 }
00175 
00176 const Coordinate ConicImp::getPoint( double p, const KigDocument& ) const
00177 {
00178   return getPoint( p );
00179 }
00180 
00181 const Coordinate ConicImp::getPoint( double p ) const
00182 {
00183   const ConicPolarData d = polarData();
00184 
00185   double costheta = cos(p * 2 * M_PI);
00186   double sintheta = sin(p * 2 * M_PI);
00187   double rho = d.pdimen / (1 - costheta* d.ecostheta0 - sintheta* d.esintheta0);
00188   return d.focus1 + Coordinate (costheta, sintheta) * rho;
00189 }
00190 
00191 int ConicImp::conicType() const
00192 {
00193   const ConicPolarData d = polarData();
00194   double ec = d.ecostheta0;
00195   double es = d.esintheta0;
00196   double esquare = ec*ec + es*es;
00197   const double parabolamiss = 1e-3;  // don't know what a good value could be
00198 
00199   if (esquare < 1.0 - parabolamiss) return 1;
00200   if (esquare > 1.0 + parabolamiss) return -1;
00201 
00202   return 0;
00203 }
00204 
00205 QString ConicImp::conicTypeString() const
00206 {
00207   switch (conicType())
00208   {
00209   case 1:
00210     return i18n("Ellipse");
00211   case -1:
00212     return i18n("Hyperbola");
00213   case 0:
00214     return i18n("Parabola");
00215   default:
00216     assert( false );
00217     return "";
00218   }
00219 }
00220 
00221 QString ConicImp::cartesianEquationString( const KigDocument& ) const
00222 {
00223   ConicCartesianData data = cartesianData();
00224   EquationString ret = EquationString( "" );
00225   bool needsign = false;
00226   if ( isVerticalParabola( data ) )
00227   {
00228     double f = - 1.0/data.coeffs[4];
00229     ret.addTerm( - f*data.coeffs[4], ret.y(), needsign );
00230     ret.append( " = " );
00231     needsign = false;
00232     ret.addTerm( f*data.coeffs[0], ret.x2(), needsign );
00233     ret.addTerm( f*data.coeffs[1], ret.y2(), needsign );
00234     ret.addTerm( f*data.coeffs[2], ret.xy(), needsign );
00235     ret.addTerm( f*data.coeffs[3], ret.x(), needsign );
00236     ret.addTerm( f*data.coeffs[5], "", needsign );
00237     return ret;
00238   }
00239   ret.addTerm( data.coeffs[0], ret.x2(), needsign );
00240   ret.addTerm( data.coeffs[1], ret.y2(), needsign );
00241   ret.addTerm( data.coeffs[2], ret.xy(), needsign );
00242   ret.addTerm( data.coeffs[3], ret.x(), needsign );
00243   ret.addTerm( data.coeffs[4], ret.y(), needsign );
00244   ret.addTerm( data.coeffs[5], "", needsign );
00245   ret.append( " = 0" );
00246   return ret;
00247 
00248 //  QString ret = i18n( "%1 x² + %2 y² + %3 xy + %4 x + %5 y + %6 = 0" );
00249 //  ConicCartesianData data = cartesianData();
00250 //  ret = ret.arg( data.coeffs[0], 0, 'g', 3 );
00251 //  ret = ret.arg( data.coeffs[1], 0, 'g', 3 );
00252 //  ret = ret.arg( data.coeffs[2], 0, 'g', 3 );
00253 //  ret = ret.arg( data.coeffs[3], 0, 'g', 3 );
00254 //  ret = ret.arg( data.coeffs[4], 0, 'g', 3 );
00255 //  ret = ret.arg( data.coeffs[5], 0, 'g', 3 );
00256 //  return ret;
00257 }
00258 
00259 QString ConicImp::polarEquationString( const KigDocument& w ) const
00260 {
00261 //  QString ret = i18n( "rho = %1/(1 + %2 cos theta + %3 sin theta)\n    [centered at %4]" );
00262   const ConicPolarData data = polarData();
00263 
00264   EquationString ret = EquationString( i18n( "rho" ) );
00265   ret.append( " = " );
00266   if ( data.pdimen < 0 ) ret.append( "- " );
00267   bool needsign = false;
00268   ret.addTerm( fabs( data.pdimen ), "", needsign );
00269   ret.append( "/(1" );
00270   needsign = true;
00271   ret.addTerm( -data.ecostheta0, i18n( "cos theta" ), needsign );
00272   ret.addTerm( -data.esintheta0, i18n( "sin theta" ), needsign );
00273   ret.append( ")\n" );
00274   ret.append( ki18n( "[centered at %1]" )
00275                    .subs( w.coordinateSystem().fromScreen( data.focus1, w ) )
00276 //                   .subs( data.pdimen, 0, 'g', 3 );
00277 //                   .subs( -data.ecostheta0, 0, 'g', 3 );
00278 //                   .subs( -data.esintheta0, 0, 'g', 3 );
00279                    .toString() );
00280 
00281   ret.prettify();
00282   return ret;
00283 }
00284 
00285 const ConicCartesianData ConicImp::cartesianData() const
00286 {
00287   return ConicCartesianData( polarData() );
00288 }
00289 
00290 Coordinate ConicImp::focus1() const
00291 {
00292   return polarData().focus1;
00293 }
00294 
00295 Coordinate ConicImp::coniccenter() const
00296 {
00297   const ConicPolarData d = polarData();
00298   double ec = d.ecostheta0;
00299   double es = d.esintheta0;
00300 
00301   double fact = d.pdimen/(1 - ec*ec - es*es);
00302 
00303   return d.focus1 + fact*Coordinate(ec, es);
00304 }
00305 
00306 Coordinate ConicImp::focus2() const
00307 {
00308   const ConicPolarData d = polarData();
00309   double ec = d.ecostheta0;
00310   double es = d.esintheta0;
00311 
00312   double fact = 2*d.pdimen/(1 - ec*ec - es*es);
00313 
00314   return d.focus1 + fact*Coordinate(ec, es);
00315 }
00316 
00317 const ConicPolarData ConicImpCart::polarData() const
00318 {
00319   return mpolardata;
00320 }
00321 
00322 const ConicCartesianData ConicImpCart::cartesianData() const
00323 {
00324   return mcartdata;
00325 }
00326 
00327 ConicImpCart::ConicImpCart( const ConicCartesianData& data )
00328   : ConicImp(), mcartdata( data ), mpolardata( data )
00329 {
00330   //assert( data.valid() );
00331 }
00332 
00333 ConicImpPolar::ConicImpPolar( const ConicPolarData& data )
00334   : ConicImp(), mdata( data )
00335 {
00336 }
00337 
00338 ConicImpPolar::~ConicImpPolar()
00339 {
00340 }
00341 
00342 const ConicPolarData ConicImpPolar::polarData() const
00343 {
00344   return mdata;
00345 }
00346 
00347 ConicImpCart* ConicImpCart::copy() const
00348 {
00349   return new ConicImpCart( mcartdata );
00350 }
00351 
00352 ConicImpPolar* ConicImpPolar::copy() const
00353 {
00354   return new ConicImpPolar( mdata );
00355 }
00356 
00357 ConicImp::ConicImp()
00358 {
00359 }
00360 
00361 ConicImp::~ConicImp()
00362 {
00363 }
00364 
00365 ConicImpCart::~ConicImpCart()
00366 {
00367 }
00368 
00369 void ConicImp::visit( ObjectImpVisitor* vtor ) const
00370 {
00371   vtor->visit( this );
00372 }
00373 
00374 bool ConicImp::equals( const ObjectImp& rhs ) const
00375 {
00376   return rhs.inherits( ConicImp::stype() ) &&
00377     static_cast<const ConicImp&>( rhs ).polarData() == polarData();
00378 }
00379 
00380 const ObjectImpType* ConicImp::stype()
00381 {
00382   static const ObjectImpType t(
00383     Parent::stype(), "conic",
00384     I18N_NOOP( "conic" ),
00385     I18N_NOOP( "Select this conic" ),
00386     I18N_NOOP( "Select conic %1" ),
00387     I18N_NOOP( "Remove a Conic" ),
00388     I18N_NOOP( "Add a Conic" ),
00389     I18N_NOOP( "Move a Conic" ),
00390     I18N_NOOP( "Attach to this conic" ),
00391     I18N_NOOP( "Show a Conic" ),
00392     I18N_NOOP( "Hide a Conic" )
00393     );
00394   return &t;
00395 }
00396 
00397 const ObjectImpType* ConicImp::type() const
00398 {
00399   return ConicImp::stype();
00400 }
00401 
00402 bool ConicImp::containsPoint( const Coordinate& p, const KigDocument& ) const
00403 {
00404   const ConicPolarData d = polarData();
00405 
00406 // the threshold is relative to the size of the conic (mp)
00407   return internalContainsPoint( p, test_threshold*d.pdimen );
00408 }
00409 
00410 bool ConicImp::internalContainsPoint( const Coordinate& p, double threshold ) const
00411 {
00412   const ConicPolarData d = polarData();
00413 
00414   Coordinate focus1 = d.focus1;
00415   double ecostheta0 = d.ecostheta0;
00416   double esintheta0 = d.esintheta0;
00417   double pdimen = d.pdimen;
00418 
00419   Coordinate pos = p - focus1;
00420   double len = pos.length();
00421   double costheta = pos.x / len;
00422   double sintheta = pos.y / len;
00423 
00424   double ecosthetamtheta0 = costheta*ecostheta0 + sintheta*esintheta0;
00425   double rho = pdimen / (1.0 - ecosthetamtheta0);
00426 
00427   double oneplus = 1.0 + ecostheta0*ecostheta0 + esintheta0*esintheta0;
00428 
00429 // fact is the cosine of the angle between the ray from the first focus
00430 // and the normal to the conic, so that we compute the real distance
00431 
00432   double fact = (1.0 - ecosthetamtheta0)/sqrt(oneplus - 2*ecosthetamtheta0);
00433   if ( fabs((len - rho)*fact) <= threshold ) return true;
00434   rho = - pdimen / ( 1.0 + ecosthetamtheta0 );
00435   fact = (1.0 + ecosthetamtheta0)/sqrt(oneplus + 2*ecosthetamtheta0);
00436   return fabs(( len - rho )*fact) <= threshold;
00437 }
00438 
00439 bool ConicImp::isPropertyDefinedOnOrThroughThisImp( int which ) const
00440 {
00441   if ( which < Parent::numberOfProperties() )
00442     return Parent::isPropertyDefinedOnOrThroughThisImp( which );
00443   return false;
00444 }
00445 
00446 bool ConicImp::isVerticalParabola( ConicCartesianData& data ) const
00447 {
00448   return (
00449            fabs( data.coeffs[1] ) < 1e-12 &&     // y^2
00450            fabs( data.coeffs[2] ) < 1e-12 &&     // xy
00451            fabs( data.coeffs[4] ) > 1e-5 );      // y
00452 }
00453 
00454 Rect ConicImp::surroundingRect() const
00455 {
00456   // it's prolly possible to calculate this ( in the case that the
00457   // conic is limited in size ), but for now we don't.
00458 
00459   return Rect::invalidRect();
00460 }
00461 
00462 /* An arc of a conic is identified by a startangle and a size (angle);
00463  * both angles are measured with respect to the first focus of the conic
00464  * (the one used for the conic polar equation
00465  */
00466 
00467 ConicArcImp::ConicArcImp( const ConicCartesianData& data,
00468                   const double startangle, const double angle )
00469   : ConicImpCart( data ), msa( startangle ), ma( angle )
00470 {
00471 }
00472 
00473 ConicArcImp::~ConicArcImp()
00474 {
00475 }
00476 
00477 ConicArcImp* ConicArcImp::copy() const
00478 {
00479   return new ConicArcImp( mcartdata, msa, ma );
00480 }
00481 
00482 ObjectImp* ConicArcImp::transform( const Transformation& t ) const
00483 {
00484   bool valid = true;
00485   ConicCartesianData d = calcConicTransformation( cartesianData(), t, valid );
00486   if ( ! valid ) return new InvalidImp;
00487   ConicArcImp* result = new ConicArcImp( d, 0.0, 2*M_PI );
00488 
00489   Coordinate a = t.apply( getPoint ( 0. ) );
00490   Coordinate b = t.apply( getPoint( 0.5 ) );
00491   Coordinate c = t.apply( getPoint( 1. ) );
00492   double anglea = 2*M_PI*result->getParam( a );
00493   double angleb = 2*M_PI*result->getParam( b );
00494   double anglec = 2*M_PI*result->getParam( c );
00495   double startangle = 0.;
00496   double angle = 2*M_PI;
00497   // anglea should be smaller than anglec
00498   if ( anglea > anglec )
00499   {
00500     double t = anglea;
00501     anglea = anglec;
00502     anglec = t;
00503   };
00504   if ( angleb > anglec || angleb < anglea )
00505   {
00506     startangle = anglec;
00507     angle = 2 * M_PI + anglea - startangle;
00508   }
00509   else
00510   {
00511     startangle = anglea;
00512     angle = anglec - anglea;
00513   };
00514 
00515   result->setStartAngle( startangle );
00516   result->setAngle( angle );
00517   return result;
00518 }
00519 
00520 bool ConicArcImp::contains( const Coordinate& o, int width, const KigWidget& w ) const
00521 {
00522   return internalContainsPoint( o, w.screenInfo().normalMiss( width ),
00523      w.document() );
00524 }
00525 
00526 int ConicArcImp::numberOfProperties() const
00527 {
00528   return Parent::numberOfProperties() + 3;
00529 }
00530 
00531 const QByteArrayList ConicArcImp::properties() const
00532 {
00533   QByteArrayList ret = Parent::properties();
00534   ret << I18N_NOOP( "Supporting Conic" );
00535   ret << I18N_NOOP( "First End Point" );
00536   ret << I18N_NOOP( "Second End Point" );
00537   assert( ret.size() == ConicArcImp::numberOfProperties() );
00538   return ret;
00539 }
00540 
00541 const QByteArrayList ConicArcImp::propertiesInternalNames() const
00542 {
00543   QByteArrayList ret = Parent::propertiesInternalNames();
00544   ret << "support";
00545   ret << "end-point-A";
00546   ret << "end-point-B";
00547   return ret;
00548 }
00549 
00550 const char* ConicArcImp::iconForProperty( int which ) const
00551 {
00552   int numprop = 0;
00553   if ( which < Parent::numberOfProperties() )
00554     return Parent::iconForProperty( which );
00555   else if ( which == Parent::numberOfProperties() + numprop++ )
00556     return "";
00557   else if ( which == Parent::numberOfProperties() + numprop++ )
00558     return "";
00559   else if ( which == Parent::numberOfProperties() + numprop++ )
00560     return "";
00561   else assert( false );
00562   return "";
00563 }
00564 
00565 ObjectImp* ConicArcImp::property( int which, const KigDocument& d ) const
00566 {
00567   int numprop = 0;
00568   if ( which < Parent::numberOfProperties() )
00569     return Parent::property( which, d );
00570   else if ( which == Parent::numberOfProperties() + numprop++ )
00571     return new ConicImpCart( cartesianData() );
00572   else if ( which == Parent::numberOfProperties() + numprop++ )
00573     return new PointImp( firstEndPoint());
00574   else if ( which == Parent::numberOfProperties() + numprop++ )
00575     return new PointImp( secondEndPoint());
00576   else return new InvalidImp;
00577   return new InvalidImp;
00578 }
00579 
00580 bool ConicArcImp::isPropertyDefinedOnOrThroughThisImp( int which ) const
00581 {
00582   int pnum = 0;
00583 
00584   if ( which < Parent::numberOfProperties() )
00585     return Parent::isPropertyDefinedOnOrThroughThisImp( which );
00586   else if ( which == Parent::numberOfProperties() + pnum++ )
00587     return false;  // support
00588   else if ( which == Parent::numberOfProperties() + pnum++ )
00589     return true;   // first end-point
00590   else if ( which == Parent::numberOfProperties() + pnum++ )
00591     return true;   // second end-point
00592   else return false;
00593   return false;
00594 }
00595 
00596 Coordinate ConicArcImp::firstEndPoint() const
00597 {
00598   return getPoint( 0. );
00599 }
00600 
00601 Coordinate ConicArcImp::secondEndPoint() const
00602 {
00603   return getPoint( 1. );
00604 }
00605 
00606 const ObjectImpType* ConicArcImp::stype()
00607 {
00608   static const ObjectImpType t(
00609     Parent::stype(), "conic arc",
00610     I18N_NOOP( "conic arc" ),
00611     I18N_NOOP( "Select this conic arc" ),
00612     I18N_NOOP( "Select conic arc %1" ),
00613     I18N_NOOP( "Remove a Conic Arc" ),
00614     I18N_NOOP( "Add a Conic Arc" ),
00615     I18N_NOOP( "Move a Conic Arc" ),
00616     I18N_NOOP( "Attach to this conic arc" ),
00617     I18N_NOOP( "Show a Conic Arc" ),
00618     I18N_NOOP( "Hide a Conic Arc" )
00619     );
00620   return &t;
00621 }
00622 
00623 const ObjectImpType* ConicArcImp::type() const
00624 {
00625   return ConicArcImp::stype();
00626 }
00627 
00628 bool ConicArcImp::containsPoint( const Coordinate& p, const KigDocument& doc) const
00629 {
00630   const ConicPolarData d = polarData();
00631 
00632 // the threshold is relative to the size of the conic (mp)
00633   return internalContainsPoint( p, test_threshold*d.pdimen, doc );
00634 }
00635 
00636 bool ConicArcImp::internalContainsPoint( const Coordinate& p, double threshold,
00637     const KigDocument& doc ) const
00638 {
00639   // this is directly stolen from locus code...
00640   double param = getParam( p, doc );
00641   Coordinate p1 = getPoint( param, doc );
00642   double dist = (p1 - p).length();
00643   return fabs( dist ) <= threshold;
00644 }
00645 
00646 double ConicArcImp::getParam( const Coordinate& p, const KigDocument& ) const
00647 {
00648   return getParam( p );
00649 }
00650 
00651 double ConicArcImp::getParam( const Coordinate& p ) const
00652 {
00653   double thetarel = 2 * M_PI * ConicImpCart::getParam( p ) - msa;
00654   while ( thetarel < 0 ) thetarel += 2 * M_PI;
00655   if ( thetarel <= ma ) return ( thetarel / ma );
00656 
00657   double antipodo = ( 2 * M_PI + ma )/2;
00658   if ( thetarel < antipodo ) return (1.0);
00659   return (0.0);
00660 }
00661 
00662 const Coordinate ConicArcImp::getPoint( double p, const KigDocument& ) const
00663 {
00664   return getPoint( p );
00665 }
00666 
00667 const Coordinate ConicArcImp::getPoint( double p ) const
00668 {
00669   double pwide = ( p * ma + msa )/ (2*M_PI);
00670   return ConicImpCart::getPoint( pwide );
00671 }
00672 

kig

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