zones.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. #include <grass/config.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <grass/lidar.h>
  6. /*----------------------------------------------------------------------------------------*/
  7. void P_zero_dim(struct Reg_dimens *dim)
  8. {
  9. dim->edge_h = 0.0;
  10. dim->edge_v = 0.0;
  11. dim->overlap = 0.0;
  12. dim->sn_size = 0.0;
  13. dim->ew_size = 0.0;
  14. return;
  15. }
  16. /*----------------------------------------------------------------------------------------*/
  17. /*
  18. --------------------------------------------
  19. | Elaboration region |
  20. | ------------------------------------ |
  21. | | General region | |
  22. | | ---------------------------- | |
  23. | | | | | |
  24. | | | | | |
  25. | | | | | |
  26. | | | Overlap region | | |
  27. | | | | | |
  28. | | | | | |
  29. | | | | | |
  30. | | ---------------------------- | |
  31. | | | |
  32. | ------------------------------------ |
  33. | |
  34. --------------------------------------------
  35. The terminology is misleading:
  36. The Overlap region does NOT overlap with neighbouring segments,
  37. but the Elaboration and General region do overlap
  38. Elaboration is used for interpolation
  39. Interpolated points in Elaboration but outside General are discarded
  40. Interpolated points in General but outside Overlap are weighed by
  41. their distance to Overlap and summed up
  42. Interpolated points in Overlap are taken as they are
  43. The buffer zones Elaboration - General and General - Overlap must be
  44. large enough to avoid artefacts
  45. */
  46. int
  47. P_set_regions(struct Cell_head *Elaboration, struct bound_box * General,
  48. struct bound_box * Overlap, struct Reg_dimens dim, int type)
  49. {
  50. /* Set the Elaboration, General, and Overlap region limits
  51. * Returns 0 on success; -1 on failure*/
  52. struct Cell_head orig;
  53. G_get_window(&orig);
  54. switch (type) {
  55. case GENERAL_ROW: /* General case N-S direction */
  56. Elaboration->north =
  57. Elaboration->south + dim.overlap + (2 * dim.edge_h);
  58. Elaboration->south = Elaboration->north - dim.sn_size;
  59. General->N = Elaboration->north - dim.edge_h;
  60. General->S = Elaboration->south + dim.edge_h;
  61. Overlap->N = General->N - dim.overlap;
  62. Overlap->S = General->S + dim.overlap;
  63. return 0;
  64. case GENERAL_COLUMN: /* General case E-W direction */
  65. Elaboration->west =
  66. Elaboration->east - dim.overlap - (2 * dim.edge_v);
  67. Elaboration->east = Elaboration->west + dim.ew_size;
  68. General->W = Elaboration->west + dim.edge_v;
  69. General->E = Elaboration->east - dim.edge_v;
  70. Overlap->W = General->W + dim.overlap;
  71. Overlap->E = General->E - dim.overlap;
  72. return 0;
  73. case FIRST_ROW: /* Just started with first row */
  74. Elaboration->north = orig.north + 2 * dim.edge_h;
  75. Elaboration->south = Elaboration->north - dim.sn_size;
  76. General->N = orig.north;
  77. General->S = Elaboration->south + dim.edge_h;
  78. Overlap->N = General->N;
  79. Overlap->S = General->S + dim.overlap;
  80. return 0;
  81. case LAST_ROW: /* Reached last row */
  82. Elaboration->south = orig.south - 2 * dim.edge_h;
  83. General->S = orig.south;
  84. Overlap->S = General->S;
  85. return 0;
  86. case FIRST_COLUMN: /* Just started with first column */
  87. Elaboration->west = orig.west - 2 * dim.edge_v;
  88. Elaboration->east = Elaboration->west + dim.ew_size;
  89. General->W = orig.west;
  90. General->E = Elaboration->east - dim.edge_v;
  91. Overlap->W = General->W;
  92. Overlap->E = General->E - dim.overlap;
  93. return 0;
  94. case LAST_COLUMN: /* Reached last column */
  95. Elaboration->east = orig.east + 2 * dim.edge_v;
  96. General->E = orig.east;
  97. Overlap->E = General->E;
  98. return 0;
  99. }
  100. return -1;
  101. }
  102. /*----------------------------------------------------------------------------------------*/
  103. int P_set_dim(struct Reg_dimens *dim, double pe, double pn, int *nsplx, int *nsply)
  104. {
  105. int total_splines, edge_splines, n_windows, minsplines;
  106. double E_extension, N_extension, edgeE, edgeN;
  107. struct Cell_head orig;
  108. int ret = 0;
  109. G_get_window(&orig);
  110. E_extension = orig.east - orig.west;
  111. N_extension = orig.north - orig.south;
  112. dim->ew_size = *nsplx * pe;
  113. dim->sn_size = *nsply * pn;
  114. edgeE = dim->ew_size - dim->overlap - 2 * dim->edge_v;
  115. edgeN = dim->sn_size - dim->overlap - 2 * dim->edge_h;
  116. /* number of moving windows: E_extension / edgeE */
  117. /* remaining steps: total steps - (floor(E_extension / edgeE) * E_extension) / passoE */
  118. /* remaining steps must be larger than edge_v + overlap + half of overlap window */
  119. total_splines = ceil(E_extension / pe);
  120. edge_splines = edgeE / pe;
  121. n_windows = floor(E_extension / edgeE); /* without last one */
  122. if (n_windows > 0) {
  123. minsplines = ceil((double)(dim->ew_size / 2.0 - dim->edge_v - dim->overlap) / pe);
  124. while (total_splines - edge_splines * n_windows < minsplines) {
  125. *nsplx -= 1;
  126. dim->ew_size = *nsplx * pe;
  127. edgeE = dim->ew_size - dim->overlap - 2 * dim->edge_v;
  128. edge_splines = edgeE / pe;
  129. n_windows = floor(E_extension / edgeE); /* without last one */
  130. minsplines = ceil((double)(dim->ew_size / 2.0 - dim->edge_v - dim->overlap) / pe);
  131. if (ret == 0)
  132. ret = 1;
  133. }
  134. while (total_splines - edge_splines * n_windows < minsplines * 2 && minsplines > 30) {
  135. *nsplx -= 1;
  136. dim->ew_size = *nsplx * pe;
  137. edgeE = dim->ew_size - dim->overlap - 2 * dim->edge_v;
  138. edge_splines = edgeE / pe;
  139. n_windows = floor(E_extension / edgeE); /* without last one */
  140. minsplines = ceil((double)(dim->ew_size / 2.0 - dim->edge_v - dim->overlap) / pe);
  141. if (ret == 0)
  142. ret = 1;
  143. }
  144. }
  145. total_splines = ceil(N_extension / pn);
  146. edge_splines = edgeN / pn;
  147. n_windows = floor(N_extension / edgeN); /* without last one */
  148. if (n_windows > 0) {
  149. minsplines = ceil((double)(dim->sn_size / 2.0 - dim->edge_h - dim->overlap) / pn);
  150. while (total_splines - edge_splines * n_windows < minsplines) {
  151. *nsply -= 1;
  152. dim->sn_size = *nsply * pn;
  153. edgeN = dim->sn_size - dim->overlap - 2 * dim->edge_h;
  154. edge_splines = edgeN / pn;
  155. n_windows = floor(N_extension / edgeN); /* without last one */
  156. minsplines = ceil((double)(dim->sn_size / 2.0 - dim->edge_h - dim->overlap) / pn);
  157. if (ret < 2)
  158. ret += 2;
  159. }
  160. while (total_splines - edge_splines * n_windows < minsplines * 2 && minsplines > 30) {
  161. *nsply -= 1;
  162. dim->sn_size = *nsply * pn;
  163. edgeN = dim->sn_size - dim->overlap - 2 * dim->edge_h;
  164. edge_splines = edgeN / pn;
  165. n_windows = floor(N_extension / edgeN); /* without last one */
  166. minsplines = ceil((double)(dim->sn_size / 2.0 - dim->edge_h - dim->overlap) / pn);
  167. if (ret < 2)
  168. ret += 2;
  169. }
  170. }
  171. return 0;
  172. }
  173. /*----------------------------------------------------------------------------------------*/
  174. int P_get_edge(int interpolator, struct Reg_dimens *dim, double pe, double pn)
  175. {
  176. /* Set the edge regions dimension
  177. * Returns 1 on success of bilinear; 2 on success of bicubic, 0 on failure */
  178. if (interpolator == P_BILINEAR) {
  179. /* in case of edge artefacts, increase as multiples of 3 */
  180. dim->edge_v = 9 * pe;
  181. dim->edge_h = 9 * pn;
  182. return 1;
  183. }
  184. else if (interpolator == P_BICUBIC) {
  185. /* in case of edge artefacts, increase as multiples of 4 */
  186. dim->edge_v = 12 * pe; /*3 */
  187. dim->edge_h = 12 * pn;
  188. return 2;
  189. }
  190. else
  191. return 0; /* The interpolator is neither bilinear nor bicubic!! */
  192. }
  193. /*----------------------------------------------------------------------------------------*/
  194. int P_get_BandWidth(int interpolator, int nsplines)
  195. {
  196. /* Returns the interpolation matrixes BandWidth dimension */
  197. if (interpolator == 1) {
  198. return (2 * nsplines + 1);
  199. }
  200. else {
  201. return (4 * nsplines + 3);
  202. }
  203. }
  204. /*----------------------------------------------------------------------------------------*/
  205. double
  206. P_Mean_Calc(struct Cell_head *Elaboration, struct Point *obs, int npoints)
  207. {
  208. int i, mean_count = 0;
  209. double mean = 0.0;
  210. struct bound_box mean_box;
  211. Vect_region_box(Elaboration, &mean_box);
  212. mean_box.W -= CONTOUR;
  213. mean_box.E += CONTOUR;
  214. mean_box.N += CONTOUR;
  215. mean_box.S -= CONTOUR;
  216. for (i = 0; i < npoints; i++) { /* */
  217. if (Vect_point_in_box
  218. (obs[i].coordX, obs[i].coordY, obs[i].coordZ, &mean_box)) {
  219. mean_count++;
  220. mean += obs[i].coordZ;
  221. }
  222. }
  223. if (mean_count == 0)
  224. mean = .0;
  225. else
  226. mean /= (double)mean_count;
  227. return mean;
  228. }
  229. double P_estimate_splinestep(struct Map_info *Map, double *dens, double *dist)
  230. {
  231. int type, npoints = 0;
  232. double xmin = 0, xmax = 0, ymin = 0, ymax = 0;
  233. double x, y, z;
  234. struct line_pnts *points;
  235. struct line_cats *categories;
  236. struct bound_box region_box;
  237. struct Cell_head orig;
  238. G_get_set_window(&orig);
  239. Vect_region_box(&orig, &region_box);
  240. points = Vect_new_line_struct();
  241. categories = Vect_new_cats_struct();
  242. Vect_rewind(Map);
  243. while ((type = Vect_read_next_line(Map, points, categories)) > 0) {
  244. if (!(type & GV_POINT))
  245. continue;
  246. x = points->x[0];
  247. y = points->y[0];
  248. if (points->z != NULL)
  249. z = points->z[0];
  250. else
  251. z = 0.0;
  252. /* only use points in current region */
  253. if (Vect_point_in_box(x, y, z, &region_box)) {
  254. npoints++;
  255. if (npoints > 1) {
  256. if (xmin > x)
  257. xmin = x;
  258. else if (xmax < x)
  259. xmax = x;
  260. if (ymin > y)
  261. ymin = y;
  262. else if (ymax < y)
  263. ymax = y;
  264. }
  265. else {
  266. xmin = xmax = x;
  267. ymin = ymax = y;
  268. }
  269. }
  270. }
  271. if (npoints > 0) {
  272. /* estimated average distance between points in map units */
  273. *dist = sqrt(((xmax - xmin) * (ymax - ymin)) / npoints);
  274. /* estimated point density as number of points per square map unit */
  275. *dens = npoints / ((xmax - xmin) * (ymax - ymin));
  276. return 0;
  277. }
  278. else {
  279. return -1;
  280. }
  281. }
  282. struct Point *P_Read_Vector_Region_Map(struct Map_info *Map,
  283. struct Cell_head *Elaboration,
  284. int *num_points, int dim_vect,
  285. int layer)
  286. {
  287. int line_num, pippo, npoints, cat, type;
  288. double x, y, z;
  289. struct Point *obs;
  290. struct line_pnts *points;
  291. struct line_cats *categories;
  292. struct bound_box elaboration_box;
  293. pippo = dim_vect;
  294. obs = (struct Point *)G_calloc(pippo, sizeof(struct Point));
  295. points = Vect_new_line_struct();
  296. categories = Vect_new_cats_struct();
  297. /* Reading points inside elaboration zone */
  298. Vect_region_box(Elaboration, &elaboration_box);
  299. npoints = 0;
  300. line_num = 0;
  301. Vect_rewind(Map);
  302. while ((type = Vect_read_next_line(Map, points, categories)) > 0) {
  303. if (!(type & GV_POINT))
  304. continue;
  305. line_num++;
  306. x = points->x[0];
  307. y = points->y[0];
  308. if (points->z != NULL)
  309. z = points->z[0];
  310. else
  311. z = 0.0;
  312. /* Reading and storing points only if in elaboration_reg */
  313. if (Vect_point_in_box(x, y, z, &elaboration_box)) {
  314. npoints++;
  315. if (npoints >= pippo) {
  316. pippo += dim_vect;
  317. obs =
  318. (struct Point *)G_realloc((void *)obs,
  319. (signed int)pippo *
  320. sizeof(struct Point));
  321. }
  322. /* Storing observation vector */
  323. obs[npoints - 1].coordX = x;
  324. obs[npoints - 1].coordY = y;
  325. obs[npoints - 1].coordZ = z;
  326. obs[npoints - 1].lineID = line_num; /* Storing also the line's number */
  327. Vect_cat_get(categories, layer, &cat);
  328. obs[npoints - 1].cat = cat;
  329. }
  330. }
  331. Vect_destroy_line_struct(points);
  332. Vect_destroy_cats_struct(categories);
  333. *num_points = npoints;
  334. return obs;
  335. }
  336. struct Point *P_Read_Raster_Region_Map(double **matrix,
  337. struct Cell_head *Elaboration,
  338. struct Cell_head *Original,
  339. int *num_points, int *num_nulls, int dim_vect)
  340. {
  341. int col, row, startcol, endcol, startrow, endrow, nrows, ncols;
  342. int pippo, npoints, nnulls;
  343. double x, y, z;
  344. struct Point *obs;
  345. struct bound_box elaboration_box;
  346. pippo = dim_vect;
  347. obs = (struct Point *)G_calloc(pippo, sizeof(struct Point));
  348. /* Reading points inside elaboration zone */
  349. Vect_region_box(Elaboration, &elaboration_box);
  350. npoints = nnulls = 0;
  351. nrows = Original->rows;
  352. ncols = Original->cols;
  353. if (Original->north > Elaboration->north)
  354. startrow = (Original->north - Elaboration->north) / Original->ns_res - 1;
  355. else
  356. startrow = 0;
  357. if (Original->north > Elaboration->south) {
  358. endrow = (Original->north - Elaboration->south) / Original->ns_res + 1;
  359. if (endrow > nrows)
  360. endrow = nrows;
  361. }
  362. else
  363. endrow = nrows;
  364. if (Elaboration->west > Original->west)
  365. startcol = (Elaboration->west - Original->west) / Original->ew_res - 1;
  366. else
  367. startcol = 0;
  368. if (Elaboration->east > Original->west) {
  369. endcol = (Elaboration->east - Original->west) / Original->ew_res + 1;
  370. if (endcol > ncols)
  371. endcol = ncols;
  372. }
  373. else
  374. endcol = ncols;
  375. for (row = startrow; row < endrow; row++) {
  376. for (col = startcol; col < endcol; col++) {
  377. z = matrix[row][col];
  378. if (!Rast_is_d_null_value(&z)) {
  379. x = Rast_col_to_easting((double)(col) + 0.5, Original);
  380. y = Rast_row_to_northing((double)(row) + 0.5, Original);
  381. if (Vect_point_in_box(x, y, 0, &elaboration_box)) {
  382. npoints++;
  383. if (npoints >= pippo) {
  384. pippo += dim_vect;
  385. obs =
  386. (struct Point *)G_realloc((void *)obs,
  387. (signed int)pippo *
  388. sizeof(struct Point));
  389. }
  390. /* Storing observation vector */
  391. obs[npoints - 1].coordX = x;
  392. obs[npoints - 1].coordY = y;
  393. obs[npoints - 1].coordZ = z;
  394. }
  395. }
  396. else {
  397. /* if point in output region */
  398. nnulls++;
  399. }
  400. }
  401. }
  402. *num_points = npoints;
  403. *num_nulls = nnulls;
  404. return obs;
  405. }
  406. /*------------------------------------------------------------------------------------------------*/
  407. int P_Create_Aux2_Table(dbDriver * driver, char *tab_name)
  408. {
  409. dbTable *auxiliar_tab;
  410. dbColumn *column;
  411. auxiliar_tab = db_alloc_table(2);
  412. db_set_table_name(auxiliar_tab, tab_name);
  413. db_set_table_description(auxiliar_tab,
  414. "Intermediate interpolated values");
  415. column = db_get_table_column(auxiliar_tab, 0);
  416. db_set_column_name(column, "ID");
  417. db_set_column_sqltype(column, DB_SQL_TYPE_INTEGER);
  418. column = db_get_table_column(auxiliar_tab, 1);
  419. db_set_column_name(column, "Interp");
  420. db_set_column_sqltype(column, DB_SQL_TYPE_REAL);
  421. if (db_create_table(driver, auxiliar_tab) == DB_OK) {
  422. G_debug(1, _("<%s> created in database."), tab_name);
  423. return TRUE;
  424. }
  425. else
  426. G_warning(_("<%s> has not been created in database."), tab_name);
  427. return FALSE;
  428. }
  429. /*------------------------------------------------------------------------------------------------*/
  430. int P_Create_Aux4_Table(dbDriver * driver, char *tab_name)
  431. {
  432. dbTable *auxiliar_tab;
  433. dbColumn *column;
  434. auxiliar_tab = db_alloc_table(4);
  435. db_set_table_name(auxiliar_tab, tab_name);
  436. db_set_table_description(auxiliar_tab,
  437. "Intermediate interpolated values");
  438. column = db_get_table_column(auxiliar_tab, 0);
  439. db_set_column_name(column, "ID");
  440. db_set_column_sqltype(column, DB_SQL_TYPE_INTEGER);
  441. column = db_get_table_column(auxiliar_tab, 1);
  442. db_set_column_name(column, "Interp");
  443. db_set_column_sqltype(column, DB_SQL_TYPE_REAL);
  444. column = db_get_table_column(auxiliar_tab, 2);
  445. db_set_column_name(column, "X");
  446. db_set_column_sqltype(column, DB_SQL_TYPE_DOUBLE_PRECISION);
  447. column = db_get_table_column(auxiliar_tab, 3);
  448. db_set_column_name(column, "Y");
  449. db_set_column_sqltype(column, DB_SQL_TYPE_DOUBLE_PRECISION);
  450. if (db_create_table(driver, auxiliar_tab) == DB_OK) {
  451. G_debug(1, _("<%s> created in database."), tab_name);
  452. return TRUE;
  453. }
  454. else
  455. G_warning(_("<%s> has not been created in database."), tab_name);
  456. return FALSE;
  457. }
  458. /*------------------------------------------------------------------------------------------------*/
  459. int P_Drop_Aux_Table(dbDriver * driver, char *tab_name)
  460. {
  461. dbString drop;
  462. db_init_string(&drop);
  463. db_append_string(&drop, "drop table ");
  464. db_append_string(&drop, tab_name);
  465. return db_execute_immediate(driver, &drop);
  466. }
  467. /*---------------------------------------------------------------------------------------*/
  468. void P_Aux_to_Raster(double **matrix, int fd)
  469. {
  470. int ncols, col, nrows, row;
  471. void *ptr, *raster;
  472. struct Cell_head Original;
  473. nrows = Rast_window_rows();
  474. ncols = Rast_window_cols();
  475. raster = Rast_allocate_buf(DCELL_TYPE);
  476. for (row = 0; row < nrows; row++) {
  477. G_percent(row, nrows, 2);
  478. Rast_set_d_null_value(raster, ncols);
  479. for (col = 0, ptr = raster; col < ncols;
  480. col++, ptr = G_incr_void_ptr(ptr, Rast_cell_size(DCELL_TYPE))) {
  481. Rast_set_d_value(ptr, (DCELL) (matrix[row][col]), DCELL_TYPE);
  482. }
  483. Rast_put_d_row(fd, raster);
  484. }
  485. G_percent(row, nrows, 2);
  486. }
  487. /*------------------------------------------------------------------------------------------------*/
  488. void
  489. P_Aux_to_Vector(struct Map_info *Map, struct Map_info *Out, dbDriver * driver,
  490. char *tab_name)
  491. {
  492. int more, line_num, type, count = 0;
  493. double coordX, coordY, coordZ;
  494. struct line_pnts *point;
  495. struct line_cats *cat;
  496. dbTable *table;
  497. dbColumn *column;
  498. dbValue *value;
  499. dbCursor cursor;
  500. dbString sql;
  501. char buf[1024];
  502. point = Vect_new_line_struct();
  503. cat = Vect_new_cats_struct();
  504. db_init_string(&sql);
  505. db_zero_string(&sql);
  506. sprintf(buf, "select ID, X, Y, sum(Interp) from %s group by ID, X, Y",
  507. tab_name);
  508. db_append_string(&sql, buf);
  509. db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL);
  510. while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
  511. count++;
  512. table = db_get_cursor_table(&cursor);
  513. column = db_get_table_column(table, 0);
  514. type = db_sqltype_to_Ctype(db_get_column_sqltype(column));
  515. if (type == DB_C_TYPE_INT)
  516. value = db_get_column_value(column);
  517. else
  518. continue;
  519. line_num = db_get_value_int(value);
  520. column = db_get_table_column(table, 1);
  521. type = db_sqltype_to_Ctype(db_get_column_sqltype(column));
  522. if (type == DB_C_TYPE_DOUBLE)
  523. value = db_get_column_value(column);
  524. else
  525. continue;
  526. coordZ = db_get_value_double(value);
  527. column = db_get_table_column(table, 2);
  528. type = db_sqltype_to_Ctype(db_get_column_sqltype(column));
  529. if (type == DB_C_TYPE_DOUBLE)
  530. value = db_get_column_value(column);
  531. else
  532. continue;
  533. coordX = db_get_value_double(value);
  534. column = db_get_table_column(table, 3);
  535. type = db_sqltype_to_Ctype(db_get_column_sqltype(column));
  536. if (type == DB_C_TYPE_DOUBLE)
  537. value = db_get_column_value(column);
  538. else
  539. continue;
  540. coordY = db_get_value_double(value);
  541. Vect_copy_xyz_to_pnts(point, &coordX, &coordY, &coordZ, 1);
  542. Vect_reset_cats(cat);
  543. Vect_cat_set(cat, 1, 1);
  544. Vect_write_line(Out, GV_POINT, point, cat);
  545. }
  546. return;
  547. }
  548. /*! DEFINITION OF THE SUBZONES
  549. 5: inside Overlap region
  550. all others: inside General region but outside Overlap region
  551. ---------------------------------
  552. | | | | | | | |
  553. ---------------------------------
  554. | | | | | | | |
  555. | | | | | | | |
  556. | | | | | | | |
  557. ---------------------------------
  558. | | |4| 3 |3| | |
  559. ---------------------------------
  560. | | | | | | | |
  561. | | |2| 5 |1| | |
  562. | | | | | | | |
  563. ---------------------------------
  564. | | |2| 1 |1| | |
  565. ---------------------------------
  566. | | | | | | | |
  567. | | | | | | | |
  568. | | | | | | | |
  569. ---------------------------------
  570. | | | | | | | |
  571. ---------------------------------
  572. */