1 // Copyright (C) 2002 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 "point_type.h"
20 #include "point_imp.h"
21 #include "curve_imp.h"
23 #include "other_imp.h"
24 #include "bogus_imp.h"
26 #include "../modes/moving.h"
27 #include "../misc/coordinate_system.h"
28 #include "../misc/common.h"
29 #include "../misc/calcpaths.h"
30 #include "../kig/kig_part.h"
31 #include "../kig/kig_document.h"
32 #include "../kig/kig_view.h"
33 #include "../kig/kig_commands.h"
37 static const ArgsParser::spec argsspecFixedPoint
[] =
39 { DoubleImp::stype(), "x", "SHOULD NOT BE SEEN", false },
40 { DoubleImp::stype(), "y", "SHOULD NOT BE SEEN", false }
43 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( FixedPointType
)
45 FixedPointType::FixedPointType()
46 : ArgsParserObjectType( "FixedPoint", argsspecFixedPoint
, 2 )
50 FixedPointType::~FixedPointType()
54 ObjectImp
* FixedPointType::calc( const Args
& parents
, const KigDocument
& ) const
56 if ( ! margsparser
.checkArgs( parents
) ) return new InvalidImp
;
58 double a
= static_cast<const DoubleImp
*>( parents
[0] )->data();
59 double b
= static_cast<const DoubleImp
*>( parents
[1] )->data();
61 return new PointImp( Coordinate( a
, b
) );
64 static const ArgsParser::spec argsspecRelativePoint
[] =
66 { DoubleImp::stype(), "relative-x", "SHOULD NOT BE SEEN", false },
67 { DoubleImp::stype(), "relative-y", "SHOULD NOT BE SEEN", false },
68 { ObjectImp::stype(), "object", "SHOULD NOT BE SEEN", false }
71 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( RelativePointType
)
73 RelativePointType::RelativePointType()
74 : ArgsParserObjectType( "RelativePoint", argsspecRelativePoint
, 3 )
78 RelativePointType::~RelativePointType()
82 ObjectImp
* RelativePointType::calc( const Args
& parents
, const KigDocument
& ) const
84 if ( ! margsparser
.checkArgs( parents
) ) return new InvalidImp
;
85 if ( ! parents
[2]->attachPoint().valid() ) return new InvalidImp
;
87 Coordinate reference
= static_cast<const ObjectImp
*>( parents
[2] )->attachPoint();
88 double a
= static_cast<const DoubleImp
*>( parents
[0] )->data();
89 double b
= static_cast<const DoubleImp
*>( parents
[1] )->data();
91 return new PointImp( reference
+ Coordinate( a
, b
) );
94 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CursorPointType
)
96 CursorPointType::CursorPointType()
97 : ObjectType( "CursorPoint" )
101 CursorPointType::~CursorPointType()
105 const CursorPointType
* CursorPointType::instance()
107 static const CursorPointType t
;
111 ObjectImp
* CursorPointType::calc( const Args
& parents
, const KigDocument
& ) const
113 assert ( parents
[0]->inherits( DoubleImp::stype() ) );
114 assert ( parents
[1]->inherits( DoubleImp::stype() ) );
115 double a
= static_cast<const DoubleImp
*>( parents
[0] )->data();
116 double b
= static_cast<const DoubleImp
*>( parents
[1] )->data();
118 return new BogusPointImp( Coordinate( a
, b
) );
121 const ObjectImpType
* CursorPointType::resultId() const
123 return BogusPointImp::stype();
126 ObjectImp
* ConstrainedPointType::calc( const Args
& parents
, const KigDocument
& doc
) const
128 if ( ! margsparser
.checkArgs( parents
) ) return new InvalidImp
;
130 double param
= static_cast<const DoubleImp
*>( parents
[0] )->data();
131 const Coordinate nc
= static_cast<const CurveImp
*>( parents
[1] )->getPoint( param
, doc
);
132 if ( nc
.valid() ) return new PointImp( nc
);
133 else return new InvalidImp
;
136 const ArgsParser::spec argsspecConstrainedPoint
[] =
138 { DoubleImp::stype(), "parameter", "SHOULD NOT BE SEEN", false },
139 { CurveImp::stype(), "Constrain the point to this curve", "SHOULD NOT BE SEEN", true }
142 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConstrainedPointType
)
144 ConstrainedPointType::ConstrainedPointType()
145 : ArgsParserObjectType( "ConstrainedPoint", argsspecConstrainedPoint
, 2 )
149 ConstrainedPointType::~ConstrainedPointType()
153 void FixedPointType::move( ObjectTypeCalcer
& ourobj
, const Coordinate
& to
,
154 const KigDocument
& ) const
156 // fetch the old coord..;
157 std::vector
<ObjectCalcer
*> pa
= ourobj
.parents();
158 assert( margsparser
.checkArgs( pa
) );
159 assert( dynamic_cast<ObjectConstCalcer
*>( pa
.front() ) );
160 assert( dynamic_cast<ObjectConstCalcer
*>( pa
.back() ) );
162 ObjectConstCalcer
* ox
= static_cast<ObjectConstCalcer
*>( pa
.front() );
163 ObjectConstCalcer
* oy
= static_cast<ObjectConstCalcer
*>( pa
.back() );
165 ox
->setImp( new DoubleImp( to
.x
) );
166 oy
->setImp( new DoubleImp( to
.y
) );
169 void RelativePointType::move( ObjectTypeCalcer
& ourobj
, const Coordinate
& to
,
170 const KigDocument
& ) const
172 // fetch the attach point..;
173 // this routine is tightly paired with what moveReferencePoint returns!
174 // right now moveReferencePoint always returns the origin
175 std::vector
<ObjectCalcer
*> pa
= ourobj
.parents();
176 assert( margsparser
.checkArgs( pa
) );
177 assert( dynamic_cast<ObjectConstCalcer
*>( pa
[0] ) );
178 assert( dynamic_cast<ObjectConstCalcer
*>( pa
[1] ) );
180 ObjectConstCalcer
* ox
= static_cast<ObjectConstCalcer
*>( pa
[0] );
181 ObjectConstCalcer
* oy
= static_cast<ObjectConstCalcer
*>( pa
[1] );
182 ObjectCalcer
* ob
= static_cast<ObjectCalcer
*>( pa
[2] );
184 Coordinate attach
= ob
->imp()->attachPoint();
185 ox
->setImp( new DoubleImp( to
.x
- attach
.x
) );
186 oy
->setImp( new DoubleImp( to
.y
- attach
.y
) );
189 void CursorPointType::move( ObjectTypeCalcer
& ourobj
, const Coordinate
& to
,
190 const KigDocument
& ) const
192 // fetch the old coord..;
194 std::vector
<ObjectCalcer
*> pa
= ourobj
.parents();
195 assert( pa
.size() == 2 );
196 assert( dynamic_cast<ObjectConstCalcer
*>( pa
.front() ) );
197 assert( dynamic_cast<ObjectConstCalcer
*>( pa
.back() ) );
199 ObjectConstCalcer
* ox
= static_cast<ObjectConstCalcer
*>( pa
.front() );
200 ObjectConstCalcer
* oy
= static_cast<ObjectConstCalcer
*>( pa
.back() );
202 ox
->setImp( new DoubleImp( to
.x
) );
203 oy
->setImp( new DoubleImp( to
.y
) );
206 void ConstrainedPointType::move( ObjectTypeCalcer
& ourobj
, const Coordinate
& to
,
207 const KigDocument
& d
) const
209 // fetch the CurveImp..
210 std::vector
<ObjectCalcer
*> parents
= ourobj
.parents();
211 assert( margsparser
.checkArgs( parents
) );
213 assert( dynamic_cast<ObjectConstCalcer
*>( parents
[0] ) );
214 ObjectConstCalcer
* paramo
= static_cast<ObjectConstCalcer
*>( parents
[0] );
215 const CurveImp
* ci
= static_cast<const CurveImp
*>( parents
[1]->imp() );
217 // fetch the new param..
218 const double np
= ci
->getParam( to
, d
);
220 paramo
->setImp( new DoubleImp( np
) );
223 bool ConstrainedPointType::canMove( const ObjectTypeCalcer
& ) const
228 bool ConstrainedPointType::isFreelyTranslatable( const ObjectTypeCalcer
& ) const
233 bool FixedPointType::canMove( const ObjectTypeCalcer
& ) const
238 bool FixedPointType::isFreelyTranslatable( const ObjectTypeCalcer
& ) const
243 bool RelativePointType::canMove( const ObjectTypeCalcer
& ) const
248 bool RelativePointType::isFreelyTranslatable( const ObjectTypeCalcer
& ) const
253 bool CursorPointType::canMove( const ObjectTypeCalcer
& ) const
258 static const ArgsParser::spec argsspecMidPoint
[] =
260 { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another point" ),
261 I18N_NOOP( "Select the first of the two points of which you want to construct the midpoint..." ), false },
262 { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another point" ),
263 I18N_NOOP( "Select the other of the two points of which you want to construct the midpoint..." ), false }
266 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MidPointType
)
268 MidPointType::MidPointType()
269 : ObjectABType( "MidPoint", argsspecMidPoint
, 2 )
273 MidPointType::~MidPointType()
277 const MidPointType
* MidPointType::instance()
279 static const MidPointType t
;
283 ObjectImp
* MidPointType::calc( const Coordinate
& a
, const Coordinate
& b
) const
285 return new PointImp( ( a
+ b
) / 2 );
288 bool ConstrainedPointType::inherits( int type
) const
290 return type
== ID_ConstrainedPointType
;
293 const ConstrainedPointType
* ConstrainedPointType::instance()
295 static const ConstrainedPointType t
;
299 bool FixedPointType::inherits( int type
) const
301 return type
== ID_FixedPointType
;
304 const FixedPointType
* FixedPointType::instance()
306 static const FixedPointType t
;
310 const ObjectImpType
* FixedPointType::resultId() const
312 return PointImp::stype();
315 const RelativePointType
* RelativePointType::instance()
317 static const RelativePointType t
;
321 const ObjectImpType
* RelativePointType::resultId() const
323 return PointImp::stype();
326 const ObjectImpType
* ConstrainedPointType::resultId() const
328 return PointImp::stype();
331 const ObjectImpType
* CursorPointType::impRequirement( const ObjectImp
* o
, const Args
& ) const
333 if ( o
->inherits( DoubleImp::stype() ) )
334 return DoubleImp::stype();
336 if ( o
->inherits( PointImp::stype() ) )
337 return PointImp::stype();
342 bool CursorPointType::isDefinedOnOrThrough( const ObjectImp
*, const Args
& ) const
347 std::vector
<ObjectCalcer
*> CursorPointType::sortArgs( const std::vector
<ObjectCalcer
*>& args
) const
352 Args
CursorPointType::sortArgs( const Args
& args
) const
357 const ObjectImpType
* MidPointType::resultId() const
359 return PointImp::stype();
362 QStringList
FixedPointType::specialActions() const
365 ret
<< i18n( "Set &Coordinate..." );
366 ret
<< i18n( "Redefine" );
370 QStringList
ConstrainedPointType::specialActions() const
373 ret
<< i18n( "Set &Parameter..." );
374 ret
<< i18n( "Redefine" );
378 static void redefinePoint( ObjectHolder
* o
, KigPart
& d
, KigWidget
& w
)
380 PointRedefineMode
pm( o
, d
, w
);
384 void FixedPointType::executeAction(
385 int i
, ObjectHolder
& oh
, ObjectTypeCalcer
& o
,
386 KigPart
& d
, KigWidget
& w
, NormalMode
& ) const
393 assert ( o
.imp()->inherits( PointImp::stype() ) );
394 Coordinate oldc
= static_cast<const PointImp
*>( o
.imp() )->coordinate();
395 Coordinate c
= d
.document().coordinateSystem().getCoordFromUser(
396 i18n( "Set Coordinate" ), i18n( "Enter the new coordinate: " ),
397 d
.document(), &w
, &ok
, &oldc
);
400 MonitorDataObjects
mon( getAllParents( &o
) );
401 o
.move( c
, d
.document() );
402 KigCommand
* kc
= new KigCommand( d
, PointImp::stype()->moveAStatement() );
405 d
.history()->addCommand( kc
);
409 redefinePoint( &oh
, d
, w
);
416 void ConstrainedPointType::executeAction(
417 int i
, ObjectHolder
& oh
, ObjectTypeCalcer
& o
, KigPart
& d
, KigWidget
& w
,
423 redefinePoint( &oh
, d
, w
);
427 std::vector
<ObjectCalcer
*> parents
= o
.parents();
428 assert( dynamic_cast<ObjectConstCalcer
*>( parents
[0] ) &&
429 parents
[0]->imp()->inherits( DoubleImp::stype() ) );
431 ObjectConstCalcer
* po
= static_cast<ObjectConstCalcer
*>( parents
[0] );
432 double oldp
= static_cast<const DoubleImp
*>( po
->imp() )->data();
435 double newp
= getDoubleFromUser(
436 i18n( "Set Point Parameter" ), i18n( "Choose the new parameter: " ),
437 oldp
, &w
, &ok
, 0, 1, 4 );
440 MonitorDataObjects
mon( parents
);
441 po
->setImp( new DoubleImp( newp
) );
442 KigCommand
* kc
= new KigCommand( d
, i18n( "Change Parameter of Constrained Point" ) );
444 d
.history()->addCommand( kc
);
452 const Coordinate
FixedPointType::moveReferencePoint( const ObjectTypeCalcer
& ourobj
) const
454 assert( ourobj
.imp()->inherits( PointImp::stype() ) );
455 return static_cast<const PointImp
*>( ourobj
.imp() )->coordinate();
458 const Coordinate
RelativePointType::moveReferencePoint( const ObjectTypeCalcer
& ourobj
) const
460 assert( ourobj
.imp()->inherits( PointImp::stype() ) );
461 // return static_cast<const PointImp*>( ourobj.imp() )->coordinate();
462 return Coordinate( 0., 0. );
465 const Coordinate
ConstrainedPointType::moveReferencePoint( const ObjectTypeCalcer
& ourobj
) const
467 assert( ourobj
.imp()->inherits( PointImp::stype() ) );
468 return static_cast<const PointImp
*>( ourobj
.imp() )->coordinate();
471 std::vector
<ObjectCalcer
*> FixedPointType::movableParents( const ObjectTypeCalcer
& ourobj
) const
473 return ourobj
.parents();
476 std::vector
<ObjectCalcer
*> RelativePointType::movableParents( const ObjectTypeCalcer
& ourobj
) const
478 std::vector
<ObjectCalcer
*> ret
;
479 ret
.push_back( ourobj
.parents()[0] );
480 ret
.push_back( ourobj
.parents()[1] );
484 std::vector
<ObjectCalcer
*> ConstrainedPointType::movableParents( const ObjectTypeCalcer
& ourobj
) const
486 std::vector
<ObjectCalcer
*> ret
;
487 ret
.push_back( ourobj
.parents()[0] );
491 /* ----------------- Transport of measure ------------------------------ */
493 ObjectImp
* MeasureTransportType::calc( const Args
& parents
, const KigDocument
& doc
) const
497 if ( parents
.size() != 3 ) return new InvalidImp
;
499 if ( parents
[0]->inherits (SegmentImp::stype()) )
501 const SegmentImp
* s
= static_cast<const SegmentImp
*>( parents
[0] );
502 measure
= s
->length();
503 } else if ( parents
[0]->inherits (ArcImp::stype()) )
505 const ArcImp
* s
= static_cast<const ArcImp
*>( parents
[0] );
506 measure
= s
->radius()*s
->angle();
507 } else return new InvalidImp
;
509 const Coordinate
& p
= static_cast<const PointImp
*>( parents
[2] )->coordinate();
510 if ( parents
[1]->inherits (LineImp::stype()) )
512 const LineImp
* c
= static_cast<const LineImp
*>( parents
[1] );
514 if ( !c
->containsPoint( p
, doc
) )
515 return new InvalidImp
;
517 const LineData line
= c
->data();
518 const Coordinate dir
= line
.dir()/line
.length();
519 const Coordinate nc
= p
+ measure
*dir
;
521 if ( nc
.valid() ) return new PointImp( nc
);
522 else return new InvalidImp
;
523 } else if ( parents
[1]->inherits (CircleImp::stype()) )
525 const CircleImp
* c
= static_cast<const CircleImp
*>( parents
[1] );
526 if ( !c
->containsPoint( p
, doc
) )
527 return new InvalidImp
;
529 double param
= c
->getParam( p
, doc
);
530 measure
/= 2*c
->radius()*M_PI
;
532 while (param
> 1) param
-= 1;
534 const Coordinate nc
= c
->getPoint( param
, doc
);
535 if ( nc
.valid() ) return new PointImp( nc
);
536 else return new InvalidImp
;
539 return new InvalidImp
;
542 // I18N_NOOP( "Select the segment/arc to transport on the circle/line..." ), false },
543 // I18N_NOOP( "Select the circle/line on which to transport a measure..." ), true },
544 // I18N_NOOP( "Select a point on the circle/line..." ), false }
546 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MeasureTransportType
)
548 MeasureTransportType::MeasureTransportType()
549 : ObjectType( "TransportOfMeasure" )
553 MeasureTransportType::~MeasureTransportType()
557 const MeasureTransportType
* MeasureTransportType::instance()
559 static const MeasureTransportType t
;
563 const ObjectImpType
* MeasureTransportType::resultId() const
565 return PointImp::stype();
568 const ObjectImpType
* MeasureTransportType::impRequirement( const ObjectImp
* obj
, const Args
& ) const
570 if ( obj
->inherits( PointImp::stype () ) )
571 return PointImp::stype ();
573 if ( obj
->inherits( LineImp::stype () ) )
574 return LineImp::stype ();
576 if ( obj
->inherits( CircleImp::stype () ) )
577 return CircleImp::stype ();
579 if ( obj
->inherits( SegmentImp::stype () ) )
580 return SegmentImp::stype ();
582 if ( obj
->inherits( ArcImp::stype () ) )
583 return ArcImp::stype ();
588 bool MeasureTransportType::isDefinedOnOrThrough( const ObjectImp
* o
, const Args
& ) const
590 if ( o
->inherits( LineImp::stype() ) ) return true;
591 if ( o
->inherits( CircleImp::stype() ) ) return true;
595 std::vector
<ObjectCalcer
*> MeasureTransportType::sortArgs( const std::vector
<ObjectCalcer
*>& args
) const
597 return args
; /* should already be in correct order */
600 Args
MeasureTransportType::sortArgs( const Args
& args
) const
605 /* - transport of measure (old, for compatibility with prev. kig files) - */
607 ObjectImp
* MeasureTransportTypeOld::calc( const Args
& parents
, const KigDocument
& doc
) const
609 if ( ! margsparser
.checkArgs( parents
) ) return new InvalidImp
;
611 const CircleImp
* c
= static_cast<const CircleImp
*>( parents
[0] );
612 const Coordinate
& p
= static_cast<const PointImp
*>( parents
[1] )->coordinate();
614 if ( !c
->containsPoint( p
, doc
) )
615 return new InvalidImp
;
617 const SegmentImp
* s
= static_cast<const SegmentImp
*>( parents
[2] );
618 double param
= c
->getParam( p
, doc
);
619 double measure
= s
->length();
620 measure
/= 2*c
->radius()*M_PI
;
622 while (param
> 1) param
-= 1;
624 const Coordinate nc
= c
->getPoint( param
, doc
);
625 if ( nc
.valid() ) return new PointImp( nc
);
626 else return new InvalidImp
;
629 static const ArgsParser::spec argsspecMeasureTransportOld
[] =
631 { CircleImp::stype(), "Transport a measure on this circle",
632 I18N_NOOP( "Select the circle on which to transport a measure..." ), true },
633 { PointImp::stype(), "Start transport from this point of the circle",
634 I18N_NOOP( "Select a point on the circle..." ), false },
635 { SegmentImp::stype(), "Segment to transport",
636 I18N_NOOP( "Select the segment to transport on the circle..." ), false }
639 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MeasureTransportTypeOld
)
641 MeasureTransportTypeOld::MeasureTransportTypeOld()
642 : ArgsParserObjectType( "MeasureTransport", argsspecMeasureTransportOld
, 3 )
646 MeasureTransportTypeOld::~MeasureTransportTypeOld()
650 const MeasureTransportTypeOld
* MeasureTransportTypeOld::instance()
652 static const MeasureTransportTypeOld t
;
656 const ObjectImpType
* MeasureTransportTypeOld::resultId() const
658 return PointImp::stype();
661 /* ----------------- end transport of measure ------------------------- */