You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
339 lines
10 KiB
339 lines
10 KiB
15 years ago
|
// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
|
||
|
|
||
|
// 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 <klocale.h>
|
||
|
|
||
|
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<const IntImp*>( parents[2] )->data();
|
||
|
assert( side == 1 || side == -1 );
|
||
|
const LineData line = static_cast<const AbstractLineImp*>( parents[1] )->data();
|
||
|
|
||
|
Coordinate ret;
|
||
|
if ( parents[0]->inherits( CircleImp::stype() ) )
|
||
|
{
|
||
|
// easy case..
|
||
|
const CircleImp* c = static_cast<const CircleImp*>( parents[0] );
|
||
|
ret = calcCircleLineIntersect(
|
||
|
c->center(), c->squareRadius(), line, side );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// harder case..
|
||
|
ret = calcConicLineIntersect(
|
||
|
static_cast<const ConicImp*>( 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<const PointImp*>( parents[2] )->coordinate();
|
||
|
const LineData line = static_cast<const AbstractLineImp*>( parents[1] )->data();
|
||
|
|
||
|
Coordinate ret;
|
||
|
// if ( parents[0]->inherits( CircleImp::stype() ) )
|
||
|
// {
|
||
|
// // easy case..
|
||
|
// const CircleImp* c = static_cast<const CircleImp*>( 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<const ConicImp*>( 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<const AbstractLineImp*>( parents[0] )->data(),
|
||
|
static_cast<const AbstractLineImp*>( parents[1] )->data() );
|
||
|
if ( static_cast<const AbstractLineImp*>( parents[0] )->containsPoint( p, d ) &&
|
||
|
static_cast<const AbstractLineImp*>( 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<const IntImp*>( parents[2] )->data();
|
||
|
bool valid = true;
|
||
|
const Coordinate c = calcCubicLineIntersect(
|
||
|
static_cast<const CubicImp*>( parents[0] )->data(),
|
||
|
static_cast<const AbstractLineImp*>( 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<const IntImp*>( parents[2] )->data();
|
||
|
assert( side == 1 || side == -1 );
|
||
|
const CircleImp* c1 = static_cast<const CircleImp*>( parents[0] );
|
||
|
const CircleImp* c2 = static_cast<const CircleImp*>( 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<const IntImp*>( parents[2] )->data();
|
||
|
assert( side == 1 || side == -1 );
|
||
|
const LineData line = static_cast<const AbstractLineImp*>( parents[1] )->data();
|
||
|
|
||
|
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 );
|
||
|
if ( ret.valid() ) return new PointImp( ret );
|
||
|
else return new InvalidImp;
|
||
|
}
|
||
|
|
||
|
const ObjectImpType* ArcLineIntersectionType::resultId() const
|
||
|
{
|
||
|
return PointImp::stype();
|
||
|
}
|