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
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"
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"
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
);
71 return new ConicImpCart( d
);
72 else return new InvalidImp
;
75 const ConicB5PType
* ConicB5PType::instance()
77 static const ConicB5PType 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
;
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
168 const EllipseBFFPType
* EllipseBFFPType::instance()
170 static const EllipseBFFPType 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
;
204 int HyperbolaBFFPType::type() const
209 const ConicBDFPType
* ConicBDFPType::instance()
211 static const ConicBDFPType 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();
245 if ( parents
.size() == 3 )
246 point
= static_cast<const PointImp
*>( parents
[2] )->coordinate();
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
;
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
);
300 return new ConicImpCart( d
);
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
;
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
;
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();
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
;
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
;
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
);
458 return new ConicImpCart( d
);
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
;
488 ObjectImp
* ParabolaBDPType::calc( const LineData
& l
, const Coordinate
& c
) const
491 Coordinate ldir
= l
.dir();
492 ldir
= ldir
.normalize();
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
;
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
;
527 ObjectImp
* ConicAsymptoteType::calc( const Args
& parents
, const KigDocument
& ) const
529 if ( ! margsparser
.checkArgs( parents
) ) return new InvalidImp
;
532 const LineData ret
= calcConicAsymptote(
533 static_cast<const ConicImp
*>( parents
[0] )->cartesianData(),
534 static_cast<const IntImp
*>( parents
[1] )->data(),
538 return new LineImp( ret
);
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
;
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
;
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
) );
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
);
596 return new LineImp( l
);
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
669 ret
<< i18n( "Switch Radical Lines" );
673 void ConicRadicalType::executeAction( int i
, ObjectHolder
&, ObjectTypeCalcer
& t
,
674 KigPart
& d
, KigWidget
&, NormalMode
& ) const
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" );
687 d
.history()->addCommand( kc
);