main.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /****************************************************************
  2. * *
  3. * MODULE: v.lidar.growing *
  4. * *
  5. * AUTHOR(S): Roberto Antolin & Gonzalo Moreno *
  6. * *
  7. * PURPOSE: Building contour determination and Region *
  8. * Growing algorithm for determining the building *
  9. * inside *
  10. * *
  11. * COPYRIGHT: (C) 2006 by Politecnico di Milano - *
  12. * Polo Regionale di Como *
  13. * *
  14. * This program is free software under the *
  15. * GNU General Public License (>=v2). *
  16. * Read the file COPYING that comes with GRASS *
  17. * for details. *
  18. * *
  19. ****************************************************************/
  20. /*INCLUDES*/
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <math.h>
  24. #include "growing.h"
  25. /* GLOBAL DEFINITIONS */
  26. int nsply, nsplx, count_obj;
  27. double stepN, stepE;
  28. /*--------------------------------------------------------------------------------*/
  29. int main(int argc, char *argv[])
  30. {
  31. /* Variables' declarations */
  32. int row, nrows, col, ncols, MaxPoints;
  33. int nsubregion_col, nsubregion_row;
  34. int subregion = 0, nsubregions = 0;
  35. int last_row, last_column;
  36. int nlines, nlines_first, line_num;
  37. int more;
  38. int clas, region = TRUE;
  39. double Z_interp;
  40. double Thres_j, Thres_d, ew_resol, ns_resol;
  41. double minNS, minEW, maxNS, maxEW;
  42. const char *mapset;
  43. char buf[1024], table_name[GNAME_MAX + 64];
  44. char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
  45. int colorBordo, ripieno, conta, lungPunti, lungHull, xi, c1, c2;
  46. double altPiano;
  47. extern double **P, **cvxHull, **punti_bordo;
  48. /* Struct declarations */
  49. struct Cell_head elaboration_reg, original_reg;
  50. struct element_grow **raster_matrix;
  51. struct Map_info In, Out, First;
  52. struct Option *in_opt, *out_opt, *first_opt, *Thres_j_opt, *Thres_d_opt;
  53. struct GModule *module;
  54. struct line_pnts *points, *points_first;
  55. struct line_cats *Cats, *Cats_first;
  56. struct field_info *field;
  57. dbDriver *driver;
  58. dbString sql;
  59. dbTable *table;
  60. dbCursor cursor;
  61. /*------------------------------------------------------------------------------------------*/
  62. /* Options' declaration */
  63. module = G_define_module();
  64. G_add_keyword(_("vector"));
  65. G_add_keyword(_("LIDAR"));
  66. module->description =
  67. _("Building contour determination and Region Growing "
  68. "algorithm for determining the building inside");
  69. in_opt = G_define_standard_option(G_OPT_V_INPUT);
  70. in_opt->description =
  71. _("Input vector (v.lidar.edgedetection output)");
  72. out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
  73. first_opt = G_define_option();
  74. first_opt->key = "first";
  75. first_opt->type = TYPE_STRING;
  76. first_opt->key_desc = "name";
  77. first_opt->required = YES;
  78. first_opt->gisprompt = "old,vector,vector";
  79. first_opt->description = _("Name of the first pulse vector map");
  80. Thres_j_opt = G_define_option();
  81. Thres_j_opt->key = "tj";
  82. Thres_j_opt->type = TYPE_DOUBLE;
  83. Thres_j_opt->required = NO;
  84. Thres_j_opt->description =
  85. _("Threshold for cell object frequency in region growing");
  86. Thres_j_opt->answer = "0.2";
  87. Thres_d_opt = G_define_option();
  88. Thres_d_opt->key = "td";
  89. Thres_d_opt->type = TYPE_DOUBLE;
  90. Thres_d_opt->required = NO;
  91. Thres_d_opt->description =
  92. _("Threshold for double pulse in region growing");
  93. Thres_d_opt->answer = "0.6";
  94. /* Parsing */
  95. G_gisinit(argv[0]);
  96. if (G_parser(argc, argv))
  97. exit(EXIT_FAILURE);
  98. Thres_j = atof(Thres_j_opt->answer);
  99. Thres_d = atof(Thres_d_opt->answer);
  100. Thres_j += 1;
  101. /* Open input vector */
  102. Vect_check_input_output_name(in_opt->answer, out_opt->answer,
  103. G_FATAL_EXIT);
  104. if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL) {
  105. G_fatal_error(_("Vector map <%s> not found"), in_opt->answer);
  106. }
  107. /* Setting auxiliary table's name */
  108. if (G_name_is_fully_qualified(in_opt->answer, xname, xmapset)) {
  109. sprintf(table_name, "%s_edge_Interpolation", xname);
  110. }
  111. else
  112. sprintf(table_name, "%s_edge_Interpolation", in_opt->answer);
  113. Vect_set_open_level(1); /* WITHOUT TOPOLOGY */
  114. if (Vect_open_old(&In, in_opt->answer, mapset) < 1)
  115. G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer);
  116. Vect_set_open_level(1); /* WITHOUT TOPOLOGY */
  117. if (Vect_open_old(&First, first_opt->answer, mapset) < 1)
  118. G_fatal_error(_("Unable to open vector map <%s>"), first_opt->answer);
  119. /* Open output vector */
  120. if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z)) {
  121. Vect_close(&In);
  122. Vect_close(&First);
  123. exit(EXIT_FAILURE);
  124. }
  125. /* Copy vector Head File */
  126. Vect_copy_head_data(&In, &Out);
  127. Vect_hist_copy(&In, &Out);
  128. Vect_hist_command(&Out);
  129. /* Starting driver and open db for edgedetection interpolation table */
  130. field = Vect_get_field(&In, F_INTERPOLATION);
  131. /*if (field == NULL)
  132. G_fatal_error (_("Cannot read field info")); */
  133. driver = db_start_driver_open_database(field->driver, field->database);
  134. if (driver == NULL)
  135. G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."),
  136. field->driver);
  137. /* is this the right place to open the cursor ??? */
  138. db_init_string(&sql);
  139. db_zero_string(&sql);
  140. sprintf(buf, "SELECT Interp,ID FROM %s", table_name);
  141. G_debug(1, "buf: %s", buf);
  142. db_append_string(&sql, buf);
  143. if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK)
  144. G_fatal_error(_("Unable to open table <%s>"), table_name);
  145. count_obj = 1;
  146. /* no topology, get number of lines in input vector */
  147. nlines = 0;
  148. points = Vect_new_line_struct();
  149. Cats = Vect_new_cats_struct();
  150. Vect_rewind(&In);
  151. while (Vect_read_next_line(&In, points, Cats) > 0) {
  152. nlines++;
  153. }
  154. Vect_rewind(&In);
  155. /* no topology, get number of lines in first pulse input vector */
  156. nlines_first = 0;
  157. points_first = Vect_new_line_struct();
  158. Cats_first = Vect_new_cats_struct();
  159. Vect_rewind(&First);
  160. while (Vect_read_next_line(&First, points_first, Cats_first) > 0) {
  161. nlines_first++;
  162. }
  163. Vect_rewind(&First);
  164. /* Setting regions and boxes */
  165. G_debug(1, _("Setting regions and boxes"));
  166. G_get_set_window(&original_reg);
  167. G_get_set_window(&elaboration_reg);
  168. /* Fixing parameters of the elaboration region */
  169. /*! The original_region will be divided into subregions */
  170. ew_resol = original_reg.ew_res;
  171. ns_resol = original_reg.ns_res;
  172. /* calculate number of subregions */
  173. nsubregion_col = ceil((original_reg.east - original_reg.west) / (LATO * ew_resol)) + 0.5;
  174. nsubregion_row = ceil((original_reg.north - original_reg.south) / (LATO * ns_resol)) + 0.5;
  175. if (nsubregion_col < 0)
  176. nsubregion_col = 0;
  177. if (nsubregion_row < 0)
  178. nsubregion_row = 0;
  179. nsubregions = nsubregion_row * nsubregion_col;
  180. /* Subdividing and working with tiles */
  181. elaboration_reg.south = original_reg.north;
  182. last_row = FALSE;
  183. while (last_row == FALSE) { /* For each strip of LATO rows */
  184. elaboration_reg.north = elaboration_reg.south;
  185. if (elaboration_reg.north > original_reg.north) /* First row */
  186. elaboration_reg.north = original_reg.north;
  187. elaboration_reg.south = elaboration_reg.north - LATO * ns_resol;
  188. if (elaboration_reg.south <= original_reg.south) { /* Last row */
  189. elaboration_reg.south = original_reg.south;
  190. last_row = TRUE;
  191. }
  192. elaboration_reg.east = original_reg.west;
  193. last_column = FALSE;
  194. while (last_column == FALSE) { /* For each strip of LATO columns */
  195. struct bound_box elaboration_box;
  196. subregion++;
  197. if (nsubregions > 1)
  198. G_message(_("Subregion %d of %d"), subregion, nsubregions);
  199. elaboration_reg.west = elaboration_reg.east;
  200. if (elaboration_reg.west < original_reg.west) /* First column */
  201. elaboration_reg.west = original_reg.west;
  202. elaboration_reg.east = elaboration_reg.west + LATO * ew_resol;
  203. if (elaboration_reg.east >= original_reg.east) { /* Last column */
  204. elaboration_reg.east = original_reg.east;
  205. last_column = TRUE;
  206. }
  207. /* Setting the active region */
  208. elaboration_reg.ns_res = ns_resol;
  209. elaboration_reg.ew_res = ew_resol;
  210. nrows = (elaboration_reg.north - elaboration_reg.south) / ns_resol + 0.1;
  211. ncols = (elaboration_reg.east - elaboration_reg.west) / ew_resol + 0.1;
  212. elaboration_reg.rows = nrows;
  213. elaboration_reg.cols = ncols;
  214. G_debug(1, _("Rows = %d"), nrows);
  215. G_debug(1, _("Columns = %d"), ncols);
  216. raster_matrix = structMatrix(0, nrows, 0, ncols);
  217. MaxPoints = nrows * ncols;
  218. /* Initializing matrix */
  219. for (row = 0; row <= nrows; row++) {
  220. for (col = 0; col <= ncols; col++) {
  221. raster_matrix[row][col].interp = 0;
  222. raster_matrix[row][col].fi = 0;
  223. raster_matrix[row][col].bordo = 0;
  224. raster_matrix[row][col].dueImp = SINGLE_PULSE;
  225. raster_matrix[row][col].orig = 0;
  226. raster_matrix[row][col].fo = 0;
  227. raster_matrix[row][col].clas = PRE_TERRAIN;
  228. raster_matrix[row][col].fc = 0;
  229. raster_matrix[row][col].obj = 0;
  230. }
  231. }
  232. G_verbose_message(_("read points in input vector"));
  233. Vect_region_box(&elaboration_reg, &elaboration_box);
  234. line_num = 0;
  235. Vect_rewind(&In);
  236. while (Vect_read_next_line(&In, points, Cats) > 0) {
  237. line_num++;
  238. if ((Vect_point_in_box
  239. (points->x[0], points->y[0], points->z[0],
  240. &elaboration_box)) &&
  241. ((points->x[0] != elaboration_reg.west) ||
  242. (points->x[0] == original_reg.west)) &&
  243. ((points->y[0] != elaboration_reg.north) ||
  244. (points->y[0] == original_reg.north))) {
  245. row =
  246. (int)(Rast_northing_to_row
  247. (points->y[0], &elaboration_reg));
  248. /* do not use Rast_easting_to_col() because of possible ll wrap */
  249. /*
  250. col =
  251. (int)(Rast_easting_to_col
  252. (points->x[0], &elaboration_reg));
  253. */
  254. col = (points->x[0] - elaboration_reg.west) / elaboration_reg.ew_res;
  255. Z_interp = 0;
  256. /* TODO: make sure the current db_fetch() usage works */
  257. /* why not: */
  258. /*
  259. db_init_string(&sql);
  260. sprintf(buf, "SELECT Interp,ID FROM %s WHERE ID=%d", table_name, line_num);
  261. db_append_string(&sql, buf);
  262. if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK)
  263. G_fatal_error(_("Unable to open table <%s>"), table_name);
  264. while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
  265. dbColumn *Z_Interp_col;
  266. dbValue *Z_Interp_value;
  267. table = db_get_cursor_table(&cursor);
  268. Z_Interp_col = db_get_table_column(table, 1);
  269. if (db_sqltype_to_Ctype(db_get_column_sqltype(Z_Interp_col)) ==
  270. DB_C_TYPE_DOUBLE)
  271. Z_Interp_value = db_get_column_value(Z_Interp_col);
  272. else
  273. continue;
  274. Z_interp = db_get_value_double(Z_Interp_value);
  275. break;
  276. }
  277. db_close_cursor(&cursor);
  278. db_free_string(&sql);
  279. */
  280. /* instead of */
  281. while (1) {
  282. if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK ||
  283. !more)
  284. break;
  285. dbColumn *Z_Interp_col, *ID_col;
  286. dbValue *Z_Interp_value, *ID_value;
  287. table = db_get_cursor_table(&cursor);
  288. ID_col = db_get_table_column(table, 1);
  289. if (db_sqltype_to_Ctype(db_get_column_sqltype(ID_col))
  290. == DB_C_TYPE_INT)
  291. ID_value = db_get_column_value(ID_col);
  292. else
  293. continue;
  294. if (db_get_value_int(ID_value) == line_num) {
  295. Z_Interp_col = db_get_table_column(table, 0);
  296. if (db_sqltype_to_Ctype
  297. (db_get_column_sqltype(Z_Interp_col)) ==
  298. DB_C_TYPE_DOUBLE)
  299. Z_Interp_value =
  300. db_get_column_value(Z_Interp_col);
  301. else
  302. continue;
  303. Z_interp = db_get_value_double(Z_Interp_value);
  304. break;
  305. }
  306. }
  307. raster_matrix[row][col].interp += Z_interp;
  308. raster_matrix[row][col].fi++;
  309. /*if (( clas = Vect_get_line_cat (&In, line_num, F_EDGE_DETECTION_CLASS) ) != UNKNOWN_EDGE) { */
  310. if (Vect_cat_get(Cats, F_EDGE_DETECTION_CLASS, &clas)) {
  311. raster_matrix[row][col].clas += clas;
  312. raster_matrix[row][col].fc++;
  313. }
  314. raster_matrix[row][col].orig += points->z[0];
  315. raster_matrix[row][col].fo++;
  316. }
  317. Vect_reset_cats(Cats);
  318. Vect_reset_line(points);
  319. }
  320. for (row = 0; row <= nrows; row++) {
  321. for (col = 0; col <= ncols; col++) {
  322. if (raster_matrix[row][col].fc != 0) {
  323. raster_matrix[row][col].clas--;
  324. raster_matrix[row][col].
  325. clas /= raster_matrix[row][col].fc;
  326. }
  327. if (raster_matrix[row][col].fi != 0)
  328. raster_matrix[row][col].
  329. interp /= raster_matrix[row][col].fi;
  330. if (raster_matrix[row][col].fo != 0)
  331. raster_matrix[row][col].
  332. orig /= raster_matrix[row][col].fo;
  333. }
  334. }
  335. /* DOUBLE IMPULSE */
  336. Vect_rewind(&First);
  337. while (Vect_read_next_line(&First, points_first, Cats_first) > 0) {
  338. if ((Vect_point_in_box
  339. (points_first->x[0], points_first->y[0],
  340. points_first->z[0], &elaboration_box)) &&
  341. ((points->x[0] != elaboration_reg.west) ||
  342. (points->x[0] == original_reg.west)) &&
  343. ((points->y[0] != elaboration_reg.north) ||
  344. (points->y[0] == original_reg.north))) {
  345. row =
  346. (int)(Rast_northing_to_row
  347. (points_first->y[0], &elaboration_reg));
  348. /* do not use Rast_easting_to_col() because of possible ll wrap */
  349. /*
  350. col =
  351. (int)(Rast_easting_to_col
  352. (points_first->x[0], &elaboration_reg));
  353. */
  354. col = (points_first->x[0] - elaboration_reg.west) / elaboration_reg.ew_res;
  355. if (fabs
  356. (points_first->z[0] - raster_matrix[row][col].orig) >=
  357. Thres_d)
  358. raster_matrix[row][col].dueImp = DOUBLE_PULSE;
  359. }
  360. Vect_reset_cats(Cats_first);
  361. Vect_reset_line(points_first);
  362. }
  363. /* REGION GROWING */
  364. if (region == TRUE) {
  365. G_verbose_message(_("Region Growing"));
  366. punti_bordo = G_alloc_matrix(MaxPoints, 3);
  367. P = Pvector(0, MaxPoints);
  368. colorBordo = 5;
  369. ripieno = 6;
  370. for (row = 0; row <= nrows; row++) {
  371. G_percent(row, nrows, 2);
  372. for (col = 0; col <= ncols; col++) {
  373. if ((raster_matrix[row][col].clas >= Thres_j) &&
  374. (raster_matrix[row][col].clas < colorBordo)
  375. && (raster_matrix[row][col].fi != 0) &&
  376. (raster_matrix[row][col].dueImp ==
  377. SINGLE_PULSE)) {
  378. /* Selecting a connected Object zone */
  379. ripieno++;
  380. if (ripieno > 10)
  381. ripieno = 6;
  382. /* Selecting points on a connected edge */
  383. for (conta = 0; conta < MaxPoints; conta++) {
  384. punti_bordo[conta][0] = 0;
  385. punti_bordo[conta][1] = 0;
  386. punti_bordo[conta][2] = 0;
  387. P[conta] = punti_bordo[conta]; /* It only makes indexes to be equal, not coord values!! */
  388. }
  389. lungPunti = 0;
  390. lungHull = 0;
  391. regGrow8(elaboration_reg, raster_matrix,
  392. punti_bordo, &lungPunti, row, col,
  393. colorBordo, Thres_j, MaxPoints);
  394. /* CONVEX-HULL COMPUTATION */
  395. lungHull = ch2d(P, lungPunti);
  396. cvxHull = G_alloc_matrix(lungHull, 3);
  397. for (xi = 0; xi < lungHull; xi++) {
  398. cvxHull[xi][0] = P[xi][0];
  399. cvxHull[xi][1] = P[xi][1];
  400. cvxHull[xi][2] = P[xi][2];
  401. }
  402. /* Computes the interpoling plane based only on Object points */
  403. altPiano =
  404. pianOriz(punti_bordo, lungPunti, &minNS,
  405. &minEW, &maxNS, &maxEW,
  406. raster_matrix, colorBordo);
  407. for (c1 = minNS; c1 <= maxNS; c1++) {
  408. for (c2 = minEW; c2 <= maxEW; c2++) {
  409. if (checkHull(c1, c2, cvxHull, lungHull)
  410. == 1) {
  411. raster_matrix[c1][c2].obj = count_obj;
  412. if ((raster_matrix[c1][c2].clas ==
  413. PRE_TERRAIN)
  414. && (raster_matrix[c1][c2].orig >=
  415. altPiano) && (lungHull > 3))
  416. raster_matrix[c1][c2].clas =
  417. ripieno;
  418. }
  419. }
  420. }
  421. G_free_matrix(cvxHull);
  422. count_obj++;
  423. }
  424. }
  425. }
  426. G_free_matrix(punti_bordo);
  427. free_Pvector(P, 0, MaxPoints);
  428. }
  429. /* WRITING THE OUTPUT VECTOR CATEGORIES */
  430. Vect_rewind(&In);
  431. while (Vect_read_next_line(&In, points, Cats) > 0) { /* Read every line for buffering points */
  432. if ((Vect_point_in_box
  433. (points->x[0], points->y[0], points->z[0],
  434. &elaboration_box)) &&
  435. ((points->x[0] != elaboration_reg.west) ||
  436. (points->x[0] == original_reg.west)) &&
  437. ((points->y[0] != elaboration_reg.north) ||
  438. (points->y[0] == original_reg.north))) {
  439. row =
  440. (int)(Rast_northing_to_row
  441. (points->y[0], &elaboration_reg));
  442. /* do not use Rast_easting_to_col() because of possible ll wrap */
  443. /*
  444. col =
  445. (int)(Rast_easting_to_col
  446. (points->x[0], &elaboration_reg));
  447. */
  448. col = (points->x[0] - elaboration_reg.west) / elaboration_reg.ew_res;
  449. if (raster_matrix[row][col].clas == PRE_TERRAIN) {
  450. if (raster_matrix[row][col].dueImp == SINGLE_PULSE)
  451. Vect_cat_set(Cats, F_CLASSIFICATION,
  452. TERRAIN_SINGLE);
  453. else
  454. Vect_cat_set(Cats, F_CLASSIFICATION,
  455. TERRAIN_DOUBLE);
  456. }
  457. else {
  458. if (raster_matrix[row][col].dueImp == SINGLE_PULSE)
  459. Vect_cat_set(Cats, F_CLASSIFICATION,
  460. OBJECT_SINGLE);
  461. else
  462. Vect_cat_set(Cats, F_CLASSIFICATION,
  463. OBJECT_DOUBLE);
  464. }
  465. Vect_cat_set(Cats, F_COUNTER_OBJ,
  466. raster_matrix[row][col].obj);
  467. Vect_write_line(&Out, GV_POINT, points, Cats);
  468. }
  469. Vect_reset_cats(Cats);
  470. Vect_reset_line(points);
  471. }
  472. free_structmatrix(raster_matrix, 0, nrows - 1, 0, ncols - 1);
  473. } /*! END WHILE; last_column = TRUE */
  474. } /*! END WHILE; last_row = TRUE */
  475. Vect_close(&In);
  476. Vect_close(&First);
  477. Vect_close(&Out);
  478. db_close_database_shutdown_driver(driver);
  479. G_done_msg(" ");
  480. exit(EXIT_SUCCESS);
  481. }