1 /*
2     This file is part of Kig, a KDE program for Interactive Geometry...
3     SPDX-FileCopyrightText: 2002 Maurizio Paolini <paolini@dmf.unicatt.it>
4 
5     SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #ifndef KIG_MISC_CONIC_COMMON_H
9 #define KIG_MISC_CONIC_COMMON_H
10 
11 #include "coordinate.h"
12 #include <vector>
13 #include "kignumerics.h"
14 
15 class ConicPolarData;
16 class Transformation;
17 class LineData;
18 
19 /**
20  * Cartesian Conic Data. This class represents an equation of a conic
21  * in the form "ax^2 + by^2 + cxy + dx + ey + f = 0".
22  * \internal The coefficients are stored in the order a - f.
23  */
24 class ConicCartesianData
25 {
26 public:
27   double coeffs[6];
28   ConicCartesianData();
29   /**
30    * Construct a ConicCartesianData from a ConicPolarData.
31    * Construct a ConicCartesianData that is the cartesian
32    * representation of the conic represented by d.
33    */
34   explicit ConicCartesianData( const ConicPolarData& d );
35   /**
36    * Construct a ConicCartesianData from its coefficients
37    * Construct a ConicCartesianData using the coefficients a through f
38    * from the equation "ax^2 + by^2 + cxy + dx + ey + f = 0"
39    */
ConicCartesianData(double a,double b,double c,double d,double e,double f)40   ConicCartesianData( double a, double b, double c,
41                       double d, double e, double f )
42     {
43       coeffs[0] = a;
44       coeffs[1] = b;
45       coeffs[2] = c;
46       coeffs[3] = d;
47       coeffs[4] = e;
48       coeffs[5] = f;
49     }
50   explicit ConicCartesianData( const double incoeffs[6] );
51 
52   /**
53    * Invalid conic.
54    * Return a ConicCartesianData representing an invalid conic.
55    * \see valid()
56    */
57   static ConicCartesianData invalidData();
58   /**
59    * Test validity.
60    * Return whether this is a valid conic.
61    * \see invalidData()
62    */
63   bool valid() const;
64 };
65 
66 /**
67  * This class represents an equation of a conic in the form
68  * \f$ \rho(\theta) = \frac{p}{1 - e \cos\theta}\f$. focus and the
69  * ecostheta stuff represent the coordinate system in which the
70  * equation yields the good result..
71  */
72 class ConicPolarData
73 {
74 public:
75   /**
76    * Construct a ConicPolarData from a ConicCartesianData.
77    *
78    * Construct a ConicPolarData that is the polar
79    * representation of the conic represented by d.
80    */
81   explicit ConicPolarData( const ConicCartesianData& data );
82   explicit ConicPolarData();
83   /**
84    * Construct a ConicPolarData using the parameters from the equation
85    * \f$ \rho(\theta) = \frac{p}{1 - e \cos\theta}\f$
86    */
87   ConicPolarData( const Coordinate& focus1, double dimen,
88                   double ecostheta0, double esintheta0 );
89 
90   /**
91    * The first focus of this conic.
92    */
93   Coordinate focus1;
94   /**
95    * The pdimen value from the polar equation.
96    */
97   double pdimen;
98   /**
99    * The ecostheta0 value from the polar equation.
100    */
101   double ecostheta0;
102   /**
103    * The esintheta0 value from the polar equation.
104    */
105   double esintheta0;
106 };
107 
108 bool operator==( const ConicPolarData& lhs, const ConicPolarData& rhs );
109 
110 /**
111  * These are the constraint values that can be passed to the
112  * calcConicThroughPoints function.  Their meaning is as follows:
113  * noconstraint: no additional points will be calculated.
114  * zerotilt: force the symmetry axes to be parallel to the coordinate
115  *           system ( zero tilt ).
116  * parabolaifzt: the returned conic should be a parabola ( if used in
117  *               combination with zerotilt )
118  * circleifzt: the returned conic should be a circle ( if used in
119  *             combination with zerotilt )
120  * equilateral: the returned conic should be equilateral
121  * ysymmetry: the returned conic should be symmetric over the Y-axis.
122  * xsymmetry: the returned conic should be symmetric over the X-axis.
123  */
124 enum LinearConstraints {
125   noconstraint, zerotilt, parabolaifzt, circleifzt,
126   equilateral, ysymmetry, xsymmetry
127 };
128 
129 /**
130  * Calculate a conic through a given set of points.  points should
131  * contain at least one, and at most five points.  If there are five
132  * points, then the conic is completely defined.  If there are less,
133  * then additional points will be calculated according to the
134  * constraints given.  See above for the various constraints.
135  *
136  * An invalid ConicCartesianData is returned if there is no conic
137  * through the given set of points, or if not enough constraints are
138  * given for a conic to be calculated.
139  */
140 const ConicCartesianData calcConicThroughPoints (
141     const std::vector<Coordinate>& points,
142     const LinearConstraints c1 = noconstraint,
143     const LinearConstraints c2 = noconstraint,
144     const LinearConstraints c3 = noconstraint,
145     const LinearConstraints c4 = noconstraint,
146     const LinearConstraints c5 = noconstraint);
147 
148 /**
149  * This function is used by ConicBFFP.  It calcs the polar equation
150  * for a hyperbola ( type == -1 ) or ellipse ( type == 1 ) with
151  * focuses args[0] and args[1], and with args[2] on the edge of the
152  * conic.  args.size() should be two or three.  If it is two, the two
153  * points are taken to be the focuses, and a third point is chosen in
154  * a sensible way..
155  */
156 const ConicPolarData calcConicBFFP(
157   const std::vector<Coordinate>& args,
158   int type );
159 
160 /**
161  * function used by ConicBDFP.  It calcs the conic with directrix d,
162  * focus f, and point p on the conic..
163  */
164 const ConicPolarData calcConicBDFP(
165   const LineData& d, const Coordinate& f, const Coordinate& p );
166 
167 /**
168  * This calcs the hyperbola defined by its two asymptotes line1 and
169  * line2, and a point p on the edge.
170  */
171 const ConicCartesianData calcConicByAsymptotes(
172   const LineData& line1,
173   const LineData& line2,
174   const Coordinate& p );
175 
176 /**
177  * This function calculates the polar line of the point cpole with
178  * respect to the given conic data.  As the last argument, you should
179  * pass a reference to a boolean.  This boolean will be set to true if
180  * the returned LineData is valid, and to false if the returned line
181  * is not valid.  The latter condition only occurs if a "line at
182  * infinity" would have had to be returned.
183  */
184 const LineData calcConicPolarLine (
185   const ConicCartesianData& data,
186   const Coordinate& cpole,
187   bool& valid );
188 
189 /**
190  * This function calculates the polar point of the line polar with
191  * respect to the given conic data.  As the last argument, you should
192  * pass a reference to a boolean.  This boolean will be set to true if
193  * the returned LineData is valid, and to false if the returned line
194  * is not valid.  The latter condition only occurs if a "point at
195  * infinity" would have had to be returned.
196  */
197 const Coordinate calcConicPolarPoint (
198   const ConicCartesianData& data,
199   const LineData& polar );
200 
201 /**
202  * This function calculates the intersection of a given line ( l ) and
203  * a given conic ( c ).  A line and a conic have two intersections in
204  * general, and as such, which should be set to -1 or 1 depending on
205  * which intersection you want.  As the last argument, you should pass
206  * a reference to a boolean.  This boolean will be set to true if the
207  * returned point is valid, and to false if the returned point is not
208  * valid.  The latter condition only occurs if the given conic and
209  * line do not have the specified intersection.
210  *
211  * knownparam is something special:  If you already know one
212  * intersection of the line and the conic, and you want the other one,
213  * then you should set which to 0, knownparam to the curve parameter
214  * of the point you already know ( i.e. the value returned by
215  * conicimp->getParam( otherpoint ) ).
216  */
217 const Coordinate calcConicLineIntersect( const ConicCartesianData& c,
218                                          const LineData& l,
219 					 double knownparam,
220                                          int which );
221 
222 /**
223  * This function calculates the asymptote of the given conic ( data ).
224  * A conic has two asymptotes in general, so which should be set to +1
225  * or -1 depending on which asymptote you want.  As the last argument,
226  * you should pass a reference to a boolean.  This boolean will be set
227  * to true if the returned line is valid, and to false if the returned
228  * line is not valid.  The latter condition only occurs if the given
229  * conic does not have the specified asymptote.
230  */
231 const LineData calcConicAsymptote(
232   const ConicCartesianData &data,
233   int which, bool &valid );
234 
235 /**
236  * This function calculates the radical line of two conics.  A radical
237  * line is the line that goes through two of the intersections of two
238  * conics.  Since two conics have up to four intersections in general,
239  * there are three sets of two radical lines.  zeroindex specifies
240  * which set of radical lines you want ( set it to 1, 2 or 3 ), and
241  * which is set to -1 or +1 depending on which of the two radical
242  * lines in the set you want.  As the last argument, you should pass a
243  * reference to a boolean.  This boolean will be set to true if the
244  * returned line is valid, and to false if the returned line is not
245  * valid.  The latter condition only occurs if the given conics do not
246  * have the specified radical line.
247  */
248 const LineData calcConicRadical( const ConicCartesianData& cequation1,
249                                  const ConicCartesianData& cequation2,
250                                  int which, int zeroindex, bool& valid );
251 
252 /**
253  * This calculates the image of the given conic ( data ) through the
254  * given transformation ( t ).  As the last argument, you should pass
255  * a reference to a boolean.  This boolean will be set to true if the
256  * returned line is valid, and to false if the returned line is not
257  * valid.  The latter condition only occurs if the given
258  * transformation is singular, and as such, the transformation of the
259  * conic cannot be calculated.
260  */
261 const ConicCartesianData calcConicTransformation (
262   const ConicCartesianData& data,
263   const Transformation& t, bool& valid );
264 
265 #endif // KIG_MISC_CONIC_COMMON_H
266