moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kig / objects / conic_types.cc
blob5aec3eafc6f049ca31fa69104e8091e64a6da8de
1 // Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
16 // 02111-1307, USA.
18 #include "conic_types.h"
20 #include "bogus_imp.h"
21 #include "conic_imp.h"
22 #include "point_imp.h"
23 #include "circle_imp.h"
24 #include "line_imp.h"
25 #include "object_calcer.h"
26 #include "../misc/conic-common.h"
27 #include "../misc/common.h"
28 #include "../kig/kig_commands.h"
29 #include "../kig/kig_part.h"
31 #include <klocale.h>
33 static const char conic_constructstatement[] = I18N_NOOP( "Construct a conic through this point" );
35 static const struct ArgsParser::spec argsspecConicB5P[] =
37 { PointImp::stype(), conic_constructstatement,
38 I18N_NOOP( "Select a point for the new conic to go through..." ), true },
39 { PointImp::stype(), conic_constructstatement,
40 I18N_NOOP( "Select a point for the new conic to go through..." ), true },
41 { PointImp::stype(), conic_constructstatement,
42 I18N_NOOP( "Select a point for the new conic to go through..." ), true },
43 { PointImp::stype(), conic_constructstatement,
44 I18N_NOOP( "Select a point for the new conic to go through..." ), true },
45 { PointImp::stype(), conic_constructstatement,
46 I18N_NOOP( "Select a point for the new conic to go through..." ),true }
49 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicB5PType )
51 ConicB5PType::ConicB5PType()
52 : ArgsParserObjectType( "ConicB5P", argsspecConicB5P, 5 )
56 ConicB5PType::~ConicB5PType()
60 ObjectImp* ConicB5PType::calc( const Args& parents, const KigDocument& ) const
62 if ( ! margsparser.checkArgs( parents, 1 ) ) return new InvalidImp;
63 std::vector<Coordinate> points;
65 for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i )
66 points.push_back( static_cast<const PointImp*>( *i )->coordinate() );
68 ConicCartesianData d =
69 calcConicThroughPoints( points, zerotilt, parabolaifzt, ysymmetry );
70 if ( d.valid() )
71 return new ConicImpCart( d );
72 else return new InvalidImp;
75 const ConicB5PType* ConicB5PType::instance()
77 static const ConicB5PType t;
78 return &t;
81 static const ArgsParser::spec argsspecConicBAAP[] =
83 { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this asymptote" ),
84 I18N_NOOP( "Select the first asymptote of the new conic..." ), false },
85 { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this asymptote" ),
86 I18N_NOOP( "Select the second asymptote of the new conic..." ), false },
87 { PointImp::stype(), I18N_NOOP( "Construct a conic through this point" ),
88 I18N_NOOP( "Select a point for the new conic to go through..." ), true }
91 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicBAAPType )
93 ConicBAAPType::ConicBAAPType()
94 : ArgsParserObjectType( "ConicBAAP", argsspecConicBAAP, 3 )
98 ConicBAAPType::~ConicBAAPType()
102 const ConicBAAPType* ConicBAAPType::instance()
104 static const ConicBAAPType t;
105 return &t;
108 ObjectImp* ConicBAAPType::calc( const Args& parents, const KigDocument& ) const
110 if ( ! margsparser.checkArgs( parents ) )
111 return new InvalidImp;
112 const LineData la = static_cast<const AbstractLineImp*>( parents[0] )->data();
113 const LineData lb = static_cast<const AbstractLineImp*>( parents[1] )->data();
114 const Coordinate c = static_cast<const PointImp*>( parents[2] )->coordinate();
116 return new ConicImpCart( calcConicByAsymptotes( la, lb, c ) );
119 ObjectImp* ConicBFFPType::calc( const Args& parents, const KigDocument& ) const
121 if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp;
122 std::vector<Coordinate> cs;
124 for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i )
125 cs.push_back( static_cast<const PointImp*>( *i )->coordinate() );
127 return new ConicImpPolar( calcConicBFFP( cs, type() ) );
130 ConicBFFPType::ConicBFFPType( const char* fullname, const ArgsParser::spec* spec, int n )
131 : ArgsParserObjectType( fullname, spec, n )
135 ConicBFFPType::~ConicBFFPType()
139 static const char constructellipsewithfocusstat[] =
140 I18N_NOOP( "Construct an ellipse with this focus" );
142 static const ArgsParser::spec argsspecEllipseBFFP[] =
144 { PointImp::stype(), constructellipsewithfocusstat,
145 I18N_NOOP( "Select the first focus of the new ellipse..." ), false },
146 { PointImp::stype(), constructellipsewithfocusstat,
147 I18N_NOOP( "Select the second focus of the new ellipse..." ), false },
148 { PointImp::stype(), I18N_NOOP( "Construct an ellipse through this point" ),
149 I18N_NOOP( "Select a point for the new ellipse to go through..." ), true }
152 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( EllipseBFFPType )
154 EllipseBFFPType::EllipseBFFPType()
155 : ConicBFFPType( "EllipseBFFP", argsspecEllipseBFFP, 3 )
159 EllipseBFFPType::~EllipseBFFPType()
163 int EllipseBFFPType::type() const
165 return 1;
168 const EllipseBFFPType* EllipseBFFPType::instance()
170 static const EllipseBFFPType t;
171 return &t;
174 static const char constructhyperbolawithfocusstat[] =
175 I18N_NOOP( "Construct a hyperbola with this focus" );
177 static const ArgsParser::spec argsspecHyperbolaBFFP[] =
179 { PointImp::stype(), constructhyperbolawithfocusstat,
180 I18N_NOOP( "Select the first focus of the new hyperbola..." ), false },
181 { PointImp::stype(), constructhyperbolawithfocusstat,
182 I18N_NOOP( "Select the second focus of the new hyperbola..." ), false },
183 { PointImp::stype(), I18N_NOOP( "Construct a hyperbola through this point" ),
184 I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true }
187 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HyperbolaBFFPType )
189 HyperbolaBFFPType::HyperbolaBFFPType()
190 : ConicBFFPType( "HyperbolaBFFP", argsspecHyperbolaBFFP, 3 )
194 HyperbolaBFFPType::~HyperbolaBFFPType()
198 const HyperbolaBFFPType* HyperbolaBFFPType::instance()
200 static const HyperbolaBFFPType t;
201 return &t;
204 int HyperbolaBFFPType::type() const
206 return -1;
209 const ConicBDFPType* ConicBDFPType::instance()
211 static const ConicBDFPType t;
212 return &t;
215 static const struct ArgsParser::spec argsspecConicBDFP[] =
217 { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this line as directrix" ),
218 I18N_NOOP( "Select the directrix of the new conic..." ), false },
219 { PointImp::stype(), I18N_NOOP( "Construct a conic with this point as focus" ),
220 I18N_NOOP( "Select the focus of the new conic..." ), false },
221 { PointImp::stype(), I18N_NOOP( "Construct a conic through this point" ),
222 I18N_NOOP( "Select a point for the new conic to go through..." ), true }
225 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicBDFPType )
227 ConicBDFPType::ConicBDFPType()
228 : ArgsParserObjectType( "ConicBDFP", argsspecConicBDFP, 3 )
232 ConicBDFPType::~ConicBDFPType()
236 ObjectImp* ConicBDFPType::calc( const Args& parents, const KigDocument& ) const
238 if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp;
240 const LineData line = static_cast<const AbstractLineImp*>( parents[0] )->data();
241 const Coordinate focus =
242 static_cast<const PointImp*>( parents[1] )->coordinate();
244 Coordinate point;
245 if ( parents.size() == 3 )
246 point = static_cast<const PointImp*>( parents[2] )->coordinate();
247 else
249 /* !!!! costruisci point come punto medio dell'altezza tra fuoco e d. */
250 Coordinate ba = line.dir();
251 Coordinate fa = focus - line.b;
252 double balsq = ba.x*ba.x + ba.y*ba.y;
253 double scal = (fa.x*ba.x + fa.y*ba.y)/balsq;
254 point = 0.5*(line.a + focus + scal*ba);
256 return new ConicImpPolar( calcConicBDFP( line, focus, point ) );
259 static const char constructparabolathroughpointstat[] =
260 I18N_NOOP( "Construct a parabola through this point" );
262 static const ArgsParser::spec argsspecParabolaBTP[] =
264 { PointImp::stype(), constructparabolathroughpointstat,
265 I18N_NOOP( "Select a point for the new parabola to go through..." ), true },
266 { PointImp::stype(), constructparabolathroughpointstat,
267 I18N_NOOP( "Select a point for the new parabola to go through..." ), true },
268 { PointImp::stype(), constructparabolathroughpointstat,
269 I18N_NOOP( "Select a point for the new parabola to go through..." ), true }
272 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ParabolaBTPType )
274 ParabolaBTPType::ParabolaBTPType()
275 : ArgsParserObjectType( "ParabolaBTP", argsspecParabolaBTP, 3 )
279 ParabolaBTPType::~ParabolaBTPType()
283 const ParabolaBTPType* ParabolaBTPType::instance()
285 static const ParabolaBTPType t;
286 return &t;
289 ObjectImp* ParabolaBTPType::calc( const Args& parents, const KigDocument& ) const
291 if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp;
293 std::vector<Coordinate> points;
294 for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i )
295 points.push_back( static_cast<const PointImp*>( *i )->coordinate() );
297 ConicCartesianData d =
298 calcConicThroughPoints( points, zerotilt, parabolaifzt, ysymmetry );
299 if ( d.valid() )
300 return new ConicImpCart( d );
301 else
302 return new InvalidImp;
305 static const ArgsParser::spec argsspecConicPolarPoint[] =
307 { ConicImp::stype(), I18N_NOOP( "Construct a polar point wrt. this conic" ),
308 I18N_NOOP( "Select the conic wrt. which you want to construct a polar point..." ), false },
309 { AbstractLineImp::stype(), I18N_NOOP( "Construct the polar point of this line" ),
310 I18N_NOOP( "Select the line of which you want to construct the polar point..." ), false }
313 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicPolarPointType )
315 ConicPolarPointType::ConicPolarPointType()
316 : ArgsParserObjectType( "ConicPolarPoint", argsspecConicPolarPoint, 2 )
320 ConicPolarPointType::~ConicPolarPointType()
324 const ConicPolarPointType* ConicPolarPointType::instance()
326 static const ConicPolarPointType t;
327 return &t;
330 ObjectImp* ConicPolarPointType::calc( const Args& parents, const KigDocument& ) const
332 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
334 const ConicCartesianData c = static_cast<const ConicImp*>( parents[0] )->cartesianData();
335 const LineData l = static_cast<const AbstractLineImp*>( parents[1] )->data();
336 const Coordinate p = calcConicPolarPoint( c, l );
337 if ( p.valid() ) return new PointImp( p );
338 else return new InvalidImp;
341 static const ArgsParser::spec argsspecConicPolarLine[] =
343 { ConicImp::stype(), I18N_NOOP( "Construct a polar line wrt. this conic" ),
344 I18N_NOOP( "Select the conic wrt. which you want to construct a polar point..." ), false },
345 { PointImp::stype(), I18N_NOOP( "Construct the polar line of this point" ),
346 I18N_NOOP( "Select the line of which you want to construct the polar point..." ), false }
349 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicPolarLineType )
351 ConicPolarLineType::ConicPolarLineType()
352 : ArgsParserObjectType( "ConicPolarLine", argsspecConicPolarLine, 2 )
356 ConicPolarLineType::~ConicPolarLineType()
360 const ConicPolarLineType* ConicPolarLineType::instance()
362 static const ConicPolarLineType t;
363 return &t;
366 ObjectImp* ConicPolarLineType::calc( const Args& parents, const KigDocument& ) const
368 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
370 const ConicCartesianData c = static_cast<const ConicImp*>( parents[0] )->cartesianData();
371 const Coordinate p = static_cast<const PointImp*>( parents[1] )->coordinate();
372 bool valid = true;
373 const LineData l = calcConicPolarLine( c, p, valid );
374 if ( valid ) return new LineImp( l );
375 else return new InvalidImp;
378 static const ArgsParser::spec argsspecConicDirectrix[] =
380 { ConicImp::stype(), I18N_NOOP( "Construct the directrix of this conic" ),
381 I18N_NOOP( "Select the conic of which you want to construct the directrix..." ), false }
384 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicDirectrixType )
386 ConicDirectrixType::ConicDirectrixType()
387 : ArgsParserObjectType( "ConicDirectrix", argsspecConicDirectrix, 1 )
391 ConicDirectrixType::~ConicDirectrixType()
395 const ConicDirectrixType* ConicDirectrixType::instance()
397 static const ConicDirectrixType t;
398 return &t;
401 ObjectImp* ConicDirectrixType::calc( const Args& parents, const KigDocument& ) const
403 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
405 const ConicPolarData data =
406 static_cast<const ConicImp*>( parents[0] )->polarData();
408 double ec = data.ecostheta0;
409 double es = data.esintheta0;
410 double eccsq = ec*ec + es*es;
412 Coordinate a = data.focus1 - data.pdimen/eccsq*Coordinate(ec,es);
413 Coordinate b = a + Coordinate(-es,ec);
414 return new LineImp( a, b );
417 static const char hyperbolatpstatement[] = I18N_NOOP( "Construct a hyperbola through this point" );
419 static const ArgsParser::spec argsspecHyperbolaB4P[] =
421 { PointImp::stype(), hyperbolatpstatement,
422 I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true },
423 { PointImp::stype(), hyperbolatpstatement,
424 I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true },
425 { PointImp::stype(), hyperbolatpstatement,
426 I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true },
427 { PointImp::stype(), hyperbolatpstatement,
428 I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true }
431 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( EquilateralHyperbolaB4PType )
433 EquilateralHyperbolaB4PType::EquilateralHyperbolaB4PType()
434 : ArgsParserObjectType( "EquilateralHyperbolaB4P", argsspecHyperbolaB4P, 4 )
438 EquilateralHyperbolaB4PType::~EquilateralHyperbolaB4PType()
442 const EquilateralHyperbolaB4PType* EquilateralHyperbolaB4PType::instance()
444 static const EquilateralHyperbolaB4PType t;
445 return &t;
448 ObjectImp* EquilateralHyperbolaB4PType::calc( const Args& parents, const KigDocument& ) const
450 if ( ! margsparser.checkArgs( parents, 1 ) ) return new InvalidImp;
452 std::vector<Coordinate> pts;
453 for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i )
454 pts.push_back( static_cast<const PointImp*>( *i )->coordinate() );
456 ConicCartesianData d = calcConicThroughPoints( pts, equilateral );
457 if ( d.valid() )
458 return new ConicImpCart( d );
459 else
460 return new InvalidImp;
463 static const ArgsParser::spec argsspecParabolaBDP[] =
465 { AbstractLineImp::stype(), I18N_NOOP( "Construct a parabola with this directrix" ),
466 I18N_NOOP( "Select the directrix of the new parabola..." ), false },
467 { PointImp::stype(), I18N_NOOP( "Construct a parabola with this focus" ),
468 I18N_NOOP( "Select the focus of the new parabola..." ), true }
471 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ParabolaBDPType )
473 ParabolaBDPType::ParabolaBDPType()
474 : ObjectLPType( "ParabolaBDP", argsspecParabolaBDP, 2 )
478 ParabolaBDPType::~ParabolaBDPType()
482 const ParabolaBDPType* ParabolaBDPType::instance()
484 static const ParabolaBDPType t;
485 return &t;
488 ObjectImp* ParabolaBDPType::calc( const LineData& l, const Coordinate& c ) const
490 ConicPolarData ret;
491 Coordinate ldir = l.dir();
492 ldir = ldir.normalize();
493 ret.focus1 = c;
494 ret.ecostheta0 = - ldir.y;
495 ret.esintheta0 = ldir.x;
496 Coordinate fa = c - l.a;
497 ret.pdimen = fa.y*ldir.x - fa.x*ldir.y;
498 ConicImpPolar* r = new ConicImpPolar( ret );
499 kdDebug() << k_funcinfo << r->conicTypeString() << endl;
500 return r;
503 static const ArgsParser::spec argsspecConicAsymptote[] =
505 { ConicImp::stype(), I18N_NOOP( "Construct the asymptotes of this conic" ),
506 I18N_NOOP( "Select the conic of which you want to construct the asymptotes..." ), false },
507 { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }
510 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicAsymptoteType )
512 ConicAsymptoteType::ConicAsymptoteType()
513 : ArgsParserObjectType( "ConicAsymptote", argsspecConicAsymptote, 2 )
517 ConicAsymptoteType::~ConicAsymptoteType()
521 const ConicAsymptoteType* ConicAsymptoteType::instance()
523 static const ConicAsymptoteType t;
524 return &t;
527 ObjectImp* ConicAsymptoteType::calc( const Args& parents, const KigDocument& ) const
529 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
531 bool valid = true;
532 const LineData ret = calcConicAsymptote(
533 static_cast<const ConicImp*>( parents[0] )->cartesianData(),
534 static_cast<const IntImp*>( parents[1] )->data(),
535 valid );
537 if ( valid )
538 return new LineImp( ret );
539 else
540 return new InvalidImp;
543 static const char radicallinesstatement[] = I18N_NOOP( "Construct the radical lines of this conic" );
545 static const ArgsParser::spec argsspecConicRadical[] =
547 { ConicImp::stype(), radicallinesstatement,
548 I18N_NOOP( "Select the first of the two conics of which you want to construct the radical line..." ), false },
549 { ConicImp::stype(), radicallinesstatement,
550 I18N_NOOP( "Select the other of the two conic of which you want to construct the radical line..." ), false },
551 { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false },
552 { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }
555 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicRadicalType )
557 ConicRadicalType::ConicRadicalType()
558 : ArgsParserObjectType( "ConicRadical", argsspecConicRadical, 4 )
562 const ConicRadicalType* ConicRadicalType::instance()
564 static const ConicRadicalType t;
565 return &t;
568 ObjectImp* ConicRadicalType::calc( const Args& parents, const KigDocument& ) const
570 if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp;
571 if ( parents[0]->inherits( CircleImp::stype() ) &&
572 parents[1]->inherits( CircleImp::stype() ) )
574 if( static_cast<const IntImp*>( parents[2] )->data() != 1 )
575 return new InvalidImp;
576 else
578 const CircleImp* c1 = static_cast<const CircleImp*>( parents[0] );
579 const CircleImp* c2 = static_cast<const CircleImp*>( parents[1] );
580 const Coordinate a = calcCircleRadicalStartPoint(
581 c1->center(), c2->center(), c1->squareRadius(), c2->squareRadius()
583 return new LineImp( a, calcPointOnPerpend(
584 LineData( c1->center(), c2->center() ), a ) );
587 else
589 bool valid = true;
590 const LineData l = calcConicRadical(
591 static_cast<const ConicImp*>( parents[0] )->cartesianData(),
592 static_cast<const ConicImp*>( parents[1] )->cartesianData(),
593 static_cast<const IntImp*>( parents[2] )->data(),
594 static_cast<const IntImp*>( parents[3] )->data(), valid );
595 if ( valid )
596 return new LineImp( l );
597 else
598 return new InvalidImp;
602 ConicRadicalType::~ConicRadicalType()
606 const ObjectImpType* ConicB5PType::resultId() const
608 return ConicImp::stype();
611 const ObjectImpType* ConicBAAPType::resultId() const
613 return ConicImp::stype();
616 const ObjectImpType* ConicBFFPType::resultId() const
618 return ConicImp::stype();
621 const ObjectImpType* ConicBDFPType::resultId() const
623 return ConicImp::stype();
626 const ObjectImpType* ParabolaBTPType::resultId() const
628 return ConicImp::stype();
631 const ObjectImpType* EquilateralHyperbolaB4PType::resultId() const
633 return ConicImp::stype();
636 const ObjectImpType* ConicPolarPointType::resultId() const
638 return PointImp::stype();
641 const ObjectImpType* ConicPolarLineType::resultId() const
643 return LineImp::stype();
646 const ObjectImpType* ConicDirectrixType::resultId() const
648 return LineImp::stype();
651 const ObjectImpType* ParabolaBDPType::resultId() const
653 return ConicImp::stype();
656 const ObjectImpType* ConicAsymptoteType::resultId() const
658 return LineImp::stype();
661 const ObjectImpType* ConicRadicalType::resultId() const
663 return LineImp::stype();
666 QStringList ConicRadicalType::specialActions() const
668 QStringList ret;
669 ret << i18n( "Switch Radical Lines" );
670 return ret;
673 void ConicRadicalType::executeAction( int i, ObjectHolder&, ObjectTypeCalcer& t,
674 KigPart& d, KigWidget&, NormalMode& ) const
676 assert( i == 0 );
677 std::vector<ObjectCalcer*> parents = t.parents();
678 assert( dynamic_cast<ObjectConstCalcer*>( parents[3] ) );
679 ObjectConstCalcer* zeroindexo = static_cast<ObjectConstCalcer*>( parents[3] );
680 MonitorDataObjects mon( zeroindexo );
681 assert( zeroindexo->imp()->inherits( IntImp::stype() ) );
682 int oldzeroindex = static_cast<const IntImp*>( zeroindexo->imp() )->data();
683 int newzeroindex = oldzeroindex % 3 + 1;
684 zeroindexo->setImp( new IntImp( newzeroindex ) );
685 KigCommand* kc = new KigCommand( d, "Switch Conic Radical Lines" );
686 mon.finish( kc );
687 d.history()->addCommand( kc );