// Copyright (C) 2003 Dominique Devriese // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301, USA. #include "intersection_types.h" #include "bogus_imp.h" #include "circle_imp.h" #include "conic_imp.h" #include "cubic_imp.h" #include "line_imp.h" #include "other_imp.h" #include "point_imp.h" #include static const char intersectlinestat[] = I18N_NOOP( "Intersect with this line" ); static const ArgsParser::spec argsspecConicLineIntersection[] = { { ConicImp::stype(), I18N_NOOP( "Intersect with this conic" ), "SHOULD NOT BE SEEN", true }, { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicLineIntersectionType ) ConicLineIntersectionType::ConicLineIntersectionType() : ArgsParserObjectType( "ConicLineIntersection", argsspecConicLineIntersection, 3 ) { } ConicLineIntersectionType::~ConicLineIntersectionType() { } const ConicLineIntersectionType* ConicLineIntersectionType::instance() { static const ConicLineIntersectionType t; return &t; } ObjectImp* ConicLineIntersectionType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; int side = static_cast( parents[2] )->data(); assert( side == 1 || side == -1 ); const LineData line = static_cast( parents[1] )->data(); Coordinate ret; if ( parents[0]->inherits( CircleImp::stype() ) ) { // easy case.. const CircleImp* c = static_cast( parents[0] ); ret = calcCircleLineIntersect( c->center(), c->squareRadius(), line, side ); } else { // harder case.. ret = calcConicLineIntersect( static_cast( parents[0] )->cartesianData(), line, 0.0, side ); } if ( ret.valid() ) return new PointImp( ret ); else return new InvalidImp; } static const ArgsParser::spec argsspecConicLineOtherIntersection[] = { { ConicImp::stype(), I18N_NOOP( "Intersect with this conic" ), "SHOULD NOT BE SEEN", true }, { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, { PointImp::stype(), I18N_NOOP( "Already computed intersection point"), "SHOULD NOT BE SEEN", true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicLineOtherIntersectionType ) ConicLineOtherIntersectionType::ConicLineOtherIntersectionType() : ArgsParserObjectType( "ConicLineOtherIntersection", argsspecConicLineOtherIntersection, 3 ) { } ConicLineOtherIntersectionType::~ConicLineOtherIntersectionType() { } const ConicLineOtherIntersectionType* ConicLineOtherIntersectionType::instance() { static const ConicLineOtherIntersectionType t; return &t; } ObjectImp* ConicLineOtherIntersectionType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; Coordinate p = static_cast( parents[2] )->coordinate(); const LineData line = static_cast( parents[1] )->data(); Coordinate ret; // if ( parents[0]->inherits( CircleImp::stype() ) ) // { // // easy case.. // const CircleImp* c = static_cast( parents[0] ); // ret = calcCircleLineIntersect( // c->center(), c->squareRadius(), line, side, valid ); // } // else // { // harder case.. double pax = p.x - line.a.x; double pay = p.y - line.a.y; double bax = line.b.x - line.a.x; double bay = line.b.y - line.a.y; double knownparam = (pax*bax + pay*bay)/(bax*bax + bay*bay); ret = calcConicLineIntersect( static_cast( parents[0] )->cartesianData(), line, knownparam, 0 ); // } if ( ret.valid() ) return new PointImp( ret ); else return new InvalidImp; } static const ArgsParser::spec argsspecLineLineIntersection[] = { { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineLineIntersectionType ) LineLineIntersectionType::LineLineIntersectionType() : ArgsParserObjectType( "LineLineIntersection", argsspecLineLineIntersection, 2 ) { } LineLineIntersectionType::~LineLineIntersectionType() { } const LineLineIntersectionType* LineLineIntersectionType::instance() { static const LineLineIntersectionType t; return &t; } ObjectImp* LineLineIntersectionType::calc( const Args& parents, const KigDocument& d ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; Coordinate p = calcIntersectionPoint( static_cast( parents[0] )->data(), static_cast( parents[1] )->data() ); if ( static_cast( parents[0] )->containsPoint( p, d ) && static_cast( parents[1] )->containsPoint( p, d ) ) return new PointImp( p ); else return new InvalidImp(); } static const ArgsParser::spec argsspecLineCubicIntersection[] = { { CubicImp::stype(), I18N_NOOP( "Intersect with this cubic curve" ), "SHOULD NOT BE SEEN", true }, { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineCubicIntersectionType ) LineCubicIntersectionType::LineCubicIntersectionType() : ArgsParserObjectType( "LineCubicIntersection", argsspecLineCubicIntersection, 3 ) { } LineCubicIntersectionType::~LineCubicIntersectionType() { } const LineCubicIntersectionType* LineCubicIntersectionType::instance() { static const LineCubicIntersectionType t; return &t; } ObjectImp* LineCubicIntersectionType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; int which = static_cast( parents[2] )->data(); bool valid = true; const Coordinate c = calcCubicLineIntersect( static_cast( parents[0] )->data(), static_cast( parents[1] )->data(), which, valid ); if ( valid ) return new PointImp( c ); else return new InvalidImp; } const ObjectImpType* ConicLineIntersectionType::resultId() const { return PointImp::stype(); } const ObjectImpType* ConicLineOtherIntersectionType::resultId() const { return PointImp::stype(); } const ObjectImpType* LineLineIntersectionType::resultId() const { return PointImp::stype(); } const ObjectImpType* LineCubicIntersectionType::resultId() const { return PointImp::stype(); } static const ArgsParser::spec argsspecCircleCircleIntersection[] = { { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ), "SHOULD NOT BE SEEN", true }, { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ), "SHOULD NOT BE SEEN", true }, { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleCircleIntersectionType ) CircleCircleIntersectionType::CircleCircleIntersectionType() : ArgsParserObjectType( "CircleCircleIntersection", argsspecCircleCircleIntersection, 3 ) { } CircleCircleIntersectionType::~CircleCircleIntersectionType() { } const CircleCircleIntersectionType* CircleCircleIntersectionType::instance() { static const CircleCircleIntersectionType t; return &t; } ObjectImp* CircleCircleIntersectionType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; int side = static_cast( parents[2] )->data(); assert( side == 1 || side == -1 ); const CircleImp* c1 = static_cast( parents[0] ); const CircleImp* c2 = static_cast( parents[1] ); const Coordinate o1 = c1->center(); const Coordinate o2 = c2->center(); 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 ); if ( ret.valid() ) return new PointImp( ret ); else return new InvalidImp; } const ObjectImpType* CircleCircleIntersectionType::resultId() const { return PointImp::stype(); } static const ArgsParser::spec argsspecArcLineIntersection[] = { { ArcImp::stype(), I18N_NOOP( "Intersect with this arc" ), "SHOULD NOT BE SEEN", true }, { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ArcLineIntersectionType ) ArcLineIntersectionType::ArcLineIntersectionType() : ArgsParserObjectType( "ArcLineIntersection", argsspecArcLineIntersection, 3 ) { } ArcLineIntersectionType::~ArcLineIntersectionType() { } const ArcLineIntersectionType* ArcLineIntersectionType::instance() { static const ArcLineIntersectionType t; return &t; } ObjectImp* ArcLineIntersectionType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; int side = static_cast( parents[2] )->data(); assert( side == 1 || side == -1 ); const LineData line = static_cast( parents[1] )->data(); const ArcImp* c = static_cast( parents[0] ); const double r = c->radius(); Coordinate ret = calcArcLineIntersect( c->center(), r*r, c->startAngle(), c->angle(), line, side ); if ( ret.valid() ) return new PointImp( ret ); else return new InvalidImp; } const ObjectImpType* ArcLineIntersectionType::resultId() const { return PointImp::stype(); }