#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.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_3D *, double *, double *, double *,
int);
static int calcls (struct Control_Points_3D *, struct MATRIX *, double *,
double *, double *, double *, double *, double *);
static int exactdet (struct Control_Points_3D *, struct MATRIX *, double *,
double *, double *, double *, double *, double *);
static int solvemat (struct MATRIX *, double *, double *, double *, double *,
double *, double *);
static double term (int, double, double, double);
GCP_PRIVATE int
gcp_CRS_georef_3d (double e1,
double n1,
double z1,
double *e,
double *n,
double *z,
double E[],
double N[],
double Z[],
int order
)
{
double e2, n2, z2, en, ez, nz,
e3, n3, z3, e2n, e2z, en2, ez2, n2z, nz2, enz;
switch (order)
{
case 1:
*e = E[0] + E[1] * e1 + E[2] * n1 + E[3] * z1;
*n = N[0] + N[1] * e1 + N[2] * n1 + N[3] * z1;
*z = Z[0] + Z[1] * e1 + Z[2] * n1 + Z[3] * z1;
break;
case 2:
e2 = e1 * e1;
en = e1 * n1;
ez = e1 * z1;
n2 = n1 * n1;
nz = n1 * z1;
z2 = z1 * z1;
*e = E[0] + E[1] * e1 + E[2] * n1 + E[3] * z1 +
E[4] * e2 + E[5] * en + E[6] * ez + E[7] * n2 + E[8] * nz +
E[9] * z2;
*n = N[0] + N[1] * e1 + N[2] * n1 + N[3] * z1 + N[4] * e2 +
N[5] * en + N[6] * ez + N[7] * n2 + N[8] * nz + N[9] * z2;
*z = Z[0] + Z[1] * e1 + Z[2] * n1 + Z[3] * z1 + Z[4] * e2 +
Z[5] * en + Z[6] * ez + Z[7] * n2 + Z[8] * nz + Z[9] * z2;
break;
case 3:
e2 = e1 * e1;
en = e1 * n1;
ez = e1 * z1;
n2 = n1 * n1;
nz = n1 * z1;
z2 = z1 * z1;
e3 = e1 * e2;
e2n = e2 * n1;
e2z = e2 * z1;
en2 = e1 * n2;
enz = e1 * n1 * z1;
ez2 = e1 * z2;
n3 = n1 * n2;
n2z = n2 * z1;
nz2 = n1 * z2;
z3 = z1 * z2;
*e = E[0] + E[1] * e1 + E[2] * n1 + E[3] * z1 +
E[4] * e2 + E[5] * en + E[6] * ez + E[7] * n2 + E[8] * nz +
E[9] * z2 + E[10] * e3 + E[11] * e2n + E[12] * e2z + E[13] * en2 +
E[14] * enz + E[15] * ez2 + E[16] * n3 + E[17] * n2z +
E[18] * nz2 + E[19] * z3;
*n = N[0] + N[1] * e1 + N[2] * n1 + N[3] * z1 + N[4] * e2 +
N[5] * en + N[6] * ez + N[7] * n2 + N[8] * nz + N[9] * z2 +
N[10] * e3 + N[11] * e2n + N[12] * e2z + N[13] * en2 +
N[14] * enz + N[15] * ez2 + N[16] * n3 + N[17] * n2z +
N[18] * nz2 + N[19] * z3;
*z = Z[0] + Z[1] * e1 + Z[2] * n1 + Z[3] * z1 + Z[4] * e2 +
Z[5] * en + Z[6] * ez + Z[7] * n2 + Z[8] * nz + Z[9] * z2 +
Z[10] * e3 + Z[11] * e2n + Z[12] * e2z + Z[13] * en2 +
Z[14] * enz + Z[15] * ez2 + Z[16] * n3 + Z[17] * n2z +
Z[18] * nz2 + Z[19] * z3;
break;
default:
return MPARMERR;
}
return MSUCCESS;
}
GCP_PRIVATE int
gcp_CRS_compute_georef_equations_3d (struct Control_Points_3D *cp,
double E12[], double N12[], double Z12[],
double E21[], double N21[], double Z21[],
int order)
{
double *tempptr;
int status;
if (order < 1 || order > MAXORDER)
return MPARMERR;
status = calccoef (cp, E12, N12, Z12, 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;
tempptr = cp->z1;
cp->z1 = cp->z2;
cp->z2 = tempptr;
status = calccoef (cp, E21, N21, Z21, order);
tempptr = cp->e1;
cp->e1 = cp->e2;
cp->e2 = tempptr;
tempptr = cp->n1;
cp->n1 = cp->n2;
cp->n2 = tempptr;
tempptr = cp->z1;
cp->z1 = cp->z2;
cp->z2 = tempptr;
return status;
}
static int
calccoef (struct Control_Points_3D *cp,
double E[], double N[], double Z[], int order)
{
struct MATRIX m;
double *a;
double *b;
double *c;
int numactive;
int status, i;
for (i = numactive = 0; i < cp->count; i++)
{
if (cp->status[i] > 0)
numactive++;
}
m.n = numactive + 1;
if (order == 1)
m.n = 4;
else if (order == 2)
m.n = 10;
else if (order == 3)
m.n = 20;
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));
c = calloc (m.n, sizeof (double));
if (numactive == m.n)
status = exactdet (cp, &m, a, b, c, E, N, Z);
else
status = calcls (cp, &m, a, b, c, E, N, Z);
free (m.v);
free (a);
free (b);
free (c);
return status;
}
static int
exactdet (struct Control_Points_3D *cp, struct MATRIX *m, double a[], double b[], double c[], double E[],
double N[],
double Z[]
)
{
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],
cp->z1[pntnow]);
a[currow - 1] = cp->e2[pntnow];
b[currow - 1] = cp->n2[pntnow];
c[currow - 1] = cp->z2[pntnow];
currow++;
}
}
if (currow - 1 != m->n)
return MINTERR;
return solvemat (m, a, b, c, E, N, Z);
}
static int
calcls (struct Control_Points_3D *cp, struct MATRIX *m, double a[], double b[], double c[], double E[],
double N[],
double Z[]
)
{
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] = c[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],
cp->z1[n]) * term (j, cp->e1[n], cp->n1[n],
cp->z1[n]);
a[i - 1] +=
cp->e2[n] * term (i, cp->e1[n], cp->n1[n], cp->z1[n]);
b[i - 1] +=
cp->n2[n] * term (i, cp->e1[n], cp->n1[n], cp->z1[n]);
c[i - 1] +=
cp->z2[n] * term (i, cp->e1[n], cp->n1[n], cp->z1[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, c, E, N, Z);
}
static double
term (int term, double e, double n, double z)
{
switch (term)
{
case 1:
return 1.0;
case 2:
return e;
case 3:
return n;
case 4:
return z;
case 5:
return e * e;
case 6:
return e * n;
case 7:
return e * z;
case 8:
return n * n;
case 9:
return n * z;
case 10:
return z * z;
case 11:
return e * e * e;
case 12:
return e * e * n;
case 13:
return e * e * z;
case 14:
return e * n * n;
case 15:
return e * n * z;
case 16:
return e * z * z;
case 17:
return n * n * n;
case 18:
return n * n * z;
case 19:
return n * z * z;
case 20:
return z * z * z;
}
return 0.0;
}
static int
solvemat (struct MATRIX *m, double a[], double b[], double c[],
double E[], double N[], double Z[])
{
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 (fabs (pivot) < GRASS_EPSILON)
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;
temp = c[imark - 1];
c[imark - 1] = c[i - 1];
c[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];
c[i2 - 1] -= factor * c[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);
Z[i - 1] = c[i - 1] / M (i, i);
}
return MSUCCESS;
}
#endif