74
75
int main(int argc, char **argv)
76
77
struct Option *in_opt, *net_opt, *out_opt;
77
struct Option *stddev_opt, *dsize_opt, *segmax_opt, *netmax_opt,
78
struct Option *radius_opt, *dsize_opt, *segmax_opt, *netmax_opt,
78
79
*multip_opt, *node_opt, *kernel_opt;
79
struct Flag *flag_o, *flag_q, *flag_normalize, *flag_multiply, *flag_v;
80
struct Flag *flag_o, *flag_q, *flag_normalize, *flag_multiply;
82
83
struct Map_info In, Net, Out;
83
85
int fdout = -1, maskfd = -1;
84
86
int node_method, kernel_function;
103
106
G_gisinit(argv[0]);
105
108
module = G_define_module();
106
module->keywords = _("vector, kernel density");
107
module->description =
108
_("Generates a raster density map from vector point data using a moving kernel or "
109
"optionally generates a vector density map on a vector network.");
109
G_add_keyword(_("vector"));
110
G_add_keyword(_("kernel density"));
112
_("Generates a raster density map from vector points map.");
113
module->description = _("Density is computed using a moving kernel. "
114
"Optionally generates a vector density map on a vector network.");
111
116
in_opt = G_define_standard_option(G_OPT_V_INPUT);
112
in_opt->description = _("Input vector with training points");
117
in_opt->label = _("Name of input vector map with training points");
118
in_opt->description = NULL;
114
120
net_opt = G_define_standard_option(G_OPT_V_INPUT);
115
121
net_opt->key = "net";
116
net_opt->description = _("Input network vector map");
122
net_opt->label = _("Name of input network vector map");
123
net_opt->description = NULL;
117
124
net_opt->required = NO;
125
net_opt->guisection = _("Network");
119
127
out_opt = G_define_option();
120
128
out_opt->key = "output";
121
129
out_opt->type = TYPE_STRING;
122
130
out_opt->key_desc = "name";
123
131
out_opt->required = YES;
124
out_opt->description = _("Output raster/vector map");
132
out_opt->label = _("Name for output raster/vector map");
133
out_opt->description = _("Outputs vector map if network map is given, otherwise raster map");
126
stddev_opt = G_define_option();
127
stddev_opt->key = "stddeviation";
128
stddev_opt->type = TYPE_DOUBLE;
129
stddev_opt->required = YES;
130
stddev_opt->description = _("Standard deviation in map units");
135
radius_opt = G_define_option();
136
radius_opt->key = "radius";
137
radius_opt->type = TYPE_DOUBLE;
138
radius_opt->required = YES;
139
radius_opt->description = _("Kernel radius in map units");
132
141
dsize_opt = G_define_option();
133
142
dsize_opt->key = "dsize";
149
159
netmax_opt->required = NO;
150
160
netmax_opt->description = _("Maximum distance from point to network");
151
161
netmax_opt->answer = "100.";
162
netmax_opt->guisection = _("Network");
153
164
multip_opt = G_define_option();
154
multip_opt->key = "mult";
165
multip_opt->key = "multiplier";
155
166
multip_opt->type = TYPE_DOUBLE;
156
167
multip_opt->required = NO;
157
168
multip_opt->description = _("Multiply the density result by this number");
164
175
node_opt->description = _("Node method");
165
176
node_opt->options = "none,split";
166
177
node_opt->answer = "none";
167
node_opt->descriptions =
168
_("none;No method applied at nodes with more than 2 arcs;"
169
"split;Equal split (Okabe 2009) applied at nodes;");
181
_("No method applied at nodes with more than 2 arcs"),
182
_("Equal split (Okabe 2009) applied at nodes"));
183
node_opt->descriptions = desc;
184
node_opt->guisection = _("Network");
171
186
kernel_opt = G_define_option();
172
187
kernel_opt->key = "kernel";
191
206
flag_normalize->key = 'n';
192
207
flag_normalize->description =
193
208
_("In network mode, normalize values by sum of density multiplied by length of each segment. Integral over the output map then gives 1.0 * mult");
209
flag_normalize->guisection = _("Network");
195
211
flag_multiply = G_define_flag();
196
212
flag_multiply->key = 'm';
197
213
flag_multiply->description =
198
_("In network mode, multiply the result by number of input points.");
200
flag_v = G_define_flag();
202
flag_v->description =
203
_("Verbose module output (retained for backwards compatibility)");
214
_("In network mode, multiply the result by number of input points");
215
flag_multiply->guisection = _("Network");
217
overwrite = G_check_overwrite(argc, argv);
205
218
if (G_parser(argc, argv))
206
219
exit(EXIT_FAILURE);
209
/* remove for grass7 */
211
G_set_verbose(G_verbose_max());
221
if (net_opt->answer) {
222
if (G_find_vector2(out_opt->answer, G_mapset()))
224
G_warning(_("Vector map <%s> already exists and will be overwritten"),
227
G_fatal_error(_("Vector map <%s> already exists"),
231
if (G_find_raster(out_opt->answer, G_mapset()))
233
G_warning(_("Raster map <%s> already exists and will be overwritten"),
236
G_fatal_error(_("Raster map <%s> already exists"),
213
240
/*read options */
214
sigma = atof(stddev_opt->answer);
241
dmax = atof(radius_opt->answer);
215
243
dsize = atof(dsize_opt->answer);
216
244
segmax = atof(segmax_opt->answer);
217
245
netmax = atof(netmax_opt->answer);
261
289
if (net_opt->answer) {
262
290
Vect_check_input_output_name(in_opt->answer, out_opt->answer,
264
292
Vect_check_input_output_name(net_opt->answer, out_opt->answer,
268
296
G_get_window(&window);
270
G_message("STDDEV: %f\nRES: %f\tROWS: %d\tCOLS: %d",
271
sigma, window.ew_res, window.rows, window.cols);
298
G_verbose_message(_("Standard deviation: %f"), sigma);
299
G_asprintf(&tmpstr1, _n("%d row", "%d rows", window.rows), window.rows);
300
G_asprintf(&tmpstr2, _n("%d column", "%d columns", window.cols), window.cols);
301
/* GTC First argument is resolution, second - number of rows as a text, third - number of columns as a text. */
302
G_verbose_message(_("Output raster map: resolution: %f\t%s\t%s"),
303
window.ew_res, tmpstr1, tmpstr2);
273
307
/* Open input vector */
274
if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL)
275
G_fatal_error(_("Vector map <%s> not found"), in_opt->answer);
277
308
Vect_set_open_level(2);
278
Vect_open_old(&In, in_opt->answer, mapset);
309
if (Vect_open_old(&In, in_opt->answer, "") < 0)
310
G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer);
281
312
if (net_opt->answer) {
282
313
int nlines, line;
288
319
/* Open input network */
289
if ((mapset = G_find_vector2(net_opt->answer, "")) == NULL)
290
G_fatal_error(_("Network input map <%s> not found"),
293
320
Vect_set_open_level(2);
294
Vect_open_old(&Net, net_opt->answer, mapset);
322
if (Vect_open_old(&Net, net_opt->answer, "") < 0)
323
G_fatal_error(_("Unable to open vector map <%s>"), net_opt->answer);
295
325
Vect_net_build_graph(&Net, GV_LINES, 0, 0, NULL, NULL, NULL, 0, 0);
297
327
if (!flag_q->answer) {
298
Vect_open_new(&Out, out_opt->answer, 0);
328
if (Vect_open_new(&Out, out_opt->answer, 0) < 0)
329
G_fatal_error(_("Unable to create vector map <%s>"),
299
331
Vect_hist_command(&Out);
316
348
if (notreachable > 0)
317
G_warning(_("%d points outside threshold"), notreachable);
349
G_warning(_n("%d point outside threshold",
350
"%d points outside threshold",
351
notreachable), notreachable);
320
354
/* check and open the name of output map */
321
355
if (!flag_q->answer) {
322
if (G_legal_filename(out_opt->answer) < 0)
323
G_fatal_error(_("<%s> is an illegal file name"),
326
G_set_fp_type(DCELL_TYPE);
327
if ((fdout = G_open_raster_new(out_opt->answer, DCELL_TYPE)) < 0)
328
G_fatal_error(_("Unable to create raster map <%s>"),
356
fdout = Rast_open_new(out_opt->answer, DCELL_TYPE);
331
358
/* open mask file */
332
if ((maskfd = G_maskfd()) >= 0)
333
mask = G_allocate_cell_buf();
359
if ((maskfd = Rast_maskfd()) >= 0)
360
mask = Rast_allocate_c_buf();
337
364
/* allocate output raster */
338
output_cell = G_allocate_raster_buf(DCELL_TYPE);
365
output_cell = Rast_allocate_buf(DCELL_TYPE);
405
438
struct line_cats *SCats;
406
439
double total = 0.0;
408
G_message(_("\nWriting output vector map using smooth parameter=%f."),
410
G_message(_("\nNormalising factor=%f."),
411
1. / gaussianFunction(sigma / 4., sigma, dimension));
441
G_verbose_message(_("Writing output vector map using smooth parameter %f"),
443
G_verbose_message(_("Normalising factor %f"),
444
1. / gaussianFunction(sigma / 4., sigma, dimension));
413
446
/* Divide lines to segments and calculate gaussian for center of each segment */
414
447
Points = Vect_new_line_struct();
445
479
compute_net_distance(x, y, &In, &Net, netmax, sigma, term,
446
&gaussian, dmax, node_method,
480
&gaussian, dmax, node_method);
448
481
gaussian *= multip;
449
482
if (gaussian > gausmax)
450
483
gausmax = gaussian;
512
544
Vect_close(&Out);
515
G_message(_("\nWriting output raster map using smooth parameter=%f."),
517
G_message(_("\nNormalising factor=%f."),
518
1. / gaussianFunction(sigma / 4., sigma, dimension));
547
/* spatial index handling, borrowed from lib/vector/Vlib/find.c */
548
struct bound_box box;
549
struct boxlist *NList = Vect_new_boxlist(1);
551
G_verbose_message(_("Writing output raster map using smooth parameter %f"),
553
G_verbose_message(_("Normalising factor %f"),
554
1. / gaussianFunction(sigma / 4., sigma, dimension));
520
556
for (row = 0; row < window.rows; row++) {
521
557
G_percent(row, window.rows, 2);
523
if (G_get_map_row(maskfd, mask, row) < 0)
524
G_fatal_error(_("Unable to read MASK"));
559
Rast_get_c_row(maskfd, mask, row);
527
561
for (col = 0; col < window.cols; col++) {
528
562
/* don't interpolate outside of the mask */
529
563
if (mask && mask[col] == 0) {
530
G_set_d_null_value(&output_cell[col], 1);
564
Rast_set_d_null_value(&output_cell[col], 1);
534
N = G_row_to_northing(row + 0.5, &window);
535
E = G_col_to_easting(col + 0.5, &window);
568
N = Rast_row_to_northing(row + 0.5, &window);
569
E = Rast_col_to_easting(col + 0.5, &window);
571
if ((col & 31) == 0) {
573
/* create bounding box 32x2*dmax size from the current cell center */
576
box.E = E + dmax + 32 * window.ew_res;
581
Vect_select_lines_by_box(&In, &box, GV_POINT, NList);
537
589
/* compute_distance(N, E, &In, sigma, term, &gaussian, dmax); */
538
compute_distance(N, E, &In, sigma, term, &gaussian, dmax,
590
compute_distance(N, E, sigma, term, &gaussian, dmax, &box, NList);
541
592
output_cell[col] = multip * gaussian;
542
593
if (gaussian > gausmax)
543
594
gausmax = gaussian;
545
G_put_raster_row(fdout, output_cell, DCELL_TYPE);
596
Rast_put_row(fdout, output_cell, DCELL_TYPE);
551
G_message(_("Maximum value in output: %e."), multip * gausmax);
603
G_done_msg(_("Maximum value in output: %e."), multip * gausmax);
628
680
int nn, kk, nalines, aline;
630
struct line_pnts *Points;
682
struct line_pnts *APoints, *BPoints;
683
struct bound_box box;
684
struct boxlist *List;
634
Points = Vect_new_line_struct();
635
List = Vect_new_list();
686
APoints = Vect_new_line_struct();
687
BPoints = Vect_new_line_struct();
688
List = Vect_new_boxlist(0);
637
690
nn = Vect_get_num_primitives(In, GV_POINTS);
638
691
nn = nn * (nn - 1);
646
699
G_debug(3, " aline = %d", aline);
648
altype = Vect_read_line(In, Points, NULL, aline);
701
altype = Vect_read_line(In, APoints, NULL, aline);
649
702
if (!(altype & GV_POINTS))
652
box.E = Points->x[0] + dmax;
653
box.W = Points->x[0] - dmax;
654
box.N = Points->y[0] + dmax;
655
box.S = Points->y[0] - dmax;
705
box.E = APoints->x[0] + dmax;
706
box.W = APoints->x[0] - dmax;
707
box.N = APoints->y[0] + dmax;
708
box.S = APoints->y[0] - dmax;
656
709
box.T = PORT_DOUBLE_MAX;
657
710
box.B = -PORT_DOUBLE_MAX;
662
715
for (i = 0; i < List->n_values; i++) {
665
bline = List->value[i];
667
720
if (bline == aline)
670
723
G_debug(3, " bline = %d", bline);
672
Vect_get_line_box(In, bline, &box);
675
G_debug(3, " SP: %f %f -> %f %f", Points->x[0], Points->y[0],
724
Vect_read_line(In, BPoints, NULL, bline);
679
Vect_net_shortest_path_coor(Net, Points->x[0], Points->y[0],
727
Vect_net_shortest_path_coor(Net, APoints->x[0], APoints->y[0],
728
0.0, BPoints->x[0], BPoints->y[0],
681
729
0.0, netmax, netmax, &dist, NULL,
682
730
NULL, NULL, NULL, NULL, NULL);
732
G_debug(3, " SP: %f %f -> %f %f", APoints->x[0], APoints->y[0],
733
BPoints->x[0], BPoints->y[0]);
684
736
G_debug(3, "not reachable");
685
737
continue; /* Not reachable */
707
759
n = Vect_get_node_n_lines(Map, node);
708
760
for (i = 0; i < n; i++) {
709
761
line = Vect_get_node_line(Map, node, i);
710
type = Vect_read_line(Map, NULL, NULL, abs(line));
762
type = Vect_get_line_type(Map, abs(line));
711
763
if (type & GV_LINES)
717
769
/* Compute gausian for x, y along Net, using all points in In */
718
770
void compute_net_distance(double x, double y, struct Map_info *In,
719
771
struct Map_info *Net, double netmax, double sigma,
720
double term, double *gaussian, double dmax,
721
int node_method, int kernel_function)
772
double term, double *gaussian, double dmax, int node_method)
724
775
double dist, kernel;
725
776
static struct line_pnts *FPoints = NULL;
727
static struct ilist *PointsList = NULL;
777
struct bound_box box;
778
static struct boxlist *PointsList = NULL;
728
779
static struct ilist *NodesList = NULL;
731
PointsList = Vect_new_list();
782
PointsList = Vect_new_boxlist(1);
733
784
if (node_method == NODE_EQUAL_SPLIT) {
756
807
for (i = 0; i < PointsList->n_values; i++) {
759
line = PointsList->value[i];
761
Vect_get_line_box(In, line, &box);
763
G_debug(3, " SP: %f %f -> %f %f", x, y, box.E, box.N);
810
line = PointsList->id[i];
812
G_debug(3, " SP: %f %f -> %f %f", x, y, PointsList->box[i].E, PointsList->box[i].N);
813
/*ret = Vect_net_shortest_path_coor(Net, x, y, 0.0, Points->x[0], */
814
/*Points->y[0], 0.0, netmax, netmax, */
815
/*&dist, NULL, NULL, NULL, NULL, NULL, */
765
817
ret = Vect_net_shortest_path_coor2(Net,
818
PointsList->box[i].E,
819
PointsList->box[i].N, 0.0,
767
820
x, y, 0.0, netmax, 1.0,
769
822
NULL, NodesList, FPoints, NULL,
811
void compute_distance(double N, double E, struct Map_info *In,
812
double sigma, double term, double *gaussian,
813
double dmax, int kernel_function)
864
void compute_distance(double N, double E, double sigma, double term,
865
double *gaussian, double dmax, struct bound_box *box,
866
struct boxlist *NList)
815
868
int line, nlines;
816
869
double a[2], b[2];
819
/* spatial index handling, borrowed from lib/vector/Vlib/find.c */
821
static struct ilist *NList = NULL;
827
NList = Vect_new_list();
829
/* create bounding box 2x2*dmax size from the current cell center */
837
875
/* number of lines within dmax box */
838
nlines = Vect_select_lines_by_box(In, &box, GV_POINT, NList);
876
nlines = NList->n_values;
842
880
for (line = 0; line < nlines; line++) {
844
Vect_get_line_box(In, NList->value[line], &box);
848
dist = euclidean_distance(a, b, 2);
851
/* *gaussian += gaussianKernel(dist / sigma, term); */
852
*gaussian += kernelFunction(kernel_function, 2, sigma, dist);
882
b[0] = NList->box[line].E;
883
b[1] = NList->box[line].N;
885
if (b[0] <= box->E && b[0] >= box->W &&
886
b[1] <= box->N && b[1] >= box->S) {
887
dist = euclidean_distance(a, b, 2);
890
/* *gaussian += gaussianKernel(dist / sigma, term); */
891
*gaussian += kernelFunction(term, sigma, dist);