opennurbs_math.h
1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #if !defined(ON_MATH_INC_)
18 #define ON_MATH_INC_
19 
20 class ON_3dVector;
21 class ON_Interval;
22 class ON_Line;
23 class ON_Arc;
24 class ON_Plane;
25 
26 /*
27 Description:
28  Class for carefully adding long list of numbers.
29 */
30 class ON_CLASS ON_Sum
31 {
32 public:
33 
34  /*
35  Description:
36  Calls ON_Sum::Begin(x)
37  */
38  void operator=(double x);
39 
40  /*
41  Description:
42  Calls ON_Sum::Plus(x);
43  */
44  void operator+=(double x);
45 
46  /*
47  Description:
48  Calls ON_Sum::Plus(-x);
49  */
50  void operator-=(double x);
51 
52  /*
53  Description:
54  Creates a sum that is ready to be used.
55  */
56  ON_Sum();
57 
58  /*
59  Description:
60  If a sum is being used more than once, call Begin()
61  before starting each sum.
62  Parameters:
63  starting_value - [in] Initial value of sum.
64  */
65  void Begin( double starting_value = 0.0 );
66 
67  /*
68  Description:
69  Add x to the current sum.
70  Parameters:
71  x - [in] value to add to the current sum.
72  */
73  void Plus( double x );
74 
75  /*
76  Description:
77  Add x to the current sum.
78  Parameters:
79  x - [in] value to add to the current sum.
80  dx - [in] symmetric uncertainty in x.
81  (true value is in the range x-dx to x+dx
82  */
83  void Plus( double x, double dx );
84 
85  /*
86  Description:
87  Calculates the total sum.
88  Parameters:
89  error_estimate - [out] if not nullptr, the returned value of
90  *error_estimate is an estimate of the error in the sum.
91  Returns:
92  Total of the sum.
93  Remarks:
94  You can get subtotals by mixing calls to Plus() and Total().
95  In delicate sums, some precision may be lost in the final
96  total if you call Total() to calculate subtotals.
97  */
98  double Total( double* error_estimate = nullptr );
99 
100  /*
101  Returns:
102  Number of summands.
103  */
104  int SummandCount() const;
105 
106 private:
107  enum {
108  sum1_max_count=256,
109  sum2_max_count=512,
110  sum3_max_count=1024
111  };
112  double m_sum_err;
113  double m_pos_sum;
114  double m_neg_sum;
115 
116  int m_zero_count; // number of zeros added
117  int m_pos_count; // number of positive numbers added
118  int m_neg_count; // number of negative numbers added
119 
120  int m_pos_sum1_count;
121  int m_pos_sum2_count;
122  int m_pos_sum3_count;
123  double m_pos_sum1[sum1_max_count];
124  double m_pos_sum2[sum2_max_count];
125  double m_pos_sum3[sum3_max_count];
126 
127  int m_neg_sum1_count;
128  int m_neg_sum2_count;
129  int m_neg_sum3_count;
130  double m_neg_sum1[sum1_max_count];
131  double m_neg_sum2[sum2_max_count];
132  double m_neg_sum3[sum3_max_count];
133 
134  double SortAndSum( int, double* );
135 };
136 
137 /*
138 Description:
139  Abstract function with an arbitrary number of parameters
140  and values. ON_Evaluator is used to pass functions to
141  local solvers.
142 */
143 class ON_CLASS ON_Evaluator
144 {
145 public:
146 
147  /*
148  Description:
149  Construction of the class for a function that takes
150  parameter_count input functions and returns
151  value_count values. If the domain is infinite, pass
152  a nullptr for the domain[] and periodic[] arrays. If
153  the domain is finite, pass a domain[] array with
154  parameter_count increasing intervals. If one or more of
155  the parameters is periodic, pass the fundamental domain
156  in the domain[] array and a true in the periodic[] array.
157  Parameters:
158  parameter_count - [in] >= 1. Number of input parameters
159  value_count - [in] >= 1. Number of output values.
160  domain - [in] If not nullptr, then this is an array
161  of parameter_count increasing intervals
162  that defines the domain of the function.
163  periodic - [in] if not nullptr, then this is an array of
164  parameter_count bools where b[i] is true if
165  the i-th parameter is periodic. Valid
166  increasing finite domains must be specificed
167  when this parameter is not nullptr.
168  */
169  ON_Evaluator(
170  int parameter_count,
171  int value_count,
172  const ON_Interval* domain,
173  const bool* periodic
174  );
175 
176  virtual ~ON_Evaluator();
177 
178  /*
179  Description:
180  Evaluate the function that takes m_parameter_count parameters
181  and returns a m_value_count dimensional point.
182  Parameters:
183  parameters - [in] array of m_parameter_count evaluation parameters
184  values - [out] array of m_value_count function values
185  jacobian - [out] If nullptr, simply evaluate the value of the function.
186  If not nullptr, this is the jacobian of the function.
187  jacobian[i][j] = j-th partial of the i-th value
188  0 <= i < m_value_count,
189  0 <= j < m_parameter_count
190  If not nullptr, then all the memory for the
191  jacobian is allocated, you just need to fill
192  in the answers.
193  Example:
194  If f(u,v) = square of the distance from a fixed point P to a
195  surface evaluated at (u,v), then
196 
197  values[0] = (S-P)o(S-P)
198  jacobian[0] = ( 2*(Du o (S-P)), 2*(Dv o (S-P)) )
199 
200  where S, Du, Dv = surface point and first partials evaluated
201  at u=parameters[0], v = parameters[1].
202 
203  If the function takes 3 parameters, say (x,y,z), and returns
204  two values, say f(x,y,z) and g(z,y,z), then
205 
206  values[0] = f(x,y,z)
207  values[1] = g(x,y,z)
208 
209  jacobian[0] = (DfDx, DfDy, DfDz)
210  jacobian[1] = (DgDx, DgDy, DgDz)
211 
212  where dfx denotes the first partial of f with respect to x.
213 
214  Returns:
215  0 = unable to evaluate
216  1 = successful evaluation
217  2 = found answer, terminate search
218  */
219  virtual int Evaluate(
220  const double* parameters,
221  double* values,
222  double** jacobian
223  ) = 0;
224 
225  /*
226  Description:
227  OPTIONAL ability to evaluate the hessian in the case when
228  m_value_count is one. If your function has more that
229  one value or it is not feasable to evaluate the hessian,
230  then do not override this function. The default implementation
231  returns -1.
232  Parameters:
233  parameters - [in] array of m_parameter_count evaluation parameters
234  value - [out] value of the function (one double)
235  gradient - [out] The gradient of the function. This is a vector
236  of length m_parameter_count; gradient[i] is
237  the first partial of the function with respect to
238  the i-th parameter.
239  hessian - [out] The hessian of the function. This is an
240  m_parameter_count x m_parameter_count
241  symmetric matrix: hessian[i][j] is the
242  second partial of the function with respect
243  to the i-th and j-th parameters. The evaluator
244  is responsible for filling in both the upper
245  and lower triangles. Since the matrix is
246  symmetrix, you should do something like evaluate
247  the upper triangle and copy the values to the
248  lower tiangle.
249  Returns:
250  -1 = Hessian evaluation not available.
251  0 = unable to evaluate
252  1 = successful evaluation
253  2 = found answer, terminate search
254  */
255  virtual int EvaluateHessian(
256  const double* parameters,
257  double* value,
258  double* gradient,
259  double** hessian
260  );
261 
262  // Number of the function's input parameters. This number
263  // is >= 1 and is specified in the constructor.
264  const int m_parameter_count;
265 
266  // Number of the function's output values. This number
267  // is >= 1 and is specified in the constructor.
268  const int m_value_count;
269 
270  /*
271  Description:
272  Functions can have finite or infinite domains. Finite domains
273  are specified by passing the domain[] array to the constructor
274  or filling in the m_domain[] member variable. If
275  m_domain.Count() == m_parameter_count > 0, then the function
276  has finite domains.
277  Returns:
278  True if the domain of the function is finite.
279  */
280  bool FiniteDomain() const;
281 
282  /*
283  Description:
284  If a function has a periodic parameter, then the m_domain
285  interval for that parameter is the fundamental domain and
286  the m_bPeriodicParameter bool for that parameter is true.
287  A parameter is periodic if, and only if,
288  m_domain.Count() == m_parameter_count, and
289  m_bPeriodicParameter.Count() == m_parameter_count, and
290  m_bPeriodicParameter[parameter_index] is true.
291  Returns:
292  True if the function parameter is periodic.
293  */
294  bool Periodic(
295  int parameter_index
296  ) const;
297 
298  /*
299  Description:
300  If a function has a periodic parameter, then the m_domain
301  interval for that parameter is the fundamental domain and
302  the m_bPeriodicParameter bool for that parameter is true.
303  A parameter is periodic if, and only if,
304  m_domain.Count() == m_parameter_count, and
305  m_bPeriodicParameter.Count() == m_parameter_count, and
306  m_bPeriodicParameter[parameter_index] is true.
307  Returns:
308  The domain of the parameter. If the domain is infinite,
309  the (-1.0e300, +1.0e300) is returned.
310  */
311  ON_Interval Domain(
312  int parameter_index
313  ) const;
314 
315 
316  // If the function has a finite domain or periodic
317  // parameters, then m_domain[] is an array of
318  // m_parameter_count finite increasing intervals.
320 
321  // If the function has periodic parameters, then
322  // m_bPeriodicParameter[] is an array of m_parameter_count
323  // bools. If m_bPeriodicParameter[i] is true, then
324  // the i-th parameter is periodic and m_domain[i] is
325  // the fundamental domain for that parameter.
326  ON_SimpleArray<bool> m_bPeriodicParameter;
327 
328 private:
329  ON_Evaluator(); // prohibit default constructor
330  ON_Evaluator& operator=(const ON_Evaluator&); // prohibit operator= (can't copy const members)
331 };
332 
333 /*
334 Description:
335  Test a double to make sure it is a valid number.
336 Returns:
337  True if x != ON_UNSET_VALUE and _finite(x) is true.
338 */
339 ON_DECL
340 bool ON_IsValid( double x );
341 
342 /*
343 Returns:
344  -1: a < b or a is not a nan and b is a nan
345  +1: a > b or a is a nan and b is a not nan
346  0: a == b or both a and b are nans
347 */
348 ON_DECL
349 int ON_CompareDouble(
350  double a,
351  double b
352  );
353 
354 ON_DECL
355 int ON_CompareDoubleArray(
356  size_t count,
357  const double* a,
358  const double* b
359  );
360 
361 /*
362 Returns:
363  -1: a < b or a is not a nan and b is a nan
364  +1: a > b or a is a nan and b is a not nan
365  0: a == b or both a and b are nans
366 */
367 ON_DECL
368 int ON_CompareFloat(
369  float a,
370  float b
371  );
372 
373 ON_DECL
374 bool ON_IsValidFloat( float x );
375 
376 ON_DECL
377 bool ON_IsNaNd(double x);
378 
379 ON_DECL
380 bool ON_IsQNaNd(double x);
381 
382 ON_DECL
383 bool ON_IsSNaNd(double x);
384 
385 ON_DECL
386 bool ON_IsNaNf(float x);
387 
388 ON_DECL
389 bool ON_IsQNaNf(float x);
390 
391 ON_DECL
392 bool ON_IsSNaNf(float x);
393 
394 /*
395 class ON_CLASS ON_TimeLimit
396 {
397  ON_TimeLimit();
398  ON_TimeLimit(ON__UINT64 time_limit_seconds);
399  void SetTimeLimit(ON__UINT64 time_limit_seconds);
400  bool Continue() const;
401  bool IsSet() const;
402 private:
403  ON__UINT64 m_time_limit[2];
404 };
405 */
406 
407 // The ON_IS_FINITE and ON_IS_VALID defines are much faster
408 // than calling ON_IsValid(), but need to be used when
409 // the macro expansion works.
410 
411 #if defined(ON_LITTLE_ENDIAN)
412 
413 // works on little endian CPUs with IEEE doubles
414 #define ON_IS_FINITE(x) (0x7FF0 != (*((unsigned short*)(&x) + 3) & 0x7FF0))
415 #define ON_IS_INFINITE(x) (0x7FF0 == (*((unsigned short*)(&x) + 3) & 0x7FF0))
416 
417 #elif defined(ON_BIG_ENDIAN)
418 
419 // works on big endian CPUs with IEEE doubles
420 #define ON_IS_FINITE(x) (0x7FF0 != (*((unsigned short*)(&x)) & 0x7FF0))
421 #define ON_IS_INFINITE(x) (0x7FF0 == (*((unsigned short*)(&x)) & 0x7FF0))
422 
423 #else
424 
425 // Returns true if x is a finite double. Specifically,
426 // _finite returns a nonzero value (true) if its argument x
427 // is not infinite, that is, if -INF < x < +INF.
428 // It returns 0 (false) if the argument is infinite or a NaN.
429 //
430 // If you are trying to compile opennurbs on a platform
431 // that does not support finite(), then see if you can
432 // use _fpclass(), fpclass(), _isnan(), or isnan(). If
433 // you can't find anything, then just set this
434 // function to return true.
435 
436 #if defined(_GNU_SOURCE)
437 // if you are using an older version of gcc, use finite()
438 //#define ON_IS_FINITE(x) (finite(x)?true:false)
439 #define ON_IS_FINITE(x) (isfinite(x)?true:false)
440 #else
441 #define ON_IS_FINITE(x) (_finite(x)?true:false)
442 #endif
443 
444 #endif
445 
446 #define ON_IS_FINITE_FLOAT(x) ((x) <= 3.402823466e+38F && (x) >= -3.402823466e+38F)
447 #define ON_IS_INFINITE_FLOAT(x) ((x) > 3.402823466e+38F || (x) < -3.402823466e+38F)
448 
449 #define ON_IS_VALID(x) ((x) != ON_UNSET_VALUE && (x) != ON_UNSET_POSITIVE_VALUE && ON_IS_FINITE(x))
450 #define ON_IS_VALID_FLOAT(x) ((x) != ON_UNSET_FLOAT && (x) != ON_UNSET_POSITIVE_FLOAT && ON_IS_FINITE_FLOAT(x))
451 #define ON_IS_UNSET_DOUBLE(x) (ON_UNSET_VALUE == (x) || ON_UNSET_POSITIVE_VALUE == (x))
452 #define ON_IS_UNSET_FLOAT(x) (ON_UNSET_FLOAT == (x) || ON_UNSET_POSITIVE_FLOAT == (x))
453 #define ON_IS_NAN(x) (!((x)==(x))
454 
455 ON_DECL
456 float ON_ArrayDotProduct( // returns AoB
457  int, // size of arrays (can be zero)
458  const float*, // A[]
459  const float* // B[]
460  );
461 
462 ON_DECL
463 void ON_ArrayScale(
464  int, // size of arrays (can be zero)
465  float, // a
466  const float*, // A[]
467  float* // returns a*A[]
468  );
469 
470 ON_DECL
471 void ON_Array_aA_plus_B(
472  int, // size of arrays (can be zero)
473  float, // a
474  const float*, // A[]
475  const float*, // B[]
476  float* // returns a*A[] + B[]
477  );
478 
479 ON_DECL
480 double ON_ArrayDotProduct( // returns AoB
481  int, // size of arrays (can be zero)
482  const double*, // A[]
483  const double* // B[]
484  );
485 
486 ON_DECL
487 double ON_ArrayDotDifference( // returns A o ( B - C )
488  int, // size of arrays (can be zero)
489  const double*, // A[]
490  const double*, // B[]
491  const double* // C[]
492  );
493 
494 ON_DECL
495 double ON_ArrayMagnitude( // returns sqrt(AoA)
496  int, // size of arrays (can be zero)
497  const double* // A[]
498  );
499 
500 ON_DECL
501 double ON_ArrayMagnitudeSquared( // returns AoA
502  int, // size of arrays (can be zero)
503  const double* // A[]
504  );
505 
506 ON_DECL
507 double ON_ArrayDistance( // returns sqrt((A-B)o(A-B))
508  int, // size of arrays (can be zero)
509  const double*, // A[]
510  const double* // B[]
511  );
512 
513 ON_DECL
514 double ON_ArrayDistanceSquared( // returns (A-B)o(A-B)
515  int, // size of arrays (can be zero)
516  const double*, // A[]
517  const double* // B[]
518  );
519 
520 ON_DECL
521 void ON_ArrayScale(
522  int, // size of arrays (can be zero)
523  double, // a
524  const double*, // A[]
525  double* // returns a*A[]
526  );
527 
528 ON_DECL
529 void ON_Array_aA_plus_B(
530  int, // size of arrays (can be zero)
531  double, // a
532  const double*, // A[]
533  const double*, // B[]
534  double* // returns a*A[] + B[]
535  );
536 
537 ON_DECL
538 int ON_SearchMonotoneArray( // find a value in an increasing array
539  // returns -1: t < array[0]
540  // i: array[i] <= t < array[i+1] ( 0 <= i < length-1 )
541  // length-1: t == array[length-1]
542  // length: t >= array[length-1]
543  const double*, // array[]
544  int, // length of array
545  double // t = value to search for
546  );
547 
548 
549 /*
550 Description:
551  Compute a binomial coefficient.
552 Parameters:
553  i - [in]
554  j - [in]
555 Returns:
556  (i+j)!/(i!j!), if 0 <= i and 0 <= j, and 0 otherwise.
557 See Also:
558  ON_TrinomialCoefficient()
559 Remarks:
560  If (i+j) <= 52, this function is fast and returns the exact
561  value of the binomial coefficient.
562 
563  For (i+j) > 52, the coefficient is computed recursively using
564  the formula bc(i,j) = bc(i-1,j) + bc(i,j-1).
565  For (i+j) much larger than 60, this is inefficient.
566  If you need binomial coefficients for large i and j, then you
567  should probably be using something like Stirling's Formula.
568  (Look up "Stirling" or "Gamma function" in a calculus book.)
569 */
570 ON_DECL
571 double ON_BinomialCoefficient(
572  int i,
573  int j
574  );
575 
576 
577 /*
578 Description:
579  Compute a trinomial coefficient.
580 Parameters:
581  i - [in]
582  j - [in]
583  k - [in]
584 Returns:
585  (i+j+k)!/(i!j!k!), if 0 <= i, 0 <= j and 0<= k, and 0 otherwise.
586 See Also:
587  ON_BinomialCoefficient()
588 Remarks:
589  The trinomial coefficient is computed using the formula
590 
591  (i+j+k)! (i+j+k)! (j+k)!
592  -------- = -------- * -------
593  i! j! k! i! (j+k)! j! k!
594 
595  = ON_BinomialCoefficient(i,j+k)*ON_BinomialCoefficient(j,k)
596 
597 */
598 ON_DECL
599 double ON_TrinomialCoefficient(
600  int i,
601  int j,
602  int k
603  );
604 
605 
606 ON_DECL
607 bool ON_GetParameterTolerance(
608  double, double, // domain
609  double, // parameter in domain
610  double*, double* // parameter tolerance (tminus, tplus) returned here
611  );
612 
613 
614 ON_DECL
615 bool ON_IsValidPointList(
616  int, // dim
617  bool, // true for homogeneous rational points
618  int, // count
619  int, // stride
620  const float*
621  );
622 
623 ON_DECL
624 bool ON_IsValidPointList(
625  int, // dim
626  bool, // true for homogeneous rational points
627  int, // count
628  int, // stride
629  const double*
630  );
631 
632 /*
633 Description:
634  Determine if a list of points is planar.
635 Parameters:
636  bRational - [in]
637  false if the points are euclidean (x,y,z)
638  true if the points are homogeneous rational (x,y,z,w)
639  point_count - [in]
640  number of points
641  point_stride - [in]
642  number of doubles between point x coordinates
643  first point's x coordinate = points[0],
644  second point's x coordinate = points[point_stride],...
645  points - [in]
646  point coordinates (3d or 4d homogeneous rational)
647  boxMin - [in]
648  boxMax - [in]
649  optional 3d bounding box - pass nulls if not readily available
650  tolerance - [in] >= 0.0
651  plane_equation0 - [in]
652  If you want to test for planarity in a specific plane,
653  pass the plane equation in here. If you want to find
654  a plane containing the points, pass null here.
655  plane_equation - [out]
656  If this point is not null, then the equation of the plane
657  containing the points is retuened here.
658 Returns:
659  0 - points are not coplanar to the specified tolerance
660  1 - points are coplanar to the specified tolerance
661  2 - points are collinear to the specified tolerance
662  (in this case, plane_equation is not a unique answer)
663  3 - points are coincident to the specified tolerance
664  (in this case, plane_equation is not a unique answer)
665 */
666 ON_DECL
667 int ON_IsPointListPlanar(
668  bool bRational,
669  int count,
670  int stride,
671  const double* points,
672  const double* boxMin,
673  const double* boxMax,
674  double tolerance,
675  ON_PlaneEquation* plane_equation
676  );
677 
678 ON_DECL
679 bool ON_IsValidPointGrid(
680  int, // dim
681  bool, // true for homogeneous rational points
682  int, int, // point_count0, point_count1,
683  int, int, // point_stride0, point_stride1,
684  const double*
685  );
686 
687 ON_DECL
688 bool ON_ReversePointList(
689  int, // dim
690  bool, // true for homogeneous rational points
691  int, // count
692  int, // stride
693  double*
694  );
695 
696 ON_DECL
697 bool ON_ReversePointGrid(
698  int, // dim
699  bool, // true for homogeneous rational points
700  int, int, // point_count0, point_count1,
701  int, int, // point_stride0, point_stride1,
702  double*,
703  int // dir = 0 or 1
704  );
705 
706 ON_DECL
707 bool ON_SwapPointListCoordinates(
708  int, // count
709  int, // stride
710  float*,
711  int, int // coordinates to swap
712  );
713 
714 ON_DECL
715 bool ON_SwapPointListCoordinates(
716  int, // count
717  int, // stride
718  double*,
719  int, int // coordinates to swap
720  );
721 
722 ON_DECL
723 bool ON_SwapPointGridCoordinates(
724  int, int, // point_count0, point_count1,
725  int, int, // point_stride0, point_stride1,
726  double*,
727  int, int // coordinates to swap
728  );
729 
730 ON_DECL
731 bool ON_TransformPointList(
732  int, // dim
733  bool, // true for homogeneous rational points
734  int, // count
735  int, // stride
736  float*,
737  const ON_Xform&
738  );
739 
740 ON_DECL
741 bool ON_TransformPointList(
742  int, // dim
743  bool, // true for homogeneous rational points
744  int, // count
745  int, // stride
746  double*,
747  const ON_Xform&
748  );
749 
750 ON_DECL
751 bool ON_TransformPointGrid(
752  int, // dim
753  bool, // true for homogeneous rational points
754  int, int, // point_count0, point_count1,
755  int, int, // point_stride0, point_stride1,
756  double*,
757  const ON_Xform&
758  );
759 
760 ON_DECL
761 bool ON_TransformVectorList(
762  int, // dim
763  int, // count
764  int, // stride
765  float*,
766  const ON_Xform&
767  );
768 
769 ON_DECL
770 bool ON_TransformVectorList(
771  int, // dim
772  int, // count
773  int, // stride
774  double*,
775  const ON_Xform&
776  );
777 
778 /*
779 Parameters:
780  dim - [in]
781  >= 1
782  is_rat - [in]
783  true if the points are rational and points[dim] is the "weight"
784  pointA - [in]
785  pointB - [in]
786  point coordinates
787 Returns:
788  True if the input is valid and for each coordinate pair,
789  |a-b| <= ON_ZERO_TOLERANCE
790  or |a-b| <= (fabs(a)+fabs(b))*ON_RELATIVE_TOLERANCE.
791  False otherwise.
792 */
793 ON_DECL
794 bool ON_PointsAreCoincident(
795  int dim,
796  bool is_rat,
797  const double* pointA,
798  const double* pointB
799  );
800 
801 /*
802 Description
803  See ON_PointsAreCoincident() for a description of when opennurbs
804  considers two points to be conincident.
805 Parameters:
806  dim - [in]
807  >= 1
808  is_rat - [in]
809  true if the points are rational and points[dim] is the "weight"
810  point_count - [in]
811  number of points >= 2
812  point_stride - [in]
813  >= (0 != is_rat) ? (dim+1) : dim
814  points - [in]
815  point coordinates
816 Returns:
817  True if the first and last points are coincident and all other
818  points in the list are coincident with the previous point.
819  False if there are points that are not coincident or
820  point_count < 2 or other input parameters are invalid.
821 */
822 ON_DECL
823 bool ON_PointsAreCoincident(
824  int dim,
825  bool is_rat,
826  int point_count,
827  int point_stride,
828  const double* points
829  );
830 
831 ON_DECL
832 int ON_ComparePoint( // returns
833  // -1: first < second
834  // 0: first == second
835  // +1: first > second
836  int dim, // dim (>=0)
837  bool israt, // true for rational CVs
838  const double* cv0, // first CV
839  const double* cv1 // secont CV
840  );
841 
842 ON_DECL
843 int ON_ComparePointList( // returns
844  // -1: first < second
845  // 0: first == second
846  // +1: first > second
847  int, // dim (>=0)
848  bool, // true for rational CVs
849  int, // count
850  // first point list
851  int, // stride
852  const double*, // point
853  // second point list
854  int, // stride
855  const double* // point
856  );
857 
858 ON_DECL
859 bool ON_IsPointListClosed(
860  int, // dim
861  bool, // true for homogeneos rational points
862  int, // count
863  int, // stride
864  const double*
865  );
866 
867 ON_DECL
868 bool ON_IsPointGridClosed(
869  int, // dim
870  bool, // true for homogeneous rational points
871  int, int, // point_count0, point_count1,
872  int, int, // point_stride0, point_stride1,
873  const double*,
874  int // dir = 0 or 1
875  );
876 
877 
878 /*
879 Description:
880  Assign a unique id to each point location. Coincident points
881  get the same id.
882 Parameters:
883  point_dim - [in]
884  2 or 3
885  point_count - [in]
886  >= 1
887  point_stride - [in]
888  number of coordinates to skip between points
889  >= point_dim
890  points - [in]
891  The first coordinate of the i-th point is points[i*point_stride]
892  first_point_id - [in]
893  Initial point id. Typically 1 or 0.
894  point_ids - [out]
895  If not null, then point_ids[] must be an array of length point_count
896  and the ids are retuened in this array. point_ids[0] = first_point_id.
897  point_id_map - [out]
898  If point_id_index is not null, then it must have length point_count.
899  The returned values are a permutation of (0,1,...,point_count-1) such that
900  (point_ids[point_id_map[0]], ..., point_ids[point_id_map[point_count-1]])
901  is an increasing list of values and point_id_map[0] = 0.
902 Returns:
903  If input is valid, then an array of point_count point location
904  ids is returned. The i-th and j-th values in the returned array are
905  equal if and only if the i-th and j-th points have the same location.
906  If the input point_ids pointer was null, then the array memory is
907  allocated on the heap by calling onmalloc(). If input is not valid,
908  nullptr is returned.
909 Remarks:
910  The ids are invarient under invertable transformations.
911  Specifically, if one point point set is a rotation of another, then
912  the assiged ids will be the same.
913 */
914 ON_DECL
915 unsigned int* ON_GetPointLocationIds(
916  size_t point_dim,
917  size_t point_count,
918  size_t point_stride,
919  const float* points,
920  unsigned int first_point_id,
921  unsigned int* point_ids,
922  unsigned int* point_id_map
923  );
924 
925 ON_DECL
926 unsigned int* ON_GetPointLocationIds(
927  size_t point_dim,
928  size_t point_count,
929  size_t point_stride,
930  const double* points,
931  unsigned int first_point_id,
932  unsigned int* point_ids,
933  unsigned int* point_id_map
934  );
935 
936 ON_DECL
937 unsigned int* ON_GetPointLocationIds(
938  size_t point_count,
939  const class ON_2fPoint* points,
940  unsigned int first_point_id,
941  unsigned int* point_ids,
942  unsigned int* point_id_map
943  );
944 
945 ON_DECL
946 unsigned int* ON_GetPointLocationIds(
947  size_t point_count,
948  const class ON_3fPoint* points,
949  unsigned int first_point_id,
950  unsigned int* point_ids,
951  unsigned int* point_id_map
952  );
953 
954 ON_DECL
955 unsigned int* ON_GetPointLocationIds(
956  size_t point_count,
957  const class ON_2dPoint* points,
958  unsigned int first_point_id,
959  unsigned int* point_ids,
960  unsigned int* point_id_map
961  );
962 
963 ON_DECL
964 unsigned int* ON_GetPointLocationIds(
965  size_t point_count,
966  const class ON_3dPoint* points,
967  unsigned int first_point_id,
968  unsigned int* point_ids,
969  unsigned int* point_id_map
970  );
971 
972 
973 ON_DECL
974 int ON_SolveQuadraticEquation( // solve a*X^2 + b*X + c = 0
975  // returns 0: two distinct real roots (r0 < r1)
976  // 1: one real root (r0 = r1)
977  // 2: two complex conjugate roots (r0 +/- (r1)*sqrt(-1))
978  // -1: failure - a = 0, b != 0 (r0 = r1 = -c/b)
979  // -2: failure - a = 0, b = 0 c != 0 (r0 = r1 = 0.0)
980  // -3: failure - a = 0, b = 0 c = 0 (r0 = r1 = 0.0)
981  double, double, double, // a, b, c
982  double*, double* // roots r0 and r1 returned here
983  );
984 
985 /*
986 Returns:
987  0: success
988  <0: failure
989 */
990 ON_DECL
991 int ON_SolveTriDiagonal( // solve TriDiagMatrix( a,b,c )*X = d
992  int, // dimension of d and X (>=1)
993  int, // number of equations (>=2)
994  double*, // a[n-1] = sub-diagonal (a is modified)
995  const double*, // b[n] = diagonal
996  double*, // c[n-1] = supra-diagonal
997  const double*, // d[n*dim]
998  double* // X[n*dim] = unknowns
999  );
1000 
1001 // returns rank - if rank != 2, system is under determined
1002 // If rank = 2, then solution to
1003 //
1004 // a00*x0 + a01*x1 = b0,
1005 // a10*x0 + a11*x1 = b1
1006 //
1007 // is returned
1008 ON_DECL
1009 int ON_Solve2x2(
1010  double, double, // a00 a01 = first row of 2x2 matrix
1011  double, double, // a10 a11 = second row of 2x2 matrix
1012  double, double, // b0 b1
1013  double*, double*, // x0, x1 if not nullptr, then solution is returned here
1014  double* // if not nullptr, then pivot_ratio returned here
1015  );
1016 
1017 // Description:
1018 // Solves a system of 3 linear equations and 2 unknowns.
1019 //
1020 // x*col0[0] + y*col1[0] = d0
1021 // x*col0[1] + y*col1[1] = d0
1022 // x*col0[2] + y*col1[2] = d0
1023 //
1024 // Parameters:
1025 // col0 - [in] coefficents for "x" unknown
1026 // col1 - [in] coefficents for "y" unknown
1027 // d0 - [in] constants
1028 // d1 - [in]
1029 // d2 - [in]
1030 // x - [out]
1031 // y - [out]
1032 // error - [out]
1033 // pivot_ratio - [out]
1034 //
1035 // Returns:
1036 // rank of the system.
1037 // If rank != 2, system is under determined
1038 // If rank = 2, then the solution is
1039 //
1040 // (*x)*[col0] + (*y)*[col1]
1041 // + (*error)*((col0 X col1)/|col0 X col1|)
1042 // = (d0,d1,d2).
1043 ON_DECL
1044 int ON_Solve3x2(
1045  const double[3], // col0
1046  const double[3], // col1
1047  double, // d0
1048  double, // d1
1049  double, // d2
1050  double*, // x
1051  double*, // y
1052  double*, // error
1053  double* // pivot_ratio
1054  );
1055 
1056 /*
1057 Description:
1058  Use Gauss-Jordan elimination with full pivoting to solve
1059  a system of 3 linear equations and 3 unknowns(x,y,z)
1060 
1061  x*row0[0] + y*row0[1] + z*row0[2] = d0
1062  x*row1[0] + y*row1[1] + z*row1[2] = d1
1063  x*row2[0] + y*row2[1] + z*row2[2] = d2
1064 
1065 Parameters:
1066  row0 - [in] first row of 3x3 matrix
1067  row1 - [in] second row of 3x3 matrix
1068  row2 - [in] third row of 3x3 matrix
1069  d0 - [in]
1070  d1 - [in]
1071  d2 - [in] (d0,d1,d2) right hand column of system
1072  x_addr - [in] first unknown
1073  y_addr - [in] second unknown
1074  z_addr - [in] third unknown
1075  pivot_ratio - [out] if not nullptr, the pivot ration is
1076  returned here. If the pivot ratio is "small",
1077  then the matrix may be singular or ill
1078  conditioned. You should test the results
1079  before you use them. "Small" depends on the
1080  precision of the input coefficients and the
1081  use of the solution. If you can't figure out
1082  what "small" means in your case, then you
1083  must check the solution before you use it.
1084 
1085 Returns:
1086  The rank of the 3x3 matrix (0,1,2, or 3)
1087  If ON_Solve3x3() is successful (returns 3), then
1088  the solution is returned in
1089  (*x_addr, *y_addr, *z_addr)
1090  and *pivot_ratio = min(|pivots|)/max(|pivots|).
1091  If the return code is < 3, then (0,0,0) is returned
1092  as the "solution".
1093 
1094 See Also:
1095  ON_Solve2x2
1096  ON_Solve3x2
1097  ON_Solve4x4
1098 */
1099 ON_DECL
1100 int ON_Solve3x3(
1101  const double row0[3],
1102  const double row1[3],
1103  const double row2[3],
1104  double d0,
1105  double d1,
1106  double d2,
1107  double* x_addr,
1108  double* y_addr,
1109  double* z_addr,
1110  double* pivot_ratio
1111  );
1112 
1113 /*
1114 Description:
1115  Use Gauss-Jordan elimination with full pivoting to solve
1116  a system of 4 linear equations and 4 unknowns(x,y,z,w)
1117 
1118  x*row0[0] + y*row0[1] + z*row0[2] + w*row0[3] = d0
1119  x*row1[0] + y*row1[1] + z*row1[2] + w*row1[3] = d1
1120  x*row2[0] + y*row2[1] + z*row2[2] + w*row2[3] = d2
1121  x*row3[0] + y*row3[1] + z*row3[2] + w*row3[2] = d3
1122 
1123 Parameters:
1124  row0 - [in] first row of 4x4 matrix
1125  row1 - [in] second row of 4x4 matrix
1126  row2 - [in] third row of 4x4 matrix
1127  row3 - [in] forth row of 4x4 matrix
1128  d0 - [in]
1129  d1 - [in]
1130  d2 - [in]
1131  d3 - [in] (d0,d1,d2,d3) right hand column of system
1132  x_addr - [in] first unknown
1133  y_addr - [in] second unknown
1134  z_addr - [in] third unknown
1135  w_addr - [in] forth unknown
1136  pivot_ratio - [out] if not nullptr, the pivot ration is
1137  returned here. If the pivot ratio is "small",
1138  then the matrix may be singular or ill
1139  conditioned. You should test the results
1140  before you use them. "Small" depends on the
1141  precision of the input coefficients and the
1142  use of the solution. If you can't figure out
1143  what "small" means in your case, then you
1144  must check the solution before you use it.
1145 
1146 Returns:
1147  The rank of the 4x4 matrix (0,1,2,3, or 4)
1148  If ON_Solve4x4() is successful (returns 4), then
1149  the solution is returned in
1150  (*x_addr, *y_addr, *z_addr, *w_addr)
1151  and *pivot_ratio = min(|pivots|)/max(|pivots|).
1152  If the return code is < 4, then, it a solution exists,
1153  on is returned. However YOU MUST CHECK THE SOLUTION
1154  IF THE RETURN CODE IS < 4.
1155 
1156 See Also:
1157  ON_Solve2x2
1158  ON_Solve3x2
1159  ON_Solve3x3
1160 */
1161 ON_DECL
1162 int
1163 ON_Solve4x4(
1164  const double row0[4],
1165  const double row1[4],
1166  const double row2[4],
1167  const double row3[4],
1168  double d0,
1169  double d1,
1170  double d2,
1171  double d3,
1172  double* x_addr,
1173  double* y_addr,
1174  double* z_addr,
1175  double* w_addr,
1176  double* pivot_ratio
1177  );
1178 
1179 /*
1180 Description:
1181  Use Gauss-Jordan elimination to find a numerical
1182  solution to M*X = B where M is a n x n matrix,
1183  B is a known n-dimensional vector and X is
1184  an unknown.
1185 Paramters:
1186  bFullPivot - [in] if true, full pivoting is used,
1187  otherwise partial pivoting is used. In rare
1188  cases full pivoting can produce a more accurate
1189  answer and never produces a less accurate answer.
1190  However full pivoting is slower. If speed is an
1191  issue, then experiement with bFullPivot=false
1192  and see if it makes a difference. Otherwise,
1193  set it to true.
1194  bNormalize - [in]
1195  If bNormalize is true, then the rows of the
1196  matrix are scaled so the sum of their squares
1197  is one. This doesn't make the solution more
1198  accurate but in some cases it makes the pivot
1199  ratio more meaningful. Set bNormalize to
1200  false unless you have a reason for setting it
1201  to true.
1202  n - [in] size of the matrix and vectors.
1203  M - [in] n x n matrix. The values in M are
1204  changed as the solution is calculated.
1205  If you need to preserve M for future use,
1206  pass in a copy.
1207  B - [in] n-dimensional vector. The values in
1208  B are changed as the solution is calculated.
1209  If you need to preserve B for future use,
1210  pass in a copy.
1211  X - [out] solution to M*X = B.
1212 Returns:
1213  If the returned value is <= 0.0, the input matrix
1214  has rank < n and no solution is returned in X.
1215  If the returned value is > 0.0, then a solution is
1216  returned in X and the returned value is the ratio
1217  (minimum pivot)/(maximum pivot). This value is
1218  called the pivot ratio and will be denoted "pr"
1219  the discussion below. If pr <= 1e-15, then
1220  M was nearly degenerate and the solution should be
1221  used with caution. If an accurate solution is
1222  critcial, then check the solution anytime pr <= 1e-10
1223  In general, the difference between M*X and B will be
1224  reasonably small. However, when the pr is small
1225  there tend to be vector E, substantually different
1226  from zero, such that M*(X+E) - B is also reasonably
1227  small.
1228 See Also:
1229  ON_Solve2x2
1230  ON_Solve3x3
1231  ON_Solve4x4
1232  ON_Solve3x2
1233 */
1234 ON_DECL
1235 double ON_SolveNxN(bool bFullPivot, bool bNormalize, int n, double* M[], double B[], double X[]);
1236 
1237 
1238 /*
1239 Description:
1240 Find the eigen values and eigen vectors of a real symmetric
1241 3x3 matrix
1242 
1243 A D F
1244 D B E
1245 F E C
1246 
1247 Parameters:
1248 A - [in] matrix entry
1249 B - [in] matrix entry
1250 C - [in] matrix entry
1251 D - [in] matrix entry
1252 E - [in] matrix entry
1253 F - [in] matrix entry
1254 e1 - [out] eigen value
1255 E1 - [out] eigen vector with eigen value e1
1256 e2 - [out] eigen value
1257 E2 - [out] eigen vector with eigen value e2
1258 e3 - [out] eigen value
1259 E3 - [out] eigen vector with eigen value e3
1260 Returns:
1261 True if successful.
1262 */
1263 ON_DECL
1264 bool ON_Sym3x3EigenSolver(double A, double B, double C,
1265  double D, double E, double F,
1266  double* e1, ON_3dVector& E1,
1267  double* e2, ON_3dVector& E2,
1268  double* e3, ON_3dVector& E3 );
1269 
1270 // return false if determinant is (nearly) singular
1271 ON_DECL
1272 bool ON_EvJacobian(
1273  double, // ds o ds
1274  double, // ds o dt
1275  double, // dt o dt
1276  double* // jacobian = determinant ( ds_o_ds dt_o_dt / ds_o_dt ds_o_dt )
1277  );
1278 
1279 /*
1280 Description:
1281  Finds scalars x and y so that the component of V in the plane
1282  of A and B is x*A + y*B.
1283 Parameters:
1284  V - [in]
1285  A - [in] nonzero and not parallel to B
1286  B - [in] nonzero and not parallel to A
1287  x - [out]
1288  y - [out]
1289 Returns:
1290  1 - The rank of the problem is 2. The decomposition is unique.
1291  0 - The rank less than 2. Either there is no solution or there
1292  are infinitely many solutions.
1293 
1294 See Also:
1295  ON_Solve2x2
1296 */
1297 ON_DECL
1298 int ON_DecomposeVector(
1299  const ON_3dVector& V,
1300  const ON_3dVector& A,
1301  const ON_3dVector& B,
1302  double* x, double* y
1303  );
1304 
1305 
1306 /*
1307 Description:
1308  Evaluate partial derivatives of surface unit normal
1309 Parameters:
1310  ds - [in]
1311  dt - [in] surface first partial derivatives
1312  dss - [in]
1313  dst - [in]
1314  dtt - [in] surface second partial derivatives
1315  ns - [out]
1316  nt - [out] First partial derivatives of surface unit normal
1317  (If the Jacobian is degenerate, ns and nt are set to zero.)
1318 Returns:
1319  true if Jacobian is nondegenerate
1320  false if Jacobian is degenerate
1321 */
1322 ON_DECL
1323 bool ON_EvNormalPartials(
1324  const ON_3dVector& ds,
1325  const ON_3dVector& dt,
1326  const ON_3dVector& dss,
1327  const ON_3dVector& dst,
1328  const ON_3dVector& dtt,
1329  ON_3dVector& ns,
1330  ON_3dVector& nt
1331  );
1332 
1333 ON_DECL
1334 bool
1335 ON_Pullback3dVector( // use to pull 3d vector back to surface parameter space
1336  const ON_3dVector&, // 3d vector
1337  double, // signed distance from vector location to closet point on surface
1338  // < 0 if point is below with respect to Du x Dv
1339  const ON_3dVector&, // ds surface first partials
1340  const ON_3dVector&, // dt
1341  const ON_3dVector&, // dss surface 2nd partials
1342  const ON_3dVector&, // dst (used only when dist != 0)
1343  const ON_3dVector&, // dtt
1344  ON_2dVector& // pullback
1345  );
1346 
1347 ON_DECL
1348 bool
1349 ON_GetParameterTolerance(
1350  double, // t0 domain
1351  double, // t1
1352  double, // t parameter in domain
1353  double*, // tminus parameter tolerance (tminus, tplus) returned here
1354  double* // tplus
1355  );
1356 
1357 
1358 ON_DECL
1359 bool ON_EvNormal(
1360  int, // limit_dir 0=default,1=from quadrant I, 2 = from quadrant II, ...
1361  const ON_3dVector&, const ON_3dVector&, // first partials (Du,Dv)
1362  const ON_3dVector&, const ON_3dVector&, const ON_3dVector&, // optional second partials (Duu, Duv, Dvv)
1363  ON_3dVector& // unit normal returned here
1364  );
1365 
1366 // returns false if the returned tangent is zero
1367 ON_DECL
1368 bool ON_EvTangent(
1369  const ON_3dVector&, // first derivative
1370  const ON_3dVector&, // second derivative
1371  ON_3dVector& // Unit tangent returned here
1372  );
1373 
1374 // returns false if first derivtive is zero
1375 ON_DECL
1376 bool ON_EvCurvature(
1377  const ON_3dVector&, // first derivative
1378  const ON_3dVector&, // second derivative
1379  ON_3dVector&, // Unit tangent returned here
1380  ON_3dVector& // Curvature returned here
1381  );
1382 
1383 ON_DECL
1384 bool ON_EvPrincipalCurvatures(
1385  const ON_3dVector&, // Ds,
1386  const ON_3dVector&, // Dt,
1387  const ON_3dVector&, // Dss,
1388  const ON_3dVector&, // Dst,
1389  const ON_3dVector&, // Dtt,
1390  const ON_3dVector&, // N, // unit normal to surface (use ON_EvNormal())
1391  double*, // gauss, // = Gaussian curvature = kappa1*kappa2
1392  double*, // mean, // = mean curvature = (kappa1+kappa2)/2
1393  double*, // kappa1, // = largest principal curvature value (may be negative)
1394  double*, // kappa2, // = smallest principal curvature value (may be negative)
1395  ON_3dVector&, // K1, // kappa1 unit principal curvature direction
1396  ON_3dVector& // K2 // kappa2 unit principal curvature direction
1397  // output K1,K2,N is right handed frame
1398  );
1399 
1400 ON_DECL
1401 bool ON_EvPrincipalCurvatures(
1402  const ON_3dVector&, // Ds,
1403  const ON_3dVector&, // Dt,
1404  double l, // Dss*N Second fundamental form coefficients
1405  double m, // Dst*N,
1406  double n, // Dtt*N,
1407  const ON_3dVector&, // N, // unit normal to surface (use ON_EvNormal())
1408  double*, // gauss, // = Gaussian curvature = kappa1*kappa2
1409  double*, // mean, // = mean curvature = (kappa1+kappa2)/2
1410  double*, // kappa1, // = largest principal curvature value (may be negative)
1411  double*, // kappa2, // = smallest principal curvature value (may be negative)
1412  ON_3dVector&, // K1, // kappa1 unit principal curvature direction
1413  ON_3dVector& // K2 // kappa2 unit principal curvature direction
1414  // output K1,K2,N is right handed frame
1415  );
1416 
1417 /*
1418 Description:
1419  Evaluate sectional curvature from surface derivatives and
1420  section plane normal.
1421 Parameters:
1422  S10, S01 - [in]
1423  surface 1st partial derivatives
1424  S20, S11, S02 - [in]
1425  surface 2nd partial derivatives
1426  planeNormal - [in]
1427  unit normal to section plane
1428  K - [out] Sectional curvature
1429  Curvature of the intersection curve of the surface
1430  and plane through the surface point where the partial
1431  derivatives were evaluationed.
1432 Returns:
1433  True if successful.
1434  False if first partials are not linearly independent, in
1435  which case the K is set to zero.
1436 */
1437 ON_DECL
1438 bool ON_EvSectionalCurvature(
1439  const ON_3dVector& S10,
1440  const ON_3dVector& S01,
1441  const ON_3dVector& S20,
1442  const ON_3dVector& S11,
1443  const ON_3dVector& S02,
1444  const ON_3dVector& planeNormal,
1445  ON_3dVector& K
1446  );
1447 
1448 
1449 ON_DECL
1450 ON_3dVector ON_NormalCurvature(
1451  const ON_3dVector&, // surface 1rst partial (Ds)
1452  const ON_3dVector&, // surface 1rst partial (Dt)
1453  const ON_3dVector&, // surface 1rst partial (Dss)
1454  const ON_3dVector&, // surface 1rst partial (Dst)
1455  const ON_3dVector&, // surface 1rst partial (Dtt)
1456  const ON_3dVector&, // surface unit normal
1457  const ON_3dVector& // unit tangent direction
1458  );
1459 
1460 /*
1461 Description:
1462  Determing if two curvatrues are different enough
1463  to qualify as a curvature discontinuity.
1464 Parameters:
1465  Km - [in]
1466  Kp - [in]
1467  Km and Kp should be curvatures evaluated at the same
1468  parameters using limits from below (minus) and above (plus).
1469  The assumption is that you have already compared the
1470  points and tangents and consider to curve to be G1 at the
1471  point in question.
1472  cos_angle_tolerance - [in]
1473  If the inut value of cos_angle_tolerance >= -1.0
1474  and cos_angle_tolerance <= 1.0 and
1475  Km o Kp < cos_angle_tolerance*|Km|*|Kp|, then
1476  true is returned. Otherwise it is assumed Km and Kp
1477  are parallel. If the curve being tested is nonplanar,
1478  then use something like cos(2*tangent angle tolerance)
1479  for this parameter. If the curve being tested is planar,
1480  then 0.0 will work fine.
1481  curvature_tolerance - [in]
1482  If |Kp-Km| <= curvature_tolerance,
1483  then false is returned, otherwise other tests are used
1484  to determing continuity.
1485  zero_curvature - [in] (ignored if < 2^-110 = 7.7037197787136e-34)
1486  If |K| <= zero_curvature, then K is treated as zero.
1487  When in doubt, use ON_ZERO_CURVATURE_TOLERANCE.
1488  radius_tolerance - [in]
1489  If radius_tolerance >= 0.0 and the difference between the
1490  radii of curvature is >= radius_tolerance, then true
1491  is returned.
1492  relative_tolerance - [in]
1493  If relative_tolerance > 0 and
1494  |(|Km| - |Kp|)|/max(|Km|,|Kp|) > relative_tolerance,
1495  then true is returned. Note that if the curvatures are
1496  nonzero and rm and rp are the radii of curvature, then
1497  |(|Km| - |Kp|)|/max(|Km|,|Kp|) = |rm-rp|/max(rm,rp).
1498  This means the relative_tolerance insures both the scalar
1499  curvature and the radii of curvature agree to the specified
1500  number of decimal places.
1501  When in doubt, use ON_RELATIVE_CURVATURE_TOLERANCE, which
1502  is currently 0.05.
1503 Returns:
1504  False if the curvatures should be considered G2.
1505  True if the curvatures are different enough that the curve should be
1506  considered not G2.
1507  In addition to the tests described under the curvature_tolerance and
1508  radius_tolerance checks, other hurestic tests are used.
1509 */
1510 ON_DECL
1511 bool ON_IsCurvatureDiscontinuity(
1512  const ON_3dVector Km,
1513  const ON_3dVector Kp,
1514  double cos_angle_tolerance,
1515  double curvature_tolerance,
1516  double zero_curvature,
1517  double radius_tolerance,
1518  double relative_tolerance
1519  );
1520 
1521 ON_DECL
1522 bool ON_IsCurvatureDiscontinuity(
1523  const ON_3dVector Km,
1524  const ON_3dVector Kp,
1525  double cos_angle_tolerance,
1526  double curvature_tolerance,
1527  double zero_curvature,
1528  double radius_tolerance
1529  );
1530 
1531 
1532 /*
1533 Description:
1534  This function is used to test curvature continuity
1535  in IsContinuous and GetNextDiscontinuity functions
1536  when the continuity parameter is ON::continuity::G2_continuous.
1537 Parameters:
1538  Km - [in]
1539  Curve's vector curvature evaluated from below
1540  Kp - [in]
1541  Curve's vector curvature evaluated from below
1542 Returns:
1543  True if the change from Km to Kp should be considered
1544  G2 continuous.
1545 */
1546 ON_DECL
1547 bool ON_IsG2CurvatureContinuous(
1548  const ON_3dVector Km,
1549  const ON_3dVector Kp,
1550  double cos_angle_tolerance,
1551  double curvature_tolerance
1552  );
1553 
1554 /*
1555 Description:
1556  This function is used to test curvature continuity
1557  in IsContinuous and GetNextDiscontinuity functions
1558  when the continuity parameter is ON::continuity::Gsmooth_continuous.
1559 Parameters:
1560  Km - [in]
1561  Curve's vector curvature evaluated from below
1562  Kp - [in]
1563  Curve's vector curvature evaluated from below
1564 Returns:
1565  True if the change from Km to Kp should be considered
1566  Gsmooth continuous.
1567 */
1568 ON_DECL
1569 bool ON_IsGsmoothCurvatureContinuous(
1570  const ON_3dVector Km,
1571  const ON_3dVector Kp,
1572  double cos_angle_tolerance,
1573  double curvature_tolerance
1574  );
1575 
1576 /*
1577 Description:
1578  Test curve continuity from derivative values.
1579 Parameters:
1580  c - [in] type of continuity to test for. Read ON::continuity
1581  comments for details.
1582  Pa - [in] point on curve A.
1583  D1a - [in] first derviative of curve A.
1584  D2a - [in] second derviative of curve A.
1585  Pb - [in] point on curve B.
1586  D1b - [in] first derviative of curve B.
1587  D3b - [in] second derviative of curve B.
1588  point_tolerance - [in] if the distance between two points is
1589  greater than point_tolerance, then the curve is not C0.
1590  d1_tolerance - [in] if the difference between two first derivatives is
1591  greater than d1_tolerance, then the curve is not C1.
1592  d2_tolerance - [in] if the difference between two second derivatives is
1593  greater than d2_tolerance, then the curve is not C2.
1594  cos_angle_tolerance - [in] default = cos(1 degree) Used only when
1595  c is ON::continuity::G1_continuous or ON::continuity::G2_continuous. If the cosine
1596  of the angle between two tangent vectors
1597  is <= cos_angle_tolerance, then a G1 discontinuity is reported.
1598  curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used only when
1599  c is ON::continuity::G2_continuous. If K0 and K1 are curvatures evaluated
1600  from above and below and |K0 - K1| > curvature_tolerance,
1601  then a curvature discontinuity is reported.
1602 Returns:
1603  true if the curve has at least the c type continuity at
1604  the parameter t.
1605 */
1606 ON_DECL
1607 bool ON_IsContinuous(
1608  ON::continuity c,
1609  ON_3dPoint Pa,
1610  ON_3dVector D1a,
1611  ON_3dVector D2a,
1612  ON_3dPoint Pb,
1613  ON_3dVector D1b,
1614  ON_3dVector D2b,
1615  double point_tolerance=ON_ZERO_TOLERANCE,
1616  double d1_tolerance=ON_ZERO_TOLERANCE,
1617  double d2_tolerance=ON_ZERO_TOLERANCE,
1618  double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE,
1619  double curvature_tolerance=ON_SQRT_EPSILON
1620  );
1621 
1622 
1623 ON_DECL
1624 bool ON_TuneupEvaluationParameter(
1625  int side,
1626  double s0, double s1, // segment domain
1627  double *s // segment parameter
1628  );
1629 
1630 
1631 ON_DECL
1632 int ON_Compare2dex( const ON_2dex* a, const ON_2dex* b);
1633 
1634 ON_DECL
1635 int ON_Compare3dex( const ON_3dex* a, const ON_3dex* b);
1636 
1637 ON_DECL
1638 int ON_Compare4dex( const ON_4dex* a, const ON_4dex* b);
1639 
1640 ON_DECL
1641 const ON_2dex* ON_BinarySearch2dexArray(
1642  int key_i,
1643  const ON_2dex* base,
1644  size_t nel
1645  );
1646 
1647 // These simple intersectors are fast and detect transverse intersections.
1648 // If the intersection is not a simple transverse case, then they
1649 // return false and you will have to use one of the slower but fancier
1650 // models.
1651 
1652 // returns closest points between the two infinite lines
1653 ON_DECL
1654 bool ON_Intersect(
1655  const ON_Line&,
1656  const ON_Line&,
1657  double*, // parameter on first line
1658  double* // parameter on second line
1659  );
1660 
1661 // Returns false unless intersection is a single point
1662 // If returned parameter is < 0 or > 1, then the line
1663 // segment between line.m_point[0] and line.m_point[1]
1664 // does not intersect the plane
1665 ON_DECL
1666 bool ON_Intersect(
1667  const ON_Line&,
1668  const ON_Plane&,
1669  double* // parameter on line
1670  );
1671 
1672 ON_DECL
1673 bool ON_Intersect(
1674  const ON_Plane&,
1675  const ON_Plane&,
1676  ON_Line& // intersection line is returned here
1677  );
1678 
1679 ON_DECL
1680 bool ON_Intersect(
1681  const ON_Plane&,
1682  const ON_Plane&,
1683  const ON_Plane&,
1684  ON_3dPoint& // intersection point is returned here
1685  );
1686 
1687 // returns 0 = no intersections,
1688 // 1 = intersection = single point,
1689 // 2 = intersection = circle
1690 // If 0 is returned, returned circle has radius=0
1691 // and center = point on sphere closest to plane.
1692 // If 1 is returned, intersection is a single
1693 // point and returned circle has radius=0
1694 // and center = intersection point on sphere.
1695 ON_DECL
1696 int ON_Intersect(
1697  const ON_Plane&, const ON_Sphere&, ON_Circle&
1698  );
1699 
1700 // Intersects an infinte line and sphere and returns
1701 // 0 = no intersections,
1702 // 1 = one intersection,
1703 // 2 = 2 intersections
1704 // If 0 is returned, first point is point
1705 // on line closest to sphere and 2nd point is the point
1706 // on the sphere closest to the line.
1707 // If 1 is returned, first point is obtained by evaluating
1708 // the line and the second point is obtained by evaluating
1709 // the sphere.
1710 ON_DECL
1711 int ON_Intersect(
1712  const ON_Line&,
1713  const ON_Sphere&,
1714  ON_3dPoint&,
1715  ON_3dPoint& // intersection point(s) returned here
1716  );
1717 
1718 
1719 // Intersects an infinte line and cylinder and returns
1720 // 0 = no intersections,
1721 // 1 = one intersection,
1722 // 2 = 2 intersections
1723 // 3 = line lies on cylinder
1724 //
1725 // If 0 is returned, first point is point
1726 // on line closest to cylinder and 2nd point is the point
1727 // on the cylinder closest to the line.
1728 // If 1 is returned, first point is obtained by evaluating
1729 // the line and the second point is obtained by evaluating
1730 // the cylinder.
1731 //
1732 // The value of cylinder.IsFinite() determines if the
1733 // intersection is performed on the finite or infinite cylinder.
1734 ON_DECL
1735 int ON_Intersect(
1736  const ON_Line&, // [in]
1737  const ON_Cylinder&, // [in]
1738  ON_3dPoint&, // [out] first intersection point
1739  ON_3dPoint& // [out] second intersection point
1740  );
1741 
1742 // Description:
1743 // Intersect an infinte line and circle.
1744 // Parameters:
1745 // line - [in]
1746 // circle - [in]
1747 // line_t0 - [out] line parameter of first intersection point
1748 // circle_point0 - [out] first intersection point on circle
1749 // line_t1 - [out] line parameter of second intersection point
1750 // circle_point1 - [out] second intersection point on circle
1751 // Returns:
1752 // 0 No intersection
1753 // 1 One intersection at line.PointAt(*line_t0)
1754 // 2 Two intersections at line.PointAt(*line_t0)
1755 // and line.PointAt(*line_t1).
1756 ON_DECL
1757 int ON_Intersect(
1758  const ON_Line& line,
1759  const ON_Circle& circle,
1760  double* line_t0,
1761  ON_3dPoint& circle_point0,
1762  double* line_t1,
1763  ON_3dPoint& circle_point1
1764  );
1765 
1766 
1767 
1768 // Description:
1769 // Intersect a infinte line and arc.
1770 // Parameters:
1771 // line - [in]
1772 // arc - [in]
1773 // line_t0 - [out] line parameter of first intersection point
1774 // arc_point0 - [out] first intersection point on arc
1775 // line_t1 - [out] line parameter of second intersection point
1776 // arc_point1 - [out] second intersection point on arc
1777 // Returns:
1778 // 0 No intersection
1779 // 1 One intersection at line.PointAt(*line_t0)
1780 // 2 Two intersections at line.PointAt(*line_t0)
1781 // and line.PointAt(*line_t1).
1782 ON_DECL
1783 int ON_Intersect(
1784  const ON_Line& line,
1785  const ON_Arc& arc,
1786  double* line_t0,
1787  ON_3dPoint& arc_point0,
1788  double* line_t1,
1789  ON_3dPoint& arc_point1
1790  );
1791 
1792 // Description:
1793 // Intersect a plane and a circle.
1794 // Parameters:
1795 // plane - [in]
1796 // circle - [in]
1797 // point0 - [out] first intersection point
1798 // point1 - [out] second intersection point
1799 // Returns:
1800 // 0 No intersection
1801 // 1 One intersection at point0
1802 // 2 Two intersections at point0
1803 // and point1.
1804 // 3 Circle lies on plane
1805 ON_DECL
1806 int ON_Intersect(
1807  const ON_Plane& plane,
1808  const ON_Circle& circle,
1809  ON_3dPoint& point0,
1810  ON_3dPoint& point1
1811  );
1812 
1813 // Description:
1814 // Intersect a plane and an arc.
1815 // Parameters:
1816 // plane - [in]
1817 // arc - [in]
1818 // point0 - [out] first intersection point
1819 // point1 - [out] second intersection point
1820 // Returns:
1821 // 0 No intersection
1822 // 1 One intersection at point0
1823 // 2 Two intersections at point0
1824 // and point1.
1825 // 3 Arc lies on plane
1826 ON_DECL
1827 int ON_Intersect(
1828  const ON_Plane& plane,
1829  const ON_Arc& arc,
1830  ON_3dPoint& point0,
1831  ON_3dPoint& point1
1832  );
1833 
1834 
1835 // returns 0 = no, 1 = yes, 2 = points are coincident and on line
1836 ON_DECL
1837 int ON_ArePointsOnLine(
1838  int, // dimension of points
1839  bool, // is_rat = true if homogeneous rational
1840  int, // count = number of points
1841  int, // stride ( >= is_rat?(dim+1) :dim)
1842  const double*, // point array
1843  const ON_BoundingBox&, // if needed, use ON_GetBoundingBox(dim,is_rat,count,stride,point)
1844  const ON_Line&,
1845  double // tolerance (if 0.0, a tolerance based on bounding box size is used)
1846  );
1847 
1848 // returns 0 = no, 1 = yes, 2 = points are coincident and on line
1849 ON_DECL
1850 int ON_ArePointsOnPlane(
1851  int, // dimension of points
1852  bool, // is_rat = true if homogeneous rational
1853  int, // count = number of points
1854  int, // stride ( >= is_rat?(dim+1) :dim)
1855  const double*, // point array
1856  const ON_BoundingBox&, // if needed, use ON_GetBoundingBox(dim,is_rat,count,stride,point)
1857  const ON_Plane&,
1858  double // tolerance (if 0.0, a tolerance based on bounding box size is used)
1859  );
1860 
1861 /*
1862 Description:
1863  Use the quotient rule to compute derivatives of a one parameter
1864  rational function F(t) = X(t)/W(t), where W is a scalar
1865  and F and X are vectors of dimension dim.
1866 Parameters:
1867  dim - [in]
1868  der_count - [in] number of derivative (>=0)
1869  v_stride - [in] (>= dim+1)
1870  v - [in/out]
1871  v[] is an array of length (der_count+1)*v_stride.
1872  The input v[] array contains derivatives of the numerator and
1873  denominator functions in the order (X, W), (Xt, Wt), (Xtt, Wtt), ...
1874  In general, the (dim+1) coordinates of the d-th derivative
1875  are in (v[n],...,v[n+dim]) where n = d*v_stride.
1876  In the output v[] array the derivatives of X are replaced with
1877  the derivatives of F and the derivatives of W are divided by
1878  w = v[dim].
1879 Returns:
1880  True if input is valid; i.e., v[dim] != 0.
1881 See Also:
1882  ON_EvaluateQuotientRule2
1883  ON_EvaluateQuotientRule3
1884 */
1885 ON_DECL
1886 bool ON_EvaluateQuotientRule(
1887  int dim,
1888  int der_count,
1889  int v_stride,
1890  double *v
1891  );
1892 
1893 /*
1894 Description:
1895  Use the quotient rule to compute partial derivatives of a two parameter
1896  rational function F(s,t) = X(s,t)/W(s,t), where W is a scalar
1897  and F and X are vectors of dimension dim.
1898 Parameters:
1899  dim - [in]
1900  der_count - [in] number of derivative (>=0)
1901  v_stride - [in] (>= dim+1)
1902  v - [in/out]
1903  v[] is an array of length (der_count+2)*(der_count+1)*v_stride.
1904  The input array contains derivatives of the numerator and denominator
1905  functions in the order X, W, Xs, Ws, Xt, Wt, Xss, Wss, Xst, Wst, Xtt, Wtt, ...
1906  In general, the (i,j)-th derivatives are in the (dim+1) entries of v[]
1907  v[k], ..., answer[k+dim], where k = ((i+j)*(i+j+1)/2 + j)*v_stride.
1908  In the output v[] array the derivatives of X are replaced with
1909  the derivatives of F and the derivatives of W are divided by
1910  w = v[dim].
1911 Returns:
1912  True if input is valid; i.e., v[dim] != 0.
1913 See Also:
1914  ON_EvaluateQuotientRule
1915  ON_EvaluateQuotientRule3
1916 */
1917 ON_DECL
1918 bool ON_EvaluateQuotientRule2(
1919  int dim,
1920  int der_count,
1921  int v_stride,
1922  double *v
1923  );
1924 
1925 /*
1926 Description:
1927  Use the quotient rule to compute partial derivatives of a 3 parameter
1928  rational function F(r,s,t) = X(r,s,t)/W(r,s,t), where W is a scalar
1929  and F and X are vectors of dimension dim.
1930 Parameters:
1931  dim - [in]
1932  der_count - [in] number of derivative (>=0)
1933  v_stride - [in] (>= dim+1)
1934  v - [in/out]
1935  v[] is an array of length
1936  v_stride*(der_count+1)*(der_count+2)*(der_count+3)/6.
1937  The input v[] array contains derivatives of the numerator and
1938  denominator functions in the order (X, W), (Xr, Wr), (Xs, Ws),
1939  (Xt, Wt), (Xrr, Wrr), (Xrs, Wrs), (Xrt, Wrt), (Xss, Wss),
1940  (Xst, Wst), (Xtt, Wtt), ...
1941  In general, the (dim+1) coordinates of the derivative
1942  (Dr^i Ds^j Dt^k, i+j+k=d) are at v[n], ..., v[n+dim] where
1943  n = v_stride*( d*(d+1)*(d+2)/6 + (d-i)*(d-i+1)/2 + k ).
1944  In the output v[] array the derivatives of X are replaced with
1945  the derivatives of F and the derivatives of W are divided by
1946  w = v[dim].
1947 Returns:
1948  True if input is valid; i.e., v[dim] != 0.
1949 See Also:
1950  ON_EvaluateQuotientRule
1951  ON_EvaluateQuotientRule2
1952 */
1953 ON_DECL
1954 bool ON_EvaluateQuotientRule3(
1955  int dim,
1956  int der_count,
1957  int v_stride,
1958  double *v
1959  );
1960 
1961 ON_DECL
1962 bool ON_GetPolylineLength(
1963  int, // dimension of points
1964  bool, // bIsRational true if points are homogeneous rational
1965  int, // number of points
1966  int, // stride between points
1967  const double*, // points
1968  double* // length returned here
1969  );
1970 
1971 
1972 /*
1973 Description:
1974  Find the index of the point in the point_list that is closest to P.
1975 Parameters:
1976  point_count - [in]
1977  point_list - [in]
1978  P - [in]
1979  closest_point_index - [out]
1980 Returns:
1981  True if successful and *closest_point_index is set.
1982  False if input is not valid, in which case *closest_point_index
1983  is undefined.
1984 */
1985 ON_DECL
1986 bool ON_GetClosestPointInPointList(
1987  int point_count,
1988  const ON_3dPoint* point_list,
1989  ON_3dPoint P,
1990  int* closest_point_index
1991  );
1992 
1993 /*
1994 Description:
1995  Test math library functions.
1996 Parameters:
1997  function_index - [in] Determines which math library function is called.
1998 
1999  1: z = x+y
2000  2: z = x-y
2001  3: z = x*y
2002  4: z = x/y
2003  5: z = fabs(x)
2004  6: z = exp(x)
2005  7: z = log(x)
2006  8: z = logb(x)
2007  9: z = log10(x)
2008  10: z = pow(x,y)
2009  11: z = sqrt(x)
2010  12: z = sin(x)
2011  13: z = cos(x)
2012  14: z = tan(x)
2013  15: z = sinh(x)
2014  16: z = cosh(x)
2015  17: z = tanh(x)
2016  18: z = asin(x)
2017  19: z = acos(x)
2018  20: z = atan(x)
2019  21: z = atan2(y,x)
2020  22: z = fmod(x,y)
2021  23: z = modf(x,&y)
2022  24: z = frexp(x,&y)
2023 
2024  double x - [in]
2025  double y - [in]
2026 Returns:
2027  Returns the "z" value listed in the function_index parameter
2028  description.
2029 Remarks:
2030  This function is used to test the results of class floating
2031  point functions. It is primarily used to see what happens
2032  when opennurbs is used as a DLL and illegal operations are
2033  performed.
2034 */
2035 ON_DECL
2036 double ON_TestMathFunction(
2037  int function_index,
2038  double x,
2039  double y
2040  );
2041 
2042 // If performance is important, then
2043 // you are better off using ((b<a)?a:b)
2044 ON_DECL double ON_Max(double a, double b);
2045 
2046 // If performance is important, then
2047 // you are better off using ((b<a)?a:b)
2048 ON_DECL float ON_Max(float a, float b);
2049 
2050 // If performance is important, then
2051 // you are better off using ((b<a)?a:b)
2052 ON_DECL int ON_Max(int a, int b);
2053 
2054 // If performance is important, then
2055 // you are better off using ((a<b)?a:b)
2056 ON_DECL double ON_Min(double a, double b);
2057 
2058 // If performance is important, then
2059 // you are better off using ((a<b)?a:b)
2060 ON_DECL float ON_Min(float a, float b);
2061 
2062 // If performance is important, then
2063 // you are better off using ((a<b)?a:b)
2064 ON_DECL int ON_Min(int a, int b);
2065 
2066 // Do not call ON_Round() in any opennurbs code, tl code
2067 // or any other code that does critical calculations or
2068 // when there is any possibility that x is invalid or
2069 // fabs(x)>2147483647. Use floor(x+0.5) instead.
2070 ON_DECL int ON_Round(double x);
2071 
2072 /*
2073 Description:
2074  Calculate the value of (1.0-t)*x + t*y so that,
2075  if 0.0 <= t <= 1.0, then the result is between x and y and
2076  if x == y and t is a valid double, the result is x.
2077 Returns:
2078  (1.0-t)*x + t*y
2079 */
2080 ON_DECL double ON_LinearInterpolation(
2081  double t,
2082  double x,
2083  double y
2084  );
2085 
2086 /*
2087 Description:
2088  Find the equation of the parabola, ellipse or hyperbola
2089  (non-degenerate conic) that passes through six distinct points.
2090 Parameters:
2091  stride - [in] (>=2)
2092  points array stride
2093  points2d - [in] (>=2)
2094  i-th point is (points[i*stride],points[i*stride+1])
2095  conic - [out]
2096  Coefficients of the conic equation.
2097  The points on the conic satisfy the equation
2098  0 = conic[0]*x^2 + conic[1]*xy + conic[2]*y^2
2099  + conic[3]*x + conic[4]*y + conic[5]
2100  max_pivot - [out] (can be null)
2101  min_pivot - [out] (can be null)
2102  zero_pivot - [out] (can be null)
2103  If there are some near duplicates in the input point set,
2104  the calculation is not stable. If you want to get an
2105  estimate of the validity of the solution, then inspect
2106  the returned values. max_pivot should around 1,
2107  min_pivot should be > 1e-4 or so, and zero_pivot should
2108  be < 1e-10 or so. If the returned pivots don't satisify
2109  these condtions, then exercise caution when using the
2110  returned solution.
2111 Returns:
2112  True if a there is an ellipse, parabola or hyperbola through the
2113  six points.
2114  False if the input is invalid or the conic degenerate (the
2115  points lie on one or two lines).
2116  If false is returned, then conic[0]=...=conic[5] = 0 and
2117  *min_pivot = *max_pivot = *zero_pivot = 0.
2118 */
2119 ON_DECL bool ON_GetConicEquationThrough6Points(
2120  int stride,
2121  const double* points2d,
2122  double conic[6],
2123  double* max_pivot,
2124  double* min_pivot,
2125  double* zero_pivot
2126  );
2127 
2128 /*
2129 Description:
2130  Test a conic equation to see if it defines and ellipse. If so,
2131  return the center and axes of the ellipse.
2132 Parameters:
2133  conic - [in]
2134  Coefficients of the conic equation.
2135  The points on the conic satisfy the equation
2136  0 = conic[0]*x^2 + conic[1]*xy + conic[2]*y^2
2137  + conic[3]*x + conic[4]*y + conic[5]
2138  center - [out]
2139  major_axis - [out]
2140  minor_axis - [out]
2141  major_radius - [out]
2142  minor_radius - [out]
2143 Returns:
2144  True if the conic is an ellipse and the center and axes were found.
2145  False if the conic is not an ellipse, in which case the input values
2146  of center, major_axis, minor_axis, major_radius, and minor_radius
2147  are not changed.
2148 */
2149 ON_DECL bool ON_IsConicEquationAnEllipse(
2150  const double conic[6],
2151  ON_2dPoint& center,
2152  ON_2dVector& major_axis,
2153  ON_2dVector& minor_axis,
2154  double* major_radius,
2155  double* minor_radius
2156  );
2157 
2158 /*
2159 Description:
2160  Get the conic equation of an ellipse.
2161 Parameters:
2162  a - [in] (a>0)
2163  b - [in] (b>0)
2164  a and b are the lengths of the axes. Either one
2165  may be largest and they can be equal.
2166  x0 - [in]
2167  y0 - [in]
2168  (x0,y0) is the enter of the ellipse.
2169  alpha - [in] (angle in radians)
2170  When alpha is 0, a corresponds to the x-axis and
2171  b corresponds to the y axis. If alpha is non-zero
2172  it specifies the rotation of these axes.
2173  conic - [out]
2174  Coefficients of the conic equation.
2175  The points on the conic satisfy the equation
2176  0 = conic[0]*x^2 + conic[1]*xy + conic[2]*y^2
2177  + conic[3]*x + conic[4]*y + conic[5]
2178  center - [out]
2179  major_axis - [out]
2180  minor_axis - [out]
2181  major_radius - [out]
2182  minor_radius - [out]
2183 Remarks:
2184  Here is the way to evaluate a point on the ellipse:
2185 
2186 
2187  double t = ellipse paramter in radians;
2188  double x = a*cos(t);
2189  double y = b*sin(t);
2190  ON_2dPoint ellipse_point;
2191  ellipse_point.x = x0 + x*cos(alpha) + y*sin(alpha);
2192  ellipse_point.y = y0 - x*sin(alpha) + y*cos(alpha);
2193 
2194 Returns:
2195  True if the input is valid and conic[] was filled in.
2196  Falis if the input is not valid. In this case the values in conic[]
2197  are not changed.
2198 */
2199 ON_DECL bool ON_GetEllipseConicEquation(
2200  double a, double b,
2201  double x0, double y0,
2202  double alpha,
2203  double conic[6]
2204  );
2205 
2206 /*
2207 Descripton:
2208  Return the length of a 2d vector (x,y)
2209 Returns:
2210  sqrt(x^2 + y^2) calculated in as precisely and safely as possible.
2211 */
2212 ON_DECL double ON_Length2d( double x, double y );
2213 
2214 /*
2215 Descripton:
2216  Return the length of a 3d vector (x,y,z)
2217 Returns:
2218  sqrt(x^2 + y^2 + z^2) calculated in as precisely and safely as possible.
2219 */
2220 ON_DECL double ON_Length3d( double x, double y, double z );
2221 
2222 
2223 /*
2224 Description:
2225  Get the area of a 3d triangle.
2226 Parameters:
2227  A - [in]
2228  B - [in]
2229  C - [in]
2230  Triangle corners
2231 Returns:
2232  Area of a 3d triangle with corners at A, B, C.
2233 */
2234 ON_DECL
2235 double ON_TriangleArea3d(
2236  ON_3dPoint A,
2237  ON_3dPoint B,
2238  ON_3dPoint C
2239  );
2240 
2241 /*
2242 Description:
2243  Get the area of a 2d triangle.
2244 Parameters:
2245  A - [in]
2246  B - [in]
2247  C - [in]
2248  Triangle corners
2249 Returns:
2250  Area of a 2d triangle with corners at A, B, C.
2251 */
2252 ON_DECL
2253 double ON_TriangleArea2d(
2254  ON_2dPoint A,
2255  ON_2dPoint B,
2256  ON_2dPoint C
2257  );
2258 
2259 
2260 /*
2261 Description:
2262  Convert a double x to the largest float f such that
2263  the mathematical value of f is at most the value of x.
2264 Parameters:
2265  x - [in]
2266 Returns
2267  The largest float f such that the mathematical value
2268  of f is at most the value of x.
2269 */
2270 ON_DECL float ON_FloatFloor(double x);
2271 
2272 /*
2273 Description:
2274  Convert a double x to the smallest float f such that
2275  the mathematical value of f is at least the value of x.
2276 Parameters:
2277  x - [in]
2278 Returns
2279  The smallest float f such that the mathematical value
2280  of f is at least the value of x.
2281 */
2282 ON_DECL float ON_FloatCeil(double x);
2283 
2284 #endif
Class for carefully adding long list of numbers.
Definition: opennurbs_math.h:29
An ON_Arc is a subcurve of 3d circle.
Definition: opennurbs_arc.h:33
ON_Cylinder is a right circular cylinder.
Definition: opennurbs_cylinder.h:27
Definition: opennurbs_fpoint.h:211
ON_Circle is a circle in 3d. The cirle is represented by a radius and an orthonormal frame of the pla...
Definition: opennurbs_circle.h:32
Definition: opennurbs_point.h:277
Definition: opennurbs_bounding_box.h:25
Definition: opennurbs_xform.h:28
Abstract function with an arbitrary number of parameters and values. ON_Evaluator is used to pass fun...
Definition: opennurbs_math.h:130
Definition: opennurbs_line.h:20
Definition: opennurbs_fpoint.h:38
Definition: opennurbs_point.h:460
Definition: opennurbs_plane.h:20
Typically the vector portion is a unit vector and m_d = -(x*P.x + y*P.y + z*P.z) for a point P on the...
Definition: opennurbs_point.h:1433
Definition: opennurbs_point.h:839
Definition: opennurbs_point.h:1152
Definition: opennurbs_point.h:46
Definition: opennurbs_sphere.h:22