1 // Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
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
18 #include "intersection_types.h"
20 #include "bogus_imp.h"
21 #include "circle_imp.h"
22 #include "conic_imp.h"
23 #include "cubic_imp.h"
25 #include "other_imp.h"
26 #include "point_imp.h"
30 static const char intersectlinestat
[] = I18N_NOOP( "Intersect with this line" );
32 static const ArgsParser::spec argsspecConicLineIntersection
[] =
34 { ConicImp::stype(), I18N_NOOP( "Intersect with this conic" ),
35 "SHOULD NOT BE SEEN", true },
36 { AbstractLineImp::stype(), intersectlinestat
, "SHOULD NOT BE SEEN", true },
37 { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }
40 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicLineIntersectionType
)
42 ConicLineIntersectionType::ConicLineIntersectionType()
43 : ArgsParserObjectType( "ConicLineIntersection",
44 argsspecConicLineIntersection
, 3 )
48 ConicLineIntersectionType::~ConicLineIntersectionType()
52 const ConicLineIntersectionType
* ConicLineIntersectionType::instance()
54 static const ConicLineIntersectionType t
;
58 ObjectImp
* ConicLineIntersectionType::calc( const Args
& parents
, const KigDocument
& ) const
60 if ( ! margsparser
.checkArgs( parents
) ) return new InvalidImp
;
62 int side
= static_cast<const IntImp
*>( parents
[2] )->data();
63 assert( side
== 1 || side
== -1 );
64 const LineData line
= static_cast<const AbstractLineImp
*>( parents
[1] )->data();
67 if ( parents
[0]->inherits( CircleImp::stype() ) )
70 const CircleImp
* c
= static_cast<const CircleImp
*>( parents
[0] );
71 ret
= calcCircleLineIntersect(
72 c
->center(), c
->squareRadius(), line
, side
);
77 ret
= calcConicLineIntersect(
78 static_cast<const ConicImp
*>( parents
[0] )->cartesianData(),
81 if ( ret
.valid() ) return new PointImp( ret
);
82 else return new InvalidImp
;
85 static const ArgsParser::spec argsspecConicLineOtherIntersection
[] =
87 { ConicImp::stype(), I18N_NOOP( "Intersect with this conic" ),
88 "SHOULD NOT BE SEEN", true },
89 { AbstractLineImp::stype(), intersectlinestat
, "SHOULD NOT BE SEEN", true },
90 { PointImp::stype(), I18N_NOOP( "Already computed intersection point"),
91 "SHOULD NOT BE SEEN", true }
94 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicLineOtherIntersectionType
)
96 ConicLineOtherIntersectionType::ConicLineOtherIntersectionType()
97 : ArgsParserObjectType( "ConicLineOtherIntersection",
98 argsspecConicLineOtherIntersection
, 3 )
102 ConicLineOtherIntersectionType::~ConicLineOtherIntersectionType()
106 const ConicLineOtherIntersectionType
* ConicLineOtherIntersectionType::instance()
108 static const ConicLineOtherIntersectionType t
;
112 ObjectImp
* ConicLineOtherIntersectionType::calc( const Args
& parents
, const KigDocument
& ) const
114 if ( ! margsparser
.checkArgs( parents
) ) return new InvalidImp
;
116 Coordinate p
= static_cast<const PointImp
*>( parents
[2] )->coordinate();
117 const LineData line
= static_cast<const AbstractLineImp
*>( parents
[1] )->data();
120 // if ( parents[0]->inherits( CircleImp::stype() ) )
123 // const CircleImp* c = static_cast<const CircleImp*>( parents[0] );
124 // ret = calcCircleLineIntersect(
125 // c->center(), c->squareRadius(), line, side, valid );
130 double pax
= p
.x
- line
.a
.x
;
131 double pay
= p
.y
- line
.a
.y
;
132 double bax
= line
.b
.x
- line
.a
.x
;
133 double bay
= line
.b
.y
- line
.a
.y
;
134 double knownparam
= (pax
*bax
+ pay
*bay
)/(bax
*bax
+ bay
*bay
);
135 ret
= calcConicLineIntersect(
136 static_cast<const ConicImp
*>( parents
[0] )->cartesianData(),
137 line
, knownparam
, 0 );
139 if ( ret
.valid() ) return new PointImp( ret
);
140 else return new InvalidImp
;
143 static const ArgsParser::spec argsspecLineLineIntersection
[] =
145 { AbstractLineImp::stype(), intersectlinestat
, "SHOULD NOT BE SEEN", true },
146 { AbstractLineImp::stype(), intersectlinestat
, "SHOULD NOT BE SEEN", true }
149 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineLineIntersectionType
)
151 LineLineIntersectionType::LineLineIntersectionType()
152 : ArgsParserObjectType( "LineLineIntersection",
153 argsspecLineLineIntersection
, 2 )
157 LineLineIntersectionType::~LineLineIntersectionType()
161 const LineLineIntersectionType
* LineLineIntersectionType::instance()
163 static const LineLineIntersectionType t
;
167 ObjectImp
* LineLineIntersectionType::calc( const Args
& parents
, const KigDocument
& d
) const
169 if ( ! margsparser
.checkArgs( parents
) ) return new InvalidImp
;
172 calcIntersectionPoint(
173 static_cast<const AbstractLineImp
*>( parents
[0] )->data(),
174 static_cast<const AbstractLineImp
*>( parents
[1] )->data() );
175 if ( static_cast<const AbstractLineImp
*>( parents
[0] )->containsPoint( p
, d
) &&
176 static_cast<const AbstractLineImp
*>( parents
[1] )->containsPoint( p
, d
) )
177 return new PointImp( p
);
178 else return new InvalidImp();
181 static const ArgsParser::spec argsspecLineCubicIntersection
[] =
183 { CubicImp::stype(), I18N_NOOP( "Intersect with this cubic curve" ),
184 "SHOULD NOT BE SEEN", true },
185 { AbstractLineImp::stype(), intersectlinestat
, "SHOULD NOT BE SEEN", true },
186 { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }
189 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineCubicIntersectionType
)
191 LineCubicIntersectionType::LineCubicIntersectionType()
192 : ArgsParserObjectType( "LineCubicIntersection",
193 argsspecLineCubicIntersection
, 3 )
197 LineCubicIntersectionType::~LineCubicIntersectionType()
201 const LineCubicIntersectionType
* LineCubicIntersectionType::instance()
203 static const LineCubicIntersectionType t
;
207 ObjectImp
* LineCubicIntersectionType::calc( const Args
& parents
, const KigDocument
& ) const
209 if ( ! margsparser
.checkArgs( parents
) ) return new InvalidImp
;
211 int which
= static_cast<const IntImp
*>( parents
[2] )->data();
213 const Coordinate c
= calcCubicLineIntersect(
214 static_cast<const CubicImp
*>( parents
[0] )->data(),
215 static_cast<const AbstractLineImp
*>( parents
[1] )->data(),
217 if ( valid
) return new PointImp( c
);
218 else return new InvalidImp
;
221 const ObjectImpType
* ConicLineIntersectionType::resultId() const
223 return PointImp::stype();
226 const ObjectImpType
* ConicLineOtherIntersectionType::resultId() const
228 return PointImp::stype();
231 const ObjectImpType
* LineLineIntersectionType::resultId() const
233 return PointImp::stype();
236 const ObjectImpType
* LineCubicIntersectionType::resultId() const
238 return PointImp::stype();
241 static const ArgsParser::spec argsspecCircleCircleIntersection
[] =
243 { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ),
244 "SHOULD NOT BE SEEN", true },
245 { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ),
246 "SHOULD NOT BE SEEN", true },
247 { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }
250 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleCircleIntersectionType
)
252 CircleCircleIntersectionType::CircleCircleIntersectionType()
253 : ArgsParserObjectType( "CircleCircleIntersection",
254 argsspecCircleCircleIntersection
, 3 )
258 CircleCircleIntersectionType::~CircleCircleIntersectionType()
262 const CircleCircleIntersectionType
* CircleCircleIntersectionType::instance()
264 static const CircleCircleIntersectionType t
;
268 ObjectImp
* CircleCircleIntersectionType::calc( const Args
& parents
, const KigDocument
& ) const
270 if ( ! margsparser
.checkArgs( parents
) ) return new InvalidImp
;
272 int side
= static_cast<const IntImp
*>( parents
[2] )->data();
273 assert( side
== 1 || side
== -1 );
274 const CircleImp
* c1
= static_cast<const CircleImp
*>( parents
[0] );
275 const CircleImp
* c2
= static_cast<const CircleImp
*>( parents
[1] );
276 const Coordinate o1
= c1
->center();
277 const Coordinate o2
= c2
->center();
278 const double r1sq
= c1
->squareRadius();
279 const Coordinate a
= calcCircleRadicalStartPoint(
280 o1
, o2
, r1sq
, c2
->squareRadius()
282 const LineData line
= LineData (a
, Coordinate ( a
.x
-o2
.y
+ o1
.y
, a
.y
+ o2
.x
- o1
.x
));
283 Coordinate ret
= calcCircleLineIntersect( o1
, r1sq
, line
, side
);
284 if ( ret
.valid() ) return new PointImp( ret
);
285 else return new InvalidImp
;
288 const ObjectImpType
* CircleCircleIntersectionType::resultId() const
290 return PointImp::stype();
293 static const ArgsParser::spec argsspecArcLineIntersection
[] =
295 { ArcImp::stype(), I18N_NOOP( "Intersect with this arc" ),
296 "SHOULD NOT BE SEEN", true },
297 { AbstractLineImp::stype(), intersectlinestat
, "SHOULD NOT BE SEEN", true },
298 { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }
301 KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ArcLineIntersectionType
)
303 ArcLineIntersectionType::ArcLineIntersectionType()
304 : ArgsParserObjectType( "ArcLineIntersection",
305 argsspecArcLineIntersection
, 3 )
309 ArcLineIntersectionType::~ArcLineIntersectionType()
313 const ArcLineIntersectionType
* ArcLineIntersectionType::instance()
315 static const ArcLineIntersectionType t
;
319 ObjectImp
* ArcLineIntersectionType::calc( const Args
& parents
, const KigDocument
& ) const
321 if ( ! margsparser
.checkArgs( parents
) ) return new InvalidImp
;
323 int side
= static_cast<const IntImp
*>( parents
[2] )->data();
324 assert( side
== 1 || side
== -1 );
325 const LineData line
= static_cast<const AbstractLineImp
*>( parents
[1] )->data();
327 const ArcImp
* c
= static_cast<const ArcImp
*>( parents
[0] );
328 const double r
= c
->radius();
329 Coordinate ret
= calcArcLineIntersect( c
->center(), r
*r
, c
->startAngle(),
330 c
->angle(), line
, side
);
331 if ( ret
.valid() ) return new PointImp( ret
);
332 else return new InvalidImp
;
335 const ObjectImpType
* ArcLineIntersectionType::resultId() const
337 return PointImp::stype();