util.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /*******************************************************************************
  2. License:
  3. This software and/or related materials was developed at the National Institute
  4. of Standards and Technology (NIST) by employees of the Federal Government
  5. in the course of their official duties. Pursuant to title 17 Section 105
  6. of the United States Code, this software is not subject to copyright
  7. protection and is in the public domain.
  8. This software and/or related materials have been determined to be not subject
  9. to the EAR (see Part 734.3 of the EAR for exact details) because it is
  10. a publicly available technology and software, and is freely distributed
  11. to any interested party with no licensing requirements. Therefore, it is
  12. permissible to distribute this software as a free download from the internet.
  13. Disclaimer:
  14. This software and/or related materials was developed to promote biometric
  15. standards and biometric technology testing for the Federal Government
  16. in accordance with the USA PATRIOT Act and the Enhanced Border Security
  17. and Visa Entry Reform Act. Specific hardware and software products identified
  18. in this software were used in order to perform the software development.
  19. In no case does such identification imply recommendation or endorsement
  20. by the National Institute of Standards and Technology, nor does it imply that
  21. the products and equipment identified are necessarily the best available
  22. for the purpose.
  23. This software and/or related materials are provided "AS-IS" without warranty
  24. of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
  25. NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
  26. or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
  27. licensed product, however used. In no event shall NIST be liable for any
  28. damages and/or costs, including but not limited to incidental or consequential
  29. damages of any kind, including economic damage or injury to property and lost
  30. profits, regardless of whether NIST shall be advised, have reason to know,
  31. or in fact shall know of the possibility.
  32. By using this software, you agree to bear all risk relating to quality,
  33. use and performance of the software and/or related materials. You agree
  34. to hold the Government harmless from any claim arising from your use
  35. of the software.
  36. *******************************************************************************/
  37. /***********************************************************************
  38. LIBRARY: LFS - NIST Latent Fingerprint System
  39. FILE: UTIL.C
  40. AUTHOR: Michael D. Garris
  41. DATE: 03/16/1999
  42. Contains general support routines required by the NIST
  43. Latent Fingerprint System (LFS).
  44. ***********************************************************************
  45. ROUTINES:
  46. maxv()
  47. minv()
  48. minmaxs()
  49. distance()
  50. squared_distance()
  51. in_int_list()
  52. remove_from_int_list()
  53. find_incr_position_dbl()
  54. angle2line()
  55. line2direction()
  56. closest_dir_dist()
  57. ***********************************************************************/
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include "lfs.h"
  61. /*************************************************************************
  62. **************************************************************************
  63. #cat: maxv - Determines the maximum value in the given list of integers.
  64. #cat: NOTE, the list is assumed to be NOT empty!
  65. Input:
  66. list - non-empty list of integers to be searched
  67. num - number of integers in the list
  68. Return Code:
  69. Maximum - maximum value in the list
  70. **************************************************************************/
  71. int maxv(const int *list, const int num)
  72. {
  73. int i;
  74. int maxval;
  75. /* NOTE: The list is assumed to be NOT empty. */
  76. /* Initialize running maximum to first item in list. */
  77. maxval = list[0];
  78. /* Foreach subsequent item in the list... */
  79. for(i = 1; i < num; i++){
  80. /* If current item is larger than running maximum... */
  81. if(list[i] > maxval)
  82. /* Set running maximum to the larger item. */
  83. maxval = list[i];
  84. /* Otherwise, skip to next item. */
  85. }
  86. /* Return the resulting maximum. */
  87. return(maxval);
  88. }
  89. /*************************************************************************
  90. **************************************************************************
  91. #cat: minv - Determines the minimum value in the given list of integers.
  92. #cat: NOTE, the list is assumed to be NOT empty!
  93. Input:
  94. list - non-empty list of integers to be searched
  95. num - number of integers in the list
  96. Return Code:
  97. Minimum - minimum value in the list
  98. **************************************************************************/
  99. int minv(const int *list, const int num)
  100. {
  101. int i;
  102. int minval;
  103. /* NOTE: The list is assumed to be NOT empty. */
  104. /* Initialize running minimum to first item in list. */
  105. minval = list[0];
  106. /* Foreach subsequent item in the list... */
  107. for(i = 1; i < num; i++){
  108. /* If current item is smaller than running minimum... */
  109. if(list[i] < minval)
  110. /* Set running minimum to the smaller item. */
  111. minval = list[i];
  112. /* Otherwise, skip to next item. */
  113. }
  114. /* Return the resulting minimum. */
  115. return(minval);
  116. }
  117. /*************************************************************************
  118. **************************************************************************
  119. #cat: minmaxs - Takes a list of integers and identifies points of relative
  120. #cat: minima and maxima. The midpoint of flat plateaus and valleys
  121. #cat: are selected when they are detected.
  122. Input:
  123. items - list of integers to be analyzed
  124. num - number of items in the list
  125. Output:
  126. ominmax_val - value of the item at each minima or maxima
  127. ominmax_type - identifies a minima as '-1' and maxima as '1'
  128. ominmax_i - index of item's position in list
  129. ominmax_alloc - number of allocated minima and/or maxima
  130. ominmax_num - number of detected minima and/or maxima
  131. Return Code:
  132. Zero - successful completion
  133. Negative - system error
  134. **************************************************************************/
  135. int minmaxs(int **ominmax_val, int **ominmax_type, int **ominmax_i,
  136. int *ominmax_alloc, int *ominmax_num,
  137. const int *items, const int num)
  138. {
  139. int i, diff, state, start, loc;
  140. int *minmax_val, *minmax_type, *minmax_i, minmax_alloc, minmax_num;
  141. /* Determine maximum length for allocation of buffers. */
  142. /* If there are fewer than 3 items ... */
  143. if(num < 3){
  144. /* Then no min/max is possible, so set allocated length */
  145. /* to 0 and return. */
  146. *ominmax_alloc = 0;
  147. *ominmax_num = 0;
  148. return(0);
  149. }
  150. /* Otherwise, set allocation length to number of items - 2 */
  151. /* (one for the first item in the list, and on for the last). */
  152. /* Every other intermediate point can potentially represent a */
  153. /* min or max. */
  154. minmax_alloc = num - 2;
  155. /* Allocate the buffers. */
  156. minmax_val = (int *)malloc(minmax_alloc * sizeof(int));
  157. if(minmax_val == (int *)NULL){
  158. fprintf(stderr, "ERROR : minmaxs : malloc : minmax_val\n");
  159. return(-290);
  160. }
  161. minmax_type = (int *)malloc(minmax_alloc * sizeof(int));
  162. if(minmax_type == (int *)NULL){
  163. free(minmax_val);
  164. fprintf(stderr, "ERROR : minmaxs : malloc : minmax_type\n");
  165. return(-291);
  166. }
  167. minmax_i = (int *)malloc(minmax_alloc * sizeof(int));
  168. if(minmax_i == (int *)NULL){
  169. free(minmax_val);
  170. free(minmax_type);
  171. fprintf(stderr, "ERROR : minmaxs : malloc : minmax_i\n");
  172. return(-292);
  173. }
  174. /* Initialize number of min/max to 0. */
  175. minmax_num = 0;
  176. /* Start witht the first item in the list. */
  177. i = 0;
  178. /* Get starting state between first pair of items. */
  179. diff = items[1] - items[0];
  180. if(diff > 0)
  181. state = 1;
  182. else if (diff < 0)
  183. state = -1;
  184. else
  185. state = 0;
  186. /* Set start location to first item in list. */
  187. start = 0;
  188. /* Bump to next item in list. */
  189. i++;
  190. /* While not at the last item in list. */
  191. while(i < num-1){
  192. /* Compute difference between next pair of items. */
  193. diff = items[i+1] - items[i];
  194. /* If items are increasing ... */
  195. if(diff > 0){
  196. /* If previously increasing ... */
  197. if(state == 1){
  198. /* Reset start to current location. */
  199. start = i;
  200. }
  201. /* If previously decreasing ... */
  202. else if (state == -1){
  203. /* Then we have incurred a minima ... */
  204. /* Compute midpoint of minima. */
  205. loc = (start + i)/2;
  206. /* Store value at minima midpoint. */
  207. minmax_val[minmax_num] = items[loc];
  208. /* Store type code for minima. */
  209. minmax_type[minmax_num] = -1;
  210. /* Store location of minima midpoint. */
  211. minmax_i[minmax_num++] = loc;
  212. /* Change state to increasing. */
  213. state = 1;
  214. /* Reset start location. */
  215. start = i;
  216. }
  217. /* If previously level (this state only can occur at the */
  218. /* beginning of the list of items) ... */
  219. else {
  220. /* If more than one level state in a row ... */
  221. if(i-start > 1){
  222. /* Then consider a minima ... */
  223. /* Compute midpoint of minima. */
  224. loc = (start + i)/2;
  225. /* Store value at minima midpoint. */
  226. minmax_val[minmax_num] = items[loc];
  227. /* Store type code for minima. */
  228. minmax_type[minmax_num] = -1;
  229. /* Store location of minima midpoint. */
  230. minmax_i[minmax_num++] = loc;
  231. /* Change state to increasing. */
  232. state = 1;
  233. /* Reset start location. */
  234. start = i;
  235. }
  236. /* Otherwise, ignore single level state. */
  237. else{
  238. /* Change state to increasing. */
  239. state = 1;
  240. /* Reset start location. */
  241. start = i;
  242. }
  243. }
  244. }
  245. /* If items are decreasing ... */
  246. else if(diff < 0){
  247. /* If previously decreasing ... */
  248. if(state == -1){
  249. /* Reset start to current location. */
  250. start = i;
  251. }
  252. /* If previously increasing ... */
  253. else if (state == 1){
  254. /* Then we have incurred a maxima ... */
  255. /* Compute midpoint of maxima. */
  256. loc = (start + i)/2;
  257. /* Store value at maxima midpoint. */
  258. minmax_val[minmax_num] = items[loc];
  259. /* Store type code for maxima. */
  260. minmax_type[minmax_num] = 1;
  261. /* Store location of maxima midpoint. */
  262. minmax_i[minmax_num++] = loc;
  263. /* Change state to decreasing. */
  264. state = -1;
  265. /* Reset start location. */
  266. start = i;
  267. }
  268. /* If previously level (this state only can occur at the */
  269. /* beginning of the list of items) ... */
  270. else {
  271. /* If more than one level state in a row ... */
  272. if(i-start > 1){
  273. /* Then consider a maxima ... */
  274. /* Compute midpoint of maxima. */
  275. loc = (start + i)/2;
  276. /* Store value at maxima midpoint. */
  277. minmax_val[minmax_num] = items[loc];
  278. /* Store type code for maxima. */
  279. minmax_type[minmax_num] = 1;
  280. /* Store location of maxima midpoint. */
  281. minmax_i[minmax_num++] = loc;
  282. /* Change state to decreasing. */
  283. state = -1;
  284. /* Reset start location. */
  285. start = i;
  286. }
  287. /* Otherwise, ignore single level state. */
  288. else{
  289. /* Change state to decreasing. */
  290. state = -1;
  291. /* Reset start location. */
  292. start = i;
  293. }
  294. }
  295. }
  296. /* Otherwise, items are level, so continue to next item pair. */
  297. /* Advance to next item pair in list. */
  298. i++;
  299. }
  300. /* Set results to output pointers. */
  301. *ominmax_val = minmax_val;
  302. *ominmax_type = minmax_type;
  303. *ominmax_i = minmax_i;
  304. *ominmax_alloc = minmax_alloc;
  305. *ominmax_num = minmax_num;
  306. /* Return normally. */
  307. return(0);
  308. }
  309. /*************************************************************************
  310. **************************************************************************
  311. #cat: distance - Takes two coordinate points and computes the
  312. #cat: Euclidean distance between the two points.
  313. Input:
  314. x1 - x-coord of first point
  315. y1 - y-coord of first point
  316. x2 - x-coord of second point
  317. y2 - y-coord of second point
  318. Return Code:
  319. Distance - computed Euclidean distance
  320. **************************************************************************/
  321. double distance(const int x1, const int y1, const int x2, const int y2)
  322. {
  323. double dx, dy, dist;
  324. /* Compute delta x between points. */
  325. dx = (double)(x1 - x2);
  326. /* Compute delta y between points. */
  327. dy = (double)(y1 - y2);
  328. /* Compute the squared distance between points. */
  329. dist = (dx*dx) + (dy*dy);
  330. /* Take square root of squared distance. */
  331. dist = sqrt(dist);
  332. /* Return the squared distance. */
  333. return(dist);
  334. }
  335. /*************************************************************************
  336. **************************************************************************
  337. #cat: squared_distance - Takes two coordinate points and computes the
  338. #cat: squared distance between the two points.
  339. Input:
  340. x1 - x-coord of first point
  341. y1 - y-coord of first point
  342. x2 - x-coord of second point
  343. y2 - y-coord of second point
  344. Return Code:
  345. Distance - computed squared distance
  346. **************************************************************************/
  347. double squared_distance(const int x1, const int y1, const int x2, const int y2)
  348. {
  349. double dx, dy, dist;
  350. /* Compute delta x between points. */
  351. dx = (double)(x1 - x2);
  352. /* Compute delta y between points. */
  353. dy = (double)(y1 - y2);
  354. /* Compute the squared distance between points. */
  355. dist = (dx*dx) + (dy*dy);
  356. /* Return the squared distance. */
  357. return(dist);
  358. }
  359. /*************************************************************************
  360. **************************************************************************
  361. #cat: in_int_list - Determines if a specified value is store in a list of
  362. #cat: integers and returns its location if found.
  363. Input:
  364. item - value to search for in list
  365. list - list of integers to be searched
  366. len - number of integers in search list
  367. Return Code:
  368. Zero or greater - first location found equal to search value
  369. Negative - search value not found in the list of integers
  370. **************************************************************************/
  371. int in_int_list(const int item, const int *list, const int len)
  372. {
  373. int i;
  374. /* Foreach item in list ... */
  375. for(i = 0; i < len; i++){
  376. /* If search item found in list ... */
  377. if(list[i] == item)
  378. /* Return the location in list where found. */
  379. return(i);
  380. }
  381. /* If we get here, then search item not found in list, */
  382. /* so return -1 ==> NOT FOUND. */
  383. return(-1);
  384. }
  385. /*************************************************************************
  386. **************************************************************************
  387. #cat: remove_from_int_list - Takes a position index into an integer list and
  388. #cat: removes the value from the list, collapsing the resulting
  389. #cat: list.
  390. Input:
  391. index - position of value to be removed from list
  392. list - input list of integers
  393. num - number of integers in the list
  394. Output:
  395. list - list with specified integer removed
  396. num - decremented number of integers in list
  397. Return Code:
  398. Zero - successful completion
  399. Negative - system error
  400. **************************************************************************/
  401. int remove_from_int_list(const int index, int *list, const int num)
  402. {
  403. int fr, to;
  404. /* Make sure the requested index is within range. */
  405. if((index < 0) && (index >= num)){
  406. fprintf(stderr, "ERROR : remove_from_int_list : index out of range\n");
  407. return(-370);
  408. }
  409. /* Slide the remaining list of integers up over top of the */
  410. /* position of the integer being removed. */
  411. for(to = index, fr = index+1; fr < num; to++, fr++)
  412. list[to] = list[fr];
  413. /* NOTE: Decrementing the number of integers remaining in the list is */
  414. /* the responsibility of the caller! */
  415. /* Return normally. */
  416. return(0);
  417. }
  418. /*************************************************************************
  419. **************************************************************************
  420. #cat: ind_incr_position_dbl - Takes a double value and a list of doubles and
  421. #cat: determines where in the list the double may be inserted,
  422. #cat: preserving the increasing sorted order of the list.
  423. Input:
  424. val - value to be inserted into the list
  425. list - list of double in increasing sorted order
  426. num - number of values in the list
  427. Return Code:
  428. Zero or Positive - insertion position in the list
  429. **************************************************************************/
  430. int find_incr_position_dbl(const double val, double *list, const int num)
  431. {
  432. int i;
  433. /* Foreach item in double list ... */
  434. for(i = 0; i < num; i++){
  435. /* If the value is smaller than the current item in list ... */
  436. if(val < list[i])
  437. /* Then we found were to insert the value in the list maintaining */
  438. /* an increasing sorted order. */
  439. return(i);
  440. /* Otherwise, the value is still larger than current item, so */
  441. /* continue to next item in the list. */
  442. }
  443. /* Otherwise, we never found a slot within the list to insert the */
  444. /* the value, so place at the end of the sorted list. */
  445. return(i);
  446. }
  447. /*************************************************************************
  448. **************************************************************************
  449. #cat: angle2line - Takes two coordinate points and computes the angle
  450. #cat: to the line formed by the two points.
  451. Input:
  452. fx - x-coord of first point
  453. fy - y-coord of first point
  454. tx - x-coord of second point
  455. ty - y-coord of second point
  456. Return Code:
  457. Angle - angle to the specified line
  458. **************************************************************************/
  459. double angle2line(const int fx, const int fy, const int tx, const int ty)
  460. {
  461. double dx, dy, theta;
  462. /* Compute slope of line connecting the 2 specified points. */
  463. dy = (double)(fy - ty);
  464. dx = (double)(tx - fx);
  465. /* If delta's are sufficiently small ... */
  466. if((fabs(dx) < MIN_SLOPE_DELTA) && (fabs(dy) < MIN_SLOPE_DELTA))
  467. theta = 0.0;
  468. /* Otherwise, compute angle to the line. */
  469. else
  470. theta = atan2(dy, dx);
  471. /* Return the compute angle in radians. */
  472. return(theta);
  473. }
  474. /*************************************************************************
  475. **************************************************************************
  476. #cat: line2direction - Takes two coordinate points and computes the
  477. #cat: directon (on a full circle) in which the first points
  478. #cat: to the second.
  479. Input:
  480. fx - x-coord of first point (pointing from)
  481. fy - y-coord of first point (pointing from)
  482. tx - x-coord of second point (pointing to)
  483. ty - y-coord of second point (pointing to)
  484. ndirs - number of IMAP directions (in semicircle)
  485. Return Code:
  486. Direction - determined direction on a "full" circle
  487. **************************************************************************/
  488. int line2direction(const int fx, const int fy,
  489. const int tx, const int ty, const int ndirs)
  490. {
  491. double theta, pi_factor;
  492. int idir, full_ndirs;
  493. static double pi2 = M_PI*2.0;
  494. /* Compute angle to line connecting the 2 points. */
  495. /* Coordinates are swapped and order of points reversed to */
  496. /* account for 0 direction is vertical and positive direction */
  497. /* is clockwise. */
  498. theta = angle2line(ty, tx, fy, fx);
  499. /* Make sure the angle is positive. */
  500. theta += pi2;
  501. theta = fmod(theta, pi2);
  502. /* Convert from radians to integer direction on range [0..(ndirsX2)]. */
  503. /* Multiply radians by units/radian ((ndirsX2)/(2PI)), and you get */
  504. /* angle in integer units. */
  505. /* Compute number of directions on full circle. */
  506. full_ndirs = ndirs<<1;
  507. /* Compute the radians to integer direction conversion factor. */
  508. pi_factor = (double)full_ndirs/pi2;
  509. /* Convert radian angle to integer direction on full circle. */
  510. theta *= pi_factor;
  511. /* Need to truncate precision so that answers are consistent */
  512. /* on different computer architectures when rounding doubles. */
  513. theta = trunc_dbl_precision(theta, TRUNC_SCALE);
  514. idir = sround(theta);
  515. /* Make sure on range [0..(ndirsX2)]. */
  516. idir %= full_ndirs;
  517. /* Return the integer direction. */
  518. return(idir);
  519. }
  520. /*************************************************************************
  521. **************************************************************************
  522. #cat: closest_dir_dist - Takes to integer IMAP directions and determines the
  523. #cat: closest distance between them accounting for
  524. #cat: wrap-around either at the beginning or ending of
  525. #cat: the range of directions.
  526. Input:
  527. dir1 - integer value of the first direction
  528. dir2 - integer value of the second direction
  529. ndirs - the number of possible directions
  530. Return Code:
  531. Non-negative - distance between the 2 directions
  532. **************************************************************************/
  533. int closest_dir_dist(const int dir1, const int dir2, const int ndirs)
  534. {
  535. int d1, d2, dist;
  536. /* Initialize distance to -1 = INVALID. */
  537. dist = INVALID_DIR;
  538. /* Measure shortest distance between to directions. */
  539. /* If both neighbors are VALID ... */
  540. if((dir1 >= 0)&&(dir2 >= 0)){
  541. /* Compute inner and outer distances to account for distances */
  542. /* that wrap around the end of the range of directions, which */
  543. /* may in fact be closer. */
  544. d1 = abs(dir2 - dir1);
  545. d2 = ndirs - d1;
  546. dist = min(d1, d2);
  547. }
  548. /* Otherwise one or both directions are INVALID, so ignore */
  549. /* and return INVALID. */
  550. /* Return determined closest distance. */
  551. return(dist);
  552. }