main.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  1. /****************************************************************************
  2. *
  3. * MODULE: v.kernel
  4. *
  5. * AUTHOR(S): Stefano Menegon, ITC-irst, Trento, Italy
  6. * Radim Blazek (additional kernel functions, network part)
  7. * PURPOSE: Generates a raster density map from vector points data using
  8. * a moving kernel function or
  9. * optionally generates a vector density map on vector network
  10. * with a 1D kernel
  11. * COPYRIGHT: (C) 2004-2011 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. *****************************************************************************/
  18. #include <math.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <float.h>
  22. #include <string.h>
  23. #include <grass/gis.h>
  24. #include <grass/raster.h>
  25. #include <grass/glocale.h>
  26. #include <grass/gmath.h>
  27. #include <grass/vector.h>
  28. #include "global.h"
  29. static int ndists; /* number of distances in dists */
  30. static double *dists; /* array of all distances < dmax */
  31. static int npoints;
  32. int net = 0;
  33. static double dimension = 2.;
  34. /* define score function L(window size) */
  35. double L(double smooth)
  36. {
  37. int ii;
  38. double resL, n, term;
  39. n = npoints;
  40. resL = 0.;
  41. term = 1. / pow((2. * M_PI), dimension / 2.);
  42. for (ii = 0; ii < ndists; ii++) {
  43. /* resL+= gaussianFunction(dists[ii]/smooth,2.,dimension) - 2. * gaussianKernel(dists[ii]/smooth,term); */
  44. resL +=
  45. gaussianFunction(dists[ii] / smooth, 2.,
  46. dimension) -
  47. 2. * gaussianFunction(dists[ii] / smooth, 1., dimension);
  48. }
  49. if (!net)
  50. resL *= 2.;
  51. resL = (1. / (pow(n, 2.) * pow(smooth, dimension))) *
  52. (resL + n * (gaussianFunction(0., 2., dimension) -
  53. 2. * gaussianFunction(0., 1., dimension))) +
  54. (2. / (n * pow(smooth, dimension))) *
  55. gaussianFunction(0., 1., dimension);
  56. /* 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); */
  57. G_debug(3, "smooth = %e resL = %e", smooth, resL);
  58. G_message(_("\tScore Value=%f\tsmoothing parameter (standard deviation)=%f"),
  59. resL, smooth);
  60. return (resL);
  61. }
  62. int main(int argc, char **argv)
  63. {
  64. struct Option *in_opt, *net_opt, *out_opt, *net_out_opt;
  65. struct Option *radius_opt, *dsize_opt, *segmax_opt, *netmax_opt,
  66. *multip_opt, *node_opt, *kernel_opt;
  67. struct Flag *flag_o, *flag_q, *flag_normalize, *flag_multiply;
  68. char *desc;
  69. struct Map_info In, Net, Out;
  70. int fdout = -1, maskfd = -1;
  71. int node_method, kernel_function;
  72. int row, col;
  73. struct Cell_head window;
  74. double gaussian;
  75. double N, E;
  76. CELL *mask = NULL;
  77. DCELL *output_cell = NULL;
  78. double sigma, dmax, segmax, netmax, multip;
  79. char *tmpstr1, *tmpstr2;
  80. struct History history;
  81. double **coordinate;
  82. double sigmaOptimal;
  83. struct GModule *module;
  84. double dsize;
  85. double term = 0;
  86. double gausmax = 0;
  87. int notreachable = 0;
  88. /* Initialize the GIS calls */
  89. G_gisinit(argv[0]);
  90. module = G_define_module();
  91. G_add_keyword(_("vector"));
  92. G_add_keyword(_("kernel density"));
  93. G_add_keyword(_("point density"));
  94. G_add_keyword(_("heatmap"));
  95. G_add_keyword(_("hotspot"));
  96. module->label =
  97. _("Generates a raster density map from vector points map.");
  98. module->description = _("Density is computed using a moving kernel. "
  99. "Optionally generates a vector density map on a vector network.");
  100. in_opt = G_define_standard_option(G_OPT_V_INPUT);
  101. in_opt->label = _("Name of input vector map with training points");
  102. in_opt->description = NULL;
  103. in_opt->guisection = _("Basic");
  104. net_opt = G_define_standard_option(G_OPT_V_INPUT);
  105. net_opt->key = "net";
  106. net_opt->label = _("Name of input network vector map");
  107. net_opt->description = NULL;
  108. net_opt->required = NO;
  109. net_opt->guisection = _("Network");
  110. out_opt = G_define_standard_option(G_OPT_R_OUTPUT);
  111. out_opt->key = "output";
  112. out_opt->required = NO;
  113. out_opt->label = _("Name for output raster map");
  114. out_opt->description = NULL;
  115. out_opt->guisection = _("Basic");
  116. net_out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
  117. net_out_opt->key = "net_output";
  118. net_out_opt->required = NO;
  119. net_out_opt->label = _("Name for output vector density map");
  120. net_out_opt->description = _("Outputs vector map if network map is given");
  121. net_out_opt->guisection = _("Network");
  122. radius_opt = G_define_option();
  123. radius_opt->key = "radius";
  124. radius_opt->type = TYPE_DOUBLE;
  125. radius_opt->required = YES;
  126. radius_opt->description = _("Kernel radius in map units");
  127. radius_opt->guisection = _("Basic");
  128. dsize_opt = G_define_option();
  129. dsize_opt->key = "dsize";
  130. dsize_opt->type = TYPE_DOUBLE;
  131. dsize_opt->required = NO;
  132. dsize_opt->description = _("Discretization error in map units");
  133. dsize_opt->answer = "0.";
  134. segmax_opt = G_define_option();
  135. segmax_opt->key = "segmax";
  136. segmax_opt->type = TYPE_DOUBLE;
  137. segmax_opt->required = NO;
  138. segmax_opt->description = _("Maximum length of segment on network");
  139. segmax_opt->answer = "100.";
  140. segmax_opt->guisection = _("Network");
  141. netmax_opt = G_define_option();
  142. netmax_opt->key = "distmax";
  143. netmax_opt->type = TYPE_DOUBLE;
  144. netmax_opt->required = NO;
  145. netmax_opt->description = _("Maximum distance from point to network");
  146. netmax_opt->answer = "100.";
  147. netmax_opt->guisection = _("Network");
  148. multip_opt = G_define_option();
  149. multip_opt->key = "multiplier";
  150. multip_opt->type = TYPE_DOUBLE;
  151. multip_opt->required = NO;
  152. multip_opt->description = _("Multiply the density result by this number");
  153. multip_opt->answer = "1.";
  154. node_opt = G_define_option();
  155. node_opt->key = "node";
  156. node_opt->type = TYPE_STRING;
  157. node_opt->required = NO;
  158. node_opt->description = _("Node method");
  159. node_opt->options = "none,split";
  160. node_opt->answer = "none";
  161. desc = NULL;
  162. G_asprintf(&desc,
  163. "none;%s;split;%s",
  164. _("No method applied at nodes with more than 2 arcs"),
  165. _("Equal split (Okabe 2009) applied at nodes"));
  166. node_opt->descriptions = desc;
  167. node_opt->guisection = _("Network");
  168. kernel_opt = G_define_option();
  169. kernel_opt->key = "kernel";
  170. kernel_opt->type = TYPE_STRING;
  171. kernel_opt->required = NO;
  172. kernel_opt->description = _("Kernel function");
  173. kernel_opt->options =
  174. "uniform,triangular,epanechnikov,quartic,triweight,gaussian,cosine";
  175. kernel_opt->answer = "gaussian";
  176. flag_o = G_define_flag();
  177. flag_o->key = 'o';
  178. flag_o->description =
  179. _("Try to calculate an optimal radius with given 'radius' taken as maximum (experimental)");
  180. flag_q = G_define_flag();
  181. flag_q->key = 'q';
  182. flag_q->description =
  183. _("Only calculate optimal radius and exit (no map is written)");
  184. flag_normalize = G_define_flag();
  185. flag_normalize->key = 'n';
  186. flag_normalize->description =
  187. _("In network mode, normalize values by sum of density multiplied by length of each segment. Integral over the output map then gives 1.0 * multiplier");
  188. flag_normalize->guisection = _("Network");
  189. flag_multiply = G_define_flag();
  190. flag_multiply->key = 'm';
  191. flag_multiply->description =
  192. _("In network mode, multiply the result by number of input points");
  193. flag_multiply->guisection = _("Network");
  194. G_option_required(out_opt, net_out_opt, NULL);
  195. G_option_exclusive(out_opt, net_out_opt, NULL);
  196. /* TODO: this should be activated for GRASS 8
  197. G_option_requires(net_opt, net_out_opt, NULL);
  198. */
  199. if (G_parser(argc, argv))
  200. exit(EXIT_FAILURE);
  201. if (net_opt->answer && out_opt->answer) {
  202. G_warning(_("Use option net_output if you compute network density. "
  203. "Name provided in option output will be used for net_output."));
  204. net_out_opt->answer = out_opt->answer;
  205. out_opt->answer = NULL;
  206. }
  207. /*read options */
  208. dmax = atof(radius_opt->answer);
  209. sigma = dmax;
  210. dsize = atof(dsize_opt->answer);
  211. segmax = atof(segmax_opt->answer);
  212. netmax = atof(netmax_opt->answer);
  213. multip = atof(multip_opt->answer);
  214. if (strcmp(node_opt->answer, "none") == 0)
  215. node_method = NODE_NONE;
  216. else if (strcmp(node_opt->answer, "split") == 0)
  217. node_method = NODE_EQUAL_SPLIT;
  218. else
  219. G_fatal_error(_("Unknown node method"));
  220. kernel_function = KERNEL_GAUSSIAN;
  221. if (strcmp(kernel_opt->answer, "uniform") == 0)
  222. kernel_function = KERNEL_UNIFORM;
  223. else if (strcmp(kernel_opt->answer, "triangular") == 0)
  224. kernel_function = KERNEL_TRIANGULAR;
  225. else if (strcmp(kernel_opt->answer, "epanechnikov") == 0)
  226. kernel_function = KERNEL_EPANECHNIKOV;
  227. else if (strcmp(kernel_opt->answer, "quartic") == 0)
  228. kernel_function = KERNEL_QUARTIC;
  229. else if (strcmp(kernel_opt->answer, "triweight") == 0)
  230. kernel_function = KERNEL_TRIWEIGHT;
  231. else if (strcmp(kernel_opt->answer, "gaussian") == 0)
  232. kernel_function = KERNEL_GAUSSIAN;
  233. else if (strcmp(kernel_opt->answer, "cosine") == 0)
  234. kernel_function = KERNEL_COSINE;
  235. else
  236. G_fatal_error(_("Unknown kernel function"));
  237. if (flag_o->answer) {
  238. if (net_opt->answer) {
  239. if (node_method != NODE_NONE ||
  240. kernel_function != KERNEL_GAUSSIAN) {
  241. G_fatal_error(_("Optimal standard deviation calculation is supported only for node method 'none' and kernel function 'gaussian'."));
  242. }
  243. }
  244. else if (kernel_function != KERNEL_GAUSSIAN) {
  245. G_fatal_error(_("Optimal standard deviation calculation is supported only for kernel function 'gaussian'."));
  246. }
  247. }
  248. if (flag_q->answer) {
  249. flag_o->answer = 1;
  250. }
  251. if (net_opt->answer) {
  252. Vect_check_input_output_name(in_opt->answer, net_out_opt->answer,
  253. G_FATAL_EXIT);
  254. Vect_check_input_output_name(net_opt->answer, net_out_opt->answer,
  255. G_FATAL_EXIT);
  256. }
  257. G_get_window(&window);
  258. G_verbose_message(_("Standard deviation: %f"), sigma);
  259. G_asprintf(&tmpstr1, n_("%d row", "%d rows", window.rows), window.rows);
  260. G_asprintf(&tmpstr2, n_("%d column", "%d columns", window.cols), window.cols);
  261. /* GTC First argument is resolution, second - number of rows as a text, third - number of columns as a text. */
  262. if (G_verbose() > G_verbose_std()) {
  263. G_verbose_message(_("Output raster map: resolution: %f\t%s\t%s"), /* mhh, this assumes square pixels */
  264. window.ew_res, tmpstr1, tmpstr2);
  265. } else {
  266. G_message(_("Output raster map resolution: %f"), window.ew_res); /* mhh, this assumes square pixels */
  267. }
  268. G_free(tmpstr1);
  269. G_free(tmpstr2);
  270. /* Open input vector */
  271. Vect_set_open_level(2);
  272. if (Vect_open_old(&In, in_opt->answer, "") < 0)
  273. G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer);
  274. if (net_opt->answer) {
  275. int nlines, line;
  276. struct line_pnts *Points;
  277. Points = Vect_new_line_struct();
  278. net = 1;
  279. dimension = 1.;
  280. /* Open input network */
  281. Vect_set_open_level(2);
  282. if (Vect_open_old(&Net, net_opt->answer, "") < 0)
  283. G_fatal_error(_("Unable to open vector map <%s>"), net_opt->answer);
  284. Vect_net_build_graph(&Net, GV_LINES, 0, 0, NULL, NULL, NULL, 0, 0);
  285. if (!flag_q->answer) {
  286. if (Vect_open_new(&Out, net_out_opt->answer, 0) < 0)
  287. G_fatal_error(_("Unable to create vector map <%s>"),
  288. net_out_opt->answer);
  289. Vect_hist_command(&Out);
  290. }
  291. /* verify not reachable points */
  292. nlines = Vect_get_num_lines(&In);
  293. for (line = 1; line <= nlines; line++) {
  294. int ltype;
  295. ltype = Vect_read_line(&In, Points, NULL, line);
  296. if (!(ltype & GV_POINTS))
  297. continue;
  298. if (Vect_find_line
  299. (&Net, Points->x[0], Points->y[0], 0.0, GV_LINES, netmax, 0,
  300. 0) == 0)
  301. notreachable++;
  302. }
  303. if (notreachable > 0)
  304. G_warning(n_("%d point outside threshold",
  305. "%d points outside threshold",
  306. notreachable), notreachable);
  307. }
  308. else {
  309. /* check and open the name of output map */
  310. if (!flag_q->answer) {
  311. fdout = Rast_open_new(out_opt->answer, DCELL_TYPE);
  312. /* open mask file */
  313. if ((maskfd = Rast_maskfd()) >= 0)
  314. mask = Rast_allocate_c_buf();
  315. else
  316. mask = NULL;
  317. /* allocate output raster */
  318. output_cell = Rast_allocate_buf(DCELL_TYPE);
  319. }
  320. }
  321. /* valutazione distanza ottimale */
  322. if (flag_o->answer) {
  323. /* Note: sigmaOptimal calculates using ALL points (also those outside the region) */
  324. G_message(_("Automatic choice of smoothing parameter (radius), maximum possible "
  325. "value of radius is set to %f"), sigma);
  326. /* maximum distance 4*sigma (3.9*sigma ~ 1.0000), keep it small, otherwise it takes
  327. * too much points and calculation on network becomes slow */
  328. dmax = 4 * sigma; /* used as maximum value */
  329. G_message(_("Using maximum distance between points: %f"), dmax);
  330. if (net_opt->answer) {
  331. npoints = Vect_get_num_primitives(&In, GV_POINTS);
  332. /* Warning: each distance is registered twice (both directions) */
  333. ndists =
  334. compute_all_net_distances(&In, &Net, netmax, &dists, dmax);
  335. }
  336. else {
  337. /* Read points */
  338. npoints = read_points(&In, &coordinate, dsize);
  339. ndists = compute_all_distances(coordinate, &dists, npoints, dmax);
  340. }
  341. G_message(_("Number of input points: %d."), npoints);
  342. G_message(n_("%d distance read from the map.",
  343. "%d distances read from the map.",
  344. ndists), ndists);
  345. if (ndists == 0)
  346. G_fatal_error(_("Distances between all points are beyond %e (4 * "
  347. "standard deviation), unable to calculate optimal value."),
  348. dmax);
  349. /* double iii;
  350. for ( iii = 1.; iii <= 10000; iii++){
  351. fprintf(stderr,"i=%f v=%.16f \n",iii,R(iii));
  352. } */
  353. /* sigma is used in brent as maximum possible value for sigmaOptimal */
  354. sigmaOptimal = brent_iterate(L, 0.0, sigma, 1000);
  355. G_message(_("Optimal smoothing parameter (standard deviation): %f."),
  356. sigmaOptimal);
  357. /* Reset sigma to calculated optimal value */
  358. sigma = sigmaOptimal;
  359. if (flag_q->answer) {
  360. Vect_close(&In);
  361. if (net_opt->answer)
  362. Vect_close(&Net);
  363. exit(EXIT_SUCCESS);
  364. }
  365. }
  366. if (kernel_function == KERNEL_GAUSSIAN)
  367. sigma /= 4.;
  368. if (net_opt->answer) {
  369. setKernelFunction(kernel_function, 1, sigma, &term);
  370. }
  371. else {
  372. setKernelFunction(kernel_function, 2, sigma, &term);
  373. }
  374. if (net) {
  375. int line, nlines;
  376. struct line_pnts *Points, *SPoints;
  377. struct line_cats *SCats;
  378. double total = 0.0;
  379. G_verbose_message(_("Writing output vector map using smooth parameter %f"),
  380. sigma);
  381. G_verbose_message(_("Normalising factor %f"),
  382. 1. / gaussianFunction(sigma / 4., sigma, dimension));
  383. /* Divide lines to segments and calculate gaussian for center of each segment */
  384. Points = Vect_new_line_struct();
  385. SPoints = Vect_new_line_struct();
  386. SCats = Vect_new_cats_struct();
  387. nlines = Vect_get_num_lines(&Net);
  388. G_debug(3, "net nlines = %d", nlines);
  389. for (line = 1; line <= nlines; line++) {
  390. int seg, nseg, ltype;
  391. double llength, length, x, y;
  392. G_percent(line, nlines, 5);
  393. ltype = Vect_read_line(&Net, Points, NULL, line);
  394. if (!(ltype & GV_LINES))
  395. continue;
  396. llength = Vect_line_length(Points);
  397. nseg = (int)(1 + llength / segmax);
  398. length = llength / nseg;
  399. G_debug(3, "net line = %d, nseg = %d, seg length = %f", line,
  400. nseg, length);
  401. for (seg = 0; seg < nseg; seg++) {
  402. double offset1, offset2;
  403. offset1 = (seg + 0.5) * length;
  404. Vect_point_on_line(Points, offset1, &x, &y, NULL, NULL, NULL);
  405. G_debug(3, " segment = %d, offset = %f, xy = %f %f", seg,
  406. offset1, x, y);
  407. compute_net_distance(x, y, &In, &Net, netmax, sigma, term,
  408. &gaussian, dmax, node_method);
  409. gaussian *= multip;
  410. if (gaussian > gausmax)
  411. gausmax = gaussian;
  412. G_debug(3, " gaussian = %f", gaussian);
  413. /* Write segment */
  414. if (gaussian > 0) {
  415. offset1 = seg * length;
  416. offset2 = (seg + 1) * length;
  417. if (offset2 > llength)
  418. offset2 = llength;
  419. Vect_line_segment(Points, offset1, offset2, SPoints);
  420. /* TODO!!! remove later
  421. if ( SPoints->n_points > 0 )
  422. Vect_append_point( SPoints, SPoints->x[SPoints->n_points-1],
  423. SPoints->y[SPoints->n_points-1], 0 );
  424. */
  425. Vect_reset_cats(SCats);
  426. Vect_cat_set(SCats, 1, (int)gaussian);
  427. Vect_write_line(&Out, GV_LINE, SPoints, SCats);
  428. total += length * gaussian;
  429. }
  430. }
  431. }
  432. if (flag_normalize->answer || flag_multiply->answer) {
  433. double m = multip;
  434. if (flag_normalize->answer) {
  435. m /= total;
  436. }
  437. if (flag_multiply->answer) {
  438. m *= (Vect_get_num_primitives(&In, GV_POINT) - notreachable);
  439. }
  440. Vect_build(&Out);
  441. gausmax = 0.0;
  442. nlines = Vect_get_num_lines(&Out);
  443. for (line = 1; line <= nlines; line++) {
  444. int cat;
  445. double gaussian;
  446. Vect_read_line(&Out, SPoints, SCats, line);
  447. Vect_cat_get(SCats, 1, &cat);
  448. gaussian = m * cat;
  449. Vect_reset_cats(SCats);
  450. Vect_cat_set(SCats, 1, (int)gaussian);
  451. Vect_rewrite_line(&Out, line, GV_LINE, SPoints, SCats);
  452. if (gaussian > gausmax)
  453. gausmax = gaussian;
  454. }
  455. Vect_build_partial(&Out, GV_BUILD_NONE); /* to force rebuild */
  456. }
  457. Vect_close(&Net);
  458. Vect_build(&Out);
  459. Vect_close(&Out);
  460. }
  461. else {
  462. /* spatial index handling, borrowed from lib/vector/Vlib/find.c */
  463. struct bound_box box;
  464. struct boxlist *NList = Vect_new_boxlist(1);
  465. G_verbose_message(_("Writing output raster map using smooth parameter %f"),
  466. sigma);
  467. G_verbose_message(_("Normalising factor %f"),
  468. 1. / gaussianFunction(sigma / 4., sigma, dimension));
  469. for (row = 0; row < window.rows; row++) {
  470. G_percent(row, window.rows, 2);
  471. if (mask)
  472. Rast_get_c_row(maskfd, mask, row);
  473. for (col = 0; col < window.cols; col++) {
  474. /* don't interpolate outside of the mask */
  475. if (mask && Rast_is_c_null_value(&mask[col])) {
  476. Rast_set_d_null_value(&output_cell[col], 1);
  477. continue;
  478. }
  479. N = Rast_row_to_northing(row + 0.5, &window);
  480. E = Rast_col_to_easting(col + 0.5, &window);
  481. if ((col & 31) == 0) {
  482. /* create bounding box 32x2*dmax size from the current cell center */
  483. box.N = N + dmax;
  484. box.S = N - dmax;
  485. box.E = E + dmax + 32 * window.ew_res;
  486. box.W = E - dmax;
  487. box.T = HUGE_VAL;
  488. box.B = -HUGE_VAL;
  489. Vect_select_lines_by_box(&In, &box, GV_POINT, NList);
  490. }
  491. box.N = N + dmax;
  492. box.S = N - dmax;
  493. box.E = E + dmax;
  494. box.W = E - dmax;
  495. box.T = HUGE_VAL;
  496. box.B = -HUGE_VAL;
  497. /* compute_distance(N, E, &In, sigma, term, &gaussian, dmax); */
  498. compute_distance(N, E, sigma, term, &gaussian, dmax, &box, NList);
  499. output_cell[col] = multip * gaussian;
  500. if (gaussian > gausmax)
  501. gausmax = gaussian;
  502. }
  503. Rast_put_row(fdout, output_cell, DCELL_TYPE);
  504. }
  505. G_percent(1, 1, 1);
  506. Rast_close(fdout);
  507. Rast_short_history(out_opt->answer, "raster", &history);
  508. Rast_command_history(&history);
  509. Rast_write_history(out_opt->answer, &history);
  510. }
  511. G_done_msg(_("Maximum value in output: %e."), multip * gausmax);
  512. Vect_close(&In);
  513. exit(EXIT_SUCCESS);
  514. }
  515. /* Read points to array return number of points */
  516. int read_points(struct Map_info *In, double ***coordinate, double dsize)
  517. {
  518. int line, nlines, npoints, ltype, i = 0;
  519. double **xySites;
  520. static struct line_pnts *Points = NULL;
  521. if (!Points)
  522. Points = Vect_new_line_struct();
  523. /* Allocate array of pointers */
  524. npoints = Vect_get_num_primitives(In, GV_POINT);
  525. xySites = (double **)G_calloc(npoints, sizeof(double *));
  526. nlines = Vect_get_num_lines(In);
  527. for (line = 1; line <= nlines; line++) {
  528. ltype = Vect_read_line(In, Points, NULL, line);
  529. if (!(ltype & GV_POINT))
  530. continue;
  531. xySites[i] = (double *)G_calloc((size_t) 2, sizeof(double));
  532. xySites[i][0] = Points->x[0];
  533. xySites[i][1] = Points->y[0];
  534. i++;
  535. }
  536. *coordinate = xySites;
  537. return (npoints);
  538. }
  539. /* Calculate distances < dmax between all sites in coordinate
  540. * Return: number of distances in dists */
  541. double compute_all_distances(double **coordinate, double **dists, int n,
  542. double dmax)
  543. {
  544. int ii, jj, kk;
  545. size_t nn;
  546. nn = n * (n - 1) / 2;
  547. *dists = (double *)G_calloc(nn, sizeof(double));
  548. kk = 0;
  549. for (ii = 0; ii < n - 1; ii++) {
  550. for (jj = ii + 1; jj < n; jj++) {
  551. double dist;
  552. dist = euclidean_distance(coordinate[ii], coordinate[jj], 2);
  553. G_debug(3, "dist = %f", dist);
  554. if (dist <= dmax) {
  555. (*dists)[kk] = dist;
  556. kk++;
  557. }
  558. }
  559. }
  560. return (kk);
  561. }
  562. /* Calculate distances < dmax between all sites in coordinate
  563. * Return: number of distances in dists */
  564. double compute_all_net_distances(struct Map_info *In, struct Map_info *Net,
  565. double netmax, double **dists, double dmax)
  566. {
  567. int nn, kk, nalines, aline;
  568. double dist;
  569. struct line_pnts *APoints, *BPoints;
  570. struct bound_box box;
  571. struct boxlist *List;
  572. APoints = Vect_new_line_struct();
  573. BPoints = Vect_new_line_struct();
  574. List = Vect_new_boxlist(0);
  575. nn = Vect_get_num_primitives(In, GV_POINTS);
  576. nn = nn * (nn - 1);
  577. *dists = (double *)G_calloc(nn, sizeof(double));
  578. kk = 0;
  579. nalines = Vect_get_num_lines(In);
  580. for (aline = 1; aline <= nalines; aline++) {
  581. int i, altype;
  582. G_debug(3, " aline = %d", aline);
  583. altype = Vect_read_line(In, APoints, NULL, aline);
  584. if (!(altype & GV_POINTS))
  585. continue;
  586. box.E = APoints->x[0] + dmax;
  587. box.W = APoints->x[0] - dmax;
  588. box.N = APoints->y[0] + dmax;
  589. box.S = APoints->y[0] - dmax;
  590. box.T = PORT_DOUBLE_MAX;
  591. box.B = -PORT_DOUBLE_MAX;
  592. Vect_select_lines_by_box(In, &box, GV_POINT, List);
  593. G_debug(3, " %d points in box", List->n_values);
  594. for (i = 0; i < List->n_values; i++) {
  595. int bline, ret;
  596. bline = List->id[i];
  597. if (bline == aline)
  598. continue;
  599. G_debug(3, " bline = %d", bline);
  600. Vect_read_line(In, BPoints, NULL, bline);
  601. ret =
  602. Vect_net_shortest_path_coor(Net, APoints->x[0], APoints->y[0],
  603. 0.0, BPoints->x[0], BPoints->y[0],
  604. 0.0, netmax, netmax, &dist, NULL,
  605. NULL, NULL, NULL, NULL, NULL, NULL);
  606. G_debug(3, " SP: %f %f -> %f %f", APoints->x[0], APoints->y[0],
  607. BPoints->x[0], BPoints->y[0]);
  608. if (ret == 0) {
  609. G_debug(3, "not reachable");
  610. continue; /* Not reachable */
  611. }
  612. G_debug(3, " dist = %f", dist);
  613. if (dist <= dmax) {
  614. (*dists)[kk] = dist;
  615. kk++;
  616. }
  617. G_debug(3, " kk = %d", kk);
  618. }
  619. }
  620. return (kk);
  621. }
  622. /* get number of arcs for a node */
  623. int count_node_arcs(struct Map_info *Map, int node)
  624. {
  625. int i, n, line, type;
  626. int count = 0;
  627. n = Vect_get_node_n_lines(Map, node);
  628. for (i = 0; i < n; i++) {
  629. line = Vect_get_node_line(Map, node, i);
  630. type = Vect_get_line_type(Map, abs(line));
  631. if (type & GV_LINES)
  632. count++;
  633. }
  634. return count;
  635. }
  636. /* Compute Gaussian for x, y along Net, using all points in In */
  637. void compute_net_distance(double x, double y, struct Map_info *In,
  638. struct Map_info *Net, double netmax, double sigma,
  639. double term, double *gaussian, double dmax, int node_method)
  640. {
  641. int i;
  642. double dist, kernel;
  643. static struct line_pnts *FPoints = NULL;
  644. struct bound_box box;
  645. static struct boxlist *PointsList = NULL;
  646. static struct ilist *NodesList = NULL;
  647. if (!PointsList)
  648. PointsList = Vect_new_boxlist(1);
  649. if (node_method == NODE_EQUAL_SPLIT) {
  650. if (!NodesList)
  651. NodesList = Vect_new_list();
  652. if (!FPoints)
  653. FPoints = Vect_new_line_struct();
  654. }
  655. *gaussian = .0;
  656. /* The network is usually much bigger than dmax and to calculate shortest path is slow
  657. * -> use spatial index to select points
  658. * enlarge the box by netmax (max permitted distance between a point and net) */
  659. box.E = x + dmax + netmax;
  660. box.W = x - dmax - netmax;
  661. box.N = y + dmax + netmax;
  662. box.S = y - dmax - netmax;
  663. box.T = PORT_DOUBLE_MAX;
  664. box.B = -PORT_DOUBLE_MAX;
  665. Vect_select_lines_by_box(In, &box, GV_POINT, PointsList);
  666. G_debug(3, " %d points in box", PointsList->n_values);
  667. for (i = 0; i < PointsList->n_values; i++) {
  668. int line, ret;
  669. line = PointsList->id[i];
  670. G_debug(3, " SP: %f %f -> %f %f", x, y, PointsList->box[i].E, PointsList->box[i].N);
  671. /*ret = Vect_net_shortest_path_coor(Net, x, y, 0.0, Points->x[0], */
  672. /*Points->y[0], 0.0, netmax, netmax, */
  673. /*&dist, NULL, NULL, NULL, NULL, NULL, NULL, */
  674. /*NULL); */
  675. ret = Vect_net_shortest_path_coor(Net,
  676. PointsList->box[i].E,
  677. PointsList->box[i].N, 0.0,
  678. x, y, 0.0, netmax, 1.0,
  679. &dist, NULL,
  680. NULL, NodesList, FPoints, NULL,
  681. NULL, NULL);
  682. if (ret == 0) {
  683. G_debug(3, "not reachable");
  684. continue; /* Not reachable */
  685. }
  686. /* if (dist <= dmax)
  687. *gaussian += gaussianKernel(dist / sigma, term); */
  688. if (dist > dmax)
  689. continue;
  690. /* kernel = gaussianKernel(dist / sigma, term); */
  691. kernel = kernelFunction(term, sigma, dist);
  692. if (node_method == NODE_EQUAL_SPLIT) {
  693. int j, node;
  694. double ndiv = 1.;
  695. int start = 0;
  696. /* Count the nodes and arcs on path (n1-1)*(n2-1)* ... (ns-1) */
  697. for (j = start; j < NodesList->n_values; j++) {
  698. node = NodesList->value[j];
  699. /* Divide into 2/n if point falls on a node */
  700. if (j == 0 && FPoints->n_points < 3) {
  701. ndiv *= count_node_arcs(Net, node) / 2.;
  702. }
  703. else {
  704. ndiv *= count_node_arcs(Net, node) - 1;
  705. }
  706. }
  707. kernel /= ndiv;
  708. }
  709. *gaussian += kernel;
  710. G_debug(3, " dist = %f gaussian = %f", dist, *gaussian);
  711. }
  712. }
  713. void compute_distance(double N, double E, double sigma, double term,
  714. double *gaussian, double dmax, struct bound_box *box,
  715. struct boxlist *NList)
  716. {
  717. int line, nlines;
  718. double a[2], b[2];
  719. double dist;
  720. a[0] = E;
  721. a[1] = N;
  722. /* number of lines within dmax box */
  723. nlines = NList->n_values;
  724. *gaussian = .0;
  725. for (line = 0; line < nlines; line++) {
  726. b[0] = NList->box[line].E;
  727. b[1] = NList->box[line].N;
  728. if (b[0] <= box->E && b[0] >= box->W &&
  729. b[1] <= box->N && b[1] >= box->S) {
  730. dist = euclidean_distance(a, b, 2);
  731. if (dist <= dmax)
  732. /* *gaussian += gaussianKernel(dist / sigma, term); */
  733. *gaussian += kernelFunction(term, sigma, dist);
  734. }
  735. }
  736. }