main.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. /****************************************************************************
  2. *
  3. * MODULE: v.kernel
  4. *
  5. * AUTHOR(S): Stefano Menegon, ITC-irst, Trento, Italy
  6. * PURPOSE: Generates a raster density map from vector points data using
  7. * a moving 2D isotropic Gaussian kernel or
  8. * optionally generates a vector density map on vector network
  9. * with a 1D kernel
  10. * COPYRIGHT: (C) 2004 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General Public
  13. * License (>=v2). Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. *****************************************************************************/
  17. #include <math.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <float.h>
  21. #include <grass/gis.h>
  22. #include <grass/glocale.h>
  23. #include <grass/gmath.h>
  24. #include <grass/Vect.h>
  25. #include "global.h"
  26. static int ndists; /* number of distances in dists */
  27. static double *dists; /* array of all distances < dmax */
  28. static int npoints;
  29. int net = 0;
  30. static double dimension = 2.;
  31. /* define score function L(window size) */
  32. double L(double smooth)
  33. {
  34. int ii;
  35. double resL, n, term;
  36. n = npoints;
  37. resL = 0.;
  38. term = 1. / pow((2. * M_PI), dimension / 2.);
  39. for (ii = 0; ii < ndists; ii++) {
  40. /* resL+= gaussianFunction(dists[ii]/smooth,2.,dimension) - 2. * gaussianKernel(dists[ii]/smooth,term); */
  41. resL +=
  42. gaussianFunction(dists[ii] / smooth, 2.,
  43. dimension) -
  44. 2. * gaussianFunction(dists[ii] / smooth, 1., dimension);
  45. }
  46. if (!net)
  47. resL *= 2.;
  48. resL =
  49. (1. / (pow(n, 2.) * pow(smooth, dimension))) * (resL +
  50. n *
  51. (gaussianFunction
  52. (0., 2.,
  53. dimension) -
  54. 2. *
  55. gaussianFunction(0.,
  56. 1.,
  57. dimension)))
  58. + (2. / (n * pow(smooth, dimension))) * gaussianFunction(0., 1.,
  59. dimension);
  60. /* resL = (1./(pow(n,2.)*pow(smooth,dimension))) * (resL + n*( gaussianFunction(0.,2.,dimension) - 2. * gaussianKernel(0.,term)) ) + (2./(n*pow(smooth,dimension)))*gaussianKernel(0.,term); */
  61. G_debug(3, "smooth = %e resL = %e", smooth, resL);
  62. G_message(_("\tScore Value=%f\tsmoothing parameter (standard deviation)=%f"),
  63. resL, smooth);
  64. return (resL);
  65. }
  66. int main(int argc, char **argv)
  67. {
  68. struct Option *in_opt, *net_opt, *out_opt;
  69. struct Option *stddev_opt, *dsize_opt, *segmax_opt, *netmax_opt,
  70. *multip_opt;
  71. struct Flag *flag_o, *flag_q;
  72. char *mapset;
  73. struct Map_info In, Net, Out;
  74. int fdout = 0, maskfd = 0;
  75. int row, col;
  76. struct Cell_head window;
  77. double gaussian;
  78. double N, E;
  79. CELL *mask = NULL;
  80. DCELL *output_cell = NULL;
  81. double sigma, dmax, segmax, netmax, multip;
  82. double **coordinate;
  83. double sigmaOptimal;
  84. struct GModule *module;
  85. double dsize;
  86. double term;
  87. double gausmax = 0;
  88. /* Initialize the GIS calls */
  89. G_gisinit(argv[0]);
  90. module = G_define_module();
  91. module->keywords = _("vector, kernel density");
  92. module->description =
  93. _
  94. ("Generates a raster density map from vector points data using a moving 2D isotropic Gaussian kernel or "
  95. "optionally generates a vector density map on vector network with a 1D kernel.");
  96. in_opt = G_define_standard_option(G_OPT_V_INPUT);
  97. in_opt->description = _("Input vector with training points");
  98. net_opt = G_define_standard_option(G_OPT_V_INPUT);
  99. net_opt->key = "net";
  100. net_opt->description = _("Input network vector map");
  101. net_opt->required = NO;
  102. out_opt = G_define_option();
  103. out_opt->key = "output";
  104. out_opt->type = TYPE_STRING;
  105. out_opt->key_desc = "name";
  106. out_opt->required = YES;
  107. out_opt->description = _("Output raster/vector map");
  108. stddev_opt = G_define_option();
  109. stddev_opt->key = "stddeviation";
  110. stddev_opt->type = TYPE_DOUBLE;
  111. stddev_opt->required = YES;
  112. stddev_opt->description = _("Standard deviation in map units");
  113. dsize_opt = G_define_option();
  114. dsize_opt->key = "dsize";
  115. dsize_opt->type = TYPE_DOUBLE;
  116. dsize_opt->required = NO;
  117. dsize_opt->description = _("Discretization error in map units");
  118. dsize_opt->answer = "0.";
  119. segmax_opt = G_define_option();
  120. segmax_opt->key = "segmax";
  121. segmax_opt->type = TYPE_DOUBLE;
  122. segmax_opt->required = NO;
  123. segmax_opt->description = _("Maximum length of segment on network");
  124. segmax_opt->answer = "100.";
  125. netmax_opt = G_define_option();
  126. netmax_opt->key = "distmax";
  127. netmax_opt->type = TYPE_DOUBLE;
  128. netmax_opt->required = NO;
  129. netmax_opt->description = _("Maximum distance from point to network");
  130. netmax_opt->answer = "100.";
  131. multip_opt = G_define_option();
  132. multip_opt->key = "mult";
  133. multip_opt->type = TYPE_DOUBLE;
  134. multip_opt->required = NO;
  135. multip_opt->description = _("Multiply the density result by this number");
  136. multip_opt->answer = "1.";
  137. flag_o = G_define_flag();
  138. flag_o->key = 'o';
  139. flag_o->description =
  140. _
  141. ("Try to calculate an optimal standard deviation with 'stddeviation' taken as maximum (experimental)");
  142. flag_q = G_define_flag();
  143. flag_q->key = 'q';
  144. flag_q->description =
  145. _
  146. ("Only calculate optimal standard deviation and exit (no map is written)");
  147. if (G_parser(argc, argv))
  148. exit(EXIT_FAILURE);
  149. /*read options */
  150. sigma = atof(stddev_opt->answer);
  151. dsize = atof(dsize_opt->answer);
  152. segmax = atof(segmax_opt->answer);
  153. netmax = atof(netmax_opt->answer);
  154. multip = atof(multip_opt->answer);
  155. if (flag_q->answer) {
  156. flag_o->answer = 1;
  157. }
  158. if (net_opt->answer) {
  159. Vect_check_input_output_name(in_opt->answer, out_opt->answer,
  160. GV_FATAL_EXIT);
  161. Vect_check_input_output_name(net_opt->answer, out_opt->answer,
  162. GV_FATAL_EXIT);
  163. }
  164. G_get_window(&window);
  165. G_message("STDDEV: %f\nRES: %f\tROWS: %d\tCOLS: %d",
  166. sigma, window.ew_res, window.rows, window.cols);
  167. /* Open input vector */
  168. if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL)
  169. G_fatal_error(_("Vector map <%s> not found"), in_opt->answer);
  170. Vect_set_open_level(2);
  171. Vect_open_old(&In, in_opt->answer, mapset);
  172. if (net_opt->answer) {
  173. int nlines, line;
  174. int notreachable = 0;
  175. struct line_pnts *Points;
  176. Points = Vect_new_line_struct();
  177. net = 1;
  178. dimension = 1.;
  179. /* Open input network */
  180. if ((mapset = G_find_vector2(net_opt->answer, "")) == NULL)
  181. G_fatal_error(_("Network input map <%s> not found"),
  182. net_opt->answer);
  183. Vect_set_open_level(2);
  184. Vect_open_old(&Net, net_opt->answer, mapset);
  185. Vect_net_build_graph(&Net, GV_LINES, 0, 0, NULL, NULL, NULL, 0, 0);
  186. if (!flag_q->answer) {
  187. Vect_open_new(&Out, out_opt->answer, 0);
  188. Vect_hist_command(&Out);
  189. }
  190. /* verify not reachable points */
  191. nlines = Vect_get_num_lines(&In);
  192. for (line = 1; line <= nlines; line++) {
  193. int ltype;
  194. ltype = Vect_read_line(&In, Points, NULL, line);
  195. if (!(ltype & GV_POINTS))
  196. continue;
  197. if (Vect_find_line
  198. (&Net, Points->x[0], Points->y[0], 0.0, GV_LINES, netmax, 0,
  199. 0) == 0)
  200. notreachable++;
  201. }
  202. if (notreachable > 0)
  203. G_warning(_("%d points outside threshold"), notreachable);
  204. }
  205. else {
  206. /* check and open the name of output map */
  207. if (!flag_q->answer) {
  208. if (G_legal_filename(out_opt->answer) < 0)
  209. G_fatal_error(_("<%s> is an illegal file name"),
  210. out_opt->answer);
  211. G_set_fp_type(DCELL_TYPE);
  212. if ((fdout = G_open_raster_new(out_opt->answer, DCELL_TYPE)) < 0)
  213. G_fatal_error(_("Unable to create raster map <%s>"),
  214. out_opt->answer);
  215. /* open mask file */
  216. if ((maskfd = G_maskfd()) >= 0)
  217. mask = G_allocate_cell_buf();
  218. else
  219. mask = NULL;
  220. /* allocate output raster */
  221. output_cell = G_allocate_raster_buf(DCELL_TYPE);
  222. }
  223. }
  224. /* valutazione distanza ottimale */
  225. if (flag_o->answer) {
  226. /* Note: sigmaOptimal calculates using ALL points (also those outside the region) */
  227. G_message(_("Automatic choose of smoothing parameter (standard deviation), maximum possible "
  228. "value of standard deviation is was set to %f"), sigma);
  229. /* maximum distance 4*sigma (3.9*sigma ~ 1.0000), keep it small, otherwise it takes
  230. * too much points and calculation on network becomes slow */
  231. dmax = 4 * sigma; /* used as maximum value */
  232. G_message(_("Using maximum distance between points: %f"), dmax);
  233. if (net_opt->answer) {
  234. npoints = Vect_get_num_primitives(&In, GV_POINTS);
  235. /* Warning: each distance is registered twice (both directions) */
  236. ndists =
  237. compute_all_net_distances(&In, &Net, netmax, &dists, dmax);
  238. }
  239. else {
  240. /* Read points */
  241. npoints = read_points(&In, &coordinate, dsize);
  242. ndists = compute_all_distances(coordinate, &dists, npoints, dmax);
  243. }
  244. G_message(_("Number of input points: %d."), npoints);
  245. G_message(_("%d distances read from the map."), ndists);
  246. if (ndists == 0)
  247. G_fatal_error(_("Distances between all points are beyond %e (4 * "
  248. "standard deviation), unable to calculate optimal value."),
  249. dmax);
  250. /* double iii;
  251. for ( iii = 1.; iii <= 10000; iii++){
  252. fprintf(stderr,"i=%f v=%.16f \n",iii,R(iii));
  253. } */
  254. /* sigma is used in brent as maximum possible value for sigmaOptimal */
  255. sigmaOptimal = brent_iterate(L, 0.0, sigma, 1000);
  256. G_message(_("Optimal smoothing parameter (standard deviation): %f."),
  257. sigmaOptimal);
  258. /* Reset sigma to calculated optimal value */
  259. sigma = sigmaOptimal;
  260. if (flag_q->answer) {
  261. Vect_close(&In);
  262. if (net_opt->answer)
  263. Vect_close(&Net);
  264. exit(EXIT_SUCCESS);
  265. }
  266. }
  267. term = 1. / (pow(sigma, dimension) * pow((2. * M_PI), dimension / 2.));
  268. dmax = sigma * 4.;
  269. if (net) {
  270. int line, nlines;
  271. struct line_pnts *Points, *SPoints;
  272. struct line_cats *SCats;
  273. G_message(_("\nWriting output vector map using smooth parameter=%f."),
  274. sigma);
  275. G_message(_("\nNormalising factor=%f."),
  276. 1. / gaussianFunction(sigma / 4., sigma, dimension));
  277. /* Divide lines to segments and calculate gaussian for center of each segment */
  278. Points = Vect_new_line_struct();
  279. SPoints = Vect_new_line_struct();
  280. SCats = Vect_new_cats_struct();
  281. nlines = Vect_get_num_lines(&Net);
  282. G_debug(3, "net nlines = %d", nlines);
  283. for (line = 1; line <= nlines; line++) {
  284. int seg, nseg, ltype;
  285. double llength, length, x, y;
  286. ltype = Vect_read_line(&Net, Points, NULL, line);
  287. if (!(ltype & GV_LINES))
  288. continue;
  289. llength = Vect_line_length(Points);
  290. nseg = (int)(1 + llength / segmax);
  291. length = llength / nseg;
  292. G_debug(3, "net line = %d, nseg = %d, seg length = %f", line,
  293. nseg, length);
  294. for (seg = 0; seg < nseg; seg++) {
  295. double offset1, offset2;
  296. offset1 = (seg + 0.5) * length;
  297. Vect_point_on_line(Points, offset1, &x, &y, NULL, NULL, NULL);
  298. G_debug(3, " segment = %d, offset = %f, xy = %f %f", seg,
  299. offset1, x, y);
  300. compute_net_distance(x, y, &In, &Net, netmax, sigma, term,
  301. &gaussian, dmax);
  302. gaussian *= multip;
  303. if (gaussian > gausmax)
  304. gausmax = gaussian;
  305. G_debug(3, " gaussian = %f", gaussian);
  306. /* Write segment */
  307. if (gaussian > 0) {
  308. offset1 = seg * length;
  309. offset2 = (seg + 1) * length;
  310. if (offset2 > llength)
  311. offset2 = llength;
  312. Vect_line_segment(Points, offset1, offset2, SPoints);
  313. /* TODO!!! remove later
  314. if ( SPoints->n_points > 0 )
  315. Vect_append_point( SPoints, SPoints->x[SPoints->n_points-1],
  316. SPoints->y[SPoints->n_points-1], 0 );
  317. */
  318. Vect_reset_cats(SCats);
  319. Vect_cat_set(SCats, 1, (int)gaussian);
  320. Vect_write_line(&Out, GV_LINE, SPoints, SCats);
  321. }
  322. }
  323. G_percent(line, nlines, 1);
  324. }
  325. Vect_close(&Net);
  326. Vect_build(&Out, stderr);
  327. Vect_close(&Out);
  328. }
  329. else {
  330. G_message(_("\nWriting output raster map using smooth parameter=%f."),
  331. sigma);
  332. G_message(_("\nNormalising factor=%f."),
  333. 1. / gaussianFunction(sigma / 4., sigma, dimension));
  334. for (row = 0; row < window.rows; row++) {
  335. G_percent(row, window.rows, 2);
  336. if (mask) {
  337. if (G_get_map_row(maskfd, mask, row) < 0)
  338. G_fatal_error(_("Unable to read MASK"));
  339. }
  340. for (col = 0; col < window.cols; col++) {
  341. /* don't interpolate outside of the mask */
  342. if (mask && mask[col] == 0) {
  343. G_set_d_null_value(&output_cell[col], 1);
  344. continue;
  345. }
  346. N = G_row_to_northing(row + 0.5, &window);
  347. E = G_col_to_easting(col + 0.5, &window);
  348. compute_distance(N, E, &In, sigma, term, &gaussian, dmax);
  349. output_cell[col] = multip * gaussian;
  350. if (gaussian > gausmax)
  351. gausmax = gaussian;
  352. }
  353. G_put_raster_row(fdout, output_cell, DCELL_TYPE);
  354. }
  355. G_close_cell(fdout);
  356. }
  357. G_message(_("Maximum value in output: %e."), gausmax);
  358. Vect_close(&In);
  359. exit(EXIT_SUCCESS);
  360. }
  361. /* Read points to array return number of points */
  362. int read_points(struct Map_info *In, double ***coordinate, double dsize)
  363. {
  364. int line, nlines, npoints, ltype, i = 0;
  365. double **xySites;
  366. static struct line_pnts *Points = NULL;
  367. if (!Points)
  368. Points = Vect_new_line_struct();
  369. /* Allocate array of pointers */
  370. npoints = Vect_get_num_primitives(In, GV_POINT);
  371. xySites = (double **)G_calloc(npoints, sizeof(double *));
  372. nlines = Vect_get_num_lines(In);
  373. for (line = 1; line <= nlines; line++) {
  374. ltype = Vect_read_line(In, Points, NULL, line);
  375. if (!(ltype & GV_POINT))
  376. continue;
  377. xySites[i] = (double *)G_calloc((size_t) 2, sizeof(double));
  378. xySites[i][0] = Points->x[0];
  379. xySites[i][1] = Points->y[0];
  380. i++;
  381. }
  382. *coordinate = xySites;
  383. return (npoints);
  384. }
  385. /* Calculate distances < dmax between all sites in coordinate
  386. * Return: number of distances in dists */
  387. double compute_all_distances(double **coordinate, double **dists, int n,
  388. double dmax)
  389. {
  390. int ii, jj, kk;
  391. size_t nn;
  392. nn = n * (n - 1) / 2;
  393. *dists = (double *)G_calloc(nn, sizeof(double));
  394. kk = 0;
  395. for (ii = 0; ii < n - 1; ii++) {
  396. for (jj = ii + 1; jj < n; jj++) {
  397. double dist;
  398. dist = euclidean_distance(coordinate[ii], coordinate[jj], 2);
  399. G_debug(3, "dist = %f", dist);
  400. if (dist <= dmax) {
  401. (*dists)[kk] = dist;
  402. kk++;
  403. }
  404. }
  405. }
  406. return (kk);
  407. }
  408. /* Calculate distances < dmax between all sites in coordinate
  409. * Return: number of distances in dists */
  410. double compute_all_net_distances(struct Map_info *In, struct Map_info *Net,
  411. double netmax, double **dists, double dmax)
  412. {
  413. int nn, kk, nalines, aline;
  414. double dist;
  415. struct line_pnts *APoints, *BPoints;
  416. BOUND_BOX box;
  417. struct ilist *List;
  418. APoints = Vect_new_line_struct();
  419. BPoints = Vect_new_line_struct();
  420. List = Vect_new_list();
  421. nn = Vect_get_num_primitives(In, GV_POINTS);
  422. nn = nn * (nn - 1);
  423. *dists = (double *)G_calloc(nn, sizeof(double));
  424. kk = 0;
  425. nalines = Vect_get_num_lines(In);
  426. for (aline = 1; aline <= nalines; aline++) {
  427. int i, altype;
  428. G_debug(3, " aline = %d", aline);
  429. altype = Vect_read_line(In, APoints, NULL, aline);
  430. if (!(altype & GV_POINTS))
  431. continue;
  432. box.E = APoints->x[0] + dmax;
  433. box.W = APoints->x[0] - dmax;
  434. box.N = APoints->y[0] + dmax;
  435. box.S = APoints->y[0] - dmax;
  436. box.T = PORT_DOUBLE_MAX;
  437. box.B = -PORT_DOUBLE_MAX;
  438. Vect_select_lines_by_box(In, &box, GV_POINT, List);
  439. G_debug(3, " %d points in box", List->n_values);
  440. for (i = 0; i < List->n_values; i++) {
  441. int bline, ret;
  442. bline = List->value[i];
  443. if (bline == aline)
  444. continue;
  445. G_debug(3, " bline = %d", bline);
  446. Vect_read_line(In, BPoints, NULL, bline);
  447. ret =
  448. Vect_net_shortest_path_coor(Net, APoints->x[0], APoints->y[0],
  449. 0.0, BPoints->x[0], BPoints->y[0],
  450. 0.0, netmax, netmax, &dist, NULL,
  451. NULL, NULL, NULL, NULL, NULL);
  452. G_debug(3, " SP: %f %f -> %f %f", APoints->x[0], APoints->y[0],
  453. BPoints->x[0], BPoints->y[0]);
  454. if (ret == 0) {
  455. G_debug(3, "not reachable");
  456. continue; /* Not reachable */
  457. }
  458. G_debug(3, " dist = %f", dist);
  459. if (dist <= dmax) {
  460. (*dists)[kk] = dist;
  461. kk++;
  462. }
  463. G_debug(3, " kk = %d", kk);
  464. }
  465. }
  466. return (kk);
  467. }
  468. /* Compute gausian for x, y along Net, using all points in In */
  469. void compute_net_distance(double x, double y, struct Map_info *In,
  470. struct Map_info *Net, double netmax, double sigma,
  471. double term, double *gaussian, double dmax)
  472. {
  473. int i;
  474. double dist;
  475. static struct line_pnts *Points = NULL;
  476. BOUND_BOX box;
  477. static struct ilist *List = NULL;
  478. if (!Points)
  479. Points = Vect_new_line_struct();
  480. if (!List)
  481. List = Vect_new_list();
  482. *gaussian = .0;
  483. /* The network is usually much bigger than dmax and to calculate shortest path is slow
  484. * -> use spatial index to select points */
  485. box.E = x + dmax;
  486. box.W = x - dmax;
  487. box.N = y + dmax;
  488. box.S = y - dmax;
  489. box.T = PORT_DOUBLE_MAX;
  490. box.B = -PORT_DOUBLE_MAX;
  491. Vect_select_lines_by_box(In, &box, GV_POINT, List);
  492. G_debug(3, " %d points in box", List->n_values);
  493. for (i = 0; i < List->n_values; i++) {
  494. int line, ret;
  495. line = List->value[i];
  496. Vect_read_line(In, Points, NULL, line);
  497. G_debug(3, " SP: %f %f -> %f %f", x, y, Points->x[0], Points->y[0]);
  498. ret =
  499. Vect_net_shortest_path_coor(Net, x, y, 0.0, Points->x[0],
  500. Points->y[0], 0.0, netmax, netmax,
  501. &dist, NULL, NULL, NULL, NULL, NULL,
  502. NULL);
  503. if (ret == 0) {
  504. G_debug(3, "not reachable");
  505. continue; /* Not reachable */
  506. }
  507. if (dist <= dmax)
  508. *gaussian += gaussianKernel(dist / sigma, term);
  509. G_debug(3, " dist = %f gaussian = %f", dist, *gaussian);
  510. }
  511. }
  512. void compute_distance(double N, double E, struct Map_info *In,
  513. double sigma, double term, double *gaussian,
  514. double dmax)
  515. {
  516. int line, nlines;
  517. double a[2], b[2];
  518. double dist;
  519. /* spatial index handling, borrowed from lib/vector/Vlib/find.c */
  520. BOUND_BOX box;
  521. static struct ilist *NList = NULL;
  522. static struct line_pnts *Points = NULL;
  523. a[0] = E;
  524. a[1] = N;
  525. if (!NList)
  526. NList = Vect_new_list();
  527. if (!Points)
  528. Points = Vect_new_line_struct();
  529. /* create bounding box 2x2*dmax size from the current cell center */
  530. box.N = N + dmax;
  531. box.S = N - dmax;
  532. box.E = E + dmax;
  533. box.W = E - dmax;
  534. box.T = HUGE_VAL;
  535. box.B = -HUGE_VAL;
  536. /* number of lines within dmax box */
  537. nlines = Vect_select_lines_by_box(In, &box, GV_POINT, NList);
  538. *gaussian = .0;
  539. for (line = 0; line < nlines; line++) {
  540. Vect_read_line(In, Points, NULL, NList->value[line]);
  541. b[0] = Points->x[0];
  542. b[1] = Points->y[0];
  543. dist = euclidean_distance(a, b, 2);
  544. if (dist <= dmax)
  545. *gaussian += gaussianKernel(dist / sigma, term);
  546. }
  547. }