moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kig / misc / special_constructors.cc
blob3660fbff93652259864d209c881de089d6793621
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 "special_constructors.h"
20 #include "calcpaths.h"
21 #include "common.h"
22 #include "conic-common.h"
23 #include "guiaction.h"
24 #include "kigpainter.h"
26 #include "../kig/kig_part.h"
27 #include "../modes/construct_mode.h"
28 #include "../objects/bogus_imp.h"
29 #include "../objects/centerofcurvature_type.h"
30 #include "../objects/circle_imp.h"
31 #include "../objects/conic_imp.h"
32 #include "../objects/conic_types.h"
33 #include "../objects/cubic_imp.h"
34 #include "../objects/intersection_types.h"
35 #include "../objects/inversion_type.h"
36 #include "../objects/line_imp.h"
37 #include "../objects/line_type.h"
38 #include "../objects/locus_imp.h"
39 #include "../objects/object_calcer.h"
40 #include "../objects/object_drawer.h"
41 #include "../objects/object_factory.h"
42 #include "../objects/object_holder.h"
43 #include "../objects/object_imp.h"
44 #include "../objects/object_type.h"
45 #include "../objects/other_imp.h"
46 #include "../objects/other_type.h"
47 #include "../objects/point_imp.h"
48 #include "../objects/point_type.h"
49 #include "../objects/polygon_imp.h"
50 #include "../objects/polygon_type.h"
51 #include "../objects/tangent_type.h"
52 #include "../objects/text_imp.h"
53 #include "../objects/transform_types.h"
55 #include <qpen.h>
57 #include <klocale.h>
59 #include <algorithm>
60 #include <functional>
62 class ConicConicIntersectionConstructor
63 : public StandardConstructorBase
65 protected:
66 ArgsParser mparser;
67 public:
68 ConicConicIntersectionConstructor();
69 ~ConicConicIntersectionConstructor();
71 void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector<ObjectCalcer*>& parents,
72 const KigDocument& ) const;
73 std::vector<ObjectHolder*> build( const std::vector<ObjectCalcer*>& os, KigDocument& d, KigWidget& w ) const;
74 void plug( KigPart* doc, KigGUIAction* kact );
76 bool isTransform() const;
79 class ConicLineIntersectionConstructor
80 : public MultiObjectTypeConstructor
82 public:
83 ConicLineIntersectionConstructor();
84 ~ConicLineIntersectionConstructor();
87 class ArcLineIntersectionConstructor
88 : public MultiObjectTypeConstructor
90 public:
91 ArcLineIntersectionConstructor();
92 ~ArcLineIntersectionConstructor();
95 ConicRadicalConstructor::ConicRadicalConstructor()
96 : StandardConstructorBase(
97 I18N_NOOP( "Radical Lines for Conics" ),
98 I18N_NOOP( "The lines constructed through the intersections "
99 "of two conics. This is also defined for "
100 "non-intersecting conics." ),
101 "conicsradicalline", mparser ),
102 mtype( ConicRadicalType::instance() ),
103 mparser( mtype->argsParser().without( IntImp::stype() ) )
107 ConicRadicalConstructor::~ConicRadicalConstructor()
111 void ConicRadicalConstructor::drawprelim(
112 const ObjectDrawer& drawer, KigPainter& p, const std::vector<ObjectCalcer*>& parents, const KigDocument& doc ) const
114 if ( parents.size() == 2 && parents[0]->imp()->inherits( ConicImp::stype() ) &&
115 parents[1]->imp()->inherits( ConicImp::stype() ) )
117 Args args;
118 std::transform( parents.begin(), parents.end(),
119 std::back_inserter( args ), std::mem_fun( &ObjectCalcer::imp ) );
120 for ( int i = -1; i < 2; i += 2 )
122 IntImp root( i );
123 IntImp zeroindex( 1 );
124 args.push_back( &root );
125 args.push_back( &zeroindex );
126 ObjectImp* data = mtype->calc( args, doc );
127 drawer.draw( *data, p, true );
128 delete data; data = 0;
129 args.pop_back();
130 args.pop_back();
135 std::vector<ObjectHolder*> ConicRadicalConstructor::build( const std::vector<ObjectCalcer*>& os, KigDocument&, KigWidget& ) const
137 using namespace std;
138 std::vector<ObjectHolder*> ret;
139 ObjectCalcer* zeroindexcalcer = new ObjectConstCalcer( new IntImp( 1 ) );
140 for ( int i = -1; i < 2; i += 2 )
142 std::vector<ObjectCalcer*> args;
143 std::copy( os.begin(), os.end(), back_inserter( args ) );
144 args.push_back( new ObjectConstCalcer( new IntImp( i ) ) );
145 // we use only one zeroindex dataobject, so that if you switch one
146 // radical line around, then the other switches along..
147 args.push_back( zeroindexcalcer );
148 ret.push_back(
149 new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) );
151 return ret;
154 static const struct ArgsParser::spec argsspecpp[] =
156 { PointImp::stype(), I18N_NOOP( "Moving Point" ),
157 I18N_NOOP( "Select the moving point, which will be moved around while drawing the locus..." ), false },
158 { PointImp::stype(), I18N_NOOP( "Following Point" ),
159 I18N_NOOP( "Select the following point, whose locations the locus will be drawn through..." ), true }
162 LocusConstructor::LocusConstructor()
163 : StandardConstructorBase( I18N_NOOP( "Locus" ), I18N_NOOP( "A locus" ),
164 "locus", margsparser ),
165 margsparser( argsspecpp, 2 )
169 LocusConstructor::~LocusConstructor()
173 void LocusConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector<ObjectCalcer*>& parents,
174 const KigDocument& ) const
176 // this function is rather ugly, but it is necessary to do it this
177 // way in order to play nice with Kig's design..
179 if ( parents.size() != 2 ) return;
180 const ObjectTypeCalcer* constrained = dynamic_cast<ObjectTypeCalcer*>( parents.front() );
181 const ObjectCalcer* moving = parents.back();
182 if ( ! constrained || ! constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) )
184 // moving is in fact the constrained point.. swap them..
185 moving = parents.front();
186 constrained = dynamic_cast<const ObjectTypeCalcer*>( parents.back() );
187 assert( constrained );
189 assert( constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) );
191 const ObjectImp* oimp = constrained->parents().back()->imp();
192 if( !oimp->inherits( CurveImp::stype() ) )
193 oimp = constrained->parents().front()->imp();
194 assert( oimp->inherits( CurveImp::stype() ) );
195 const CurveImp* cimp = static_cast<const CurveImp*>( oimp );
197 ObjectHierarchy hier( constrained, moving );
199 LocusImp limp( cimp->copy(), hier );
200 drawer.draw( limp, p, true );
203 const int LocusConstructor::wantArgs(
204 const std::vector<ObjectCalcer*>& os, const KigDocument&, const KigWidget&
205 ) const
207 int ret = margsparser.check( os );
208 if ( ret == ArgsParser::Invalid ) return ret;
209 else if ( os.size() != 2 ) return ret;
210 if ( dynamic_cast<ObjectTypeCalcer*>( os.front() ) &&
211 static_cast<ObjectTypeCalcer*>( os.front() )->type()->inherits( ObjectType::ID_ConstrainedPointType ) )
213 std::set<ObjectCalcer*> children = getAllChildren( os.front() );
214 return children.find( os.back() ) != children.end() ? ret : ArgsParser::Invalid;
216 if ( dynamic_cast<ObjectTypeCalcer*>( os.back() ) &&
217 static_cast<ObjectTypeCalcer*>( os.back() )->type()->inherits( ObjectType::ID_ConstrainedPointType ) )
219 std::set<ObjectCalcer*> children = getAllChildren( os.back() );
220 return children.find( os.front() ) != children.end() ? ret : ArgsParser::Invalid;
222 return ArgsParser::Invalid;
225 std::vector<ObjectHolder*> LocusConstructor::build( const std::vector<ObjectCalcer*>& parents, KigDocument&, KigWidget& ) const
227 std::vector<ObjectHolder*> ret;
228 assert( parents.size() == 2 );
230 ObjectTypeCalcer* constrained = dynamic_cast<ObjectTypeCalcer*>( parents.front() );
231 ObjectCalcer* moving = parents.back();
232 if ( ! constrained || ! constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) )
234 // moving is in fact the constrained point.. swap them..
235 moving = parents.front();
236 constrained = dynamic_cast<ObjectTypeCalcer*>( parents.back() );
237 assert( constrained );
239 assert( constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) );
241 ret.push_back( ObjectFactory::instance()->locus( constrained, moving ) );
242 return ret;
245 QString LocusConstructor::useText( const ObjectCalcer& o, const std::vector<ObjectCalcer*>& os,
246 const KigDocument&, const KigWidget& ) const
248 if ( dynamic_cast<const ObjectTypeCalcer*>( &o ) &&
249 static_cast<const ObjectTypeCalcer&>( o ).type()->inherits( ObjectType::ID_ConstrainedPointType ) &&
250 ( os.empty() || !dynamic_cast<ObjectTypeCalcer*>( os[0] ) ||
251 !static_cast<const ObjectTypeCalcer*>( os[0] )->type()->inherits( ObjectType::ID_ConstrainedPointType ) )
252 ) return i18n( "Moving Point" );
253 else return i18n( "Dependent Point" );
256 void ConicRadicalConstructor::plug( KigPart*, KigGUIAction* )
260 void LocusConstructor::plug( KigPart*, KigGUIAction* )
264 bool ConicRadicalConstructor::isTransform() const
266 return mtype->isTransform();
269 bool LocusConstructor::isTransform() const
271 return false;
275 * generic polygon constructor
278 PolygonBNPTypeConstructor::PolygonBNPTypeConstructor()
279 : mtype( PolygonBNPType::instance() )
283 PolygonBNPTypeConstructor::~PolygonBNPTypeConstructor()
287 const QString PolygonBNPTypeConstructor::descriptiveName() const
289 return i18n("Polygon by Its Vertices");
292 const QString PolygonBNPTypeConstructor::description() const
294 return i18n("Construct a polygon by giving its vertices");
297 const QCString PolygonBNPTypeConstructor::iconFileName( const bool ) const
299 return "polygon";
302 const bool PolygonBNPTypeConstructor::isAlreadySelectedOK(
303 const std::vector<ObjectCalcer*>& os, const int& pos ) const
305 if ( pos == 0 && os.size() >= 3 ) return true;
306 return false;
309 const int PolygonBNPTypeConstructor::wantArgs( const std::vector<ObjectCalcer*>& os,
310 const KigDocument&,
311 const KigWidget& ) const
313 int count=os.size() - 1;
315 for ( int i = 0; i <= count; i++ )
317 if ( ! ( os[i]->imp()->inherits( PointImp::stype() ) ) ) return ArgsParser::Invalid;
319 if ( count < 3 ) return ArgsParser::Valid;
320 if ( os[0] == os[count] ) return ArgsParser::Complete;
321 return ArgsParser::Valid;
324 void PolygonBNPTypeConstructor::handleArgs(
325 const std::vector<ObjectCalcer*>& os, KigPart& d,
326 KigWidget& v ) const
328 std::vector<ObjectHolder*> bos = build( os, d.document(), v );
329 for ( std::vector<ObjectHolder*>::iterator i = bos.begin();
330 i != bos.end(); ++i )
332 (*i)->calc( d.document() );
335 d.addObjects( bos );
338 void PolygonBNPTypeConstructor::handlePrelim(
339 KigPainter& p, const std::vector<ObjectCalcer*>& os,
340 const KigDocument& d, const KigWidget&
341 ) const
343 uint count = os.size();
344 if ( count < 2 ) return;
346 for ( uint i = 0; i < count; i++ )
348 assert ( os[i]->imp()->inherits( PointImp::stype() ) );
351 std::vector<ObjectCalcer*> args = os;
352 p.setBrushStyle( Qt::NoBrush );
353 p.setBrushColor( Qt::red );
354 p.setPen( QPen ( Qt::red, 1) );
355 p.setWidth( -1 ); // -1 means the default width for the object being
356 // drawn..
358 ObjectDrawer drawer( Qt::red );
359 drawprelim( drawer, p, args, d );
362 QString PolygonBNPTypeConstructor::useText( const ObjectCalcer&, const std::vector<ObjectCalcer*>& os,
363 const KigDocument&, const KigWidget& ) const
365 if ( os.size() > 3 )
366 return i18n("... with this vertex (click on the first vertex to terminate construction)");
367 else return i18n("Construct a polygon with this vertex");
370 QString PolygonBNPTypeConstructor::selectStatement(
371 const std::vector<ObjectCalcer*>&, const KigDocument&,
372 const KigWidget& ) const
374 return i18n("Select a point to be a vertex of the new polygon...");
377 void PolygonBNPTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector<ObjectCalcer*>& parents,
378 const KigDocument& ) const
380 if ( parents.size() < 2 ) return;
382 std::vector<Coordinate> points;
384 for ( uint i = 0; i < parents.size(); ++i )
386 const Coordinate vertex =
387 static_cast<const PointImp*>( parents[i]->imp() )->coordinate();
388 points.push_back( vertex );
391 if ( parents.size() == 2 )
393 SegmentImp segment = SegmentImp( points[0], points[1] );
394 drawer.draw( segment, p, true );
395 } else {
396 PolygonImp polygon = PolygonImp( points );
397 drawer.draw( polygon, p, true );
401 std::vector<ObjectHolder*> PolygonBNPTypeConstructor::build( const std::vector<ObjectCalcer*>& parents, KigDocument&, KigWidget& ) const
403 uint count = parents.size() - 1;
404 assert ( count >= 3 );
405 std::vector<ObjectCalcer*> args;
406 for ( uint i = 0; i < count; ++i ) args.push_back( parents[i] );
407 ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, args );
408 ObjectHolder* h = new ObjectHolder( calcer );
409 std::vector<ObjectHolder*> ret;
410 ret.push_back( h );
411 return ret;
414 void PolygonBNPTypeConstructor::plug( KigPart*, KigGUIAction* )
418 bool PolygonBNPTypeConstructor::isTransform() const
420 return false;
424 * construction of polygon vertices
427 static const struct ArgsParser::spec argsspecpv[] =
429 { PolygonImp::stype(), I18N_NOOP( "Polygon" ),
430 I18N_NOOP( "Construct the vertices of this polygon..." ), true }
433 PolygonVertexTypeConstructor::PolygonVertexTypeConstructor()
434 : StandardConstructorBase( I18N_NOOP( "Vertices of a Polygon" ),
435 I18N_NOOP( "The vertices of a polygon." ),
436 "polygonvertices", margsparser ),
437 mtype( PolygonVertexType::instance() ),
438 margsparser( argsspecpv, 1 )
442 PolygonVertexTypeConstructor::~PolygonVertexTypeConstructor()
446 void PolygonVertexTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector<ObjectCalcer*>& parents,
447 const KigDocument& ) const
449 if ( parents.size() != 1 ) return;
451 const PolygonImp* polygon = dynamic_cast<const PolygonImp*>( parents.front()->imp() );
452 const std::vector<Coordinate> points = polygon->points();
454 int sides = points.size();
455 for ( int i = 0; i < sides; ++i )
457 PointImp point = PointImp( points[i] );
458 drawer.draw( point, p, true );
462 std::vector<ObjectHolder*> PolygonVertexTypeConstructor::build( const std::vector<ObjectCalcer*>& parents, KigDocument&, KigWidget& ) const
464 std::vector<ObjectHolder*> ret;
465 assert( parents.size() == 1 );
466 const PolygonImp* polygon = dynamic_cast<const PolygonImp*>( parents.front()->imp() );
467 const std::vector<Coordinate> points = polygon->points();
469 int sides = points.size();
471 for ( int i = 0; i < sides; ++i )
473 ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( i ) );
474 std::vector<ObjectCalcer*> args( parents );
475 args.push_back( d );
476 ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) );
478 return ret;
481 void PolygonVertexTypeConstructor::plug( KigPart*, KigGUIAction* )
485 bool PolygonVertexTypeConstructor::isTransform() const
487 return false;
491 * construction of polygon sides
494 static const struct ArgsParser::spec argsspecps[] =
496 { PolygonImp::stype(), I18N_NOOP( "Polygon" ),
497 I18N_NOOP( "Construct the sides of this polygon..." ), false }
500 PolygonSideTypeConstructor::PolygonSideTypeConstructor()
501 : StandardConstructorBase( I18N_NOOP( "Sides of a Polygon" ),
502 I18N_NOOP( "The sides of a polygon." ),
503 "polygonsides", margsparser ),
504 mtype( PolygonSideType::instance() ),
505 margsparser( argsspecps, 1 )
509 PolygonSideTypeConstructor::~PolygonSideTypeConstructor()
513 void PolygonSideTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector<ObjectCalcer*>& parents,
514 const KigDocument& ) const
516 if ( parents.size() != 1 ) return;
518 const PolygonImp* polygon = dynamic_cast<const PolygonImp*>( parents.front()->imp() );
519 const std::vector<Coordinate> points = polygon->points();
521 uint sides = points.size();
522 for ( uint i = 0; i < sides; ++i )
524 uint nexti = ( i + 1 < sides )?(i + 1):0;
525 SegmentImp segment = SegmentImp( points[i], points[nexti] );
526 drawer.draw( segment, p, true );
530 std::vector<ObjectHolder*> PolygonSideTypeConstructor::build( const std::vector<ObjectCalcer*>& parents, KigDocument&, KigWidget& ) const
532 std::vector<ObjectHolder*> ret;
533 assert( parents.size() == 1 );
534 const PolygonImp* polygon = dynamic_cast<const PolygonImp*>( parents.front()->imp() );
535 const std::vector<Coordinate> points = polygon->points();
537 uint sides = points.size();
539 for ( uint i = 0; i < sides; ++i )
541 ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( i ) );
542 std::vector<ObjectCalcer*> args( parents );
543 args.push_back( d );
544 ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) );
546 return ret;
549 void PolygonSideTypeConstructor::plug( KigPart*, KigGUIAction* )
553 bool PolygonSideTypeConstructor::isTransform() const
555 return false;
559 * polygon by center and vertex
562 PolygonBCVConstructor::PolygonBCVConstructor()
563 : mtype( PolygonBCVType::instance() )
567 PolygonBCVConstructor::~PolygonBCVConstructor()
571 const QString PolygonBCVConstructor::descriptiveName() const
573 return i18n("Regular Polygon with Given Center");
576 const QString PolygonBCVConstructor::description() const
578 return i18n("Construct a regular polygon with a given center and vertex");
581 const QCString PolygonBCVConstructor::iconFileName( const bool ) const
583 return "hexagonbcv";
586 const bool PolygonBCVConstructor::isAlreadySelectedOK(
587 const std::vector<ObjectCalcer*>&, const int& ) const
589 return false;
592 const int PolygonBCVConstructor::wantArgs( const std::vector<ObjectCalcer*>& os,
593 const KigDocument&,
594 const KigWidget& ) const
596 if ( os.size() > 3 ) return ArgsParser::Invalid;
598 uint imax = ( os.size() <= 2) ? os.size() : 2;
599 for ( uint i = 0; i < imax; ++i )
600 if ( ! ( os[i]->imp()->inherits( PointImp::stype() ) ) ) return ArgsParser::Invalid;
602 if ( os.size() < 3 ) return ArgsParser::Valid;
604 if ( ! ( os[2]->imp()->inherits( BogusPointImp::stype() ) ) )
605 return ArgsParser::Invalid;
607 return ArgsParser::Complete;
610 void PolygonBCVConstructor::handleArgs(
611 const std::vector<ObjectCalcer*>& os, KigPart& d,
612 KigWidget& v ) const
614 std::vector<ObjectHolder*> bos = build( os, d.document(), v );
615 for ( std::vector<ObjectHolder*>::iterator i = bos.begin();
616 i != bos.end(); ++i )
618 (*i)->calc( d.document() );
621 d.addObjects( bos );
624 void PolygonBCVConstructor::handlePrelim(
625 KigPainter& p, const std::vector<ObjectCalcer*>& os,
626 const KigDocument& d, const KigWidget&
627 ) const
629 if ( os.size() < 2 ) return;
631 for ( uint i = 0; i < 2; i++ )
633 assert ( os[i]->imp()->inherits( PointImp::stype() ) );
636 Coordinate c = static_cast<const PointImp*>( os[0]->imp() )->coordinate();
637 Coordinate v = static_cast<const PointImp*>( os[1]->imp() )->coordinate();
639 int nsides = 6;
640 bool moreinfo = false;
641 int winding = 0; // 0 means allow winding > 1
642 if ( os.size() == 3 )
644 assert ( os[2]->imp()->inherits( BogusPointImp::stype() ) );
645 Coordinate cntrl = static_cast<const PointImp*>( os[2]->imp() )->coordinate();
646 nsides = computeNsides( c, v, cntrl, winding );
647 moreinfo = true;
650 std::vector<ObjectCalcer*> args;
651 args.push_back( os[0] );
652 args.push_back( os[1] );
653 ObjectConstCalcer* ns = new ObjectConstCalcer( new IntImp( nsides ) );
654 args.push_back( ns );
655 if ( winding > 1 )
657 ns = new ObjectConstCalcer( new IntImp( winding ) );
658 args.push_back( ns );
661 p.setBrushStyle( Qt::NoBrush );
662 p.setBrushColor( Qt::red );
663 p.setPen( QPen ( Qt::red, 1) );
664 p.setWidth( -1 ); // -1 means the default width for the object being
665 // drawn..
667 ObjectDrawer drawer( Qt::red );
668 drawprelim( drawer, p, args, d );
669 if ( moreinfo )
671 p.setPointStyle( 1 );
672 p.setWidth( 6 );
673 double ro = 1.0/(2.5);
674 Coordinate where = getRotatedCoord( c, (1-ro)*c+ro*v, 4*M_PI/5.0 );
675 PointImp ptn = PointImp( where );
676 TextImp text = TextImp( "(5,2)", where, false );
677 ptn.draw( p );
678 text.draw( p );
679 for ( int i = 3; i < 9; ++i )
681 where = getRotatedCoord( c, v, 2.0*M_PI/i );
682 ptn = PointImp( where );
683 ptn.draw( p );
684 if ( i > 5 ) continue;
685 text = TextImp( QString( "(%1)" ).arg(i), where, false );
686 text.draw( p );
688 p.setStyle( Qt::DotLine );
689 p.setWidth( 1 );
690 double radius = ( v - c ).length();
691 CircleImp circle = CircleImp( c, radius );
692 circle.draw( p );
693 for ( int i = 2; i < 5; i++ )
695 ro = 1.0/(i+0.5);
696 CircleImp circle = CircleImp( c, ro*radius );
697 circle.draw( p );
702 std::vector<ObjectHolder*> PolygonBCVConstructor::build( const std::vector<ObjectCalcer*>& parents, KigDocument&, KigWidget& ) const
704 assert ( parents.size() == 3 );
705 std::vector<ObjectCalcer*> args;
707 Coordinate c = static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
708 Coordinate v = static_cast<const PointImp*>( parents[1]->imp() )->coordinate();
709 Coordinate cntrl = static_cast<const PointImp*>( parents[2]->imp() )->coordinate();
711 args.push_back( parents[0] );
712 args.push_back( parents[1] );
713 int winding = 0;
714 int nsides = computeNsides( c, v, cntrl, winding );
715 ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( nsides ) );
716 args.push_back( d );
717 if ( winding > 1 )
719 d = new ObjectConstCalcer( new IntImp( winding ) );
720 args.push_back( d );
723 ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, args );
724 ObjectHolder* h = new ObjectHolder( calcer );
725 std::vector<ObjectHolder*> ret;
726 ret.push_back( h );
727 return ret;
730 QString PolygonBCVConstructor::useText( const ObjectCalcer&, const std::vector<ObjectCalcer*>& os,
731 const KigDocument&, const KigWidget& ) const
733 switch ( os.size() )
735 case 1:
736 return i18n( "Construct a regular polygon with this center" );
737 break;
739 case 2:
740 return i18n( "Construct a regular polygon with this vertex" );
741 break;
743 case 3:
744 Coordinate c = static_cast<const PointImp*>( os[0]->imp() )->coordinate();
745 Coordinate v = static_cast<const PointImp*>( os[1]->imp() )->coordinate();
746 Coordinate cntrl = static_cast<const PointImp*>( os[2]->imp() )->coordinate();
747 int winding = 0;
748 int nsides = computeNsides( c, v, cntrl, winding );
750 if ( winding > 1 )
752 QString result = QString(
753 i18n( "Adjust the number of sides (%1/%2)" )
754 ).arg( nsides ).arg( winding );
755 return result;
756 } else
758 QString result = QString(
759 i18n( "Adjust the number of sides (%1)" )
760 ).arg( nsides );
761 return result;
763 break;
766 return "";
769 QString PolygonBCVConstructor::selectStatement(
770 const std::vector<ObjectCalcer*>& os, const KigDocument&,
771 const KigWidget& ) const
773 switch ( os.size() )
775 case 1:
776 return i18n( "Select the center of the new polygon..." );
777 break;
779 case 2:
780 return i18n( "Select a vertex for the new polygon..." );
781 break;
783 case 3:
784 return i18n( "Move the cursor to get the desired number of sides..." );
785 break;
788 return "";
791 void PolygonBCVConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector<ObjectCalcer*>& parents,
792 const KigDocument& doc ) const
794 if ( parents.size() < 3 || parents.size() > 4 ) return;
796 assert ( parents[0]->imp()->inherits( PointImp::stype() ) &&
797 parents[1]->imp()->inherits( PointImp::stype() ) &&
798 parents[2]->imp()->inherits( IntImp::stype() ) );
800 if ( parents.size() == 4 )
801 assert ( parents[3]->imp()->inherits( IntImp::stype() ) );
803 Args args;
804 std::transform( parents.begin(), parents.end(),
805 std::back_inserter( args ), std::mem_fun( &ObjectCalcer::imp ) );
807 ObjectImp* data = mtype->calc( args, doc );
808 drawer.draw( *data, p, true );
809 delete data;
810 data = 0;
813 void PolygonBCVConstructor::plug( KigPart*, KigGUIAction* )
817 bool PolygonBCVConstructor::isTransform() const
819 return false;
822 Coordinate PolygonBCVConstructor::getRotatedCoord( const Coordinate& c,
823 const Coordinate& v, double alpha ) const
825 double cosalpha = cos(alpha);
826 double sinalpha = sin(alpha);
827 double dx = v.x - c.x;
828 double dy = v.y - c.y;
829 return c + Coordinate( cosalpha*dx - sinalpha*dy, sinalpha*dx + cosalpha*dy );
832 int PolygonBCVConstructor::computeNsides ( const Coordinate& c,
833 const Coordinate& v, const Coordinate& cntrl, int& winding ) const
835 Coordinate lvect = v - c;
836 Coordinate rvect = cntrl - c;
838 double angle = atan2( rvect.y, rvect.x ) - atan2( lvect.y, lvect.x );
839 angle = fabs( angle/(2*M_PI) );
840 while ( angle > 1 ) angle -= 1;
841 if ( angle > 0.5 ) angle = 1 - angle;
843 double realsides = 1.0/angle; // this is bigger that 2
844 if ( angle == 0. ) realsides = 3;
845 if ( winding <= 0 ) // free to compute winding
847 winding = 1;
848 double ratio = lvect.length()/rvect.length();
849 winding = int ( ratio );
850 if ( winding < 1 ) winding = 1;
851 if ( winding > 50 ) winding = 50;
853 int nsides = int( winding*realsides + 0.5 ); // nsides/winding should be reduced!
854 if ( nsides > 100 ) nsides = 100; // well, 100 seems large enough!
855 if ( nsides < 3 ) nsides = 3;
856 while ( !relativePrimes ( nsides, winding ) ) ++nsides;
857 return nsides;
861 * ConicConic intersection...
864 static const ArgsParser::spec argsspectc[] = {
865 { ConicImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true },
866 { ConicImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true }
869 ConicConicIntersectionConstructor::ConicConicIntersectionConstructor()
870 : StandardConstructorBase( "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
871 "curvelineintersection", mparser ),
872 mparser( argsspectc, 2 )
876 ConicConicIntersectionConstructor::~ConicConicIntersectionConstructor()
880 void ConicConicIntersectionConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector<ObjectCalcer*>& parents,
881 const KigDocument& ) const
883 if ( parents.size() != 2 ) return;
884 assert ( parents[0]->imp()->inherits( ConicImp::stype() ) &&
885 parents[1]->imp()->inherits( ConicImp::stype() ) );
886 const ConicCartesianData conica =
887 static_cast<const ConicImp*>( parents[0]->imp() )->cartesianData();
888 const ConicCartesianData conicb =
889 static_cast<const ConicImp*>( parents[1]->imp() )->cartesianData();
890 bool ok = true;
891 for ( int wr = -1; wr < 2; wr += 2 )
893 LineData radical = calcConicRadical( conica, conicb, wr, 1, ok );
894 if ( ok )
896 for ( int wi = -1; wi < 2; wi += 2 )
898 Coordinate c = calcConicLineIntersect( conica, radical, 0.0, wi );
899 if ( c.valid() ) {
900 PointImp pi( c );
901 drawer.draw( pi, p, true );
908 std::vector<ObjectHolder*> ConicConicIntersectionConstructor::build(
909 const std::vector<ObjectCalcer*>& os, KigDocument& doc, KigWidget& ) const
911 assert( os.size() == 2 );
912 std::vector<ObjectHolder*> ret;
913 ObjectCalcer* conica = os[0];
914 ObjectConstCalcer* zeroindexdo = new ObjectConstCalcer( new IntImp( 1 ) );
916 for ( int wr = -1; wr < 2; wr += 2 )
918 std::vector<ObjectCalcer*> args = os;
919 args.push_back( new ObjectConstCalcer( new IntImp( wr ) ) );
920 args.push_back( zeroindexdo );
921 ObjectTypeCalcer* radical =
922 new ObjectTypeCalcer( ConicRadicalType::instance(), args );
923 radical->calc( doc );
924 for ( int wi = -1; wi < 2; wi += 2 )
926 args.clear();
927 args.push_back( conica );
928 args.push_back( radical );
929 args.push_back( new ObjectConstCalcer( new IntImp( wi ) ) );
930 ret.push_back(
931 new ObjectHolder(
932 new ObjectTypeCalcer(
933 ConicLineIntersectionType::instance(), args ) ) );
936 return ret;
939 void ConicConicIntersectionConstructor::plug( KigPart*, KigGUIAction* )
943 bool ConicConicIntersectionConstructor::isTransform() const
945 return false;
948 ConicLineIntersectionConstructor::ConicLineIntersectionConstructor()
949 : MultiObjectTypeConstructor(
950 ConicLineIntersectionType::instance(),
951 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
952 "curvelineintersection", -1, 1 )
956 ConicLineIntersectionConstructor::~ConicLineIntersectionConstructor()
960 ArcLineIntersectionConstructor::ArcLineIntersectionConstructor()
961 : MultiObjectTypeConstructor(
962 ArcLineIntersectionType::instance(),
963 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
964 "curvelineintersection", -1, 1 )
968 ArcLineIntersectionConstructor::~ArcLineIntersectionConstructor()
972 QString ConicRadicalConstructor::useText( const ObjectCalcer& o, const std::vector<ObjectCalcer*>&,
973 const KigDocument&, const KigWidget& ) const
975 if ( o.imp()->inherits( CircleImp::stype() ) )
976 return i18n( "Construct the Radical Lines of This Circle" );
977 else
978 return i18n( "Construct the Radical Lines of This Conic" );
982 * generic affinity and generic projectivity. A unique affinity can be
983 * obtained by specifying the image of three points (four for projectivity)
984 * in the end we need, besides the object to be transformed, a total of
985 * six point or (alternatively) two triangles; our affinity will map the
986 * first triangle onto the second with corresponding ordering of their
987 * vertices. Since we allow for two different ways of specifying the six
988 * points we shall use a Generic constructor, like that for intersections.
991 GenericAffinityConstructor::GenericAffinityConstructor()
992 : MergeObjectConstructor(
993 I18N_NOOP( "Generic Affinity" ),
994 I18N_NOOP( "The unique affinity that maps three points (or a triangle) onto three other points (or a triangle)" ),
995 "genericaffinity" )
997 SimpleObjectTypeConstructor* b2tr =
998 new SimpleObjectTypeConstructor(
999 AffinityB2TrType::instance(),
1000 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1001 "genericaffinity" );
1003 SimpleObjectTypeConstructor* gi3p =
1004 new SimpleObjectTypeConstructor(
1005 AffinityGI3PType::instance(),
1006 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1007 "genericaffinity" );
1009 merge( b2tr );
1010 merge( gi3p );
1013 GenericAffinityConstructor::~GenericAffinityConstructor() {}
1015 GenericProjectivityConstructor::GenericProjectivityConstructor()
1016 : MergeObjectConstructor(
1017 I18N_NOOP( "Generic Projective Transformation" ),
1018 I18N_NOOP( "The unique projective transformation that maps four points (or a quadrilateral) onto four other points (or a quadrilateral)" ),
1019 "genericprojectivity" )
1021 SimpleObjectTypeConstructor* b2qu =
1022 new SimpleObjectTypeConstructor(
1023 ProjectivityB2QuType::instance(),
1024 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1025 "genericprojectivity" );
1027 SimpleObjectTypeConstructor* gi4p =
1028 new SimpleObjectTypeConstructor(
1029 ProjectivityGI4PType::instance(),
1030 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1031 "genericprojectivity" );
1033 merge( b2qu );
1034 merge( gi4p );
1037 GenericProjectivityConstructor::~GenericProjectivityConstructor() {}
1040 * inversion of points, lines with respect to a circle
1043 InversionConstructor::InversionConstructor()
1044 : MergeObjectConstructor(
1045 I18N_NOOP( "Inversion of Point, Line or Circle" ),
1046 I18N_NOOP( "The inversion of a point, line or circle with respect to a circle" ),
1047 "inversion" )
1049 SimpleObjectTypeConstructor* pointobj =
1050 new SimpleObjectTypeConstructor(
1051 InvertPointType::instance(),
1052 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1053 "inversion" );
1055 SimpleObjectTypeConstructor* lineobj =
1056 new SimpleObjectTypeConstructor(
1057 InvertLineType::instance(),
1058 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1059 "inversion" );
1061 SimpleObjectTypeConstructor* circleobj =
1062 new SimpleObjectTypeConstructor(
1063 InvertCircleType::instance(),
1064 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1065 "inversion" );
1067 merge( circleobj );
1068 merge( pointobj );
1069 merge( lineobj );
1072 InversionConstructor::~InversionConstructor() {}
1075 * Transport of Measure
1078 MeasureTransportConstructor::MeasureTransportConstructor()
1079 : mtype( MeasureTransportType::instance() )
1083 MeasureTransportConstructor::~MeasureTransportConstructor()
1087 const QString MeasureTransportConstructor::descriptiveName() const
1089 return i18n("Measure Transport");
1092 const QString MeasureTransportConstructor::description() const
1094 return i18n("Transport the measure of a segment or arc over a line or circle.");
1097 const QCString MeasureTransportConstructor::iconFileName( const bool ) const
1099 return "measuretransport";
1102 const bool MeasureTransportConstructor::isAlreadySelectedOK(
1103 const std::vector<ObjectCalcer*>&, const int& ) const
1105 return false;
1109 * we want the arguments in the exact order, this makes
1110 * the code simpler, but I guess it is also less confusing
1111 * to the user
1114 const int MeasureTransportConstructor::wantArgs(
1115 const std::vector<ObjectCalcer*>& os,
1116 const KigDocument&,
1117 const KigWidget& ) const
1119 if ( os.size() == 0 ) return ArgsParser::Valid;
1121 if ( ! os[0]->imp()->inherits( SegmentImp::stype() ) &&
1122 ! os[0]->imp()->inherits( ArcImp::stype() ) )
1123 return ArgsParser::Invalid;
1125 if ( os.size() == 1 ) return ArgsParser::Valid;
1127 if ( ! os[1]->imp()->inherits( LineImp::stype() ) &&
1128 ! os[1]->imp()->inherits( CircleImp::stype() ) )
1129 return ArgsParser::Invalid;
1131 if ( os.size() == 2 ) return ArgsParser::Valid;
1133 if ( ! os[2]->imp()->inherits( PointImp::stype() ) )
1134 return ArgsParser::Invalid;
1136 // we here use the "isPointOnCurve", which relies on
1137 // "by construction" incidence, instead of a numerical
1138 // check
1139 if ( ! isPointOnCurve( os[2], os[1] ) )
1140 return ArgsParser::Invalid;
1142 if ( os.size() == 3 ) return ArgsParser::Complete;
1144 return ArgsParser::Invalid;
1147 void MeasureTransportConstructor::handleArgs(
1148 const std::vector<ObjectCalcer*>& os, KigPart& d,
1149 KigWidget& v ) const
1151 std::vector<ObjectHolder*> bos = build( os, d.document(), v );
1152 for ( std::vector<ObjectHolder*>::iterator i = bos.begin();
1153 i != bos.end(); ++i )
1155 (*i)->calc( d.document() );
1158 d.addObjects( bos );
1161 void MeasureTransportConstructor::handlePrelim(
1162 KigPainter& p, const std::vector<ObjectCalcer*>& os,
1163 const KigDocument& d, const KigWidget&
1164 ) const
1166 p.setBrushStyle( Qt::NoBrush );
1167 p.setBrushColor( Qt::red );
1168 p.setPen( QPen ( Qt::red, 1) );
1169 p.setWidth( -1 ); // -1 means the default width for the object being
1170 // drawn..
1172 ObjectDrawer drawer( Qt::red );
1173 drawprelim( drawer, p, os, d );
1176 void MeasureTransportConstructor::drawprelim( const ObjectDrawer& drawer,
1177 KigPainter& p,
1178 const std::vector<ObjectCalcer*>& parents,
1179 const KigDocument& doc ) const
1181 Args args;
1182 using namespace std;
1183 transform( parents.begin(), parents.end(),
1184 back_inserter( args ), mem_fun( &ObjectCalcer::imp ) );
1185 ObjectImp* data = mtype->calc( args, doc );
1186 drawer.draw( *data, p, true );
1187 delete data;
1190 QString MeasureTransportConstructor::useText( const ObjectCalcer& o,
1191 const std::vector<ObjectCalcer*>& os,
1192 const KigDocument&, const KigWidget& ) const
1194 if ( o.imp()->inherits( SegmentImp::stype() ) )
1195 return i18n("Segment to transport");
1196 if ( o.imp()->inherits( ArcImp::stype() ) )
1197 return i18n("Arc to transport");
1198 if ( o.imp()->inherits( LineImp::stype() ) )
1199 return i18n("Transport a measure on this line");
1200 if ( o.imp()->inherits( CircleImp::stype() ) )
1201 return i18n("Transport a measure on this circle");
1202 if ( o.imp()->inherits( PointImp::stype() ) )
1204 if ( os[1]->imp()->inherits( CircleImp::stype() ) )
1205 return i18n("Start transport from this point of the circle");
1206 if ( os[1]->imp()->inherits( LineImp::stype() ) )
1207 return i18n("Start transport from this point of the line");
1208 else
1209 return i18n("Start transport from this point of the curve");
1210 // well, this isn't impemented yet, should never get here
1212 return "";
1215 QString MeasureTransportConstructor::selectStatement(
1216 const std::vector<ObjectCalcer*>&, const KigDocument&,
1217 const KigWidget& ) const
1219 //TODO
1220 return i18n("Select a point to be a vertex of the new polygon...");
1223 std::vector<ObjectHolder*> MeasureTransportConstructor::build(
1224 const std::vector<ObjectCalcer*>& parents,
1225 KigDocument&, KigWidget& ) const
1227 assert ( parents.size() == 3 );
1228 // std::vector<ObjectCalcer*> args;
1229 // for ( uint i = 0; i < count; ++i ) args.push_back( parents[i] );
1230 ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, parents );
1231 ObjectHolder* h = new ObjectHolder( calcer );
1232 std::vector<ObjectHolder*> ret;
1233 ret.push_back( h );
1234 return ret;
1237 void MeasureTransportConstructor::plug( KigPart*, KigGUIAction* )
1241 bool MeasureTransportConstructor::isTransform() const
1243 return false;
1247 * Generic intersection
1250 GenericIntersectionConstructor::GenericIntersectionConstructor()
1251 : MergeObjectConstructor(
1252 I18N_NOOP( "Intersect" ),
1253 I18N_NOOP( "The intersection of two objects" ),
1254 "curvelineintersection" )
1256 // intersection type..
1257 // There is one "toplevel" object_constructor, that is composed
1258 // of multiple subconstructors.. First we build the
1259 // subconstructors:
1260 SimpleObjectTypeConstructor* lineline =
1261 new SimpleObjectTypeConstructor(
1262 LineLineIntersectionType::instance(),
1263 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1264 "curvelineintersection" );
1266 ObjectConstructor* lineconic =
1267 new ConicLineIntersectionConstructor();
1269 ObjectConstructor* arcline =
1270 new ArcLineIntersectionConstructor();
1272 MultiObjectTypeConstructor* linecubic =
1273 new MultiObjectTypeConstructor(
1274 LineCubicIntersectionType::instance(),
1275 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1276 "curvelineintersection", 1, 2, 3 );
1278 ObjectConstructor* conicconic =
1279 new ConicConicIntersectionConstructor();
1281 MultiObjectTypeConstructor* circlecircle =
1282 new MultiObjectTypeConstructor(
1283 CircleCircleIntersectionType::instance(),
1284 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1285 "circlecircleintersection", -1, 1 );
1287 SimpleObjectTypeConstructor* polygonline =
1288 new SimpleObjectTypeConstructor(
1289 PolygonLineIntersectionType::instance(),
1290 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1291 "curvelineintersection" );
1293 merge( lineline );
1294 merge( circlecircle );
1295 merge( lineconic );
1296 merge( linecubic );
1297 merge( conicconic );
1298 merge( arcline );
1299 merge( polygonline );
1302 GenericIntersectionConstructor::~GenericIntersectionConstructor()
1306 bool GenericIntersectionConstructor::isIntersection() const
1308 return true;
1311 QString GenericIntersectionConstructor::useText(
1312 const ObjectCalcer& o, const std::vector<ObjectCalcer*>& os,
1313 const KigDocument&, const KigWidget& ) const
1315 QString preamble;
1316 switch (os.size())
1318 case 1:
1319 if ( o.imp()->inherits( CircleImp::stype() ) )
1320 return i18n( "Intersect this Circle" );
1321 else if ( o.imp()->inherits( ConicImp::stype() ) )
1322 return i18n( "Intersect this Conic" );
1323 else if ( o.imp()->inherits( AbstractLineImp::stype() ) )
1324 return i18n( "Intersect this Line" );
1325 else if ( o.imp()->inherits( CubicImp::stype() ) )
1326 return i18n( "Intersect this Cubic Curve" );
1327 else if ( o.imp()->inherits( ArcImp::stype() ) )
1328 return i18n( "Intersect this Arc" );
1329 else if ( o.imp()->inherits( PolygonImp::stype() ) )
1330 return i18n( "Intersect this Polygon" );
1331 else assert( false );
1332 break;
1333 case 2:
1334 if ( o.imp()->inherits( CircleImp::stype() ) )
1335 return i18n( "with this Circle" );
1336 else if ( o.imp()->inherits( ConicImp::stype() ) )
1337 return i18n( "with this Conic" );
1338 else if ( o.imp()->inherits( AbstractLineImp::stype() ) )
1339 return i18n( "with this Line" );
1340 else if ( o.imp()->inherits( CubicImp::stype() ) )
1341 return i18n( "with this Cubic Curve" );
1342 else if ( o.imp()->inherits( ArcImp::stype() ) )
1343 return i18n( "with this Arc" );
1344 else if ( o.imp()->inherits( PolygonImp::stype() ) )
1345 return i18n( "with this Polygon" );
1346 else assert( false );
1347 break;
1350 return QString::null;
1353 static const ArgsParser::spec argsspecMidPointOfTwoPoints[] =
1355 { PointImp::stype(), I18N_NOOP( "Construct Midpoint of This Point and Another One" ),
1356 I18N_NOOP( "Select the first of the points of which you want to construct the midpoint..." ), false },
1357 { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another one" ),
1358 I18N_NOOP( "Select the other of the points of which to construct the midpoint..." ), false }
1361 MidPointOfTwoPointsConstructor::MidPointOfTwoPointsConstructor()
1362 : StandardConstructorBase( "Mid Point",
1363 "Construct the midpoint of two points",
1364 "bisection", mparser ),
1365 mparser( argsspecMidPointOfTwoPoints, 2 )
1369 MidPointOfTwoPointsConstructor::~MidPointOfTwoPointsConstructor()
1373 void MidPointOfTwoPointsConstructor::drawprelim(
1374 const ObjectDrawer& drawer, KigPainter& p, const std::vector<ObjectCalcer*>& parents,
1375 const KigDocument& ) const
1377 if ( parents.size() != 2 ) return;
1378 assert( parents[0]->imp()->inherits( PointImp::stype() ) );
1379 assert( parents[1]->imp()->inherits( PointImp::stype() ) );
1380 const Coordinate m =
1381 ( static_cast<const PointImp*>( parents[0]->imp() )->coordinate() +
1382 static_cast<const PointImp*>( parents[1]->imp() )->coordinate() ) / 2;
1383 drawer.draw( PointImp( m ), p, true );
1386 std::vector<ObjectHolder*> MidPointOfTwoPointsConstructor::build(
1387 const std::vector<ObjectCalcer*>& os, KigDocument& d, KigWidget& ) const
1389 ObjectTypeCalcer* seg = new ObjectTypeCalcer( SegmentABType::instance(), os );
1390 seg->calc( d );
1391 int index = seg->imp()->propertiesInternalNames().findIndex( "mid-point" );
1392 assert( index != -1 );
1393 ObjectPropertyCalcer* prop = new ObjectPropertyCalcer( seg, index );
1394 prop->calc( d );
1395 std::vector<ObjectHolder*> ret;
1396 ret.push_back( new ObjectHolder( prop ) );
1397 return ret;
1400 void MidPointOfTwoPointsConstructor::plug( KigPart*, KigGUIAction* )
1404 bool MidPointOfTwoPointsConstructor::isTransform() const
1406 return false;
1409 TestConstructor::TestConstructor( const ArgsParserObjectType* type, const char* descname,
1410 const char* desc, const char* iconfile )
1411 : StandardConstructorBase( descname, desc, iconfile, type->argsParser() ),
1412 mtype( type )
1416 TestConstructor::~TestConstructor()
1420 void TestConstructor::drawprelim( const ObjectDrawer&, KigPainter&, const std::vector<ObjectCalcer*>&,
1421 const KigDocument& ) const
1423 // not used, only here because of the wrong
1424 // ObjectConstructor-GUIAction design. See the TODO
1427 std::vector<ObjectHolder*> TestConstructor::build( const std::vector<ObjectCalcer*>&, KigDocument&,
1428 KigWidget& ) const
1430 // not used, only here because of the wrong
1431 // ObjectConstructor-GUIAction design. See the TODO
1432 std::vector<ObjectHolder*> ret;
1433 return ret;
1436 void TestConstructor::plug( KigPart*, KigGUIAction* )
1440 bool TestConstructor::isTransform() const
1442 return false;
1445 bool TestConstructor::isTest() const
1447 return true;
1450 BaseConstructMode* TestConstructor::constructMode( KigPart& doc )
1452 return new TestConstructMode( doc, mtype );
1455 const int TestConstructor::wantArgs( const std::vector<ObjectCalcer*>& os,
1456 const KigDocument& d, const KigWidget& v ) const
1458 int ret = StandardConstructorBase::wantArgs( os, d, v );
1459 if ( ret == ArgsParser::Complete ) ret = ArgsParser::Valid;
1460 return ret;
1463 QString GenericIntersectionConstructor::selectStatement(
1464 const std::vector<ObjectCalcer*>& sel, const KigDocument&,
1465 const KigWidget& ) const
1467 if ( sel.size() == 0 )
1468 return i18n( "Select the first object to intersect..." );
1469 else
1470 return i18n( "Select the second object to intersect..." );
1473 TangentConstructor::TangentConstructor()
1474 : MergeObjectConstructor(
1475 I18N_NOOP( "Tangent" ),
1476 I18N_NOOP( "The line tangent to a curve" ),
1477 "tangent" )
1479 SimpleObjectTypeConstructor* conic =
1480 new SimpleObjectTypeConstructor(
1481 TangentConicType::instance(),
1482 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1483 "tangentconic" );
1485 SimpleObjectTypeConstructor* arc =
1486 new SimpleObjectTypeConstructor(
1487 TangentArcType::instance(),
1488 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1489 "tangentarc" );
1491 SimpleObjectTypeConstructor* cubic =
1492 new SimpleObjectTypeConstructor(
1493 TangentCubicType::instance(),
1494 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1495 "tangentcubic" );
1497 SimpleObjectTypeConstructor* curve =
1498 new SimpleObjectTypeConstructor(
1499 TangentCurveType::instance(),
1500 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1501 "tangentcurve" );
1503 merge( conic );
1504 merge( arc );
1505 merge( cubic );
1506 merge( curve );
1509 TangentConstructor::~TangentConstructor()
1513 QString TangentConstructor::useText(
1514 const ObjectCalcer& o, const std::vector<ObjectCalcer*>&,
1515 const KigDocument&, const KigWidget& ) const
1517 if ( o.imp()->inherits( CircleImp::stype() ) )
1518 return i18n( "Tangent to This Circle" );
1519 else if ( o.imp()->inherits( ConicImp::stype() ) )
1520 return i18n( "Tangent to This Conic" );
1521 else if ( o.imp()->inherits( ArcImp::stype() ) )
1522 return i18n( "Tangent to This Arc" );
1523 else if ( o.imp()->inherits( CubicImp::stype() ) )
1524 return i18n( "Tangent to This Cubic Curve" );
1525 else if ( o.imp()->inherits( CurveImp::stype() ) )
1526 return i18n( "Tangent to This Curve" );
1527 else if ( o.imp()->inherits( PointImp::stype() ) )
1528 return i18n( "Tangent at This Point" );
1529 // else assert( false );
1530 return QString::null;
1533 //QString TangentConstructor::selectStatement(
1534 // const std::vector<ObjectCalcer*>& sel, const KigDocument&,
1535 // const KigWidget& ) const
1537 // if ( sel.size() == 0 )
1538 // return i18n( "Select the object..." );
1539 // else
1540 // return i18n( "Select the point for the tangent to go through..." );
1544 * center of curvature of a curve
1547 CocConstructor::CocConstructor()
1548 : MergeObjectConstructor(
1549 I18N_NOOP( "Center Of Curvature" ),
1550 I18N_NOOP( "The center of the osculating circle to a curve" ),
1551 "centerofcurvature" )
1553 SimpleObjectTypeConstructor* conic =
1554 new SimpleObjectTypeConstructor(
1555 CocConicType::instance(),
1556 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1557 "cocconic" );
1559 SimpleObjectTypeConstructor* cubic =
1560 new SimpleObjectTypeConstructor(
1561 CocCubicType::instance(),
1562 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1563 "coccubic" );
1565 SimpleObjectTypeConstructor* curve =
1566 new SimpleObjectTypeConstructor(
1567 CocCurveType::instance(),
1568 "SHOULDNOTBESEEN", "SHOULDNOTBESEEN",
1569 "coccurve" );
1571 merge( conic );
1572 merge( cubic );
1573 merge( curve );
1576 CocConstructor::~CocConstructor()
1580 QString CocConstructor::useText(
1581 const ObjectCalcer& o, const std::vector<ObjectCalcer*>&,
1582 const KigDocument&, const KigWidget& ) const
1584 if ( o.imp()->inherits( ConicImp::stype() ) )
1585 return i18n( "Center of Curvature of This Conic" );
1586 else if ( o.imp()->inherits( CubicImp::stype() ) )
1587 return i18n( "Center of Curvature of This Cubic Curve" );
1588 else if ( o.imp()->inherits( CurveImp::stype() ) )
1589 return i18n( "Center of Curvature of This Curve" );
1590 else if ( o.imp()->inherits( PointImp::stype() ) )
1591 return i18n( "Center of Curvature at This Point" );
1592 return QString::null;
1595 bool relativePrimes( int n, int p )
1597 if ( p > n ) return relativePrimes( p, n );
1598 assert ( p >= 0 );
1599 if ( p == 0 ) return false;
1600 if ( p == 1 ) return true;
1601 int d = int( n/p );
1602 return relativePrimes( p, n-d*p );
1605 //QString CocConstructor::selectStatement(
1606 // const std::vector<ObjectCalcer*>& sel, const KigDocument&,
1607 // const KigWidget& ) const
1609 // if ( sel.size() == 0 )
1610 // return i18n( "Select the object..." );
1611 // else
1612 // return i18n( "Select the point where to compute the center of curvature..." );