moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kig / objects / inversion_type.cc
blob061f15954fb4e6ec3d66e727824874f9a2c4dab8
1 // Copyright (C) 2005 Maurizio Paolini <paolini@dmf.unicatt.it>
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 "inversion_type.h"
19 #include "point_imp.h"
20 #include "line_imp.h"
21 #include "circle_imp.h"
22 #include "bogus_imp.h"
24 #include "../misc/common.h"
26 #include <klocale.h>
28 static const char str1[] = I18N_NOOP( "Invert with respect to this circle" );
29 static const char str2[] = I18N_NOOP( "Select the circle we want to invert against..." );
31 static const ArgsParser::spec argsspecInvertPoint[] =
33 { PointImp::stype(), I18N_NOOP( "Compute the inversion of this point" ),
34 I18N_NOOP( "Select the point to invert..." ), false },
35 { CircleImp::stype(), str1, str2, false }
38 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertPointType )
40 InvertPointType::InvertPointType()
41 : ArgsParserObjectType( "InvertPoint", argsspecInvertPoint, 2 )
45 InvertPointType::~InvertPointType()
49 const InvertPointType* InvertPointType::instance()
51 static const InvertPointType s;
52 return &s;
55 const ObjectImpType* InvertPointType::resultId() const
57 return PointImp::stype();
60 ObjectImp* InvertPointType::calc( const Args& args, const KigDocument& ) const
62 if ( ! margsparser.checkArgs( args ) ) return new InvalidImp;
64 const CircleImp* c = static_cast<const CircleImp*>( args[1] );
65 Coordinate center = c->center();
66 Coordinate relp = static_cast<const PointImp*>( args[0] )->coordinate() - center;
67 double radiussq = c->squareRadius();
68 double normsq = relp.x*relp.x + relp.y*relp.y;
69 if ( normsq == 0 ) return new InvalidImp;
70 return new PointImp( center + (radiussq/normsq)*relp );
74 * inversion of a line
77 static const ArgsParser::spec argsspecInvertLine[] =
79 { LineImp::stype(), I18N_NOOP( "Compute the inversion of this line" ),
80 I18N_NOOP( "Select the line to invert..." ), false },
81 { CircleImp::stype(), str1, str2, false }
84 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertLineType )
86 InvertLineType::InvertLineType()
87 : ArgsParserObjectType( "InvertLine", argsspecInvertLine, 2 )
91 InvertLineType::~InvertLineType()
95 const InvertLineType* InvertLineType::instance()
97 static const InvertLineType s;
98 return &s;
101 const ObjectImpType* InvertLineType::resultId() const
103 return CircleImp::stype();
106 ObjectImp* InvertLineType::calc( const Args& args, const KigDocument& ) const
108 if ( ! margsparser.checkArgs( args ) ) return new InvalidImp;
110 const CircleImp* c = static_cast<const CircleImp*>( args[1] );
111 Coordinate center = c->center();
112 double radiussq = c->squareRadius();
113 const LineData line = static_cast<const AbstractLineImp*>( args[0] )->data();
114 Coordinate relb = line.b - center;
115 Coordinate ab = line.b - line.a;
116 double t = (relb.x*ab.x + relb.y*ab.y)/(ab.x*ab.x + ab.y*ab.y);
117 Coordinate relh = relb - t*ab;
118 double normhsq = relh.x*relh.x + relh.y*relh.y;
119 if ( normhsq < 1e-12*radiussq ) return new LineImp( line.a, line.b );
120 Coordinate newcenter = center + 0.5*radiussq/normhsq*relh;
121 double newradius = 0.5*radiussq/sqrt(normhsq);
123 return new CircleImp( newcenter, newradius );
127 * inversion of a circle
130 static const ArgsParser::spec argsspecInvertCircle[] =
132 { CircleImp::stype(), I18N_NOOP( "Compute the inversion of this circle" ),
133 I18N_NOOP( "Select the circle to invert..." ), false },
134 { CircleImp::stype(), str1, str2, false }
137 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertCircleType )
139 InvertCircleType::InvertCircleType()
140 : ArgsParserObjectType( "InvertCircle", argsspecInvertCircle, 2 )
144 InvertCircleType::~InvertCircleType()
148 const InvertCircleType* InvertCircleType::instance()
150 static const InvertCircleType s;
151 return &s;
154 const ObjectImpType* InvertCircleType::resultId() const
156 return CircleImp::stype();
159 ObjectImp* InvertCircleType::calc( const Args& args, const KigDocument& ) const
161 if ( ! margsparser.checkArgs( args ) ) return new InvalidImp;
163 const CircleImp* refcircle = static_cast<const CircleImp*>( args[1] );
164 Coordinate refc = refcircle->center();
165 double refrsq = refcircle->squareRadius();
166 const CircleImp* circle = static_cast<const CircleImp*>( args[0] );
167 Coordinate c = circle->center() - refc;
168 double rsq = circle->squareRadius();
169 if ( c.length() == 0.0 ) return new InvalidImp;
170 double t = sqrt( rsq )/c.length();
171 Coordinate b = (1 + t)*c;
172 double bsq = b.x*b.x + b.y*b.y;
173 Coordinate bprime = refrsq*b/bsq;
174 if ( std::fabs( 1 - t ) < 1e-6 ) // circle through origin -> line
176 return new LineImp( bprime+refc, bprime+refc+Coordinate( -c.y, c.x ) );
179 Coordinate a = (1 - t)*c;
180 double asq = a.x*a.x + a.y*a.y;
181 Coordinate aprime = refrsq*a/asq;
183 Coordinate cprime = 0.5*(aprime + bprime);
184 double rprime = 0.5*( bprime - aprime ).length();
186 return new CircleImp( cprime + refc, rprime );