Hello community, here is the log from the commit of package kig for openSUSE:Factory checked in at 2016-08-31 00:07:34 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kig (Old) and /work/SRC/openSUSE:Factory/.kig.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kig" Changes: -------- --- /work/SRC/openSUSE:Factory/kig/kig.changes 2016-07-24 19:46:33.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.kig.new/kig.changes 2016-08-31 00:07:36.000000000 +0200 @@ -1,0 +2,16 @@ +Fri Aug 12 10:17:43 UTC 2016 - [email protected] + +- Update to KDE Applications 16.08.0 + * KDE Applications 16.08.0 + * https://www.kde.org/announcements/announce-applications-16.08.0.php + + +------------------------------------------------------------------- +Mon Aug 8 15:04:50 UTC 2016 - [email protected] + +- Update to KDE Applications 16.07.90 + * KDE Applications 16.07.90 (16.08-RC) + * https://www.kde.org/announcements/announce-applications-16.07.90.php + + +------------------------------------------------------------------- Old: ---- kig-16.04.3.tar.xz New: ---- kig-16.08.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kig.spec ++++++ --- /var/tmp/diff_new_pack.2bk2c6/_old 2016-08-31 00:07:37.000000000 +0200 +++ /var/tmp/diff_new_pack.2bk2c6/_new 2016-08-31 00:07:37.000000000 +0200 @@ -17,7 +17,7 @@ Name: kig -Version: 16.04.3 +Version: 16.08.0 Release: 0 Summary: Interactive Geometry License: GPL-2.0+ ++++++ kig-16.04.3.tar.xz -> kig-16.08.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/misc/common.cpp new/kig-16.08.0/misc/common.cpp --- old/kig-16.04.3/misc/common.cpp 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/misc/common.cpp 2016-04-28 00:34:52.000000000 +0200 @@ -366,7 +366,8 @@ double b2 = xao*xao + yao*yao; double numerator = (xdo * yao - xao * ydo); - if ( numerator == 0 ) + /* mp: note that we should never compare with zero due to floating-point arithmetic */ + if ( isSingular (xdo, ydo, xao, yao) ) { // problem: xdo * yao == xao * ydo <=> xdo/ydo == xao / yao // this means that the lines ac and ab have the same direction, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/misc/kigpainter.cpp new/kig-16.08.0/misc/kigpainter.cpp --- old/kig-16.04.3/misc/kigpainter.cpp 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/misc/kigpainter.cpp 2016-04-28 00:34:52.000000000 +0200 @@ -86,14 +86,14 @@ Coordinate bottomLeft = center - Coordinate(radius, radius); Coordinate topRight = center + Coordinate(radius, radius); Rect r( bottomLeft, topRight ); - QRect qr = toScreen( r ); + QRectF qr = toScreenF( r ); mP.drawEllipse ( qr ); if( mNeedOverlay ) circleOverlay( center, radius ); } void KigPainter::drawSegment( const Coordinate& from, const Coordinate& to ) { - QPoint tF = toScreen(from), tT = toScreen(to); + QPointF tF = toScreenF(from), tT = toScreenF(to); mP.drawLine( tF, tT ); if( mNeedOverlay ) segmentOverlay( from, to ); } @@ -506,6 +506,11 @@ return msi.toScreen( p ); } +QPointF KigPainter::toScreenF( const Coordinate& p ) const +{ + return msi.toScreenF( p ); +} + void KigPainter::drawGrid( const CoordinateSystem& c, bool showGrid, bool showAxes ) { c.drawGrid( *this, showGrid, showAxes ); @@ -549,6 +554,11 @@ return msi.toScreen( r ); } +QRectF KigPainter::toScreenF( const Rect& r ) const +{ + return msi.toScreenF( r ); +} + QRect KigPainter::toScreenEnlarge( const Rect& r ) const { if ( overlayenlarge == 0 ) return msi.toScreen( r ); @@ -973,7 +983,7 @@ { Rect krect( 0, 0, 2*radius, 2*radius ); krect.setCenter( center ); - QRect rect = toScreen( krect ); + QRectF rect = toScreenF( krect ); mP.drawArc( rect, startangle, angle ); setWholeWinOverlay(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/misc/kigpainter.h new/kig-16.08.0/misc/kigpainter.h --- old/kig-16.04.3/misc/kigpainter.h 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/misc/kigpainter.h 2016-04-28 00:34:52.000000000 +0200 @@ -89,6 +89,8 @@ QPoint toScreen( const Coordinate& p ) const; QRect toScreen( const Rect& r ) const; + QPointF toScreenF( const Coordinate& p ) const; + QRectF toScreenF( const Rect& r ) const; QRect toScreenEnlarge( const Rect& r ) const; Coordinate fromScreen( const QPoint& p ) const; Rect fromScreen( const QRect& r ) const; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/misc/screeninfo.cc new/kig-16.08.0/misc/screeninfo.cc --- old/kig-16.04.3/misc/screeninfo.cc 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/misc/screeninfo.cc 2016-04-28 00:34:52.000000000 +0200 @@ -58,6 +58,23 @@ ).normalized(); } +QPointF ScreenInfo::toScreenF( const Coordinate& p ) const +{ + Coordinate t = p - mkrect.bottomLeft(); + t *= mqrect.width(); + t /= mkrect.width(); + // invert the y-axis: 0 is at the bottom ! + return QPointF( t.x, mqrect.height() - t.y ); +} + +QRectF ScreenInfo::toScreenF( const Rect& r ) const +{ + return QRectF( + toScreenF( r.bottomLeft() ), + toScreenF( r.topRight() ) + ).normalized(); +} + double ScreenInfo::pixelWidth() const { Coordinate a = fromScreen( QPoint( 0, 0 ) ); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/misc/screeninfo.h new/kig-16.08.0/misc/screeninfo.h --- old/kig-16.04.3/misc/screeninfo.h 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/misc/screeninfo.h 2016-04-28 00:34:52.000000000 +0200 @@ -40,6 +40,8 @@ QPoint toScreen( const Coordinate& p ) const; QRect toScreen( const Rect& r ) const; + QPointF toScreenF( const Coordinate& p ) const; + QRectF toScreenF( const Rect& r ) const; double pixelWidth() const; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/objects/arc_type.cc new/kig-16.08.0/objects/arc_type.cc --- old/kig-16.04.3/objects/arc_type.cc 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/objects/arc_type.cc 2016-04-28 00:34:52.000000000 +0200 @@ -41,7 +41,7 @@ #include <qstringlist.h> /* - * arc by three points + * oriented arc by three points */ static const char constructarcstartingstat[] = I18N_NOOP( "Construct an arc starting at this point" ); @@ -85,12 +85,14 @@ Coordinate center; double angle = 0.; double startangle = 0.; + int orientation = 1; if ( args.size() == 3 ) { Coordinate c = static_cast<const PointImp*>( args[2] )->coordinate(); center = calcCenter( a, b, c ); if ( ! center.valid() ) { +/* TODO: return correctly oriented segment! */ if ( fabs( a.x - c.x ) > fabs( a.y - c.y ) ) { if ( ( b.x - a.x)*(c.x - b.x) > 1e-12 ) return new SegmentImp(a, c); @@ -100,6 +102,15 @@ } return new InvalidImp; } + /* this is also done in calcCenter... should optimize in some way */ + double xdo = b.x-a.x; + double ydo = b.y-a.y; + + double xao = c.x-a.x; + double yao = c.y-a.y; + + if ( xdo * yao - xao * ydo < 0.0 ) orientation = -1; + Coordinate ad = a - center; Coordinate bd = b - center; Coordinate cd = c - center; @@ -138,7 +149,7 @@ }; double radius = ( a - center ).length(); - return new ArcImp( center, radius, startangle, angle ); + return new ArcImp( center, orientation*radius, startangle, angle ); } const ObjectImpType* ArcBTPType::impRequirement( const ObjectImp*, const Args& ) const diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/objects/arc_type.h new/kig-16.08.0/objects/arc_type.h --- old/kig-16.04.3/objects/arc_type.h 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/objects/arc_type.h 2016-04-28 00:34:52.000000000 +0200 @@ -23,6 +23,7 @@ /** * an arc by a start point, an intermediate point and an end point + * (with orientation) */ class ArcBTPType : public ArgsParserObjectType diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/objects/circle_imp.cc new/kig-16.08.0/objects/circle_imp.cc --- old/kig-16.04.3/objects/circle_imp.cc 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/objects/circle_imp.cc 2016-04-28 00:34:52.000000000 +0200 @@ -59,12 +59,12 @@ void CircleImp::draw( KigPainter& p ) const { - p.drawCircle( mcenter, mradius ); + p.drawCircle( mcenter, fabs( mradius ) ); } bool CircleImp::contains( const Coordinate& p, int width, const KigWidget& w ) const { - return fabs((mcenter - p).length() - mradius) <= w.screenInfo().normalMiss( width ); + return fabs((mcenter - p).length() - fabs( mradius )) <= w.screenInfo().normalMiss( width ); } bool CircleImp::inRect( const Rect& r, int width, const KigWidget& w ) const @@ -78,9 +78,9 @@ // we allow a miss of some pixels .. double miss = w.screenInfo().normalMiss( width ); - double bigradius = mradius + miss; + double bigradius = fabs( mradius ) + miss; bigradius *= bigradius; - double smallradius = mradius - miss; + double smallradius = fabs( mradius ) - miss; smallradius *= smallradius; const int in = -1; @@ -212,7 +212,12 @@ double CircleImp::radius() const { - return mradius; + return fabs( mradius ); +} + +double CircleImp::orientation() const +{ + return (mradius > 0)?1:(-1); } double CircleImp::surface() const @@ -369,6 +374,6 @@ Rect CircleImp::surroundingRect() const { - Coordinate d( mradius, mradius ); + Coordinate d( fabs( mradius ), fabs( mradius ) ); return Rect( mcenter - d, mcenter + d ); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/objects/circle_imp.h new/kig-16.08.0/objects/circle_imp.h --- old/kig-16.04.3/objects/circle_imp.h 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/objects/circle_imp.h 2016-04-28 00:34:52.000000000 +0200 @@ -74,6 +74,10 @@ */ double radius() const; /** + * Return the orientation of this circle. + */ + double orientation() const; + /** * Return the square radius of this circle. Use this in preference * to sqr( radius() ). */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/objects/circle_type.cc new/kig-16.08.0/objects/circle_type.cc --- old/kig-16.04.3/objects/circle_type.cc 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/objects/circle_type.cc 2016-04-28 00:34:52.000000000 +0200 @@ -61,12 +61,6 @@ return new CircleImp( a, ( b - a ).length() ); } -const CircleBTPType* CircleBTPType::instance() -{ - static const CircleBTPType t; - return &t; -} - static const ArgsParser::spec argsspecCircleBTP[] = { { PointImp::stype(), constructcirclethroughpointstat, @@ -88,6 +82,12 @@ { } +const CircleBTPType* CircleBTPType::instance() +{ + static const CircleBTPType t; + return &t; +} + ObjectImp* CircleBTPType::calc( const Args& args, const KigDocument& ) const { if ( ! margsparser.checkArgs( args, 2 ) ) return new InvalidImp; @@ -131,7 +131,18 @@ const Coordinate center = calcCenter( a, b, c ); if ( center.valid() ) - return new CircleImp( center, (center - a ).length() ); + { + /* this is also done in calcCenter... should optimize in some way */ + double xdo = b.x-a.x; + double ydo = b.y-a.y; + + double xao = c.x-a.x; + double yao = c.y-a.y; + + double determinant = (xdo * yao - xao * ydo); + if (determinant > 0) return new CircleImp( center, (center - a ).length() ); + else return new CircleImp( center, -(center - a ).length() ); + } /* * case of collinear points, we need to identify the intermediate one @@ -141,7 +152,7 @@ double xmax = fmax( a.x, fmax( b.x, c.x) ); double ymin = fmin( a.y, fmin( b.y, c.y) ); double ymax = fmax( a.y, fmax( b.y, c.y) ); - double axy, bxy, cxy; + double d, axy, bxy, cxy; /* decide whether to work with x coordinate or y coordinate */ @@ -150,30 +161,30 @@ axy = a.x; bxy = b.x; cxy = c.x; + d = xmax - xmin; } else { axy = a.y; bxy = b.y; cxy = c.y; + d = ymax - ymin; } - /* - * compute baricentric coordinate of c with respect to a and b - * (if a and c are not coincident) - */ - if ( fabs( cxy - axy ) < 1e-6*fabs( bxy - axy ) ) return new InvalidImp; - double t = (bxy - axy)/(cxy - axy); + if ( fabs( axy - cxy ) >= d ) // b between a and c + return new LineImp( a, c ); + if ( fabs( cxy - bxy ) >= d ) // a between c and b + return new LineImp( c, b ); - if ( fabs( t ) < 1e-6 || fabs( 1.0 - t ) < 1e-6 ) return new InvalidImp; + // otherwise: c between b and a + return new LineImp( b, a); /* - * t < 0: a between c and b - * 0 < t < 1: b between a and c - * t > 1: c between a and b + * mp: note that the orientation of the new line is from a to c + * if b is intermediate, otherwise it is reversed whenever + * two of the three points cross each-other. + * This should give consistent results when intersecting circles that + * degenerate into lines */ - if ( t < 0.0 ) return new LineImp( c, b ); - if ( t > 1.0 ) return new LineImp( a, b ); - return new LineImp( a, c ); } const ObjectImpType* CircleBCPType::resultId() const diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/objects/circle_type.h new/kig-16.08.0/objects/circle_type.h --- old/kig-16.04.3/objects/circle_type.h 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/objects/circle_type.h 2016-04-28 00:34:52.000000000 +0200 @@ -51,7 +51,7 @@ }; /** - * Circle by three points + * Circle by three points (with orientation) */ class CircleBTPType : public ArgsParserObjectType @@ -66,4 +66,5 @@ const ObjectImpType* resultId() const; }; + #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/objects/intersection_types.cc new/kig-16.08.0/objects/intersection_types.cc --- old/kig-16.04.3/objects/intersection_types.cc 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/objects/intersection_types.cc 2016-04-28 00:34:52.000000000 +0200 @@ -57,6 +57,32 @@ ObjectImp* ConicLineIntersectionType::calc( const Args& parents, const KigDocument& doc ) const { + /* + * special case of a circle that degenerates into a line. This is possible e.g. for + * circles by three points when the points get aligned. + */ + if ( parents.size() == 3 && parents[0]->inherits( AbstractLineImp::stype() ) && + parents[1]->inherits( AbstractLineImp::stype() ) && + parents[2]->inherits( IntImp::stype() ) ) + { + int side = static_cast<const IntImp*>( parents[2] )->data(); + assert( side == 1 || side == -1 ); + const LineData degline = static_cast<const AbstractLineImp*>( parents[0] )->data(); + const LineData line = static_cast<const AbstractLineImp*>( parents[1] )->data(); + const double vecprod = degline.dir().y * line.dir().x - degline.dir().x * line.dir().y; + /* + * mp: In this case only one of the two points must be valid (the other is "pushed" + * to infinity). The choice of which one is done such that we avoid abrupt points exchange + * when dinamically movint points + */ + if (side*vecprod < 0) + { + Coordinate p = calcIntersectionPoint( degline, line ); + return new PointImp( p ); + } + return new InvalidImp(); + } + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; int side = static_cast<const IntImp*>( parents[2] )->data(); @@ -70,7 +96,7 @@ // easy case.. const CircleImp* c = static_cast<const CircleImp*>( parents[0] ); ret = calcCircleLineIntersect( - c->center(), c->squareRadius(), line, side ); + c->center(), c->squareRadius(), line, c->orientation()*side ); } else { @@ -493,6 +519,41 @@ ObjectImp* CircleCircleIntersectionType::calc( const Args& parents, const KigDocument& ) const { + if ( parents.size() == 3 && + ( parents[0]->inherits( LineImp::stype() ) || parents[1]->inherits( LineImp::stype() ) ) && + parents[2]->inherits( IntImp::stype() ) ) + { + /* This the special case when one or both circles degenerate into a line + */ + int il = 0; + int ori = 1; + if ( parents[1]->inherits( LineImp::stype() ) ) { il = 1; ori = -1; } + const LineData line = static_cast<const AbstractLineImp*>( parents[il] )->data(); + int side = static_cast<const IntImp*>( parents[2] )->data(); + assert( side == 1 || side == -1 ); + if ( parents[1 - il]->inherits( CircleImp::stype() ) ) + { + const CircleImp* c = static_cast<const CircleImp*>( parents[1 - il] ); + const Coordinate o = c->center(); + const double rsq = c->squareRadius(); + ori *= c->orientation(); + Coordinate ret = calcCircleLineIntersect( o, rsq, line, ori*side ); + if ( ret.valid() ) return new PointImp( ret ); + else return new InvalidImp; + } else { + // same code as for ConicLineIntersection with degenerate conic + assert (il == 1); + const LineData degline = static_cast<const AbstractLineImp*>( parents[0] )->data(); + const double vecprod = degline.dir().y * line.dir().x - degline.dir().x * line.dir().y; + if (side*vecprod > 0) + { + Coordinate p = calcIntersectionPoint( degline, line ); + return new PointImp( p ); + } + return new InvalidImp(); + } + } + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; int side = static_cast<const IntImp*>( parents[2] )->data(); @@ -501,12 +562,13 @@ const CircleImp* c2 = static_cast<const CircleImp*>( parents[1] ); const Coordinate o1 = c1->center(); const Coordinate o2 = c2->center(); + const int ori = ( c1->orientation()*c2->orientation() < 0 )?(-1):(1); const double r1sq = c1->squareRadius(); const Coordinate a = calcCircleRadicalStartPoint( o1, o2, r1sq, c2->squareRadius() ); const LineData line = LineData (a, Coordinate ( a.x -o2.y + o1.y, a.y + o2.x - o1.x )); - Coordinate ret = calcCircleLineIntersect( o1, r1sq, line, side ); + Coordinate ret = calcCircleLineIntersect( o1, r1sq, line, ori*side ); if ( ret.valid() ) return new PointImp( ret ); else return new InvalidImp; } @@ -544,6 +606,32 @@ ObjectImp* ArcLineIntersectionType::calc( const Args& parents, const KigDocument& ) const { + /* + * special case of an arc that degenerates into a line. This is possible e.g. for + * arcs by three points when the points get aligned. + */ + if ( parents.size() == 3 && parents[0]->inherits( AbstractLineImp::stype() ) && + parents[1]->inherits( AbstractLineImp::stype() ) && + parents[2]->inherits( IntImp::stype() ) ) + { + int side = static_cast<const IntImp*>( parents[2] )->data(); + assert( side == 1 || side == -1 ); + const LineData degline = static_cast<const AbstractLineImp*>( parents[0] )->data(); + const LineData line = static_cast<const AbstractLineImp*>( parents[1] )->data(); + const double vecprod = degline.dir().y * line.dir().x - degline.dir().x * line.dir().y; + /* + * mp: In this case only one of the two points must be valid (the other is "pushed" + * to infinity). The choice of which one is done such that we avoid abrupt points exchange + * when dinamically movint points + */ + if (side*vecprod < 0) + { + Coordinate p = calcIntersectionPoint( degline, line ); + return new PointImp( p ); + } + return new InvalidImp(); + } + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; int side = static_cast<const IntImp*>( parents[2] )->data(); @@ -553,7 +641,7 @@ const ArcImp* c = static_cast<const ArcImp*>( parents[0] ); const double r = c->radius(); Coordinate ret = calcArcLineIntersect( c->center(), r*r, c->startAngle(), - c->angle(), line, side ); + c->angle(), line, c->orientation()*side ); if ( ret.valid() ) return new PointImp( ret ); else return new InvalidImp; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/objects/other_imp.cc new/kig-16.08.0/objects/other_imp.cc --- old/kig-16.04.3/objects/other_imp.cc 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/objects/other_imp.cc 2016-04-28 00:34:52.000000000 +0200 @@ -346,7 +346,7 @@ if ( ! t.isHomothetic() ) { //CircleImp support = CircleImp( mcenter, mradius ); - ConicCartesianData data = CircleImp( mcenter, mradius ).cartesianData(); + ConicCartesianData data = CircleImp( mcenter, fabs( mradius ) ).cartesianData(); //return new InvalidImp(); ConicArcImp conicarc = ConicArcImp( data, msa, ma ); return conicarc.transform ( t ); @@ -373,7 +373,7 @@ void ArcImp::draw( KigPainter& p ) const { - p.drawArc( mcenter, mradius, msa, ma ); + p.drawArc( mcenter, fabs( mradius ), msa, ma ); } bool ArcImp::contains( const Coordinate& p, int width, const KigWidget& w ) const @@ -467,7 +467,7 @@ else if ( which == Parent::numberOfProperties() + numprop++ ) return new PointImp( mcenter ); else if ( which == Parent::numberOfProperties() + numprop++ ) - return new DoubleImp( mradius ); + return new DoubleImp( fabs( mradius ) ); else if ( which == Parent::numberOfProperties() + numprop++ ) return new AngleImp( mcenter, msa, ma, false ); else if ( which == Parent::numberOfProperties() + numprop++ ) @@ -477,7 +477,7 @@ else if ( which == Parent::numberOfProperties() + numprop++ ) return new DoubleImp( sectorSurface() ); else if ( which == Parent::numberOfProperties() + numprop++ ) - return new DoubleImp( mradius * ma ); + return new DoubleImp( fabs( mradius ) * ma ); else if ( which == Parent::numberOfProperties() + numprop++ ) return new CircleImp( mcenter, mradius ); else if ( which == Parent::numberOfProperties() + numprop++ ) @@ -517,13 +517,15 @@ // angle = max( 0., min( angle, ma ) ); angle /= ma; + if ( mradius < 0 ) angle = 1.0 - angle; // this is to avoid abrupt jumps when an ArcBTPType changes concavity return angle; } const Coordinate ArcImp::getPoint( double p, const KigDocument& ) const { + if ( mradius < 0 ) p = 1.0 - p; // this is to avoid abrupt jumps when an ArcBTPType changes concavity double angle = msa + p * ma; - Coordinate d = Coordinate( cos( angle ), sin( angle ) ) * mradius; + Coordinate d = Coordinate( cos( angle ), sin( angle ) ) * fabs( mradius ); return mcenter + d; } @@ -534,7 +536,12 @@ double ArcImp::radius() const { - return mradius; + return fabs( mradius ); +} + +double ArcImp::orientation() const +{ + return ( mradius >= 0)?1:(-1); } double ArcImp::startAngle() const @@ -549,14 +556,18 @@ Coordinate ArcImp::firstEndPoint() const { - double angle = msa; - return mcenter + Coordinate( cos( angle ), sin( angle ) ) * mradius; + /** + * mp: We take advantage of the arc orientation (mainly for the benefit of arc through 3 points) + * in order to avoid abrupt jumps when moving points + */ + const double angle = mradius >= 0 ? msa : msa+ma; + return mcenter + Coordinate( cos( angle ), sin( angle ) ) * fabs( mradius ); } Coordinate ArcImp::secondEndPoint() const { - double angle = msa + ma; - return mcenter + Coordinate( cos( angle ), sin( angle ) ) * mradius; + const double angle = mradius >= 0 ? msa+ma : msa; + return mcenter + Coordinate( cos( angle ), sin( angle ) ) * fabs( mradius ); } const Coordinate VectorImp::a() const @@ -663,7 +674,7 @@ bool ArcImp::internalContainsPoint( const Coordinate& p, double threshold ) const { - return isOnArc( p, mcenter, mradius, msa, ma, threshold ); + return isOnArc( p, mcenter, fabs( mradius ), msa, ma, threshold ); } bool AngleImp::isPropertyDefinedOnOrThroughThisImp( int which ) const @@ -724,13 +735,13 @@ // points, and all extreme x and y positions in between. //Rect ret( mcenter, 0, 0 ); double a = msa; - //ret.setContains( mcenter + mradius*Coordinate( cos( a ), sin( a ) ) ); - Rect ret ( mcenter + mradius*Coordinate( cos( a ), sin( a ) ), 0, 0 ); + //ret.setContains( mcenter + fabs( mradius )*Coordinate( cos( a ), sin( a ) ) ); + Rect ret ( mcenter + fabs( mradius )*Coordinate( cos( a ), sin( a ) ), 0, 0 ); a = msa + ma; - ret.setContains( mcenter + mradius*Coordinate( cos( a ), sin( a ) ) ); + ret.setContains( mcenter + fabs( mradius )*Coordinate( cos( a ), sin( a ) ) ); for ( a = -2*M_PI; a <= 2*M_PI; a+=M_PI/2 ) { - Coordinate d = mcenter + mradius*Coordinate( cos( a ), sin( a ) ); + Coordinate d = mcenter + fabs( mradius )*Coordinate( cos( a ), sin( a ) ); if ( msa <= a && a <= msa + ma ) ret.setContains( d ); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kig-16.04.3/objects/other_imp.h new/kig-16.08.0/objects/other_imp.h --- old/kig-16.04.3/objects/other_imp.h 2016-04-28 00:33:28.000000000 +0200 +++ new/kig-16.08.0/objects/other_imp.h 2016-04-28 00:34:52.000000000 +0200 @@ -220,6 +220,10 @@ */ double radius() const; /** + * Return the orientation of this arc (usually > 0) + */ + double orientation() const; + /** * Return the start angle in radians of this arc. */ double startAngle() const;
