PageRenderTime 62ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/v5_2_1_rc2/lib/csa/csa.c

#
C | 1817 lines | 1408 code | 259 blank | 150 comment | 373 complexity | 675e1382e18e558b6900a18294229ba3 MD5 | raw file
Possible License(s): LGPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, Apache-2.0, GPL-2.0
  1. /******************************************************************************
  2. *
  3. * File: csa.c
  4. *
  5. * Created: 16/10/2002
  6. *
  7. * Author: Pavel Sakov
  8. * CSIRO Marine Research
  9. *
  10. * Purpose: 2D data approximation with bivariate cubic spline.
  11. * A set of library functions + standalone utility.
  12. *
  13. * Description: See J. Haber, F. Zeilfelder, O.Davydov and H.-P. Seidel,
  14. * Smooth approximation and rendering of large scattered data
  15. * sets, in ``Proceedings of IEEE Visualization 2001''
  16. * (Th.Ertl, K.Joy and A.Varshney, Eds.), pp.341-347, 571,
  17. * IEEE Computer Society, 2001.
  18. * http://www.uni-giessen.de/www-Numerische-Mathematik/
  19. * davydov/VIS2001.ps.gz
  20. * http://www.math.uni-mannheim.de/~lsmath4/paper/
  21. * VIS2001.pdf.gz
  22. *
  23. * Revisions: None
  24. *
  25. *****************************************************************************/
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <stdarg.h>
  29. #include <limits.h>
  30. #include <float.h>
  31. #include <math.h>
  32. #include <assert.h>
  33. #include <string.h>
  34. #include "version.h"
  35. #include "csa_internal.h"
  36. #include "nan.h"
  37. #define NPASTART 5 /* Number of Points Allocated at Start */
  38. /* default algorithm parameters */
  39. #define NMIN_DEF 3
  40. #define NMAX_DEF 40
  41. #define K_DEF 140
  42. extern int errno;
  43. int csa_verbose = 0;
  44. static void csa_quit(char* format, ...)
  45. {
  46. va_list args;
  47. fflush(stdout); /* just in case -- to have the exit message
  48. * last */
  49. fprintf(stderr, "error: csa: ");
  50. va_start(args, format);
  51. vfprintf(stderr, format, args);
  52. va_end(args);
  53. exit(1);
  54. }
  55. static double** dalloc2d(int n1, int n2)
  56. {
  57. unsigned int size;
  58. double* p;
  59. double** pp;
  60. int i;
  61. assert(n1 > 0);
  62. assert(n2 > 0);
  63. size = n1 * n2;
  64. assert(size <= UINT_MAX);
  65. if ((p = calloc(size, sizeof(double))) == NULL)
  66. csa_quit("dalloc2d(): %s\n", strerror(errno));
  67. size = n2 * sizeof(double*);
  68. if ((pp = malloc(size)) == NULL)
  69. csa_quit("dalloc2d(): %s\n", strerror(errno));
  70. for (i = 0; i < n2; i++)
  71. pp[i] = p + i * n1;
  72. return pp;
  73. }
  74. static void dfree2d(double** pp)
  75. {
  76. double* p;
  77. p = pp[0];
  78. assert(pp != NULL);
  79. free(pp);
  80. assert(p != NULL);
  81. free(p);
  82. }
  83. static void*** palloc2d(int n1, int n2)
  84. {
  85. unsigned int size;
  86. void** p;
  87. void*** pp;
  88. int i;
  89. assert(n1 > 0);
  90. assert(n2 > 0);
  91. size = n1 * n2;
  92. assert(size <= UINT_MAX);
  93. if ((p = calloc(size, sizeof(void*))) == NULL)
  94. csa_quit("palloc2d(): %s\n", strerror(errno));
  95. size = n2 * sizeof(void*);
  96. if ((pp = malloc(size)) == NULL)
  97. csa_quit("palloc2d(): %s\n", strerror(errno));
  98. for (i = 0; i < n2; ++i, p += n1)
  99. pp[i] = p;
  100. return pp;
  101. }
  102. static void pfree2d(void*** pp)
  103. {
  104. void** p;
  105. p = pp[0];
  106. assert(pp != NULL);
  107. free(pp);
  108. assert(p != NULL);
  109. free(p);
  110. }
  111. static triangle* triangle_create(square* s, point vertices[], int index)
  112. {
  113. triangle* t = malloc(sizeof(triangle));
  114. t->parent = s;
  115. memcpy(t->vertices, vertices, sizeof(point) * 3);
  116. t->middle.x = (vertices[0].x + vertices[1].x + vertices[2].x) / 3.0;
  117. t->middle.y = (vertices[0].y + vertices[1].y + vertices[2].y) / 3.0;
  118. t->h = s->parent->h;
  119. t->index = index;
  120. t->r = 0.0;
  121. t->points = 0;
  122. t->nallocated = 0;
  123. t->npoints = 0;
  124. t->hascoeffs = 0;
  125. t->primary = 0;
  126. t->order = -1;
  127. return t;
  128. }
  129. static void triangle_addpoint(triangle* t, point* p)
  130. {
  131. if (t->nallocated == t->npoints) {
  132. if (t->nallocated == 0) {
  133. t->points = malloc(NPASTART * sizeof(point*));
  134. t->nallocated = NPASTART;
  135. } else {
  136. t->points = realloc(t->points, t->nallocated * 2 * sizeof(point*));
  137. t->nallocated *= 2;
  138. }
  139. }
  140. t->points[t->npoints] = p;
  141. t->npoints++;
  142. }
  143. static void triangle_destroy(triangle* t)
  144. {
  145. if (t->points != NULL)
  146. free(t->points);
  147. free(t);
  148. }
  149. /* Calculates barycentric coordinates of a point.
  150. * Takes into account that possible triangles are rectangular, with the right
  151. * angle at t->vertices[0], the vertices[1] vertex being in
  152. * (-3*PI/4) + (PI/2) * t->index direction from vertices[0], and
  153. * vertices[2] being at (-5*PI/4) + (PI/2) * t->index.
  154. */
  155. static void triangle_calculatebc(triangle* t, point* p, double bc[])
  156. {
  157. double dx = p->x - t->vertices[0].x;
  158. double dy = p->y - t->vertices[0].y;
  159. if (t->index == 0) {
  160. bc[1] = (dy - dx) / t->h;
  161. bc[2] = -(dx + dy) / t->h;
  162. } else if (t->index == 1) {
  163. bc[1] = (dx + dy) / t->h;
  164. bc[2] = (dy - dx) / t->h;
  165. } else if (t->index == 2) {
  166. bc[1] = (dx - dy) / t->h;
  167. bc[2] = (dx + dy) / t->h;
  168. } else {
  169. bc[1] = -(dx + dy) / t->h;
  170. bc[2] = (dx - dy) / t->h;
  171. }
  172. bc[0] = 1.0 - bc[1] - bc[2];
  173. }
  174. static square* square_create(csa* parent, double xmin, double ymin, int i, int j)
  175. {
  176. int ii;
  177. square* s = malloc(sizeof(square));
  178. double h = parent->h;
  179. s->parent = parent;
  180. s->i = i;
  181. s->j = j;
  182. s->points = NULL;
  183. s->nallocated = 0;
  184. s->npoints = 0;
  185. s->primary = 0;
  186. for (ii = 0; ii < 4; ++ii) {
  187. point vertices[3];
  188. vertices[0].x = xmin + h / 2.0;
  189. vertices[0].y = ymin + h / 2.0;
  190. vertices[1].x = xmin + h * (((ii + 1) % 4) / 2); /* 0 1 1 0 */
  191. vertices[1].y = ymin + h * (((ii + 2) % 4) / 2); /* 1 1 0 0 */
  192. vertices[2].x = xmin + h * (ii / 2); /* 0 0 1 1 */
  193. vertices[2].y = ymin + h * (((ii + 1) % 4) / 2); /* 0 1 1 0 */
  194. s->triangles[ii] = triangle_create(s, vertices, ii);
  195. }
  196. for (ii = 0; ii < 25; ++ii)
  197. s->coeffs[ii] = NaN;
  198. return s;
  199. }
  200. static void square_destroy(square* s)
  201. {
  202. int i;
  203. for (i = 0; i < 4; ++i)
  204. triangle_destroy(s->triangles[i]);
  205. if (s->points != NULL)
  206. free(s->points);
  207. free(s);
  208. }
  209. static void square_addpoint(square* s, point* p)
  210. {
  211. if (s->nallocated == s->npoints) {
  212. if (s->nallocated == 0) {
  213. s->points = malloc(NPASTART * sizeof(point*));
  214. s->nallocated = NPASTART;
  215. } else {
  216. s->points = realloc(s->points, s->nallocated * 2 * sizeof(point*));
  217. s->nallocated *= 2;
  218. }
  219. }
  220. s->points[s->npoints] = p;
  221. s->npoints++;
  222. }
  223. csa* csa_create()
  224. {
  225. csa* a = malloc(sizeof(csa));
  226. a->verbose = 0;
  227. a->xmin = DBL_MAX;
  228. a->xmax = -DBL_MAX;
  229. a->ymin = DBL_MAX;
  230. a->ymax = -DBL_MAX;
  231. a->points = malloc(NPASTART * sizeof(point*));
  232. a->nallocated = NPASTART;
  233. a->npoints = 0;
  234. a->ni = 0;
  235. a->nj = 0;
  236. a->h = NaN;
  237. a->squares = NULL;
  238. a->npt = 0;
  239. a->pt = NULL;
  240. a->nmin = NMIN_DEF;
  241. a->nmax = NMAX_DEF;
  242. a->k = K_DEF;
  243. return a;
  244. }
  245. void csa_destroy(csa* a)
  246. {
  247. int i, j;
  248. if (a->squares != NULL) {
  249. for (j = 0; j < a->nj; ++j)
  250. for (i = 0; i < a->ni; ++i)
  251. square_destroy(a->squares[j][i]);
  252. pfree2d((void***) a->squares);
  253. }
  254. if (a->pt != NULL)
  255. free(a->pt);
  256. if (a->points != NULL)
  257. free(a->points);
  258. free(a);
  259. }
  260. void csa_addpoints(csa* a, int n, point points[])
  261. {
  262. int na = a->nallocated;
  263. int i;
  264. assert(a->squares == NULL);
  265. /*
  266. * (can be called prior to squarization only)
  267. */
  268. while (na < a->npoints + n)
  269. na *= 2;
  270. if (na != a->nallocated) {
  271. a->points = realloc(a->points, na * sizeof(point*));
  272. a->nallocated = na;
  273. }
  274. for (i = 0; i < n; ++i) {
  275. point* p = &points[i];
  276. a->points[a->npoints] = p;
  277. a->npoints++;
  278. if (p->x < a->xmin)
  279. a->xmin = p->x;
  280. if (p->x > a->xmax)
  281. a->xmax = p->x;
  282. if (p->y < a->ymin)
  283. a->ymin = p->y;
  284. if (p->y > a->ymax)
  285. a->ymax = p->y;
  286. }
  287. }
  288. /* Marks the squares containing "primary" triangles by setting "primary" flag
  289. * to 1.
  290. */
  291. static void csa_setprimaryflag(csa* a)
  292. {
  293. square*** squares = a->squares;
  294. int nj1 = a->nj - 1;
  295. int ni1 = a->ni - 1;
  296. int i, j;
  297. for (j = 1; j < nj1; ++j) {
  298. for (i = 1; i < ni1; ++i) {
  299. if (squares[j][i]->npoints > 0) {
  300. if ((i + j) % 2 == 0) {
  301. squares[j][i]->primary = 1;
  302. squares[j - 1][i - 1]->primary = 1;
  303. squares[j + 1][i - 1]->primary = 1;
  304. squares[j - 1][i + 1]->primary = 1;
  305. squares[j + 1][i + 1]->primary = 1;
  306. } else {
  307. squares[j - 1][i]->primary = 1;
  308. squares[j + 1][i]->primary = 1;
  309. squares[j][i - 1]->primary = 1;
  310. squares[j][i + 1]->primary = 1;
  311. }
  312. }
  313. }
  314. }
  315. }
  316. /* Splits the data domain in a number of squares.
  317. */
  318. static void csa_squarize(csa* a, int n)
  319. {
  320. int nps[7] = { 0, 0, 0, 0, 0, 0 }; /* stats on number of points per
  321. * square */
  322. double dx = a->xmax - a->xmin;
  323. double dy = a->ymax - a->ymin;
  324. int npoints = a->npoints;
  325. double h;
  326. int i, j, ii, nadj;
  327. if (csa_verbose) {
  328. fprintf(stderr, "squarizing csa:\n");
  329. fflush(stderr);
  330. }
  331. assert(a->squares == NULL);
  332. /*
  333. * (can be done only once)
  334. */
  335. h = sqrt(dx * dy * n / npoints); /* square edge size */
  336. if (dx < h)
  337. h = dy * n / npoints;
  338. if (dy < h)
  339. h = dx * n / npoints;
  340. a->h = h;
  341. a->ni = ceil(dx / h) + 2;
  342. a->nj = ceil(dy / h) + 2;
  343. if (csa_verbose) {
  344. fprintf(stderr, " %d x %d squares\n", a->ni, a->nj);
  345. fflush(stderr);
  346. }
  347. /*
  348. * create squares
  349. */
  350. a->squares = (square***) palloc2d(a->ni, a->nj);
  351. for (j = 0; j < a->nj; ++j)
  352. for (i = 0; i < a->ni; ++i)
  353. a->squares[j][i] = square_create(a, a->xmin + h * (i - 1), a->ymin + h * (j - 1), i, j);
  354. /*
  355. * map points to squares
  356. */
  357. for (ii = 0; ii < npoints; ++ii) {
  358. point* p = a->points[ii];
  359. i = floor((p->x - a->xmin) / h) + 1;
  360. j = floor((p->y - a->ymin) / h) + 1;
  361. square_addpoint(a->squares[j][i], p);
  362. }
  363. /*
  364. * mark relevant squares with no points
  365. */
  366. csa_setprimaryflag(a);
  367. /*
  368. * Create a list of "primary" triangles, for which spline coefficients
  369. * will be calculated directy (by least squares method), without using
  370. * C1 smoothness condiftions.
  371. */
  372. a->pt = malloc((a->ni / 2 + 1) * a->nj * sizeof(triangle*));
  373. for (j = 0, ii = 0, nadj = 0; j < a->nj; ++j) {
  374. for (i = 0; i < a->ni; ++i) {
  375. square* s = a->squares[j][i];
  376. if (s->npoints > 0) {
  377. int nn = s->npoints / 5;
  378. if (nn > 6)
  379. nn = 6;
  380. nps[nn]++;
  381. ii++;
  382. }
  383. if (s->primary && s->npoints == 0)
  384. nadj++;
  385. if (s->primary) {
  386. a->pt[a->npt] = s->triangles[0];
  387. s->triangles[0]->primary = 1;
  388. a->npt++;
  389. }
  390. }
  391. }
  392. if (csa_verbose) {
  393. fprintf(stderr, " %d non-empty squares\n", ii);
  394. fprintf(stderr, " %d primary squares\n", a->npt);
  395. fprintf(stderr, " %d primary squares with no data\n", nadj);
  396. fprintf(stderr, " %.2f points per square \n", (double) a->npoints / ii);
  397. }
  398. if (csa_verbose == 2) {
  399. for (i = 0; i < 6; ++i)
  400. fprintf(stderr, " %d-%d points -- %d squares\n", i * 5, i * 5 + 4, nps[i]);
  401. fprintf(stderr, " %d or more points -- %d squares\n", i * 5, nps[i]);
  402. }
  403. if (csa_verbose == 2) {
  404. fprintf(stderr, " j\\i");
  405. for (i = 0; i < a->ni; ++i)
  406. fprintf(stderr, "%3d ", i);
  407. fprintf(stderr, "\n");
  408. for (j = a->nj - 1; j >= 0; --j) {
  409. fprintf(stderr, "%3d ", j);
  410. for (i = 0; i < a->ni; ++i) {
  411. square* s = a->squares[j][i];
  412. if (s->npoints > 0)
  413. fprintf(stderr, "%3d ", s->npoints);
  414. else
  415. fprintf(stderr, " . ");
  416. }
  417. fprintf(stderr, "\n");
  418. }
  419. }
  420. if (csa_verbose)
  421. fflush(stderr);
  422. }
  423. /* Returns all squares intersecting with a square with center in t->middle
  424. * and edges of length 2*t->r parallel to X and Y axes.
  425. */
  426. static void getsquares(csa* a, triangle* t, int* n, square*** squares)
  427. {
  428. int imin = floor((t->middle.x - t->r - a->xmin) / t->h);
  429. int imax = ceil((t->middle.x + t->r - a->xmin) / t->h);
  430. int jmin = floor((t->middle.y - t->r - a->ymin) / t->h);
  431. int jmax = ceil((t->middle.y + t->r - a->ymin) / t->h);
  432. int i, j;
  433. if (imin < 0)
  434. imin = 0;
  435. if (imax >= a->ni)
  436. imax = a->ni - 1;
  437. if (jmin < 0)
  438. jmin = 0;
  439. if (jmax >= a->nj)
  440. jmax = a->nj - 1;
  441. *n = 0;
  442. (*squares) = malloc((imax - imin + 1) * (jmax - jmin + 1) * sizeof(square*));
  443. for (j = jmin; j <= jmax; ++j) {
  444. for (i = imin; i <= imax; ++i) {
  445. square* s = a->squares[j][i];
  446. if (s->npoints > 0) {
  447. (*squares)[*n] = a->squares[j][i];
  448. (*n)++;
  449. }
  450. }
  451. }
  452. }
  453. static double distance(point* p1, point* p2)
  454. {
  455. return hypot(p1->x - p2->x, p1->y - p2->y);
  456. }
  457. /* Thins data by creating an auxiliary regular grid and for leaving only
  458. * the most central point within each grid cell.
  459. * (I follow the paper here. It is possible that taking average -- in terms of
  460. * both value and position -- of all points within a cell would be a bit more
  461. * robust.)
  462. */
  463. static void thindata(triangle* t, int nmax)
  464. {
  465. csa* a = t->parent->parent;
  466. int imax = ceil(sqrt((double) (nmax * 3 / 2)));
  467. square*** squares = (square***) palloc2d(imax, imax);
  468. double h = t->r * 2.0 / imax;
  469. double h2 = h / 2.0;
  470. double xmin = t->middle.x - t->r;
  471. double ymin = t->middle.y - t->r;
  472. int i, j, ii;
  473. for (j = 0; j < imax; ++j)
  474. for (i = 0; i < imax; ++i)
  475. squares[j][i] = square_create(a, xmin + h * i, ymin + h * j, i, j);
  476. for (ii = 0; ii < t->npoints; ++ii) {
  477. point* p = t->points[ii];
  478. int i = floor((p->x - xmin) / h);
  479. int j = floor((p->y - ymin) / h);
  480. square* s = squares[j][i];
  481. if (s->npoints == 0)
  482. square_addpoint(s, p);
  483. else { /* npoints == 1 */
  484. point pmiddle = { xmin + h * i + h2, ymin + h * j + h2 };
  485. if (distance(s->points[0], &pmiddle) > distance(p, &pmiddle))
  486. s->points[0] = p;
  487. }
  488. }
  489. t->npoints = 0;
  490. for (j = 0; j < imax; ++j) {
  491. for (i = 0; i < imax; ++i) {
  492. square* s = squares[j][i];
  493. if (squares[j][i]->npoints != 0)
  494. triangle_addpoint(t, s->points[0]);
  495. square_destroy(s);
  496. }
  497. }
  498. pfree2d((void***) squares);
  499. imax++;
  500. }
  501. /* Finds data points to be used in calculating spline coefficients for each
  502. * primary triangle.
  503. */
  504. static void csa_attachpoints(csa* a)
  505. {
  506. int nmin = a->nmin;
  507. int nmax = a->nmax;
  508. int nincreased = 0;
  509. int nthinned = 0;
  510. int i;
  511. assert(a->npt > 0);
  512. if (csa_verbose) {
  513. fprintf(stderr, "distributing data points:\n ");
  514. fflush(stderr);
  515. }
  516. for (i = 0; i < a->npt; ++i) {
  517. triangle* t = a->pt[i];
  518. int increased = 0;
  519. if (csa_verbose) {
  520. fprintf(stderr, ".");
  521. fflush(stderr);
  522. }
  523. t->r = t->h * 1.25;
  524. while (1) {
  525. int nsquares = 0;
  526. square** squares = NULL;
  527. int ii;
  528. getsquares(a, t, &nsquares, &squares);
  529. for (ii = 0; ii < nsquares; ++ii) {
  530. square* s = squares[ii];
  531. int iii;
  532. for (iii = 0; iii < s->npoints; ++iii) {
  533. point* p = s->points[iii];
  534. if (distance(p, &t->middle) <= t->r)
  535. triangle_addpoint(t, p);
  536. }
  537. }
  538. free(squares);
  539. if (t->npoints < nmin) {
  540. if (!increased) {
  541. increased = 1;
  542. nincreased++;
  543. }
  544. t->r *= 1.25;
  545. t->npoints = 0;
  546. } else if (t->npoints > nmax) {
  547. nthinned++;
  548. thindata(t, nmax);
  549. if (t->npoints > nmin)
  550. break;
  551. else {
  552. /*
  553. * Sometimes you have too much data, you thin it and --
  554. * oops -- you have too little. This is not a frequent
  555. * event, so let us not bother to put a new subdivision.
  556. */
  557. t->r *= 1.25;
  558. t->npoints = 0;
  559. }
  560. } else
  561. break;
  562. }
  563. }
  564. if (csa_verbose) {
  565. fprintf(stderr, "\n %d sets enhanced, %d sets thinned\n", nincreased, nthinned);
  566. fflush(stderr);
  567. }
  568. }
  569. static int n2q(int n)
  570. {
  571. assert(n >= 3);
  572. if (n >= 10)
  573. return 3;
  574. else if (n >= 6)
  575. return 2;
  576. else /* n == 3 */
  577. return 1;
  578. }
  579. /* Borrowed from Numerical Recipes. Stripped from unnecessary stuff like
  580. * matrices, vectors etc. and converted to double precision.
  581. *
  582. * Given a matrix a[0..m-1][0..n-1], this routine computes its singular value
  583. * decomposition, A = U.W.V' The matrix U replaces a on output. The
  584. * diagonal matrix of singular values W is output as a vector w[0..n-1]. The
  585. * matrix V (not the transpose V') is output as v[0..n-1][0..n-1].
  586. */
  587. static void svdcmp(double** a, int n, int m, double w[], double** v)
  588. {
  589. double* rv1 = malloc(n * sizeof(double));
  590. int i, j, k, l = -1;
  591. double anorm, c, f, g, h, s, scale, x, y, z;
  592. /*
  593. * Householder reduction to bidiagonal form
  594. */
  595. anorm = g = s = scale = 0.0;
  596. for (i = 0; i < n; i++) {
  597. l = i + 1;
  598. rv1[i] = scale * g;
  599. g = s = scale = 0.0;
  600. if (i <= m - 1) {
  601. for (k = i; k < m; k++)
  602. scale += fabs(a[k][i]);
  603. if (scale != 0.0) {
  604. for (k = i; k < m; k++) {
  605. a[k][i] /= scale;
  606. s += a[k][i] * a[k][i];
  607. }
  608. f = a[i][i];
  609. g = -copysign(sqrt(s), f);
  610. h = f * g - s;
  611. a[i][i] = f - g;
  612. for (j = l; j < n; j++) {
  613. for (s = 0.0, k = i; k < m; k++)
  614. s += a[k][i] * a[k][j];
  615. f = s / h;
  616. for (k = i; k < m; k++)
  617. a[k][j] += f * a[k][i];
  618. }
  619. for (k = i; k < m; k++)
  620. a[k][i] *= scale;
  621. }
  622. }
  623. w[i] = scale * g;
  624. g = s = scale = 0.0;
  625. if (i < m && i != n - 1) {
  626. for (k = l; k < n; k++)
  627. scale += fabs(a[i][k]);
  628. if (scale != 0.0) {
  629. for (k = l; k < n; k++) {
  630. a[i][k] /= scale;
  631. s += a[i][k] * a[i][k];
  632. }
  633. f = a[i][l];
  634. g = -copysign(sqrt(s), f);
  635. h = f * g - s;
  636. a[i][l] = f - g;
  637. for (k = l; k < n; k++)
  638. rv1[k] = a[i][k] / h;
  639. for (j = l; j < m; j++) {
  640. for (s = 0.0, k = l; k < n; k++)
  641. s += a[j][k] * a[i][k];
  642. for (k = l; k < n; k++)
  643. a[j][k] += s * rv1[k];
  644. }
  645. for (k = l; k < n; k++)
  646. a[i][k] *= scale;
  647. }
  648. }
  649. {
  650. double tmp = fabs(w[i]) + fabs(rv1[i]);
  651. anorm = (anorm > tmp) ? anorm : tmp;
  652. }
  653. }
  654. /*
  655. * Accumulation of right-hand transformations
  656. */
  657. for (i = n - 1; i >= 0; i--) {
  658. if (i < n - 1) {
  659. if (g != 0.0) {
  660. for (j = l; j < n; j++)
  661. /*
  662. * Double division to avoid underflow
  663. */
  664. v[j][i] = (a[i][j] / a[i][l]) / g;
  665. for (j = l; j < n; j++) {
  666. for (s = 0.0, k = l; k < n; k++)
  667. s += a[i][k] * v[k][j];
  668. for (k = l; k < n; k++)
  669. v[k][j] += s * v[k][i];
  670. }
  671. }
  672. for (j = l; j < n; j++)
  673. v[i][j] = v[j][i] = 0.0;
  674. }
  675. v[i][i] = 1.0;
  676. g = rv1[i];
  677. l = i;
  678. }
  679. /*
  680. * Accumulation of left-hand transformations
  681. */
  682. for (i = (m < n) ? m - 1 : n - 1; i >= 0; i--) {
  683. l = i + 1;
  684. g = w[i];
  685. for (j = l; j < n; j++)
  686. a[i][j] = 0.0;
  687. if (g) {
  688. g = 1.0 / g;
  689. for (j = l; j < n; j++) {
  690. for (s = 0.0, k = l; k < m; k++)
  691. s += a[k][i] * a[k][j];
  692. f = (s / a[i][i]) * g;
  693. for (k = i; k < m; k++)
  694. a[k][j] += f * a[k][i];
  695. }
  696. for (j = i; j < m; j++)
  697. a[j][i] *= g;
  698. } else
  699. for (j = i; j < m; j++)
  700. a[j][i] = 0.0;
  701. ++a[i][i];
  702. }
  703. /*
  704. * Diagonalization of the bidagonal form: loop over singular values, and
  705. * over allowed iterations
  706. */
  707. for (k = n - 1; k >= 0; k--) {
  708. int its;
  709. for (its = 1; its <= 30; its++) {
  710. int flag = 1;
  711. int nm = -1;
  712. for (l = k; l >= 0; l--) { /* test for splitting */
  713. nm = l - 1; /* rv1[0] is always zero */
  714. if ((fabs(rv1[l]) + anorm) == anorm) {
  715. flag = 0;
  716. break;
  717. }
  718. if ((fabs(w[nm]) + anorm) == anorm)
  719. break;
  720. }
  721. if (flag) {
  722. c = 0.0; /* cancellation of rv1[l], if l > 1 */
  723. s = 1.0;
  724. for (i = l; i <= k; i++) {
  725. f = s * rv1[i];
  726. rv1[i] = c * rv1[i];
  727. if ((fabs(f) + anorm) == anorm)
  728. break;
  729. g = w[i];
  730. h = hypot(f, g);
  731. w[i] = h;
  732. h = 1.0 / h;
  733. c = g * h;
  734. s = -f * h;
  735. for (j = 0; j < m; j++) {
  736. y = a[j][nm];
  737. z = a[j][i];
  738. a[j][nm] = y * c + z * s;
  739. a[j][i] = z * c - y * s;
  740. }
  741. }
  742. }
  743. z = w[k];
  744. if (l == k) { /* convergence */
  745. if (z < 0.0) { /* sing. val. is made non-negative */
  746. w[k] = -z;
  747. for (j = 0; j < n; j++)
  748. v[j][k] = -v[j][k];
  749. }
  750. break;
  751. }
  752. if (its == 30)
  753. csa_quit("svdcmp(): no convergence in 30 iterations");
  754. x = w[l]; /* shift from bottom 2-by-2 minor */
  755. nm = k - 1;
  756. y = w[nm];
  757. g = rv1[nm];
  758. h = rv1[k];
  759. f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
  760. g = hypot(f, 1.0);
  761. f = ((x - z) * (x + z) + h * ((y / (f + copysign(g, f))) - h)) / x;
  762. /*
  763. * Next QR transformation
  764. */
  765. c = s = 1.0;
  766. for (j = l; j <= nm; j++) {
  767. int jj;
  768. i = j + 1;
  769. g = rv1[i];
  770. y = w[i];
  771. h = s * g;
  772. g = c * g;
  773. z = hypot(f, h);
  774. rv1[j] = z;
  775. c = f / z;
  776. s = h / z;
  777. f = x * c + g * s;
  778. g = g * c - x * s;
  779. h = y * s;
  780. y *= c;
  781. for (jj = 0; jj < n; jj++) {
  782. x = v[jj][j];
  783. z = v[jj][i];
  784. v[jj][j] = x * c + z * s;
  785. v[jj][i] = z * c - x * s;
  786. }
  787. z = hypot(f, h);
  788. w[j] = z; /* rotation can be arbitrary if z = 0 */
  789. if (z != 0.0) {
  790. z = 1.0 / z;
  791. c = f * z;
  792. s = h * z;
  793. }
  794. f = c * g + s * y;
  795. x = c * y - s * g;
  796. for (jj = 0; jj < m; jj++) {
  797. y = a[jj][j];
  798. z = a[jj][i];
  799. a[jj][j] = y * c + z * s;
  800. a[jj][i] = z * c - y * s;
  801. }
  802. }
  803. rv1[l] = 0.0;
  804. rv1[k] = f;
  805. w[k] = x;
  806. }
  807. }
  808. free(rv1);
  809. }
  810. /* Least squares fitting via singular value decomposition.
  811. */
  812. static void lsq(double** A, int ni, int nj, double* z, double* w, double* sol)
  813. {
  814. double** V = dalloc2d(ni, ni);
  815. double** B = dalloc2d(nj, ni);
  816. int i, j, ii;
  817. svdcmp(A, ni, nj, w, V);
  818. for (j = 0; j < ni; ++j)
  819. for (i = 0; i < ni; ++i)
  820. V[j][i] /= w[i];
  821. for (i = 0; i < ni; ++i) {
  822. double* v = V[i];
  823. for (j = 0; j < nj; ++j) {
  824. double* a = A[j];
  825. double* b = &B[i][j];
  826. for (ii = 0; ii < ni; ++ii)
  827. *b += v[ii] * a[ii];
  828. }
  829. }
  830. for (i = 0; i < ni; ++i)
  831. sol[i] = 0.0;
  832. for (i = 0; i < ni; ++i)
  833. for (j = 0; j < nj; ++j)
  834. sol[i] += B[i][j] * z[j];
  835. dfree2d(B);
  836. dfree2d(V);
  837. }
  838. /*
  839. * square->coeffs[]:
  840. *
  841. * ---------------------
  842. * | 3 10 17 24 |
  843. * | 6 13 20 |
  844. * | 2 9 16 23 |
  845. * | 5 12 19 |
  846. * | 1 8 15 22 |
  847. * | 4 11 18 |
  848. * | 0 7 14 21 |
  849. * ---------------------
  850. */
  851. /* Calculates spline coefficients in each primary triangle by least squares
  852. * fitting to data attached by csa_attachpoints().
  853. */
  854. static void csa_findprimarycoeffs(csa* a)
  855. {
  856. int n[4] = { 0, 0, 0, 0 };
  857. int i;
  858. if (csa_verbose)
  859. fprintf(stderr, "finding spline coefficients for primary triangles:\n ");
  860. for (i = 0; i < a->npt; ++i) {
  861. triangle* t = a->pt[i];
  862. int npoints = t->npoints;
  863. point** points = t->points;
  864. double* z = malloc(npoints * sizeof(double));
  865. int q = n2q(t->npoints);
  866. int ok = 1;
  867. double b[10];
  868. double b1[6];
  869. int ii;
  870. if (csa_verbose) {
  871. fprintf(stderr, ".");
  872. fflush(stderr);
  873. }
  874. for (ii = 0; ii < npoints; ++ii)
  875. z[ii] = points[ii]->z;
  876. do {
  877. double bc[3];
  878. double wmin, wmax;
  879. if (!ok)
  880. q--;
  881. assert(q >= 0);
  882. if (q == 3) {
  883. double** A = dalloc2d(10, npoints);
  884. double w[10];
  885. for (ii = 0; ii < npoints; ++ii) {
  886. double* aii = A[ii];
  887. double tmp;
  888. triangle_calculatebc(t, points[ii], bc);
  889. /*
  890. * 0 1 2 3 4 5 6 7 8 9
  891. * 300 210 201 120 111 102 030 021 012 003
  892. */
  893. tmp = bc[0] * bc[0];
  894. aii[0] = tmp * bc[0];
  895. tmp *= 3.0;
  896. aii[1] = tmp * bc[1];
  897. aii[2] = tmp * bc[2];
  898. tmp = bc[1] * bc[1];
  899. aii[6] = tmp * bc[1];
  900. tmp *= 3.0;
  901. aii[3] = tmp * bc[0];
  902. aii[7] = tmp * bc[2];
  903. tmp = bc[2] * bc[2];
  904. aii[9] = tmp * bc[2];
  905. tmp *= 3.0;
  906. aii[5] = tmp * bc[0];
  907. aii[8] = tmp * bc[1];
  908. aii[4] = bc[0] * bc[1] * bc[2] * 6.0;
  909. }
  910. lsq(A, 10, npoints, z, w, b);
  911. wmin = w[0];
  912. wmax = w[0];
  913. for (ii = 1; ii < 10; ++ii) {
  914. if (w[ii] < wmin)
  915. wmin = w[ii];
  916. else if (w[ii] > wmax)
  917. wmax = w[ii];
  918. }
  919. if (wmin < wmax / a->k)
  920. ok = 0;
  921. dfree2d(A);
  922. } else if (q == 2) {
  923. double** A = dalloc2d(6, npoints);
  924. double w[6];
  925. for (ii = 0; ii < npoints; ++ii) {
  926. double* aii = A[ii];
  927. triangle_calculatebc(t, points[ii], bc);
  928. /*
  929. * 0 1 2 3 4 5
  930. * 200 110 101 020 011 002
  931. */
  932. aii[0] = bc[0] * bc[0];
  933. aii[1] = bc[0] * bc[1] * 2.0;
  934. aii[2] = bc[0] * bc[2] * 2.0;
  935. aii[3] = bc[1] * bc[1];
  936. aii[4] = bc[1] * bc[2] * 2.0;
  937. aii[5] = bc[2] * bc[2];
  938. }
  939. lsq(A, 6, npoints, z, w, b1);
  940. wmin = w[0];
  941. wmax = w[0];
  942. for (ii = 1; ii < 6; ++ii) {
  943. if (w[ii] < wmin)
  944. wmin = w[ii];
  945. else if (w[ii] > wmax)
  946. wmax = w[ii];
  947. }
  948. if (wmin < wmax / a->k)
  949. ok = 0;
  950. else { /* degree raising */
  951. ok = 1;
  952. b[0] = b1[0];
  953. b[1] = (b1[0] + 2.0 * b1[1]) / 3.0;
  954. b[2] = (b1[0] + 2.0 * b1[2]) / 3.0;
  955. b[3] = (b1[3] + 2.0 * b1[1]) / 3.0;
  956. b[4] = (b1[1] + b1[2] + b1[4]) / 3.0;
  957. b[5] = (b1[5] + 2.0 * b1[2]) / 3.0;
  958. b[6] = b1[3];
  959. b[7] = (b1[3] + 2.0 * b1[4]) / 3.0;
  960. b[8] = (b1[5] + 2.0 * b1[4]) / 3.0;
  961. b[9] = b1[5];
  962. }
  963. dfree2d(A);
  964. } else if (q == 1) {
  965. double** A = dalloc2d(3, npoints);
  966. double w[3];
  967. for (ii = 0; ii < npoints; ++ii) {
  968. double* aii = A[ii];
  969. triangle_calculatebc(t, points[ii], bc);
  970. aii[0] = bc[0];
  971. aii[1] = bc[1];
  972. aii[2] = bc[2];
  973. }
  974. lsq(A, 3, npoints, z, w, b1);
  975. wmin = w[0];
  976. wmax = w[0];
  977. for (ii = 1; ii < 3; ++ii) {
  978. if (w[ii] < wmin)
  979. wmin = w[ii];
  980. else if (w[ii] > wmax)
  981. wmax = w[ii];
  982. }
  983. if (wmin < wmax / a->k)
  984. ok = 0;
  985. else { /* degree raising */
  986. ok = 1;
  987. b[0] = b1[0];
  988. b[1] = (2.0 * b1[0] + b1[1]) / 3.0;
  989. b[2] = (2.0 * b1[0] + b1[2]) / 3.0;
  990. b[3] = (2.0 * b1[1] + b1[0]) / 3.0;
  991. b[4] = (b1[0] + b1[1] + b1[2]) / 3.0;
  992. b[5] = (2.0 * b1[2] + b1[0]) / 3.0;
  993. b[6] = b1[1];
  994. b[7] = (2.0 * b1[1] + b1[2]) / 3.0;
  995. b[8] = (2.0 * b1[2] + b1[1]) / 3.0;
  996. b[9] = b1[2];
  997. }
  998. dfree2d(A);
  999. } else if (q == 0) {
  1000. double** A = dalloc2d(1, npoints);
  1001. double w[1];
  1002. for (ii = 0; ii < npoints; ++ii)
  1003. A[ii][0] = 1.0;
  1004. lsq(A, 1, npoints, z, w, b1);
  1005. ok = 1;
  1006. b[0] = b1[0];
  1007. b[1] = b1[0];
  1008. b[2] = b1[0];
  1009. b[3] = b1[0];
  1010. b[4] = b1[0];
  1011. b[5] = b1[0];
  1012. b[6] = b1[0];
  1013. b[7] = b1[0];
  1014. b[8] = b1[0];
  1015. b[9] = b1[0];
  1016. dfree2d(A);
  1017. }
  1018. } while (!ok);
  1019. n[q]++;
  1020. t->order = q;
  1021. {
  1022. square* s = t->parent;
  1023. double* coeffs = s->coeffs;
  1024. coeffs[12] = b[0];
  1025. coeffs[9] = b[1];
  1026. coeffs[6] = b[3];
  1027. coeffs[3] = b[6];
  1028. coeffs[2] = b[7];
  1029. coeffs[1] = b[8];
  1030. coeffs[0] = b[9];
  1031. coeffs[4] = b[5];
  1032. coeffs[8] = b[2];
  1033. coeffs[5] = b[4];
  1034. }
  1035. free(z);
  1036. }
  1037. if (csa_verbose) {
  1038. fprintf(stderr, "\n 3rd order -- %d sets\n", n[3]);
  1039. fprintf(stderr, " 2nd order -- %d sets\n", n[2]);
  1040. fprintf(stderr, " 1st order -- %d sets\n", n[1]);
  1041. fprintf(stderr, " 0th order -- %d sets\n", n[0]);
  1042. fflush(stderr);
  1043. }
  1044. if (csa_verbose == 2) {
  1045. int j;
  1046. fprintf(stderr, " j\\i");
  1047. for (i = 0; i < a->ni; ++i)
  1048. fprintf(stderr, "%2d ", i);
  1049. fprintf(stderr, "\n");
  1050. for (j = a->nj - 1; j >= 0; --j) {
  1051. fprintf(stderr, "%2d ", j);
  1052. for (i = 0; i < a->ni; ++i) {
  1053. square* s = a->squares[j][i];
  1054. if (s->triangles[0]->primary)
  1055. fprintf(stderr, "%2d ", s->triangles[0]->order);
  1056. else
  1057. fprintf(stderr, " . ");
  1058. }
  1059. fprintf(stderr, "\n");
  1060. }
  1061. }
  1062. }
  1063. /* Find spline coefficients in (adjacent to primary triangles) secondary
  1064. * triangles from C1 smoothness conditions.
  1065. */
  1066. static void csa_findsecondarycoeffs(csa* a)
  1067. {
  1068. square*** squares = a->squares;
  1069. int ni = a->ni;
  1070. int nj = a->nj;
  1071. int ii;
  1072. if (csa_verbose) {
  1073. fprintf(stderr, "propagating spline coefficients to the remaining triangles:\n");
  1074. fflush(stderr);
  1075. }
  1076. /*
  1077. * red
  1078. */
  1079. for (ii = 0; ii < a->npt; ++ii) {
  1080. triangle* t = a->pt[ii];
  1081. square* s = t->parent;
  1082. int i = s->i;
  1083. int j = s->j;
  1084. double* c = s->coeffs;
  1085. double* cl = (i > 0) ? squares[j][i - 1]->coeffs : NULL;
  1086. double* cb = (j > 0) ? squares[j - 1][i]->coeffs : NULL;
  1087. double* cbl = (i > 0 && j > 0) ? squares[j - 1][i - 1]->coeffs : NULL;
  1088. double* ca = (j < nj - 1) ? squares[j + 1][i]->coeffs : NULL;
  1089. double* cal = (j < nj - 1 && i > 0) ? squares[j + 1][i - 1]->coeffs : NULL;
  1090. c[7] = 2.0 * c[4] - c[1];
  1091. c[11] = 2.0 * c[8] - c[5];
  1092. c[15] = 2.0 * c[12] - c[9];
  1093. c[10] = 2.0 * c[6] - c[2];
  1094. c[13] = 2.0 * c[9] - c[5];
  1095. c[16] = 2.0 * c[12] - c[8];
  1096. c[19] = 2.0 * c[15] - c[11];
  1097. if (cl != NULL) {
  1098. cl[21] = c[0];
  1099. cl[22] = c[1];
  1100. cl[23] = c[2];
  1101. cl[24] = c[3];
  1102. cl[18] = c[0] + c[1] - c[4];
  1103. cl[19] = c[1] + c[2] - c[5];
  1104. cl[20] = c[2] + c[3] - c[6];
  1105. cl[17] = 2.0 * cl[20] - cl[23];
  1106. cl[14] = 2.0 * cl[18] - cl[22];
  1107. }
  1108. if (cb != NULL) {
  1109. cb[3] = c[0];
  1110. cb[10] = c[7];
  1111. cb[6] = c[0] + c[7] - c[4];
  1112. cb[2] = 2.0 * cb[6] - cb[10];
  1113. }
  1114. if (cbl != NULL) {
  1115. cbl[23] = cb[2];
  1116. cbl[24] = cb[3];
  1117. cbl[20] = cb[2] + cb[3] - cb[6];
  1118. cbl[17] = cl[14];
  1119. }
  1120. if (ca != NULL) {
  1121. ca[0] = c[3];
  1122. ca[7] = c[10];
  1123. ca[4] = c[3] + c[10] - c[6];
  1124. ca[1] = 2.0 * ca[4] - ca[7];
  1125. }
  1126. if (cal != NULL) {
  1127. cal[21] = c[3];
  1128. cal[22] = ca[1];
  1129. cal[18] = ca[0] + ca[1] - ca[4];
  1130. cal[14] = cl[17];
  1131. }
  1132. }
  1133. /*
  1134. * blue
  1135. */
  1136. for (ii = 0; ii < a->npt; ++ii) {
  1137. triangle* t = a->pt[ii];
  1138. square* s = t->parent;
  1139. int i = s->i;
  1140. int j = s->j;
  1141. double* c = s->coeffs;
  1142. double* cr = (i < ni - 1) ? squares[j][i + 1]->coeffs : NULL;
  1143. double* car = (i < ni - 1 && j < nj - 1) ? squares[j + 1][i + 1]->coeffs : NULL;
  1144. double* cbr = (i < ni - 1 && j > 0) ? squares[j - 1][i + 1]->coeffs : NULL;
  1145. if (car != NULL)
  1146. cr[13] = car[7] + car[14] - car[11];
  1147. if (cbr != NULL)
  1148. cr[11] = cbr[10] + cbr[17] - cbr[13];
  1149. if (cr != NULL)
  1150. cr[5] = c[22] + c[23] - c[19];
  1151. }
  1152. /*
  1153. * green & yellow
  1154. */
  1155. for (ii = 0; ii < a->npt; ++ii) {
  1156. triangle* t = a->pt[ii];
  1157. square* s = t->parent;
  1158. int i = s->i;
  1159. int j = s->j;
  1160. double* cr = (i < ni - 1) ? squares[j][i + 1]->coeffs : NULL;
  1161. if (cr != NULL) {
  1162. cr[9] = (cr[5] + cr[13]) / 2.0;
  1163. cr[8] = (cr[5] + cr[11]) / 2.0;
  1164. cr[15] = (cr[11] + cr[19]) / 2.0;
  1165. cr[16] = (cr[13] + cr[19]) / 2.0;
  1166. cr[12] = (cr[8] + cr[16]) / 2.0;
  1167. }
  1168. }
  1169. if (csa_verbose) {
  1170. fprintf(stderr, "checking that all coefficients have been set:\n");
  1171. fflush(stderr);
  1172. }
  1173. for (ii = 0; ii < ni * nj; ++ii) {
  1174. square* s = squares[0][ii];
  1175. double* c = s->coeffs;
  1176. int i;
  1177. if (s->npoints == 0)
  1178. continue;
  1179. for (i = 0; i < 25; ++i)
  1180. if (isnan(c[i]))
  1181. fprintf(stderr, " squares[%d][%d]->coeffs[%d] = NaN\n", s->j, s->i, i);
  1182. }
  1183. }
  1184. static int i300[] = { 12, 12, 12, 12 };
  1185. static int i030[] = { 3, 24, 21, 0 };
  1186. static int i003[] = { 0, 3, 24, 21 };
  1187. static int i210[] = { 9, 16, 15, 8 };
  1188. static int i021[] = { 2, 17, 22, 7 };
  1189. static int i102[] = { 4, 6, 20, 18 };
  1190. static int i120[] = { 6, 20, 18, 4 };
  1191. static int i012[] = { 1, 10, 23, 14 };
  1192. static int i201[] = { 8, 9, 16, 15 };
  1193. static int i111[] = { 5, 13, 19, 11 };
  1194. static int* iall[] = { i300, i030, i003, i210, i021, i102, i120, i012, i201, i111 };
  1195. static void csa_sethascoeffsflag(csa* a)
  1196. {
  1197. int i, j;
  1198. for (j = 0; j < a->nj; ++j) {
  1199. for (i = 0; i < a->ni; ++i) {
  1200. square* s = a->squares[j][i];
  1201. double* coeffs = s->coeffs;
  1202. int ii;
  1203. for (ii = 0; ii < 4; ++ii) {
  1204. triangle* t = s->triangles[ii];
  1205. int cc;
  1206. for (cc = 0; cc < 10; ++cc)
  1207. if (isnan(coeffs[iall[cc][ii]]))
  1208. break;
  1209. if (cc == 10)
  1210. t->hascoeffs = 1;
  1211. }
  1212. }
  1213. }
  1214. }
  1215. void csa_calculatespline(csa* a)
  1216. {
  1217. csa_squarize(a, 5);
  1218. csa_attachpoints(a);
  1219. csa_findprimarycoeffs(a);
  1220. csa_findsecondarycoeffs(a);
  1221. csa_sethascoeffsflag(a);
  1222. }
  1223. void csa_approximate_point(csa* a, point* p)
  1224. {
  1225. double h = a->h;
  1226. double ii = (p->x - a->xmin) / h + 1.0;
  1227. double jj = (p->y - a->ymin) / h + 1.0;
  1228. int i, j;
  1229. square* s;
  1230. double fi, fj;
  1231. int ti;
  1232. triangle* t;
  1233. double bc[3];
  1234. if (ii < 0 || jj < 0 || ii > a->ni - 1 || jj > a->nj - 1) {
  1235. p->z = NaN;
  1236. return;
  1237. }
  1238. i = floor(ii);
  1239. j = floor(jj);
  1240. s = a->squares[j][i];
  1241. fi = ii - i;
  1242. fj = jj - j;
  1243. if (fj < fi) {
  1244. if (fi + fj < 1.0)
  1245. ti = 3;
  1246. else
  1247. ti = 2;
  1248. } else {
  1249. if (fi + fj < 1.0)
  1250. ti = 0;
  1251. else
  1252. ti = 1;
  1253. }
  1254. t = s->triangles[ti];
  1255. if (!t->hascoeffs) {
  1256. p->z = NaN;
  1257. return;
  1258. }
  1259. triangle_calculatebc(t, p, bc);
  1260. {
  1261. double* c = s->coeffs;
  1262. double bc1 = bc[0];
  1263. double bc2 = bc[1];
  1264. double bc3 = bc[2];
  1265. double tmp1 = bc1 * bc1;
  1266. double tmp2 = bc2 * bc2;
  1267. double tmp3 = bc3 * bc3;
  1268. switch (ti) {
  1269. case 0:
  1270. p->z = c[12] * bc1 * tmp1 + c[3] * bc2 * tmp2 + c[0] * bc3 * tmp3 + 3.0 * (c[9] * tmp1 * bc2 + c[2] * tmp2 * bc3 + c[4] * tmp3 * bc1 + c[6] * bc1 * tmp2 + c[1] * bc2 * tmp3 + c[8] * tmp1 * bc3) + 6.0 * c[5] * bc1 * bc2 * bc3;
  1271. break;
  1272. case 1:
  1273. p->z = c[12] * bc1 * tmp1 + c[24] * bc2 * tmp2 + c[3] * bc3 * tmp3 + 3.0 * (c[16] * tmp1 * bc2 + c[17] * tmp2 * bc3 + c[6] * tmp3 * bc1 + c[20] * bc1 * tmp2 + c[10] * bc2 * tmp3 + c[9] * tmp1 * bc3) + 6.0 * c[13] * bc1 * bc2 * bc3;
  1274. break;
  1275. case 2:
  1276. p->z = c[12] * bc1 * tmp1 + c[21] * bc2 * tmp2 + c[24] * bc3 * tmp3 + 3.0 * (c[15] * tmp1 * bc2 + c[22] * tmp2 * bc3 + c[20] * tmp3 * bc1 + c[18] * bc1 * tmp2 + c[23] * bc2 * tmp3 + c[16] * tmp1 * bc3) + 6.0 * c[19] * bc1 * bc2 * bc3;
  1277. break;
  1278. default: /* 3 */
  1279. p->z = c[12] * bc1 * tmp1 + c[0] * bc2 * tmp2 + c[21] * bc3 * tmp3 + 3.0 * (c[8] * tmp1 * bc2 + c[7] * tmp2 * bc3 + c[18] * tmp3 * bc1 + c[4] * bc1 * tmp2 + c[14] * bc2 * tmp3 + c[15] * tmp1 * bc3) + 6.0 * c[11] * bc1 * bc2 * bc3;
  1280. }
  1281. }
  1282. }
  1283. void csa_approximate_points(csa* a, int n, point* points)
  1284. {
  1285. int ii;
  1286. for (ii = 0; ii < n; ++ii)
  1287. csa_approximate_point(a, &points[ii]);
  1288. }
  1289. void csa_setnmin(csa* a, int nmin)
  1290. {
  1291. a->nmin = nmin;
  1292. }
  1293. void csa_setnmax(csa* a, int nmax)
  1294. {
  1295. a->nmax = nmax;
  1296. }
  1297. void csa_setk(csa* a, int k)
  1298. {
  1299. a->k = k;
  1300. }
  1301. #if defined(STANDALONE)
  1302. #define NIMAX 2048
  1303. #define BUFSIZE 10240
  1304. static void points_generate(double xmin, double xmax, double ymin, double ymax, int nx, int ny, int* nout, point** pout)
  1305. {
  1306. double stepx, stepy;
  1307. double x0, xx, yy;
  1308. int i, j, ii;
  1309. if (nx < 1 || ny < 1) {
  1310. *pout = NULL;
  1311. *nout = 0;
  1312. return;
  1313. }
  1314. *nout = nx * ny;
  1315. *pout = malloc(*nout * sizeof(point));
  1316. stepx = (nx > 1) ? (xmax - xmin) / (nx - 1) : 0.0;
  1317. stepy = (ny > 1) ? (ymax - ymin) / (ny - 1) : 0.0;
  1318. x0 = (nx > 1) ? xmin : (xmin + xmax) / 2.0;
  1319. yy = (ny > 1) ? ymin : (ymin + ymax) / 2.0;
  1320. ii = 0;
  1321. for (j = 0; j < ny; ++j) {
  1322. xx = x0;
  1323. for (i = 0; i < nx; ++i) {
  1324. point* p = &(*pout)[ii];
  1325. p->x = xx;
  1326. p->y = yy;
  1327. xx += stepx;
  1328. ii++;
  1329. }
  1330. yy += stepy;
  1331. }
  1332. }
  1333. static int str2double(char* token, double* value)
  1334. {
  1335. char* end = NULL;
  1336. if (token == NULL) {
  1337. *value = NaN;
  1338. return 0;
  1339. }
  1340. *value = strtod(token, &end);
  1341. if (end == token) {
  1342. *value = NaN;
  1343. return 0;
  1344. }
  1345. return 1;
  1346. }
  1347. /* Reads array of points from a columnar file.
  1348. *
  1349. * @param f File handle
  1350. * @param dim Number of dimensions (must be 2 or 3)
  1351. * @param n Pointer to number of points (output)
  1352. * @param points Pointer to array of points [*n] (output) (to be freed)
  1353. */
  1354. static void points_read(FILE* f, int dim, int* n, point** points)
  1355. {
  1356. char buf[BUFSIZE];
  1357. char seps[] = " ,;\t";
  1358. char* token;
  1359. int i;
  1360. if (csa_verbose) {
  1361. fprintf(stderr, "reading points:\n");
  1362. fflush(stderr);
  1363. }
  1364. if (dim < 2 || dim > 3) {
  1365. *n = 0;
  1366. *points = NULL;
  1367. return;
  1368. }
  1369. i = 0;
  1370. while (fgets(buf, BUFSIZE, f) != NULL) {
  1371. double v;
  1372. if (buf[0] == '#')
  1373. continue;
  1374. if ((token = strtok(buf, seps)) == NULL)
  1375. continue;
  1376. if (!str2double(token, &v))
  1377. continue;
  1378. if ((token = strtok(NULL, seps)) == NULL)
  1379. continue;
  1380. if (!str2double(token, &v))
  1381. continue;
  1382. if (dim == 3) {
  1383. if ((token = strtok(NULL, seps)) == NULL)
  1384. continue;
  1385. if (!str2double(token, &v))
  1386. continue;
  1387. }
  1388. i++;
  1389. }
  1390. *n = i;
  1391. if (i == 0) {
  1392. *points = NULL;
  1393. return;
  1394. }
  1395. *points = malloc(i * sizeof(point));
  1396. rewind(f);
  1397. i = 0;
  1398. while (fgets(buf, BUFSIZE, f) != NULL && i < *n) {
  1399. point* p = &(*points)[i];
  1400. if (buf[0] == '#')
  1401. continue;
  1402. if ((token = strtok(buf, seps)) == NULL)
  1403. continue;
  1404. if (!str2double(token, &p->x))
  1405. continue;
  1406. if ((token = strtok(NULL, seps)) == NULL)
  1407. continue;
  1408. if (!str2double(token, &p->y))
  1409. continue;
  1410. if (dim == 2)
  1411. p->z = NaN;
  1412. else {
  1413. if ((token = strtok(NULL, seps)) == NULL)
  1414. continue;
  1415. if (!str2double(token, &p->z))
  1416. continue;
  1417. }
  1418. i++;
  1419. }
  1420. if (csa_verbose) {
  1421. fprintf(stderr, " %d points\n", i);
  1422. fflush(stderr);
  1423. }
  1424. }
  1425. static void points_write(int n, point* points)
  1426. {
  1427. int i;
  1428. if (csa_verbose)
  1429. printf("Output:\n");
  1430. for (i = 0; i < n; ++i) {
  1431. point* p = &points[i];
  1432. printf("%.15g %.15g %.15g\n", p->x, p->y, p->z);
  1433. }
  1434. }
  1435. /* *INDENT-OFF* */
  1436. static void usage()
  1437. {
  1438. printf(
  1439. "Usage: csabathy -i <XYZ file> {-o <XY file>|-n <nx>x<ny>} [-v|-V]\n"
  1440. "Options:\n"
  1441. " -i <XYZ file> -- three-column file with points to approximate from\n"
  1442. " -o <XY file> -- two-column file with points to approximate in\n"
  1443. " -n <nx>x<ny> -- do generate <nx>x<ny> output rectangular grid\n"
  1444. " -v -- verbose / version\n"
  1445. " -V -- very verbose / version\n"
  1446. "Description:\n"
  1447. " `csabathy' approximates irregular scalar 2D data in specified points using\n"
  1448. " C1-continuous bivariate cubic spline. The calculated values are written to\n"
  1449. " standard output.\n"
  1450. );
  1451. exit(0);
  1452. }
  1453. /* *INDENT-ON* */
  1454. static void version()
  1455. {
  1456. printf("csa version %s\n", csa_version);
  1457. exit(0);
  1458. }
  1459. static void parse_commandline(int argc, char* argv[], FILE** fdata, FILE** fpoints, int* generate_points, int* nx, int* ny)
  1460. {
  1461. int i;
  1462. if (argc <= 1)
  1463. usage();
  1464. i = 1;
  1465. while (i < argc) {
  1466. switch (argv[i][1]) {
  1467. case 'i':
  1468. i++;
  1469. if (i >= argc)
  1470. csa_quit("no file name found after -i\n");
  1471. if (*fdata == NULL) {
  1472. *fdata = fopen(argv[i], "r");
  1473. if (*fdata == NULL)
  1474. csa_quit("%s: %s\n", argv[i], strerror(errno));
  1475. }
  1476. i++;
  1477. break;
  1478. case 'n':
  1479. i++;
  1480. if (*fpoints != NULL) {
  1481. fclose(*fpoints);
  1482. *fpoints = NULL;
  1483. }
  1484. *generate_points = 1;
  1485. if (i >= argc)
  1486. csa_quit("no grid dimensions found after -n\n");
  1487. if (sscanf(argv[i], "%dx%d", nx, ny) != 2)
  1488. csa_quit("could not read grid dimensions after \"-n\"\n");
  1489. if (*nx <= 0 || *nx > NIMAX || *ny <= 0 || *ny > NIMAX)
  1490. csa_quit("invalid size for output grid\n");
  1491. i++;
  1492. break;
  1493. case 'o':
  1494. i++;
  1495. if (i >= argc)
  1496. csa_quit("no file name found after -o\n");
  1497. if (*fpoints == NULL) {
  1498. generate_points = 0;
  1499. *fpoints = fopen(argv[i], "r");
  1500. if (*fpoints == NULL)
  1501. csa_quit("%s: %s\n", argv[i], strerror(errno));
  1502. }
  1503. i++;
  1504. break;
  1505. case 'v':
  1506. i++;
  1507. csa_verbose = 1;
  1508. break;
  1509. case 'V':
  1510. i++;
  1511. csa_verbose = 2;
  1512. break;
  1513. default:
  1514. usage();
  1515. break;
  1516. }
  1517. }
  1518. if (csa_verbose && argc == 2)
  1519. version();
  1520. }
  1521. int main(int argc, char* argv[])
  1522. {
  1523. FILE* fdata = NULL;
  1524. FILE* fpoints = NULL;
  1525. int nin = 0;
  1526. point* pin = NULL;
  1527. int nout = 0;
  1528. int generate_points = 0;
  1529. point* pout = NULL;
  1530. int nx = -1;
  1531. int ny = -1;
  1532. csa* a = NULL;
  1533. parse_commandline(argc, argv, &fdata, &fpoints, &generate_points, &nx, &ny);
  1534. if (fdata == NULL)
  1535. csa_quit("error: no data file specified\n");
  1536. if (!generate_points && fpoints == NULL)
  1537. csa_quit("error: no output grid specified\n");
  1538. points_read(fdata, 3, &nin, &pin);
  1539. if (nin < 3)
  1540. return 0;
  1541. a = csa_create();
  1542. csa_addpoints(a, nin, pin);
  1543. csa_calculatespline(a);
  1544. if (generate_points)
  1545. points_generate(a->xmin - a->h, a->xmax + a->h, a->ymin - a->h, a->ymax + a->h, nx, ny, &nout, &pout);
  1546. else
  1547. points_read(fpoints, 2, &nout, &pout);
  1548. csa_approximate_points(a, nout, pout);
  1549. points_write(nout, pout);
  1550. csa_destroy(a);
  1551. fclose(fdata);
  1552. if (fpoints != NULL)
  1553. fclose(fpoints);
  1554. free(pin);
  1555. free(pout);
  1556. return 0;
  1557. }
  1558. #endif /* STANDALONE */