• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

kig

  • sources
  • kde-4.14
  • kdeedu
  • kig
  • objects
inversion_type.cc
Go to the documentation of this file.
1 // Copyright (C) 2005 Maurizio Paolini <paolini@dmf.unicatt.it>
2 
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.
7 
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.
12 
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., 51 Franklin Street, Fifth Floor, Boston, MA
16 // 02110-1301, USA.
17 
18 #include "inversion_type.h"
19 
20 #include <math.h>
21 
22 #include "object_imp.h"
23 #include "point_imp.h"
24 #include "line_imp.h"
25 #include "circle_imp.h"
26 #include "other_imp.h"
27 #include "bogus_imp.h"
28 #include "special_imptypes.h"
29 
30 #include "../misc/common.h"
31 
32 #include <klocale.h>
33 
34 static const char str1[] = I18N_NOOP( "Invert with respect to this circle" );
35 static const char str2[] = I18N_NOOP( "Select the circle we want to invert against..." );
36 
37 static const ArgsParser::spec argsspecCircularInversion[] =
38 {
39  { &invertibleimptypeinstance,
40  I18N_NOOP( "Compute the inversion of this object" ),
41  I18N_NOOP( "Select the object to invert..." ), false },
42  { CircleImp::stype(), str1, str2, false }
43 };
44 
45 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircularInversionType )
46 
47 CircularInversionType::CircularInversionType()
48  : ArgsParserObjectType( "CircularInversion", argsspecCircularInversion, 2 )
49 {
50 }
51 
52 CircularInversionType::~CircularInversionType()
53 {
54 }
55 
56 const CircularInversionType* CircularInversionType::instance()
57 {
58  static const CircularInversionType s;
59  return &s;
60 }
61 
62 const ObjectImpType* CircularInversionType::resultId() const
63 {
64  return &invertibleimptypeinstance;
65 }
66 
67 ObjectImp* CircularInversionType::calc( const Args& args, const KigDocument& ) const
68 {
69  if ( args.size() == 2 && args[1]->inherits( LineImp::stype() ) )
70  {
71  /* we also accept the special case when the circle becomes a
72  * straight line (this is not accepted during interactive construction,
73  * but could happen dinamically when a construction can result either
74  * with a circle or a line.
75  * In this case we simply have a reflection
76  */
77  LineData d = static_cast<const AbstractLineImp*>( args[1] )->data();
78  Transformation t = Transformation::lineReflection( d );
79  return args[0]->transform( t );
80  }
81  if ( ! margsparser.checkArgs( args ) ) return new InvalidImp;
82 
83  const CircleImp* refcircle = static_cast<const CircleImp*>( args[1] );
84  Coordinate refc = refcircle->center();
85  double refrsq = refcircle->squareRadius();
86 
87  if ( args[0]->inherits( PointImp::stype() ) )
88  {
89  Coordinate relp = static_cast<const PointImp*>( args[0] )->coordinate() - refc;
90  double normsq = relp.x*relp.x + relp.y*relp.y;
91  if ( normsq == 0 ) return new InvalidImp;
92  return new PointImp( refc + (refrsq/normsq)*relp );
93  }
94 
95  if ( args[0]->inherits( AbstractLineImp::stype() ) )
96  {
97  bool isline = args[0]->inherits( LineImp::stype() );
98  bool issegment = args[0]->inherits( SegmentImp::stype() );
99  bool isray = args[0]->inherits( RayImp::stype() );
100  const LineData line = static_cast<const AbstractLineImp*>( args[0] )->data();
101  Coordinate rela = line.a - refc;
102  Coordinate relb = line.b - refc;
103  Coordinate ab = relb - rela;
104  double t = (relb.x*ab.x + relb.y*ab.y)/(ab.x*ab.x + ab.y*ab.y);
105  Coordinate relh = relb - t*ab;
106  double normhsq = relh.x*relh.x + relh.y*relh.y;
107  if ( isline )
108  {
109  if ( normhsq < 1e-12*refrsq ) return new LineImp( line.a, line.b );
110  Coordinate newcenter = refc + 0.5*refrsq/normhsq*relh;
111  double newradius = 0.5*refrsq/sqrt(normhsq);
112 
113  return new CircleImp( newcenter, newradius );
114  }
115  if ( issegment || isray )
116  {
117  /*
118  * now for the SegmentImp or RayImp
119  * compute the inversion of the two endpoints
120  */
121 
122  Coordinate newcenterrel = 0.5*refrsq/normhsq*relh;
123  Coordinate relainv = refrsq/rela.squareLength() * rela;
124  Coordinate relbinv = Coordinate( 0., 0. );
125  if ( issegment ) relbinv = refrsq/relb.squareLength() * relb;
126 
127  if ( normhsq < 1e-12*refrsq )
128  {
129  if ( rela.squareLength() < 1e-12 )
130  {
131  return new RayImp( relbinv + refc, 2*relbinv + refc );
132  }
133  if ( issegment && relb.squareLength() < 1e-12 )
134  {
135  return new RayImp( relainv + refc, 2*relainv + refc );
136  }
137  if ( relb.x*rela.x + relb.y*rela.y > 0 )
138  {
139  return new SegmentImp( relainv + refc, relbinv + refc );
140  }
141  return new InvalidImp();
142  }
143  double newradius = 0.5*refrsq/sqrt(normhsq);
144 
145  relainv -= newcenterrel;
146  relbinv -= newcenterrel;
147  double angle1 = atan2( relainv.y, relainv.x );
148  double angle2 = atan2( relbinv.y, relbinv.x );
149  double angle = angle2 - angle1;
150  if ( ab.x*rela.y - ab.y*rela.x > 0 )
151  {
152  angle1 = angle2;
153  angle = -angle;
154  }
155  while ( angle1 <= -M_PI ) angle1 += 2*M_PI;
156  while ( angle1 > M_PI ) angle1 -= 2*M_PI;
157  while ( angle < 0 ) angle += 2*M_PI;
158  while ( angle >= 2*M_PI ) angle -= 2*M_PI;
159  return new ArcImp( newcenterrel + refc, newradius, angle1, angle );
160  }
161  return new InvalidImp;
162  }
163 
164  if ( args[0]->inherits( CircleImp::stype() ) )
165  {
166  const CircleImp* circle = static_cast<const CircleImp*>( args[0] );
167  Coordinate c = circle->center() - refc;
168  double clength = c.length();
169  Coordinate cnorm = Coordinate (1.,0.);
170  if ( clength != 0.0 ) cnorm = c/clength;
171  double r = circle->radius();
172  Coordinate tc = r*cnorm;
173  Coordinate b = c + tc; //(1 + t)*c;
174  double bsq = b.x*b.x + b.y*b.y;
175  Coordinate bprime = refrsq*b/bsq;
176  if ( std::fabs( clength - r ) < 1e-6*clength ) // circle through origin -> line
177  {
178  return new LineImp( bprime+refc, bprime+refc+Coordinate( -c.y, c.x ) );
179  }
180 
181  Coordinate a = c - tc;
182  double asq = a.x*a.x + a.y*a.y;
183  Coordinate aprime = refrsq*a/asq;
184 
185  Coordinate cprime = 0.5*(aprime + bprime);
186  double rprime = 0.5*( bprime - aprime ).length();
187 
188  return new CircleImp( cprime + refc, rprime );
189  }
190 
191  if ( args[0]->inherits( ArcImp::stype() ) )
192  {
193  const ArcImp* arc = static_cast<const ArcImp*>( args[0] );
194  Coordinate c = arc->center() - refc;
195  double clength = c.length();
196  Coordinate cnorm = Coordinate (1.,0.);
197  if ( clength != 0.0 ) cnorm = c/clength;
198  double r = arc->radius();
199  /*
200  * r > clength means center of inversion circle inside of circle supporting arc
201  */
202  Coordinate tc = r*cnorm;
203  Coordinate b = c + tc;
204  double bsq = b.x*b.x + b.y*b.y;
205  Coordinate bprime = refrsq*b/bsq;
206  if ( std::fabs( clength - r ) < 1e-6*clength ) // support circle through origin ->
207  // segment, ray or invalid
208  // (reversed segment, union of two rays)
209  {
210  bool valid1 = false;
211  bool valid2 = false;
212  Coordinate ep1 = arc->firstEndPoint() - refc;
213  Coordinate ep2 = arc->secondEndPoint() - refc;
214  Coordinate ep1inv = Coordinate::invalidCoord();
215  Coordinate ep2inv = Coordinate::invalidCoord();
216  double ep1sq = ep1.squareLength();
217  if ( ep1sq > 1e-12 )
218  {
219  valid1 = true;
220  ep1inv = refrsq/ep1sq * ep1;
221  }
222  Coordinate rayendp = ep1inv;
223  int sign = 1;
224  double ep2sq = ep2.squareLength();
225  if ( ep2sq > 1e-12 )
226  {
227  valid2 = true;
228  ep2inv = refrsq/ep2sq * ep2;
229  rayendp = ep2inv;
230  sign = -1;
231  }
232  if ( valid1 || valid2 )
233  {
234  if ( valid1 && valid2 )
235  {
236  // this gives either a segment or the complement of a segment (relative
237  // to its support line). We return a segment in any case (fixme)
238  double ang = atan2( -c.y, -c.x );
239  double sa = arc->startAngle();
240  if ( ang < sa ) ang += 2*M_PI;
241  if ( ang - sa - arc->angle() < 0 ) return new InvalidImp();
242  return new SegmentImp( ep1inv + refc, ep2inv + refc );
243  } else
244  return new RayImp ( rayendp + refc,
245  rayendp + refc + sign*Coordinate( -c.y, c.x ) ); // this should give a Ray
246  } else
247  return new LineImp( bprime+refc, bprime+refc+Coordinate( -c.y, c.x ) );
248  }
249 
250  Coordinate a = c - tc;
251  double asq = a.x*a.x + a.y*a.y;
252  Coordinate aprime = refrsq*a/asq;
253 
254  Coordinate cprime = 0.5*(aprime + bprime);
255  double rprime = 0.5*( bprime - aprime ).length();
256 
257  Coordinate ep1 = arc->firstEndPoint() - refc;
258  double ang1 = arc->startAngle();
259  double newstartangle = 2*atan2(ep1.y,ep1.x) - ang1;
260  Coordinate ep2 = arc->secondEndPoint() - refc;
261  double ang2 = ang1 + arc->angle();
262  double newendangle = 2*atan2(ep2.y,ep2.x) - ang2;
263  double newangle = newendangle - newstartangle;
264 
265  /*
266  * newstartangle and newendangle might have to be exchanged:
267  * this is the case if the circle supporting our arc does not
268  * contain the center of the inversion circle
269  */
270  if ( r < clength )
271  {
272  newstartangle = newendangle - M_PI;
273  newangle = - newangle;
274  // newendangle is no-longer valid
275  }
276  while ( newstartangle <= -M_PI ) newstartangle += 2*M_PI;
277  while ( newstartangle > M_PI ) newstartangle -= 2*M_PI;
278  while ( newangle < 0 ) newangle += 2*M_PI;
279  while ( newangle >= 2*M_PI ) newangle -= 2*M_PI;
280  return new ArcImp( cprime + refc, rprime, newstartangle, newangle );
281  }
282 
283  return new InvalidImp;
284 }
285 
286 /*
287  * inversion of a point
288  */
289 
290 static const ArgsParser::spec argsspecInvertPoint[] =
291 {
292  { PointImp::stype(), I18N_NOOP( "Compute the inversion of this point" ),
293  I18N_NOOP( "Select the point to invert..." ), false },
294  { CircleImp::stype(), str1, str2, false }
295 };
296 
297 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertPointType )
298 
299 InvertPointType::InvertPointType()
300  : ArgsParserObjectType( "InvertPoint", argsspecInvertPoint, 2 )
301 {
302 }
303 
304 InvertPointType::~InvertPointType()
305 {
306 }
307 
308 const InvertPointType* InvertPointType::instance()
309 {
310  static const InvertPointType s;
311  return &s;
312 }
313 
314 const ObjectImpType* InvertPointType::resultId() const
315 {
316  return PointImp::stype();
317 }
318 
319 ObjectImp* InvertPointType::calc( const Args& args, const KigDocument& ) const
320 {
321  if ( args.size() == 2 && args[1]->inherits( LineImp::stype() ) )
322  {
323  /* we also accept the special case when the circle becomes a
324  * straight line (see comment above)
325  */
326  LineData d = static_cast<const AbstractLineImp*>( args[1] )->data();
327  Transformation t = Transformation::lineReflection( d );
328  return args[0]->transform( t );
329  }
330  if ( ! margsparser.checkArgs( args ) ) return new InvalidImp;
331 
332  const CircleImp* c = static_cast<const CircleImp*>( args[1] );
333  Coordinate center = c->center();
334  Coordinate relp = static_cast<const PointImp*>( args[0] )->coordinate() - center;
335  double radiussq = c->squareRadius();
336  double normsq = relp.x*relp.x + relp.y*relp.y;
337  if ( normsq == 0 ) return new InvalidImp;
338  return new PointImp( center + (radiussq/normsq)*relp );
339 }
340 
341 /*
342  * old-style invertion types. These can be safely removed, since trying
343  * to load kig files that use these constructions are correctly converted
344  * into the new CircularInversion.
345  */
346 
347 /*
348  * inversion of a line
349  */
350 
351 static const ArgsParser::spec argsspecInvertLine[] =
352 {
353  { LineImp::stype(), I18N_NOOP( "Compute the inversion of this line" ),
354  I18N_NOOP( "Select the line to invert..." ), false },
355  { CircleImp::stype(), str1, str2, false }
356 };
357 
358 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertLineType )
359 
360 InvertLineType::InvertLineType()
361  : ArgsParserObjectType( "InvertLineObsolete", argsspecInvertLine, 2 )
362 {
363 }
364 
365 InvertLineType::~InvertLineType()
366 {
367 }
368 
369 const InvertLineType* InvertLineType::instance()
370 {
371  static const InvertLineType s;
372  return &s;
373 }
374 
375 const ObjectImpType* InvertLineType::resultId() const
376 {
377  return CircleImp::stype();
378 }
379 
380 ObjectImp* InvertLineType::calc( const Args& args, const KigDocument& ) const
381 {
382  if ( ! margsparser.checkArgs( args ) ) return new InvalidImp;
383 
384  const CircleImp* c = static_cast<const CircleImp*>( args[1] );
385  Coordinate center = c->center();
386  double radiussq = c->squareRadius();
387  const LineData line = static_cast<const AbstractLineImp*>( args[0] )->data();
388  Coordinate relb = line.b - center;
389  Coordinate ab = line.b - line.a;
390  double t = (relb.x*ab.x + relb.y*ab.y)/(ab.x*ab.x + ab.y*ab.y);
391  Coordinate relh = relb - t*ab;
392  double normhsq = relh.x*relh.x + relh.y*relh.y;
393  if ( normhsq < 1e-12*radiussq ) return new LineImp( line.a, line.b );
394  Coordinate newcenter = center + 0.5*radiussq/normhsq*relh;
395  double newradius = 0.5*radiussq/sqrt(normhsq);
396 
397  return new CircleImp( newcenter, newradius );
398 }
399 
400 /*
401  * inversion of a segment
402  */
403 
404 static const ArgsParser::spec argsspecInvertSegment[] =
405 {
406  { SegmentImp::stype(), I18N_NOOP( "Compute the inversion of this segment" ),
407  I18N_NOOP( "Select the segment to invert..." ), false },
408  { CircleImp::stype(), str1, str2, false }
409 };
410 
411 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertSegmentType )
412 
413 InvertSegmentType::InvertSegmentType()
414  : ArgsParserObjectType( "InvertSegmentObsolete", argsspecInvertSegment, 2 )
415 {
416 }
417 
418 InvertSegmentType::~InvertSegmentType()
419 {
420 }
421 
422 const InvertSegmentType* InvertSegmentType::instance()
423 {
424  static const InvertSegmentType s;
425  return &s;
426 }
427 
428 const ObjectImpType* InvertSegmentType::resultId() const
429 {
430  return ArcImp::stype();
431 }
432 
433 ObjectImp* InvertSegmentType::calc( const Args& args, const KigDocument& ) const
434 {
435  if ( ! margsparser.checkArgs( args ) ) return new InvalidImp;
436 
437  const CircleImp* c = static_cast<const CircleImp*>( args[1] );
438  Coordinate center = c->center();
439  double radiussq = c->squareRadius();
440  const LineData line = static_cast<const AbstractLineImp*>( args[0] )->data();
441  Coordinate rela = line.a - center;
442  Coordinate relb = line.b - center;
443  Coordinate ab = relb - rela;
444  double t = (relb.x*ab.x + relb.y*ab.y)/(ab.x*ab.x + ab.y*ab.y);
445  Coordinate relh = relb - t*ab;
446  double normhsq = relh.x*relh.x + relh.y*relh.y;
447 
448  /*
449  * compute the inversion of the two endpoints
450  */
451 
452  Coordinate newcenterrel = 0.5*radiussq/normhsq*relh;
453  Coordinate relainv = radiussq/rela.squareLength() * rela;
454  Coordinate relbinv = radiussq/relb.squareLength() * relb;
455 
456  if ( normhsq < 1e-12*radiussq )
457  {
458  if ( rela.squareLength() < 1e-12 )
459  {
460  return new RayImp( relbinv + center, 2*relbinv + center );
461  }
462  if ( relb.squareLength() < 1e-12 )
463  {
464  return new RayImp( relainv + center, 2*relainv + center );
465  }
466  if ( relb.x*rela.x + relb.y*rela.y > 0 )
467  {
468  return new SegmentImp( relainv + center, relbinv + center );
469  }
470  return new InvalidImp();
471  }
472  double newradius = 0.5*radiussq/sqrt(normhsq);
473 
474  relainv -= newcenterrel;
475  relbinv -= newcenterrel;
476  double angle1 = atan2( relainv.y, relainv.x );
477  double angle2 = atan2( relbinv.y, relbinv.x );
478  double angle = angle2 - angle1;
479  if ( ab.x*rela.y - ab.y*rela.x > 0 )
480  {
481  angle1 = angle2;
482  angle = -angle;
483  }
484  while ( angle1 < 0 ) angle1 += 2*M_PI;
485  while ( angle1 >= 2*M_PI ) angle1 -= 2*M_PI;
486  while ( angle < 0 ) angle += 2*M_PI;
487  while ( angle >= 2*M_PI ) angle -= 2*M_PI;
488  return new ArcImp( newcenterrel + center, newradius, angle1, angle );
489 }
490 
491 /*
492  * inversion of a circle
493  */
494 
495 static const ArgsParser::spec argsspecInvertCircle[] =
496 {
497  { CircleImp::stype(), I18N_NOOP( "Compute the inversion of this circle" ),
498  I18N_NOOP( "Select the circle to invert..." ), false },
499  { CircleImp::stype(), str1, str2, false }
500 };
501 
502 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertCircleType )
503 
504 InvertCircleType::InvertCircleType()
505  : ArgsParserObjectType( "InvertCircleObsolete", argsspecInvertCircle, 2 )
506 {
507 }
508 
509 InvertCircleType::~InvertCircleType()
510 {
511 }
512 
513 const InvertCircleType* InvertCircleType::instance()
514 {
515  static const InvertCircleType s;
516  return &s;
517 }
518 
519 const ObjectImpType* InvertCircleType::resultId() const
520 {
521  return CircleImp::stype();
522 }
523 
524 ObjectImp* InvertCircleType::calc( const Args& args, const KigDocument& ) const
525 {
526  if ( ! margsparser.checkArgs( args ) ) return new InvalidImp;
527 
528  const CircleImp* refcircle = static_cast<const CircleImp*>( args[1] );
529  Coordinate refc = refcircle->center();
530  double refrsq = refcircle->squareRadius();
531  const CircleImp* circle = static_cast<const CircleImp*>( args[0] );
532  Coordinate c = circle->center() - refc;
533  double clength = c.length();
534  Coordinate cnorm = Coordinate (1.,0.);
535  if ( clength != 0.0 ) cnorm = c/clength;
536  double r = circle->radius();
537  Coordinate tc = r*cnorm;
538  Coordinate b = c + tc; //(1 + t)*c;
539  double bsq = b.x*b.x + b.y*b.y;
540  Coordinate bprime = refrsq*b/bsq;
541  if ( std::fabs( clength - r ) < 1e-6*clength ) // circle through origin -> line
542  {
543  return new LineImp( bprime+refc, bprime+refc+Coordinate( -c.y, c.x ) );
544  }
545 
546  Coordinate a = c - tc;
547  double asq = a.x*a.x + a.y*a.y;
548  Coordinate aprime = refrsq*a/asq;
549 
550  Coordinate cprime = 0.5*(aprime + bprime);
551  double rprime = 0.5*( bprime - aprime ).length();
552 
553  return new CircleImp( cprime + refc, rprime );
554 }
555 
556 /*
557  * inversion of an arc
558  */
559 
560 static const ArgsParser::spec argsspecInvertArc[] =
561 {
562  { ArcImp::stype(), I18N_NOOP( "Compute the inversion of this arc" ),
563  I18N_NOOP( "Select the arc to invert..." ), false },
564  { CircleImp::stype(), str1, str2, false }
565 };
566 
567 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertArcType )
568 
569 InvertArcType::InvertArcType()
570  : ArgsParserObjectType( "InvertArcObsolete", argsspecInvertArc, 2 )
571 {
572 }
573 
574 InvertArcType::~InvertArcType()
575 {
576 }
577 
578 const InvertArcType* InvertArcType::instance()
579 {
580  static const InvertArcType s;
581  return &s;
582 }
583 
584 const ObjectImpType* InvertArcType::resultId() const
585 {
586  return ArcImp::stype();
587 }
588 
589 ObjectImp* InvertArcType::calc( const Args& args, const KigDocument& ) const
590 {
591  if ( ! margsparser.checkArgs( args ) ) return new InvalidImp;
592 
593  const CircleImp* refcircle = static_cast<const CircleImp*>( args[1] );
594  Coordinate refc = refcircle->center();
595  double refrsq = refcircle->squareRadius();
596  const ArcImp* arc = static_cast<const ArcImp*>( args[0] );
597  Coordinate c = arc->center() - refc;
598  double clength = c.length();
599  Coordinate cnorm = Coordinate (1.,0.);
600  if ( clength != 0.0 ) cnorm = c/clength;
601  double r = arc->radius();
602  /*
603  * r > clength means center of inversion circle inside of circle supporting arc
604  */
605  Coordinate tc = r*cnorm;
606  Coordinate b = c + tc;
607  double bsq = b.x*b.x + b.y*b.y;
608  Coordinate bprime = refrsq*b/bsq;
609  if ( std::fabs( clength - r ) < 1e-6*clength ) // support circle through origin ->
610  // segment, ray or invalid
611  // (reversed segment, union of two rays)
612  {
613  bool valid1 = false;
614  bool valid2 = false;
615  Coordinate ep1 = arc->firstEndPoint() - refc;
616  Coordinate ep2 = arc->secondEndPoint() - refc;
617  Coordinate ep1inv = Coordinate::invalidCoord();
618  Coordinate ep2inv = Coordinate::invalidCoord();
619  double ep1sq = ep1.squareLength();
620  if ( ep1sq > 1e-12 )
621  {
622  valid1 = true;
623  ep1inv = refrsq/ep1sq * ep1;
624  }
625  Coordinate rayendp = ep1inv;
626  int sign = 1;
627  double ep2sq = ep2.squareLength();
628  if ( ep2sq > 1e-12 )
629  {
630  valid2 = true;
631  ep2inv = refrsq/ep2sq * ep2;
632  rayendp = ep2inv;
633  sign = -1;
634  }
635  if ( valid1 || valid2 )
636  {
637  if ( valid1 && valid2 )
638  {
639  // this gives either a segment or the complement of a segment (relative
640  // to its support line). We return a segment in any case (fixme)
641  double ang = atan2( -c.y, -c.x );
642  double sa = arc->startAngle();
643  if ( ang < sa ) ang += 2*M_PI;
644  if ( ang - sa - arc->angle() < 0 ) return new InvalidImp();
645  return new SegmentImp( ep1inv + refc, ep2inv + refc );
646  } else
647  return new RayImp ( rayendp + refc,
648  rayendp + refc + sign*Coordinate( -c.y, c.x ) ); // this should give a Ray
649  } else
650  return new LineImp( bprime+refc, bprime+refc+Coordinate( -c.y, c.x ) );
651  }
652 
653  Coordinate a = c - tc;
654  double asq = a.x*a.x + a.y*a.y;
655  Coordinate aprime = refrsq*a/asq;
656 
657  Coordinate cprime = 0.5*(aprime + bprime);
658  double rprime = 0.5*( bprime - aprime ).length();
659 
660  Coordinate ep1 = arc->firstEndPoint() - refc;
661  double ang1 = arc->startAngle();
662  double newstartangle = 2*atan2(ep1.y,ep1.x) - ang1;
663  Coordinate ep2 = arc->secondEndPoint() - refc;
664  double ang2 = ang1 + arc->angle();
665  double newendangle = 2*atan2(ep2.y,ep2.x) - ang2;
666  double newangle = newendangle - newstartangle;
667 
668  /*
669  * newstartangle and newendangle might have to be exchanged:
670  * this is the case if the circle supporting our arc does not
671  * contain the center of the inversion circle
672  */
673  if ( r < clength )
674  {
675  newstartangle = newendangle - M_PI;
676  newangle = - newangle;
677  // newendangle is no-longer valid
678  }
679  while ( newstartangle < 0 ) newstartangle += 2*M_PI;
680  while ( newstartangle >= 2*M_PI ) newstartangle -= 2*M_PI;
681  while ( newangle < 0 ) newangle += 2*M_PI;
682  while ( newangle >= 2*M_PI ) newangle -= 2*M_PI;
683  return new ArcImp( cprime + refc, rprime, newstartangle, newangle );
684 }
685 
object_imp.h
Transformation::lineReflection
static const Transformation lineReflection(const LineData &l)
Line Reflection.
Definition: kigtransform.cpp:316
ObjectImpType
Instances of this class represent a certain ObjectImp type.
Definition: object_imp.h:95
KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE
KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE(SegmentAxisType)
point_imp.h
ArgsParserObjectType
This is a convenience subclass of ObjectType that a type should inherit from if its parents can be sp...
Definition: object_type.h:113
InvertCircleType
Definition: inversion_type.h:78
ObjectType::inherits
virtual bool inherits(int type) const
Definition: object_type.cc:64
AbstractLineImp
An ObjectImp class that is the base of the line-like ObjectImp's: SegmentImp, LineImp and RayImp...
Definition: line_imp.h:31
LineData
Simple class representing a line.
Definition: misc/common.h:49
LineData::b
Coordinate b
Another point on the line.
Definition: misc/common.h:68
CircleImp
An ObjectImp representing a circle.
Definition: circle_imp.h:27
RayImp
An ObjectImp representing a ray.
Definition: line_imp.h:136
CircleImp::center
const Coordinate center() const
Return the center of this circle.
Definition: circle_imp.cc:210
ArcImp::firstEndPoint
Coordinate firstEndPoint() const
Return the start point of this arc.
Definition: other_imp.cc:552
special_imptypes.h
RayImp::stype
static const ObjectImpType * stype()
Returns the ObjectImpType representing the RayImp type.
Definition: line_imp.cc:562
InvertPointType
Inversion of a point, line.
Definition: inversion_type.h:42
circle_imp.h
LineImp::stype
static const ObjectImpType * stype()
Returns the ObjectImpType representing the LineImp type.
Definition: line_imp.cc:528
InvertSegmentType::calc
ObjectImp * calc(const Args &args, const KigDocument &) const
Definition: inversion_type.cc:433
InvertSegmentType
Definition: inversion_type.h:66
argsspecInvertCircle
static const ArgsParser::spec argsspecInvertCircle[]
Definition: inversion_type.cc:495
ArcImp::radius
double radius() const
Return the radius of this arc.
Definition: other_imp.cc:537
argsspecInvertArc
static const ArgsParser::spec argsspecInvertArc[]
Definition: inversion_type.cc:560
Coordinate
The Coordinate class is the basic class representing a 2D location by its x and y components...
Definition: coordinate.h:33
InvertSegmentType::resultId
const ObjectImpType * resultId() const
returns the ObjectImp id of the ObjectImp's produced by this ObjectType.
Definition: inversion_type.cc:428
Coordinate::length
double length() const
Length.
Definition: coordinate.cpp:144
ArgsParserObjectType::margsparser
const ArgsParser margsparser
Definition: object_type.h:117
argsspecInvertLine
static const ArgsParser::spec argsspecInvertLine[]
Definition: inversion_type.cc:351
invertibleimptypeinstance
InvertibleImpType invertibleimptypeinstance
CircularInversionType::instance
static const CircularInversionType * instance()
Definition: inversion_type.cc:56
InvertLineType::resultId
const ObjectImpType * resultId() const
returns the ObjectImp id of the ObjectImp's produced by this ObjectType.
Definition: inversion_type.cc:375
argsspecCircularInversion
static const ArgsParser::spec argsspecCircularInversion[]
Definition: inversion_type.cc:37
InvertSegmentType::instance
static const InvertSegmentType * instance()
Definition: inversion_type.cc:422
InvertLineType::instance
static const InvertLineType * instance()
Definition: inversion_type.cc:369
ArcImp::angle
double angle() const
Return the dimension in radians of this arc.
Definition: other_imp.cc:547
bogus_imp.h
PointImp
An ObjectImp representing a point.
Definition: point_imp.h:27
Args
std::vector< const ObjectImp * > Args
Definition: objects/common.h:47
Transformation
Class representing a transformation.
Definition: kigtransform.h:37
InvertPointType::instance
static const InvertPointType * instance()
Definition: inversion_type.cc:308
ArcImp::secondEndPoint
Coordinate secondEndPoint() const
Return the end point of this arc.
Definition: other_imp.cc:558
LineData::a
Coordinate a
One point on the line.
Definition: misc/common.h:64
ArgsParser::checkArgs
bool checkArgs(const std::vector< ObjectCalcer * > &os) const
Definition: argsparser.cpp:222
SegmentImp::stype
static const ObjectImpType * stype()
Returns the ObjectImpType representing the SegmentImp type.
Definition: line_imp.cc:545
CircularInversionType::calc
ObjectImp * calc(const Args &args, const KigDocument &) const
Definition: inversion_type.cc:67
ArgsParser::spec
Definition: argsparser.h:113
ArcImp::stype
static const ObjectImpType * stype()
Returns the ObjectImpType representing the ArcImp type.
Definition: other_imp.cc:629
InvertCircleType::calc
ObjectImp * calc(const Args &args, const KigDocument &) const
Definition: inversion_type.cc:524
InvertLineType
Definition: inversion_type.h:54
ArcImp::center
const Coordinate center() const
Return the center of this arc.
Definition: other_imp.cc:532
CircleImp::stype
static const ObjectImpType * stype()
Returns the ObjectImpType representing the CircleImp type.
Definition: circle_imp.cc:342
Coordinate::squareLength
double squareLength() const
Square length.
Definition: coordinate.h:163
ArcImp::startAngle
double startAngle() const
Return the start angle in radians of this arc.
Definition: other_imp.cc:542
InvertArcType::resultId
const ObjectImpType * resultId() const
returns the ObjectImp id of the ObjectImp's produced by this ObjectType.
Definition: inversion_type.cc:584
InvertPointType::resultId
const ObjectImpType * resultId() const
returns the ObjectImp id of the ObjectImp's produced by this ObjectType.
Definition: inversion_type.cc:314
InvertArcType
Definition: inversion_type.h:90
Coordinate::invalidCoord
static Coordinate invalidCoord()
Create an invalid Coordinate.
Definition: coordinate.cpp:171
CircularInversionType
Circular inversion (new style)
Definition: inversion_type.h:27
CircleImp::radius
double radius() const
Return the radius of this circle.
Definition: circle_imp.cc:215
PointImp::stype
static const ObjectImpType * stype()
Returns the ObjectImpType representing PointImp's.
Definition: point_imp.cc:159
line_imp.h
KigDocument
KigDocument is the class holding the real data in a Kig document.
Definition: kig_document.h:36
AbstractLineImp::stype
static const ObjectImpType * stype()
Returns the ObjectImpType representing the AbstractLineImp type.
Definition: line_imp.cc:520
InvertPointType::calc
ObjectImp * calc(const Args &args, const KigDocument &) const
Definition: inversion_type.cc:319
LineImp
An ObjectImp representing a line.
Definition: line_imp.h:184
argsspecInvertSegment
static const ArgsParser::spec argsspecInvertSegment[]
Definition: inversion_type.cc:404
InvertCircleType::instance
static const InvertCircleType * instance()
Definition: inversion_type.cc:513
ArcImp
An ObjectImp representing an arc.
Definition: other_imp.h:169
Coordinate::x
double x
X Component.
Definition: coordinate.h:126
InvertLineType::calc
ObjectImp * calc(const Args &args, const KigDocument &) const
Definition: inversion_type.cc:380
Coordinate::y
double y
Y Component.
Definition: coordinate.h:129
ObjectImp
The ObjectImp class represents the behaviour of an object after it is calculated. ...
Definition: object_imp.h:226
argsspecInvertPoint
static const ArgsParser::spec argsspecInvertPoint[]
Definition: inversion_type.cc:290
InvertArcType::instance
static const InvertArcType * instance()
Definition: inversion_type.cc:578
CircleImp::squareRadius
double squareRadius() const
Return the square radius of this circle.
Definition: circle_imp.cc:225
inversion_type.h
str1
static const char str1[]
Definition: inversion_type.cc:34
InvertCircleType::resultId
const ObjectImpType * resultId() const
returns the ObjectImp id of the ObjectImp's produced by this ObjectType.
Definition: inversion_type.cc:519
InvalidImp
This ObjectImp represents an invalid object.
Definition: bogus_imp.h:61
InvertArcType::calc
ObjectImp * calc(const Args &args, const KigDocument &) const
Definition: inversion_type.cc:589
CircularInversionType::resultId
const ObjectImpType * resultId() const
returns the ObjectImp id of the ObjectImp's produced by this ObjectType.
Definition: inversion_type.cc:62
other_imp.h
str2
static const char str2[]
Definition: inversion_type.cc:35
SegmentImp
An ObjectImp representing a segment.
Definition: line_imp.h:81
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:12:05 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kig

Skip menu "kig"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal