main.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /**************************************************************
  2. *
  3. * MODULE: v.lidar.edgedetection
  4. *
  5. * AUTHOR(S): Original version in GRASS 5.4 (s.edgedetection):
  6. * Maria Antonia Brovelli, Massimiliano Cannata,
  7. * Ulisse Longoni and Mirko Reguzzoni
  8. *
  9. * Update for GRASS 6.X and improvements:
  10. * Roberto Antolin and Gonzalo Moreno
  11. *
  12. * PURPOSE: Detection of object's edges on a LIDAR data set
  13. *
  14. * COPYRIGHT: (C) 2006 by Politecnico di Milano -
  15. * Polo Regionale di Como
  16. *
  17. * This program is free software under the
  18. * GNU General Public License (>=v2).
  19. * Read the file COPYING that comes with GRASS
  20. * for details.
  21. *
  22. **************************************************************/
  23. /*INCLUDES*/
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <grass/gis.h>
  27. #include <grass/Vect.h>
  28. #include <grass/dbmi.h>
  29. #include <grass/glocale.h>
  30. #include <grass/config.h>
  31. #include <grass/PolimiFunct.h>
  32. #include "edgedetection.h"
  33. int nsply, nsplx, line_out_counter, first_it;
  34. double passoN, passoE;
  35. /**************************************************************************************
  36. **************************************************************************************/
  37. int main(int argc, char *argv[])
  38. {
  39. /* Variables' declarations */
  40. int dim_vect, nparameters, BW, npoints;
  41. double lambda_B, lambda_F, grad_H, grad_L, alpha, ew_resol, ns_resol,
  42. mean;
  43. char *dvr, *db, *mapset, table_interpolation[1024], table_name[1024];
  44. int last_row, last_column, flag_auxiliar = FALSE;
  45. int *lineVect;
  46. double *TN, *Q, *parVect_bilin, *parVect_bicub; /* Interpolating and least-square vectors */
  47. double **N, **obsVect; /* Interpolation and least-square matrix */
  48. /* Structs' declarations */
  49. struct Map_info In, Out;
  50. struct Option *in_opt, *out_opt, *passoE_opt, *passoN_opt,
  51. *lambdaF_opt, *lambdaB_opt, *gradH_opt, *gradL_opt, *alfa_opt;
  52. struct GModule *module;
  53. struct Cell_head elaboration_reg, original_reg;
  54. struct Reg_dimens dims;
  55. BOUND_BOX general_box, overlap_box;
  56. struct Point *observ;
  57. dbDriver *driver;
  58. /*------------------------------------------------------------------------------------------*/
  59. /* Options' declaration */
  60. module = G_define_module();
  61. module->keywords = _("vector, LIDAR, edges");
  62. module->description =
  63. _("Detects the object's edges from a LIDAR data set.");
  64. in_opt = G_define_standard_option(G_OPT_V_INPUT);
  65. out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
  66. passoE_opt = G_define_option();
  67. passoE_opt->key = "see";
  68. passoE_opt->type = TYPE_DOUBLE;
  69. passoE_opt->required = NO;
  70. passoE_opt->answer = "4";
  71. passoE_opt->description =
  72. _("Interpolation spline step value in east direction");
  73. passoE_opt->guisection = _("Settings");
  74. passoN_opt = G_define_option();
  75. passoN_opt->key = "sen";
  76. passoN_opt->type = TYPE_DOUBLE;
  77. passoN_opt->required = NO;
  78. passoN_opt->answer = "4";
  79. passoN_opt->description =
  80. _("Interpolation spline step value in north direction");
  81. passoN_opt->guisection = _("Settings");
  82. lambdaB_opt = G_define_option();
  83. lambdaB_opt->key = "lambda_g";
  84. lambdaB_opt->type = TYPE_DOUBLE;
  85. lambdaB_opt->required = NO;
  86. lambdaB_opt->description =
  87. _("Regularization weight in gradient evaluation");
  88. lambdaB_opt->answer = "0.01";
  89. lambdaB_opt->guisection = _("Settings");
  90. gradH_opt = G_define_option();
  91. gradH_opt->key = "tgh";
  92. gradH_opt->type = TYPE_DOUBLE;
  93. gradH_opt->required = NO;
  94. gradH_opt->description =
  95. _("High gradient threshold for edge classification");
  96. gradH_opt->answer = "6";
  97. gradH_opt->guisection = _("Settings");
  98. gradL_opt = G_define_option();
  99. gradL_opt->key = "tgl";
  100. gradL_opt->type = TYPE_DOUBLE;
  101. gradL_opt->required = NO;
  102. gradL_opt->description =
  103. _("Low gradient threshold for edge classification");
  104. gradL_opt->answer = "3";
  105. gradL_opt->guisection = _("Settings");
  106. alfa_opt = G_define_option();
  107. alfa_opt->key = "theta_g";
  108. alfa_opt->type = TYPE_DOUBLE;
  109. alfa_opt->required = NO;
  110. alfa_opt->description = _("Angle range for same direction detection");
  111. alfa_opt->answer = "0.26";
  112. alfa_opt->guisection = _("Settings");
  113. lambdaF_opt = G_define_option();
  114. lambdaF_opt->key = "lambda_r";
  115. lambdaF_opt->type = TYPE_DOUBLE;
  116. lambdaF_opt->required = NO;
  117. lambdaF_opt->description =
  118. _("Regularization weight in residual evaluation");
  119. lambdaF_opt->answer = "2";
  120. lambdaF_opt->guisection = _("Settings");
  121. /* Parsing */
  122. G_gisinit(argv[0]);
  123. if (G_parser(argc, argv))
  124. exit(EXIT_FAILURE);
  125. line_out_counter = 1;
  126. passoN = atof(passoN_opt->answer);
  127. passoE = atof(passoE_opt->answer);
  128. lambda_F = atof(lambdaF_opt->answer);
  129. lambda_B = atof(lambdaB_opt->answer);
  130. grad_H = atof(gradH_opt->answer);
  131. grad_L = atof(gradL_opt->answer);
  132. alpha = atof(alfa_opt->answer);
  133. if (!(db = G__getenv2("DB_DATABASE", G_VAR_MAPSET)))
  134. G_fatal_error(_("Unable to read name of database"));
  135. if (!(dvr = G__getenv2("DB_DRIVER", G_VAR_MAPSET)))
  136. G_fatal_error(_("Unable to read name of driver"));
  137. /* Setting auxiliar table's name */
  138. sprintf(table_name, "%s_aux", out_opt->answer);
  139. /* Checking vector names */
  140. Vect_check_input_output_name(in_opt->answer, out_opt->answer,
  141. GV_FATAL_EXIT);
  142. if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL) {
  143. G_fatal_error(_("Vector map <%s> not found"), in_opt->answer);
  144. }
  145. /* Open output vector */
  146. if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z))
  147. G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer);
  148. Vect_set_open_level(1);
  149. /* Open input vector */
  150. if (1 > Vect_open_old(&In, in_opt->answer, mapset))
  151. G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer);
  152. /* Copy vector Head File */
  153. Vect_copy_head_data(&In, &Out);
  154. Vect_hist_copy(&In, &Out);
  155. Vect_hist_command(&Out);
  156. /* Start driver and open db */
  157. driver = db_start_driver_open_database(dvr, db);
  158. if (driver == NULL)
  159. G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."),
  160. dvr);
  161. if (Create_Interpolation_Table(out_opt->answer, driver) != DB_OK)
  162. G_fatal_error(_("It was impossible to create <%s> interpolation table in database."),
  163. out_opt->answer);
  164. /* Setting regions and boxes */
  165. G_get_set_window(&original_reg);
  166. G_get_set_window(&elaboration_reg);
  167. Vect_region_box(&elaboration_reg, &overlap_box);
  168. Vect_region_box(&elaboration_reg, &general_box);
  169. /* Fixxing parameters of the elaboration region */
  170. /*! Each original_region will be divided into several subregions. These
  171. * subregion will be overlaped by its neibourgh subregions. This overlaping
  172. * is calculated as OVERLAP_PASS times the east-west resolution. */
  173. ew_resol = original_reg.ew_res;
  174. ns_resol = original_reg.ns_res;
  175. P_zero_dim(&dims);
  176. dims.latoE = NSPLX_MAX * passoE;
  177. dims.latoN = NSPLY_MAX * passoN;
  178. dims.overlap = OVERLAP_SIZE * ew_resol;
  179. P_get_orlo(P_BICUBIC, &dims, passoE, passoN);
  180. elaboration_reg.south = original_reg.north;
  181. last_row = FALSE;
  182. first_it = TRUE;
  183. while (last_row == FALSE) { /* For each row */
  184. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  185. GENERAL_ROW);
  186. if (elaboration_reg.north > original_reg.north) { /* First row */
  187. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  188. FIRST_ROW);
  189. }
  190. if (elaboration_reg.south <= original_reg.south) { /* Last row */
  191. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  192. LAST_ROW);
  193. last_row = TRUE;
  194. }
  195. nsply =
  196. ceil((elaboration_reg.north - elaboration_reg.south) / passoN) +
  197. 1;
  198. if (nsply > NSPLY_MAX) {
  199. nsply = NSPLY_MAX;
  200. }
  201. G_debug(1, _("nsply = %d"), nsply);
  202. elaboration_reg.east = original_reg.west;
  203. last_column = FALSE;
  204. while (last_column == FALSE) { /* For each column */
  205. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  206. GENERAL_COLUMN);
  207. if (elaboration_reg.west < original_reg.west) { /* First column */
  208. P_set_regions(&elaboration_reg, &general_box, &overlap_box,
  209. dims, FIRST_COLUMN);
  210. }
  211. if (elaboration_reg.east >= original_reg.east) { /* Last column */
  212. P_set_regions(&elaboration_reg, &general_box, &overlap_box,
  213. dims, LAST_COLUMN);
  214. last_column = TRUE;
  215. }
  216. nsplx =
  217. ceil((elaboration_reg.east - elaboration_reg.west) / passoE) +
  218. 1;
  219. if (nsplx > NSPLX_MAX) {
  220. nsplx = NSPLX_MAX;
  221. }
  222. G_debug(1, _("nsplx = %d"), nsplx);
  223. /*Setting the active region */
  224. dim_vect = nsplx * nsply;
  225. G_debug(1, _("read vector region map"));
  226. observ =
  227. P_Read_Vector_Region_Map(&In, &elaboration_reg, &npoints,
  228. dim_vect, 1);
  229. if (npoints > 0) { /* If there is any point falling into elaboration_reg... */
  230. int i, tn;
  231. nparameters = nsplx * nsply;
  232. /* Mean's calculation */
  233. mean = P_Mean_Calc(&elaboration_reg, observ, npoints);
  234. /* Least Squares system */
  235. G_debug(1, _("Allocation memory for bilinear interpolation"));
  236. BW = P_get_BandWidth(P_BILINEAR, nsply); /* Bilinear interpolation */
  237. N = G_alloc_matrix(nparameters, BW); /* Normal matrix */
  238. TN = G_alloc_vector(nparameters); /* vector */
  239. parVect_bilin = G_alloc_vector(nparameters); /* Bicubic parameters vector */
  240. obsVect = G_alloc_matrix(npoints + 1, 3); /* Observation vector */
  241. Q = G_alloc_vector(npoints + 1); /* "a priori" var-cov matrix */
  242. lineVect = G_alloc_ivector(npoints + 1);
  243. /* Setting obsVect vector & Q matrix */
  244. for (i = 0; i < npoints; i++) {
  245. obsVect[i][0] = observ[i].coordX;
  246. obsVect[i][1] = observ[i].coordY;
  247. obsVect[i][2] = observ[i].coordZ - mean;
  248. lineVect[i] = observ[i].lineID;
  249. Q[i] = 1; /* Q=I */
  250. }
  251. /*G_free (observ); */
  252. G_debug(1, _("Bilinear interpolation"));
  253. normalDefBilin(N, TN, Q, obsVect, passoE, passoN, nsplx,
  254. nsply, elaboration_reg.west,
  255. elaboration_reg.south, npoints, nparameters,
  256. BW);
  257. nCorrectGrad(N, lambda_B, nsplx, nsply, passoE, passoN);
  258. tcholSolve(N, TN, parVect_bilin, nparameters, BW);
  259. G_free_matrix(N);
  260. for (tn = 0; tn < nparameters; tn++)
  261. TN[tn] = 0;
  262. G_debug(1, _("Allocation memory for bicubic interpolation"));
  263. BW = P_get_BandWidth(P_BICUBIC, nsply);
  264. N = G_alloc_matrix(nparameters, BW); /* Normal matrix */
  265. parVect_bicub = G_alloc_vector(nparameters); /* Bicubic parameters vector */
  266. G_debug(1, _("Bicubic interpolation"));
  267. normalDefBicubic(N, TN, Q, obsVect, passoE, passoN, nsplx,
  268. nsply, elaboration_reg.west,
  269. elaboration_reg.south, npoints, nparameters,
  270. BW);
  271. nCorrectLapl(N, lambda_F, nsplx, nsply, passoE, passoN);
  272. tcholSolve(N, TN, parVect_bicub, nparameters, BW);
  273. G_free_matrix(N);
  274. G_free_vector(TN);
  275. G_free_vector(Q);
  276. if (flag_auxiliar == FALSE) {
  277. G_debug(1,
  278. _
  279. ("Creating auxiliar table for archiving overlaping zones"));
  280. if ((flag_auxiliar =
  281. Create_AuxEdge_Table(driver)) == FALSE)
  282. G_fatal_error(_("It was impossible to create <%s>."),
  283. table_name);
  284. }
  285. G_debug(1, _("Point classification"));
  286. classification(&Out, elaboration_reg, general_box,
  287. overlap_box, obsVect, parVect_bilin,
  288. parVect_bicub, mean, alpha, grad_H, grad_L,
  289. dims.overlap, lineVect, npoints, driver,
  290. out_opt->answer);
  291. G_free_vector(parVect_bilin);
  292. G_free_vector(parVect_bicub);
  293. G_free_matrix(obsVect);
  294. G_free_ivector(lineVect);
  295. } /* IF */
  296. G_free(observ);
  297. first_it = FALSE;
  298. } /*! END WHILE; last_column = TRUE */
  299. } /*! END WHILE; last_row = TRUE */
  300. /* Dropping auxiliar table */
  301. if (npoints > 0) {
  302. G_debug(1, _("Dropping <%s>"), table_name);
  303. if (Drop_Aux_Table(driver) != DB_OK)
  304. G_warning(_("Auxiliar table could not be dropped"));
  305. }
  306. db_close_database_shutdown_driver(driver);
  307. Vect_close(&In);
  308. sprintf(table_interpolation, "%s_edge_Interpolation", out_opt->answer);
  309. Vect_map_add_dblink(&Out, F_INTERPOLATION, NULL, table_interpolation,
  310. "id", db, dvr);
  311. Vect_close(&Out);
  312. G_done_msg(" ");
  313. exit(EXIT_SUCCESS);
  314. } /*!END MAIN */