DYT/Tool/3rdParty_x64/include/dcmtk/dcmimgle/dicrvfit.h
2024-11-22 23:19:31 +08:00

326 lines
10 KiB
C++

/*
*
* Copyright (C) 1996-2016, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* OFFIS e.V.
* R&D Division Health
* Escherweg 2
* D-26121 Oldenburg, Germany
*
*
* Module: dcmimgle
*
* Author: Joerg Riesmeier
*
* Purpose: DiCurveFitting (header/implementation)
*
*/
#ifndef DICRVFIT_H
#define DICRVFIT_H
#include "dcmtk/config/osconfig.h"
#include "dcmtk/ofstd/oftypes.h"
#include "dcmtk/ofstd/ofcast.h"
#define INCLUDE_CMATH
#define INCLUDE_CSTDDEF /* For NULL */
#include "dcmtk/ofstd/ofstdinc.h"
/*---------------------*
* macro definitions *
*---------------------*/
// SunCC 4.x does not support default values for template types :-/
#define T3_ double
/*------------------*
* template class *
*------------------*/
/** Template class for polynomial curve fitting algorithm
*/
template <class T1, class T2 /*, class T3 = double*/>
class DiCurveFitting
{
public:
/** calculate coefficients for resulting polynomial function.
* T1 = type of x coordinates
* T2 = type of y coordinates
* T3_ = type of coefficients (and for internal calculations)
*
** @param x array with x coordinates of given points
* @param y array with y coordinates of given points
* @param n number of entries in array (= points)
* @param o order of polynomial function
* @param c array to store the resulting coefficients (o+1 entries !)
*
** @return true if successful, false otherwise
*/
static int calculateCoefficients(const T1 *x,
const T2 *y,
const unsigned int n,
const unsigned int o,
T3_ *c)
{
int result = 0;
if ((x != NULL) && (y != NULL) && (c !=NULL) && (n > 0))
{
const unsigned int order = o + 1;
const unsigned int order2 = order * order;
T3_ *basis = new T3_[order * n];
T3_ *alpha = new T3_[order2];
T3_ *beta = new T3_[order];
if ((basis != NULL) && (alpha != NULL) && (beta != NULL))
{
unsigned int i;
unsigned int j;
unsigned int k;
for (i = 0; i < order; ++i)
{
for (j = 0; j < n; ++j)
{
k = i + j * order;
if (i == 0)
basis[k] = 1;
else
basis[k] = OFstatic_cast(T3_, x[j]) * basis[k - 1];
}
}
T3_ sum;
for (i = 0; i < order; ++i)
{
const unsigned int i_order = i * order;
for (j = 0; j <= i; ++j)
{
sum = 0;
for (k = 0; k < n; ++k)
sum += basis[i + k * order] * basis[j + k * order];
alpha[i + j * order] = sum;
if (i != j)
alpha[j + i_order] = sum;
}
}
for (i = 0; i < order; ++i)
{
sum = 0;
for (j = 0; j < n; ++j)
sum += OFstatic_cast(T3_, y[j]) * basis[i + j * order];
beta[i] = sum;
}
if (solve(alpha, beta, order))
{
for (i = 0; i < order; ++i)
c[i] = beta[i];
result = 1;
}
}
delete[] basis;
delete[] alpha;
delete[] beta;
}
return result;
}
/** calculate y coordinates for the given range of x coordinates.
* The polynomial function is defined by the specified coefficients.
* T1 = type of x coordinates
* T2 = type of y coordinates
* T3_ = type of coefficients (and for internal calculations)
*
** @param xs first x coordinate for computation
* @param xe last x coordinate for computation
* @param y array to store the resulting y coordinates (n entries !)
* @param n number of entries in array (= points)
* @param o order of polynomial function
* @param c array of coefficients computed by the above method (o+1 entries !)
*
** @return true if successful, false otherwise
*/
static int calculateValues(const T1 xs,
const T1 xe,
T2 *y,
const unsigned int n,
const unsigned int o,
const T3_ *c)
{
int result = 0;
if ((y != NULL) && (c != NULL) && (n > 0) && (xe > xs))
{
unsigned int i;
unsigned int j;
T3_ x;
T3_ x2;
T3_ w;
const T3_ xo = OFstatic_cast(T3_, xs);
const T3_ xi = OFstatic_cast(T3_, (OFstatic_cast(T3_, xe) - OFstatic_cast(T3_, xs)) / (n - 1));
for (i = 0; i < n; ++i)
{
x = xo + OFstatic_cast(T3_, i) * xi;
x2 = 1;
w = 0;
for (j = 0; j <= o; ++j)
{
w += c[j] * x2;
x2 *= x;
}
convertValue(w, y[i]); // cut value if necessary
}
result = 1;
}
return result;
}
private:
/** helper routine: convert to unsigned 8 bit value
*
** @param input input value to be converted
* @param output output value (range: 0..255)
*
** @return output value
*/
static void convertValue(const T3_ input, Uint8 &output)
{
output = (input <= 0) ? 0 : ((input >= 255) ? 255 : OFstatic_cast(Uint8, input));
}
/** helper routine: convert to signed 8 bit value
*
** @param input input value to be converted
* @param output output value (range: -128..127)
*
** @return output value
*/
static void convertValue(const T3_ input, Sint8 &output)
{
output = (input <= -128) ? -128 : ((input >= 127) ? 127 : OFstatic_cast(Sint8, input));
}
/** helper routine: convert to unsigned 16 bit value
*
** @param input input value to be converted
* @param output output value (range: 0..65535)
*
** @return output value
*/
static void convertValue(const T3_ input, Uint16 &output)
{
output = (input <= 0) ? 0 : ((input >= 65535) ? 65535 : OFstatic_cast(Uint16, input));
}
/** helper routine: convert to signed 16 bit value
*
** @param input input value to be converted
* @param output output value (range: -32768..32767)
*
** @return output value
*/
static void convertValue(const T3_ input, Sint16 &output)
{
output = (input <= -32768) ? -32768 : ((input >= 32767) ? 32767 : OFstatic_cast(Sint16, input));
}
/** helper routine: convert to floating point value (double precision)
*
** @param input input value to be converted
* @param output output value (double)
*
** @return output value
*/
static inline void convertValue(const T3_ input, double &output)
{
output = OFstatic_cast(double, input);
}
/** solve the equation given by the two matrixes.
* T3_ = type of coefficients (and for internal calculations)
*
** @param a first matrix (array of values)
* @param b second matrix (array of values)
* @param n number of entries in array
*
** @return true if successful, false otherwise
*/
static int solve(T3_ *a,
T3_ *b,
const unsigned int n)
{
int result = 0;
if ((a != NULL) && (b != NULL) && (n > 0))
{
unsigned int i;
unsigned int j;
unsigned int k;
signed int pivot;
T3_ mag;
T3_ mag2;
T3_ temp;
for (i = 0; i < n; ++i)
{
mag = 0;
pivot = -1;
for (j = i; j < n; ++j)
{
mag2 = fabs(a[i + j * n]);
if (mag2 > mag)
{
mag = mag2;
pivot = j;
}
}
if ((pivot == -1) || (mag == 0))
break;
else
{
const unsigned int piv = OFstatic_cast(unsigned int, pivot);
const unsigned int i_n = i * n;
if (piv != i)
{
const unsigned int piv_n = piv * n;
for (j = i; j < n; ++j)
{
temp = a[j + i_n];
a[j + i_n] = a[j + piv_n];
a[j + piv_n] = temp;
}
temp = b[i];
b[i] = b[piv];
b[piv] = temp;
}
mag = a[i + i_n];
for (j = i; j < n; ++j)
a[j + i_n] /= mag;
b[i] /= mag;
for (j = 0; j < n; ++j)
{
if (i == j)
continue;
const unsigned int j_n = j * n;
mag2 = a[i + j_n];
for (k = i; k < n; ++k)
a[k + j_n] -= mag2 * a[k + i_n];
b[j] -= mag2 * b[i];
}
result = 1;
}
}
}
return result;
}
};
#endif