main.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. /*
  2. ***************************************************************
  3. *
  4. * MODULE: v.out.ogr
  5. *
  6. * AUTHOR(S): Radim Blazek
  7. * Some extensions: Markus Neteler, Benjamin Ducke
  8. * Update for GRASS 7 by Martin Landa <landa.martin gmail.com> (create new OGR layer)
  9. *
  10. * PURPOSE: Converts GRASS vector to one of supported OGR vector formats.
  11. *
  12. * COPYRIGHT: (C) 2001-2009 by the GRASS Development Team
  13. *
  14. * This program is free software under the GNU General
  15. * Public License (>=v2). Read the file COPYING that
  16. * comes with GRASS for details.
  17. *
  18. **************************************************************/
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <grass/config.h>
  22. #include <grass/gis.h>
  23. #include <grass/gprojects.h>
  24. #include <grass/glocale.h>
  25. #include "local_proto.h"
  26. int main(int argc, char *argv[])
  27. {
  28. int i, j, k, centroid, otype, donocat;
  29. int num_to_export;
  30. int field;
  31. struct GModule *module;
  32. struct Options options;
  33. struct Flags flags;
  34. char buf[2000];
  35. char key1[200], key2[200];
  36. struct Key_Value *projinfo, *projunits;
  37. struct Cell_head cellhd;
  38. char **tokens;
  39. /* Vector */
  40. struct Map_info In;
  41. struct line_pnts *Points;
  42. struct line_cats *Cats;
  43. int type, cat;
  44. /* Attributes */
  45. int doatt = 0, ncol = 0, colsqltype, colctype, keycol = -1;
  46. struct field_info *Fi = NULL;
  47. dbDriver *Driver = NULL;
  48. dbHandle handle;
  49. dbTable *Table;
  50. dbString dbstring;
  51. dbColumn *Column;
  52. int fout, fskip; /* features written/ skip */
  53. int nocat, noatt, nocatskip; /* number of features without cats/atts written/skip */
  54. /* OGR */
  55. int drn, ogr_ftype = OFTInteger;
  56. OGRDataSourceH Ogr_ds;
  57. OGRSFDriverH Ogr_driver;
  58. OGRLayerH Ogr_layer;
  59. OGRFieldDefnH Ogr_field;
  60. OGRFeatureH Ogr_feature;
  61. OGRFeatureDefnH Ogr_featuredefn;
  62. OGRGeometryH Ogr_geometry;
  63. unsigned int wkbtype = wkbUnknown; /* ?? */
  64. OGRSpatialReferenceH Ogr_projection;
  65. char **papszDSCO = NULL, **papszLCO = NULL;
  66. int num_types;
  67. G_gisinit(argv[0]);
  68. /* Module options */
  69. module = G_define_module();
  70. G_add_keyword(_("vector"));
  71. G_add_keyword(_("export"));
  72. G_add_keyword(_("ogr"));
  73. module->description =
  74. _("Converts GRASS vector map to one of the supported OGR vector formats.");
  75. /* parse & read options */
  76. parse_args(argc, argv,
  77. &options, &flags);
  78. field = atoi(options.field->answer);
  79. /* parse dataset creation options */
  80. i = 0;
  81. while (options.dsco->answers[i]) {
  82. tokens = G_tokenize(options.dsco->answers[i], "=");
  83. if (G_number_of_tokens(tokens))
  84. papszDSCO = CSLSetNameValue(papszDSCO, tokens[0], tokens[1]);
  85. G_free_tokens(tokens);
  86. i++;
  87. }
  88. /* parse layer creation options */
  89. i = 0;
  90. while (options.lco->answers[i]) {
  91. tokens = G_tokenize(options.lco->answers[i], "=");
  92. if (G_number_of_tokens(tokens))
  93. papszLCO = CSLSetNameValue(papszLCO, tokens[0], tokens[1]);
  94. G_free_tokens(tokens);
  95. i++;
  96. }
  97. /*
  98. If no output type specified: determine one automatically.
  99. Centroids, Boundaries and Kernels always have to be exported
  100. explicitely, using the "type=" option.
  101. */
  102. if (!flags.new->answer) {
  103. /* open input vector (topology required) */
  104. Vect_set_open_level(2);
  105. Vect_open_old(&In, options.input->answer, "");
  106. if (strcmp(options.type->answer, "auto") == 0) {
  107. G_debug(2, "Automatic type determination.");
  108. options.type->answers = G_malloc(sizeof(char*) * 10);
  109. G_zero(options.type->answers, sizeof(char *) * 10);
  110. num_types = 0;
  111. if (Vect_get_num_primitives (&In, GV_POINT) > 0) {
  112. options.type->answers[num_types++] = G_store("point");
  113. G_debug(3, "Adding points to export list.");
  114. }
  115. if (Vect_get_num_primitives (&In, GV_LINE) > 0 ) {
  116. options.type->answers[num_types++] = G_store("line");
  117. G_debug(3, "Adding lines to export list.");
  118. }
  119. if (Vect_get_num_areas (&In) > 0) {
  120. options.type->answers[num_types++] = G_store("area");
  121. G_debug(3, "Adding areas to export list.");
  122. }
  123. /* Faces and volumes:
  124. For now, volumes will just be exported as sets of faces.
  125. */
  126. if (Vect_get_num_primitives (&In, GV_FACE) > 0) {
  127. options.type->answers[num_types++] = G_store("face");
  128. G_debug(3, "Adding faces to export list.");
  129. }
  130. /* this check HAS TO FOLLOW RIGHT AFTER check for GV_FACE! */
  131. if ( Vect_get_num_volumes (&In) > 0) {
  132. G_warning(_("Volumes will be exported as sets of faces"));
  133. if (num_types == 0) {
  134. /* no other types yet? */
  135. options.type->answers[num_types++] = G_store("volume");
  136. G_debug(3, "Adding volumes to export list.");
  137. } else {
  138. if (strcmp(options.type->answers[num_types-1], "face") != 0) {
  139. /* only put faces on export list if that's not the case already */
  140. options.type->answers[num_types++] = G_store("volume");
  141. G_debug(3, "Adding volumes to export list.");
  142. }
  143. }
  144. }
  145. if (num_types == 0)
  146. G_fatal_error(_("Unable to determine input map's vector feature type(s)."));
  147. }
  148. }
  149. /* check output feature type */
  150. otype = Vect_option_to_types(options.type);
  151. if (!options.layer->answer) {
  152. char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
  153. if (G_name_is_fully_qualified(options.input->answer, xname, xmapset))
  154. options.layer->answer = G_store(xname);
  155. else
  156. options.layer->answer = G_store(options.input->answer);
  157. }
  158. if (otype & GV_POINTS)
  159. wkbtype = wkbPoint;
  160. else if (otype & GV_LINES)
  161. wkbtype = wkbLineString;
  162. else if (otype & GV_AREA)
  163. wkbtype = wkbPolygon;
  164. else if (otype & GV_FACE)
  165. wkbtype = wkbPolygon25D;
  166. else if (otype & GV_VOLUME)
  167. wkbtype = wkbPolygon25D;
  168. if (flags.poly->answer)
  169. wkbtype = wkbPolygon;
  170. if (((GV_POINTS & otype) && (GV_LINES & otype)) ||
  171. ((GV_POINTS & otype) && (GV_AREA & otype)) ||
  172. ((GV_POINTS & otype) && (GV_FACE & otype)) ||
  173. ((GV_POINTS & otype) && (GV_KERNEL & otype)) ||
  174. ((GV_POINTS & otype) && (GV_VOLUME & otype)) ||
  175. ((GV_LINES & otype) && (GV_AREA & otype)) ||
  176. ((GV_LINES & otype) && (GV_FACE & otype)) ||
  177. ((GV_LINES & otype) && (GV_KERNEL & otype)) ||
  178. ((GV_LINES & otype) && (GV_VOLUME & otype)) ||
  179. ((GV_KERNEL & otype) && (GV_POINTS & otype)) ||
  180. ((GV_KERNEL & otype) && (GV_LINES & otype)) ||
  181. ((GV_KERNEL & otype) && (GV_AREA & otype)) ||
  182. ((GV_KERNEL & otype) && (GV_FACE & otype)) ||
  183. ((GV_KERNEL & otype) && (GV_VOLUME & otype))
  184. ) {
  185. G_warning(_("The combination of types is not supported"
  186. " by all formats."));
  187. wkbtype = wkbUnknown;
  188. }
  189. /* fetch PROJ info */
  190. G_get_default_window(&cellhd);
  191. if (cellhd.proj == PROJECTION_XY)
  192. Ogr_projection = NULL;
  193. else {
  194. projinfo = G_get_projinfo();
  195. projunits = G_get_projunits();
  196. Ogr_projection = GPJ_grass_to_osr(projinfo, projunits);
  197. if (flags.esristyle->answer &&
  198. (strcmp(options.format->answer, "ESRI_Shapefile") == 0))
  199. OSRMorphToESRI(Ogr_projection);
  200. }
  201. /* create new OGR layer in datasource */
  202. if (flags.new->answer) {
  203. const char *name;
  204. name = options.layer->answer ? options.layer->answer : options.input->answer;
  205. create_ogr_layer(options.dsn->answer, options.format->answer, name,
  206. wkbtype, (const char **) papszDSCO, (const char **) papszLCO);
  207. G_message(_("OGR layer <%s> created in datasource <%s> (format '%s')"),
  208. name, options.dsn->answer, options.format->answer);
  209. exit(EXIT_SUCCESS);
  210. }
  211. if (flags.cat->answer)
  212. donocat = 1;
  213. else
  214. donocat = 0;
  215. Points = Vect_new_line_struct();
  216. Cats = Vect_new_cats_struct();
  217. if ((GV_AREA & otype) && Vect_get_num_islands(&In) > 0 && flags.cat->answer)
  218. G_warning(_("The map contains islands. With the -c flag, "
  219. "islands will appear as filled areas, not holes in the output map."));
  220. /* Open OGR DSN */
  221. G_debug(2, "driver count = %d", OGRGetDriverCount());
  222. drn = -1;
  223. for (i = 0; i < OGRGetDriverCount(); i++) {
  224. Ogr_driver = OGRGetDriver(i);
  225. G_debug(2, "driver %d : %s", i, OGR_Dr_GetName(Ogr_driver));
  226. /* chg white space to underscore in OGR driver names */
  227. sprintf(buf, "%s", OGR_Dr_GetName(Ogr_driver));
  228. G_strchg(buf, ' ', '_');
  229. if (strcmp(buf, options.format->answer) == 0) {
  230. drn = i;
  231. G_debug(2, " -> driver = %d", drn);
  232. }
  233. }
  234. if (drn == -1)
  235. G_fatal_error(_("OGR driver <%s> not found"), options.format->answer);
  236. Ogr_driver = OGRGetDriver(drn);
  237. if (flags.update->answer) {
  238. G_debug(1, "Update OGR data source");
  239. Ogr_ds = OGR_Dr_Open(Ogr_driver, options.dsn->answer, TRUE);
  240. } else {
  241. G_debug(1, "Create OGR data source");
  242. Ogr_ds = OGR_Dr_CreateDataSource(Ogr_driver, options.dsn->answer, papszDSCO);
  243. }
  244. CSLDestroy(papszDSCO);
  245. if (Ogr_ds == NULL)
  246. G_fatal_error(_("Unable to open OGR data source '%s'"),
  247. options.dsn->answer);
  248. /* check if OGR layer exists */
  249. if (!G_check_overwrite(argc, argv) && OGR_DS_GetLayerByName(Ogr_ds, options.layer->answer)) {
  250. G_fatal_error(_("OGR layer <%s> already exists in '%s'"),
  251. options.layer->answer, options.dsn->answer);
  252. }
  253. /* check if the map is 3d */
  254. if (Vect_is_3d(&In)) {
  255. /* specific check for shp */
  256. if (strcmp(options.format->answer, "ESRI_Shapefile") == 0) {
  257. const char *shpt;
  258. shpt = CSLFetchNameValue(papszLCO, "SHPT");
  259. if (!shpt || shpt[strlen(shpt) - 1] != 'Z') {
  260. G_warning(_("Vector map <%s> is 3D. "
  261. "Use format specific layer creation options (parameter 'lco') "
  262. "to export in 3D rather than 2D (default)"),
  263. options.input->answer);
  264. }
  265. }
  266. else {
  267. G_warning(_("Vector map <%s> is 3D. "
  268. "Use format specific layer creation options (parameter 'lco') "
  269. "to export in 3D rather than 2D (default)"),
  270. options.input->answer);
  271. }
  272. }
  273. G_debug(1, "Create OGR layer");
  274. Ogr_layer =
  275. OGR_DS_CreateLayer(Ogr_ds, options.layer->answer, Ogr_projection, wkbtype,
  276. papszLCO);
  277. CSLDestroy(papszLCO);
  278. if (Ogr_layer == NULL)
  279. G_fatal_error(_("Unable to create OGR layer"));
  280. db_init_string(&dbstring);
  281. /* Vector attributes -> OGR fields */
  282. if (field > 0) {
  283. G_debug(1, "Create attribute table");
  284. doatt = 1; /* do attributes */
  285. Fi = Vect_get_field(&In, field);
  286. if (Fi == NULL) {
  287. G_warning(_("No attribute table found -> using only category numbers as attributes"));
  288. /* if we have no more than a 'cat' column, then that has to
  289. be exported in any case */
  290. if (flags.nocat->answer) {
  291. G_warning(_("Exporting 'cat' anyway, as it is the only attribute table field"));
  292. flags.nocat->answer=0;
  293. }
  294. Ogr_field = OGR_Fld_Create("cat", OFTInteger);
  295. OGR_L_CreateField(Ogr_layer, Ogr_field, 0);
  296. OGR_Fld_Destroy(Ogr_field);
  297. doatt = 0;
  298. }
  299. else {
  300. Driver = db_start_driver(Fi->driver);
  301. if (Driver == NULL)
  302. G_fatal_error(_("Unable to start driver <%s>"), Fi->driver);
  303. db_init_handle(&handle);
  304. db_set_handle(&handle, Fi->database, NULL);
  305. if (db_open_database(Driver, &handle) != DB_OK)
  306. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  307. Fi->database, Fi->driver);
  308. db_set_string(&dbstring, Fi->table);
  309. if (db_describe_table(Driver, &dbstring, &Table) != DB_OK)
  310. G_fatal_error(_("Unable to describe table <%s>"), Fi->table);
  311. ncol = db_get_table_number_of_columns(Table);
  312. G_debug(2, "ncol = %d", ncol);
  313. keycol = -1;
  314. for (i = 0; i < ncol; i++) {
  315. Column = db_get_table_column(Table, i);
  316. colsqltype = db_get_column_sqltype(Column);
  317. G_debug(2, "col %d: %s (%s)", i, db_get_column_name(Column),
  318. db_sqltype_name(colsqltype));
  319. colctype = db_sqltype_to_Ctype(colsqltype);
  320. switch (colctype) {
  321. case DB_C_TYPE_INT:
  322. ogr_ftype = OFTInteger;
  323. break;
  324. case DB_C_TYPE_DOUBLE:
  325. ogr_ftype = OFTReal;
  326. break;
  327. case DB_C_TYPE_STRING:
  328. ogr_ftype = OFTString;
  329. break;
  330. case DB_C_TYPE_DATETIME:
  331. ogr_ftype = OFTString;
  332. break;
  333. }
  334. G_debug(2, "ogr_ftype = %d", ogr_ftype);
  335. strcpy(key1, Fi->key);
  336. G_tolcase(key1);
  337. strcpy(key2, db_get_column_name(Column));
  338. G_tolcase(key2);
  339. if (strcmp(key1, key2) == 0)
  340. keycol = i;
  341. G_debug(2, "%s x %s -> %s x %s -> keycol = %d", Fi->key,
  342. db_get_column_name(Column), key1, key2, keycol);
  343. Ogr_field =
  344. OGR_Fld_Create(db_get_column_name(Column), ogr_ftype);
  345. OGR_L_CreateField(Ogr_layer, Ogr_field, 0);
  346. OGR_Fld_Destroy(Ogr_field);
  347. if (!flags.nocat->answer) {
  348. Ogr_field =
  349. OGR_Fld_Create(db_get_column_name(Column), ogr_ftype);
  350. OGR_L_CreateField(Ogr_layer, Ogr_field, 0);
  351. OGR_Fld_Destroy(Ogr_field);
  352. } else {
  353. /* skip export of 'cat' field */
  354. if (strcmp (Fi->key,db_get_column_name(Column)) != 0) {
  355. Ogr_field =
  356. OGR_Fld_Create(db_get_column_name(Column), ogr_ftype);
  357. OGR_L_CreateField(Ogr_layer, Ogr_field, 0);
  358. OGR_Fld_Destroy(Ogr_field);
  359. }
  360. }
  361. }
  362. if (keycol == -1)
  363. G_fatal_error(_("Key column '%s' not found"), Fi->key);
  364. }
  365. }
  366. Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
  367. fout = fskip = nocat = noatt = nocatskip = 0;
  368. /* check what users wants to export and what's present in the map */
  369. if (Vect_get_num_primitives(&In, GV_POINT) > 0 && !(otype & GV_POINTS))
  370. G_warning(_("%d point(s) found, but not requested to be exported. "
  371. "Verify 'type' parameter."), Vect_get_num_primitives(&In,
  372. GV_POINT));
  373. if (Vect_get_num_primitives(&In, GV_LINE) > 0 && !(otype & GV_LINES))
  374. G_warning(_("%d line(s) found, but not requested to be exported. "
  375. "Verify 'type' parameter."), Vect_get_num_primitives(&In,
  376. GV_LINE));
  377. if (Vect_get_num_primitives(&In, GV_BOUNDARY) > 0 &&
  378. !(otype & GV_BOUNDARY) && !(otype & GV_AREA))
  379. G_warning(_("%d boundary(ies) found, but not requested to be exported. "
  380. "Verify 'type' parameter."), Vect_get_num_primitives(&In,
  381. GV_BOUNDARY));
  382. if (Vect_get_num_primitives(&In, GV_CENTROID) > 0 &&
  383. !(otype & GV_CENTROID) && !(otype & GV_AREA))
  384. G_warning(_("%d centroid(s) found, but not requested to be exported. "
  385. "Verify 'type' parameter."), Vect_get_num_primitives(&In,
  386. GV_CENTROID));
  387. if (Vect_get_num_areas(&In) > 0 && !(otype & GV_AREA))
  388. G_warning(_("%d areas found, but not requested to be exported. "
  389. "Verify 'type' parameter."), Vect_get_num_areas(&In));
  390. if (Vect_get_num_primitives(&In, GV_FACE) > 0 && !(otype & GV_FACE))
  391. G_warning(_("%d faces found, but not requested to be exported. "
  392. "Verify 'type' parameter."), Vect_get_num_primitives(&In,
  393. GV_FACE));
  394. if (Vect_get_num_volumes(&In) > 0 && !(otype & GV_VOLUME))
  395. G_warning(_("%d volume(s) found, but not requested to be exported. "
  396. "Verify 'type' parameter."), Vect_get_num_volumes(&In));
  397. /* warn and eventually abort if there is nothing to be exported */
  398. num_to_export = 0;
  399. if (Vect_get_num_primitives(&In, GV_POINT) < 1 && (otype & GV_POINTS)) {
  400. G_warning(_("No points found, but requested to be exported. "
  401. "Will skip this feature type."));
  402. } else {
  403. if (otype & GV_POINT)
  404. num_to_export = num_to_export + Vect_get_num_primitives(&In, GV_POINT);
  405. }
  406. if (Vect_get_num_primitives(&In, GV_LINE) < 1 && (otype & GV_LINE)) {
  407. G_warning(_("No lines found, but requested to be exported. "
  408. "Will skip this feature type."));
  409. } else {
  410. if (otype & GV_LINE)
  411. num_to_export = num_to_export + Vect_get_num_primitives(&In, GV_LINE);
  412. }
  413. if (Vect_get_num_primitives(&In, GV_BOUNDARY) < 1 && (otype & GV_BOUNDARY)) {
  414. G_warning(_("No boundaries found, but requested to be exported. "
  415. "Will skip this feature type."));
  416. } else {
  417. if (otype & GV_BOUNDARY)
  418. num_to_export = num_to_export + Vect_get_num_primitives(&In, GV_BOUNDARY);
  419. }
  420. if (Vect_get_num_areas(&In) < 1 && (otype & GV_AREA)) {
  421. G_warning(_("No areas found, but requested to be exported. "
  422. "Will skip this feature type."));
  423. } else {
  424. if (otype & GV_AREA)
  425. num_to_export = num_to_export + Vect_get_num_areas(&In);
  426. }
  427. if (Vect_get_num_primitives(&In, GV_CENTROID) < 1 && (otype & GV_CENTROID)) {
  428. G_warning(_("No centroids found, but requested to be exported. "
  429. "Will skip this feature type."));
  430. } else {
  431. if (otype & GV_CENTROID)
  432. num_to_export = num_to_export + Vect_get_num_primitives(&In, GV_CENTROID);
  433. }
  434. if (Vect_get_num_primitives(&In, GV_FACE) < 1 && (otype & GV_FACE)) {
  435. G_warning(_("No faces found, but requested to be exported. "
  436. "Will skip this feature type."));
  437. } else {
  438. if (otype & GV_FACE)
  439. num_to_export = num_to_export + Vect_get_num_primitives(&In, GV_FACE);
  440. }
  441. if (Vect_get_num_primitives(&In, GV_KERNEL) < 1 && (otype & GV_KERNEL)) {
  442. G_warning(_("No kernels found, but requested to be exported. "
  443. "Will skip this feature type."));
  444. } else {
  445. if (otype & GV_KERNEL)
  446. num_to_export = num_to_export + Vect_get_num_primitives(&In, GV_KERNEL);
  447. }
  448. if (Vect_get_num_volumes(&In) < 1 && (otype & GV_VOLUME)) {
  449. G_warning(_("No volumes found, but requested to be exported. "
  450. "Will skip this feature type."));
  451. } else {
  452. if (otype & GV_VOLUME)
  453. num_to_export = num_to_export + Vect_get_num_volumes(&In);
  454. }
  455. G_debug(1, "Requested to export %d features", num_to_export);
  456. if (num_to_export < 1) {
  457. G_warning(_("Nothing to export"));
  458. exit(EXIT_SUCCESS);
  459. }
  460. /* Lines (run always to count features of different type) */
  461. if ((otype & GV_POINTS) || (otype & GV_LINES)) {
  462. G_message(_("Exporting %i features..."), Vect_get_num_lines(&In));
  463. for (i = 1; i <= Vect_get_num_lines(&In); i++) {
  464. G_percent(i, Vect_get_num_lines(&In), 1);
  465. type = Vect_read_line(&In, Points, Cats, i);
  466. G_debug(2, "line = %d type = %d", i, type);
  467. if (!(otype & type)) {
  468. G_debug(2, "type %d not specified -> skipping", type);
  469. fskip++;
  470. continue;
  471. }
  472. Vect_cat_get(Cats, field, &cat);
  473. if (cat < 0 && !donocat) { /* Do not export not labeled */
  474. nocatskip++;
  475. continue;
  476. }
  477. /* Geometry */
  478. if (type == GV_LINE && flags.poly->answer) {
  479. OGRGeometryH ring;
  480. ring = OGR_G_CreateGeometry(wkbLinearRing);
  481. Ogr_geometry = OGR_G_CreateGeometry(wkbPolygon);
  482. /* Area */
  483. for (j = 0; j < Points->n_points; j++) {
  484. OGR_G_AddPoint(ring, Points->x[j], Points->y[j],
  485. Points->z[j]);
  486. }
  487. if (Points->x[Points->n_points - 1] != Points->x[0] ||
  488. Points->y[Points->n_points - 1] != Points->y[0] ||
  489. Points->z[Points->n_points - 1] != Points->z[0]) {
  490. OGR_G_AddPoint(ring, Points->x[0], Points->y[0],
  491. Points->z[0]);
  492. }
  493. OGR_G_AddGeometryDirectly(Ogr_geometry, ring);
  494. }
  495. else if ((type == GV_POINT) || ((type == GV_CENTROID) && (otype & GV_CENTROID))) {
  496. Ogr_geometry = OGR_G_CreateGeometry(wkbPoint);
  497. OGR_G_AddPoint(Ogr_geometry, Points->x[0], Points->y[0],
  498. Points->z[0]);
  499. }
  500. else { /* GV_LINE or GV_BOUNDARY */
  501. Ogr_geometry = OGR_G_CreateGeometry(wkbLineString);
  502. for (j = 0; j < Points->n_points; j++) {
  503. OGR_G_AddPoint(Ogr_geometry, Points->x[j], Points->y[j],
  504. Points->z[j]);
  505. }
  506. }
  507. Ogr_feature = OGR_F_Create(Ogr_featuredefn);
  508. OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
  509. /* Output one feature for each category */
  510. for (j = -1; j < Cats->n_cats; j++) {
  511. if (j == -1) {
  512. if (cat >= 0)
  513. continue; /* cat(s) exists */
  514. }
  515. else {
  516. if (Cats->field[j] == field)
  517. cat = Cats->cat[j];
  518. else
  519. continue;
  520. }
  521. mk_att(cat, Fi, Driver, ncol, doatt, flags.nocat->answer, Ogr_feature, &noatt, &fout);
  522. OGR_L_CreateFeature(Ogr_layer, Ogr_feature);
  523. }
  524. OGR_G_DestroyGeometry(Ogr_geometry);
  525. OGR_F_Destroy(Ogr_feature);
  526. }
  527. }
  528. /* Areas (run always to count features of different type) */
  529. if (Vect_get_num_areas(&In) > 0 && otype & GV_AREA) {
  530. G_message(_("Exporting %i areas (may take some time)..."),
  531. Vect_get_num_areas(&In));
  532. for (i = 1; i <= Vect_get_num_areas(&In); i++) {
  533. OGRGeometryH ring;
  534. G_percent(i, Vect_get_num_areas(&In), 1);
  535. centroid = Vect_get_area_centroid(&In, i);
  536. cat = -1;
  537. if (centroid > 0) {
  538. Vect_read_line(&In, NULL, Cats, centroid);
  539. Vect_cat_get(Cats, field, &cat);
  540. }
  541. G_debug(3, "area = %d centroid = %d ncats = %d", i, centroid,
  542. Cats->n_cats);
  543. if (cat < 0 && !donocat) { /* Do not export not labeled */
  544. nocatskip++;
  545. continue;
  546. }
  547. Vect_get_area_points(&In, i, Points);
  548. /* Geometry */
  549. Ogr_geometry = OGR_G_CreateGeometry(wkbPolygon);
  550. ring = OGR_G_CreateGeometry(wkbLinearRing);
  551. /* Area */
  552. for (j = 0; j < Points->n_points; j++) {
  553. OGR_G_AddPoint(ring, Points->x[j], Points->y[j],
  554. Points->z[j]);
  555. }
  556. OGR_G_AddGeometryDirectly(Ogr_geometry, ring);
  557. /* Isles */
  558. for (k = 0; k < Vect_get_area_num_isles(&In, i); k++) {
  559. Vect_get_isle_points(&In, Vect_get_area_isle(&In, i, k),
  560. Points);
  561. ring = OGR_G_CreateGeometry(wkbLinearRing);
  562. for (j = 0; j < Points->n_points; j++) {
  563. OGR_G_AddPoint(ring, Points->x[j], Points->y[j],
  564. Points->z[j]);
  565. }
  566. OGR_G_AddGeometryDirectly(Ogr_geometry, ring);
  567. }
  568. Ogr_feature = OGR_F_Create(Ogr_featuredefn);
  569. OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
  570. /* Output one feature for each category */
  571. for (j = -1; j < Cats->n_cats; j++) {
  572. if (j == -1) {
  573. if (cat >= 0)
  574. continue; /* cat(s) exists */
  575. }
  576. else {
  577. if (Cats->field[j] == field)
  578. cat = Cats->cat[j];
  579. else
  580. continue;
  581. }
  582. mk_att(cat, Fi, Driver, ncol, doatt, flags.nocat->answer, Ogr_feature, &noatt, &fout);
  583. OGR_L_CreateFeature(Ogr_layer, Ogr_feature);
  584. }
  585. OGR_G_DestroyGeometry(Ogr_geometry);
  586. OGR_F_Destroy(Ogr_feature);
  587. }
  588. }
  589. /* Faces (run always to count features of different type) - Faces are similar to lines */
  590. if (Vect_get_num_primitives(&In, GV_FACE) > 0 && otype & GV_FACE) {
  591. G_message(_("Exporting %i faces..."),
  592. Vect_get_num_faces(&In));
  593. for (i = 1; i <= Vect_get_num_faces(&In); i++) {
  594. OGRGeometryH ring;
  595. G_percent(i, Vect_get_num_faces(&In), 1);
  596. type = Vect_read_line(&In, Points, Cats, i);
  597. G_debug(3, "line type = %d", type);
  598. cat = -1;
  599. Vect_cat_get(Cats, field, &cat);
  600. G_debug(3, "face = %d ncats = %d", i, Cats->n_cats);
  601. if (cat < 0 && !donocat) { /* Do not export not labeled */
  602. nocatskip++;
  603. continue;
  604. }
  605. if (type & GV_FACE) {
  606. Ogr_feature = OGR_F_Create(Ogr_featuredefn);
  607. /* Geometry */
  608. Ogr_geometry = OGR_G_CreateGeometry(wkbPolygon25D);
  609. ring = OGR_G_CreateGeometry(wkbLinearRing);
  610. /* Face */
  611. for (j = 0; j < Points->n_points; j++) {
  612. OGR_G_AddPoint(ring, Points->x[j], Points->y[j],
  613. Points->z[j]);
  614. }
  615. OGR_G_AddGeometryDirectly(Ogr_geometry, ring);
  616. OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
  617. /* Output one feature for each category */
  618. for (j = -1; j < Cats->n_cats; j++) {
  619. if (j == -1) {
  620. if (cat >= 0)
  621. continue; /* cat(s) exists */
  622. }
  623. else {
  624. if (Cats->field[j] == field)
  625. cat = Cats->cat[j];
  626. else
  627. continue;
  628. }
  629. mk_att(cat, Fi, Driver, ncol, doatt, flags.nocat->answer, Ogr_feature, &noatt, &fout);
  630. OGR_L_CreateFeature(Ogr_layer, Ogr_feature);
  631. }
  632. OGR_G_DestroyGeometry(Ogr_geometry);
  633. OGR_F_Destroy(Ogr_feature);
  634. } /* if type & GV_FACE */
  635. } /* for */
  636. }
  637. /* Kernels */
  638. if (Vect_get_num_primitives(&In, GV_KERNEL) > 0 && otype & GV_KERNEL) {
  639. G_message(_("Exporting %i kernels..."), Vect_get_num_kernels(&In));
  640. for (i = 1; i <= Vect_get_num_lines(&In); i++) {
  641. G_percent(i, Vect_get_num_lines(&In), 1);
  642. type = Vect_read_line(&In, Points, Cats, i);
  643. G_debug(2, "line = %d type = %d", i, type);
  644. if (!(otype & type)) {
  645. G_debug(2, "type %d not specified -> skipping", type);
  646. fskip++;
  647. continue;
  648. }
  649. Vect_cat_get(Cats, field, &cat);
  650. if (cat < 0 && !donocat) { /* Do not export not labeled */
  651. nocatskip++;
  652. continue;
  653. }
  654. /* Geometry */
  655. if (type == GV_KERNEL) {
  656. Ogr_geometry = OGR_G_CreateGeometry(wkbPoint);
  657. OGR_G_AddPoint(Ogr_geometry, Points->x[0], Points->y[0],
  658. Points->z[0]);
  659. Ogr_feature = OGR_F_Create(Ogr_featuredefn);
  660. OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
  661. /* Output one feature for each category */
  662. for (j = -1; j < Cats->n_cats; j++) {
  663. if (j == -1) {
  664. if (cat >= 0)
  665. continue; /* cat(s) exists */
  666. }
  667. else {
  668. if (Cats->field[j] == field)
  669. cat = Cats->cat[j];
  670. else
  671. continue;
  672. }
  673. mk_att(cat, Fi, Driver, ncol, doatt, flags.nocat->answer, Ogr_feature, &noatt, &fout);
  674. OGR_L_CreateFeature(Ogr_layer, Ogr_feature);
  675. }
  676. OGR_G_DestroyGeometry(Ogr_geometry);
  677. OGR_F_Destroy(Ogr_feature);
  678. }
  679. }
  680. }
  681. /*
  682. TODO: Volumes. Do not export kernels here, that's already done.
  683. We do need to worry about holes, though.
  684. NOTE: We can probably just merge this with faces export function.
  685. Except for GRASS, which output format would know the difference?
  686. */
  687. if ((otype & GV_VOLUME)) {
  688. G_message(_("Exporting %i volumes..."), Vect_get_num_volumes(&In));
  689. G_warning(_("Export of volumes not implemented yet. Skipping."));
  690. }
  691. OGR_DS_Destroy(Ogr_ds);
  692. Vect_close(&In);
  693. if (doatt) {
  694. db_close_database(Driver);
  695. db_shutdown_driver(Driver);
  696. }
  697. /* Summary */
  698. G_message(_("%d features written"), fout);
  699. if (nocat > 0)
  700. G_warning(_("%d features without category were written"), nocat);
  701. if (noatt > 0)
  702. G_warning(_("%d features without attributes were written"), noatt);
  703. if (nocatskip > 0)
  704. G_message(_("%d features found without category were skipped"),
  705. nocatskip);
  706. /* Enable this? May be confusing that for area type are not reported
  707. * all boundaries/centroids.
  708. * OTOH why should be reported? */
  709. /*
  710. if (((otype & GV_POINTS) || (otype & GV_LINES)) && fskip > 0)
  711. G_warning ("%d features of different type skip", fskip);
  712. */
  713. G_done_msg(" ");
  714. exit(EXIT_SUCCESS);
  715. }