#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#if defined(_WIN32) && !defined(__MINGW32__)
#include "config-msvc.h"
#else
#include "config.h"
#endif
#ifdef ENABLE_GCP
#include "grass_crs.h"
static int calccoef (struct Control_Points *, double *, double *, int);
static int calcls (struct Control_Points *, struct MATRIX *, double *,
double *, double *, double *);
static int exactdet (struct Control_Points *, struct MATRIX *, double *,
double *, double *, double *);
static int solvemat (struct MATRIX *, double *, double *, double *, double *);
static double term (int, double, double);
GCP_PRIVATE int
gcp_I_georef (double e1,
double n1,
double *e,
double *n,
double E[],
double N[],
int order
)
{
double e3, e2n, en2, n3, e2, en, n2;
switch (order)
{
case 1:
*e = E[0] + E[1] * e1 + E[2] * n1;
*n = N[0] + N[1] * e1 + N[2] * n1;
break;
case 2:
e2 = e1 * e1;
n2 = n1 * n1;
en = e1 * n1;
*e = E[0] + E[1] * e1 + E[2] * n1 + E[3] * e2 + E[4] * en + E[5] * n2;
*n = N[0] + N[1] * e1 + N[2] * n1 + N[3] * e2 + N[4] * en + N[5] * n2;
break;
case 3:
e2 = e1 * e1;
en = e1 * n1;
n2 = n1 * n1;
e3 = e1 * e2;
e2n = e2 * n1;
en2 = e1 * n2;
n3 = n1 * n2;
*e = E[0] +
E[1] * e1 + E[2] * n1 +
E[3] * e2 + E[4] * en + E[5] * n2 +
E[6] * e3 + E[7] * e2n + E[8] * en2 + E[9] * n3;
*n = N[0] +
N[1] * e1 + N[2] * n1 +
N[3] * e2 + N[4] * en + N[5] * n2 +
N[6] * e3 + N[7] * e2n + N[8] * en2 + N[9] * n3;
break;
default:
return MPARMERR;
}
return MSUCCESS;
}
GCP_PRIVATE int
gcp_I_compute_georef_equations (struct Control_Points *cp, double E12[],
double N12[], double E21[], double N21[],
int order)
{
double *tempptr;
int status;
if (order < 1 || order > MAXORDER)
return MPARMERR;
status = calccoef (cp, E12, N12, order);
if (status != MSUCCESS)
return status;
tempptr = cp->e1;
cp->e1 = cp->e2;
cp->e2 = tempptr;
tempptr = cp->n1;
cp->n1 = cp->n2;
cp->n2 = tempptr;
status = calccoef (cp, E21, N21, order);
tempptr = cp->e1;
cp->e1 = cp->e2;
cp->e2 = tempptr;
tempptr = cp->n1;
cp->n1 = cp->n2;
cp->n2 = tempptr;
return status;
}
static int
calccoef (struct Control_Points *cp, double E[], double N[], int order)
{
struct MATRIX m;
double *a;
double *b;
int numactive;
int status, i;
for (i = numactive = 0; i < cp->count; i++)
{
if (cp->status[i] > 0)
numactive++;
}
m.n = ((order + 1) * (order + 2)) / 2;
if (numactive < m.n)
return MNPTERR;
m.v = calloc (m.n * m.n, sizeof (double));
a = calloc (m.n, sizeof (double));
b = calloc (m.n, sizeof (double));
if (numactive == m.n)
status = exactdet (cp, &m, a, b, E, N);
else
status = calcls (cp, &m, a, b, E, N);
free (m.v);
free (a);
free (b);
return status;
}
static int
exactdet (struct Control_Points *cp, struct MATRIX *m, double a[], double b[], double E[],
double N[]
)
{
int pntnow, currow, j;
currow = 1;
for (pntnow = 0; pntnow < cp->count; pntnow++)
{
if (cp->status[pntnow] > 0)
{
for (j = 1; j <= m->n; j++)
M (currow, j) = term (j, cp->e1[pntnow], cp->n1[pntnow]);
a[currow - 1] = cp->e2[pntnow];
b[currow - 1] = cp->n2[pntnow];
currow++;
}
}
if (currow - 1 != m->n)
return MINTERR;
return solvemat (m, a, b, E, N);
}
static int
calcls (struct Control_Points *cp, struct MATRIX *m, double a[], double b[], double E[],
double N[]
)
{
int i, j, n, numactive = 0;
for (i = 1; i <= m->n; i++)
{
for (j = i; j <= m->n; j++)
M (i, j) = 0.0;
a[i - 1] = b[i - 1] = 0.0;
}
for (n = 0; n < cp->count; n++)
{
if (cp->status[n] > 0)
{
numactive++;
for (i = 1; i <= m->n; i++)
{
for (j = i; j <= m->n; j++)
M (i, j) +=
term (i, cp->e1[n], cp->n1[n]) * term (j,
cp->e1[n],
cp->n1[n]);
a[i - 1] += cp->e2[n] * term (i, cp->e1[n], cp->n1[n]);
b[i - 1] += cp->n2[n] * term (i, cp->e1[n], cp->n1[n]);
}
}
}
if (numactive <= m->n)
return MINTERR;
for (i = 2; i <= m->n; i++)
for (j = 1; j < i; j++)
M (i, j) = M (j, i);
return solvemat (m, a, b, E, N);
}
static double
term (int term, double e, double n)
{
switch (term)
{
case 1:
return 1.0;
case 2:
return e;
case 3:
return n;
case 4:
return e * e;
case 5:
return e * n;
case 6:
return n * n;
case 7:
return e * e * e;
case 8:
return e * e * n;
case 9:
return e * n * n;
case 10:
return n * n * n;
}
return 0.0;
}
static int
solvemat (struct MATRIX *m, double a[], double b[], double E[], double N[])
{
int i, j, i2, j2, imark;
double factor, temp;
double pivot;
for (i = 1; i <= m->n; i++)
{
j = i;
pivot = M (i, j);
imark = i;
for (i2 = i + 1; i2 <= m->n; i2++)
{
temp = fabs (M (i2, j));
if (temp > fabs (pivot))
{
pivot = M (i2, j);
imark = i2;
}
}
if (pivot == 0.0)
return MUNSOLVABLE;
if (imark != i)
{
for (j2 = 1; j2 <= m->n; j2++)
{
temp = M (imark, j2);
M (imark, j2) = M (i, j2);
M (i, j2) = temp;
}
temp = a[imark - 1];
a[imark - 1] = a[i - 1];
a[i - 1] = temp;
temp = b[imark - 1];
b[imark - 1] = b[i - 1];
b[i - 1] = temp;
}
for (i2 = 1; i2 <= m->n; i2++)
{
if (i2 != i)
{
factor = M (i2, j) / pivot;
for (j2 = j; j2 <= m->n; j2++)
M (i2, j2) -= factor * M (i, j2);
a[i2 - 1] -= factor * a[i - 1];
b[i2 - 1] -= factor * b[i - 1];
}
}
}
for (i = 1; i <= m->n; i++)
{
E[i - 1] = a[i - 1] / M (i, i);
N[i - 1] = b[i - 1] / M (i, i);
}
return MSUCCESS;
}
#endif