You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

shape.cc 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. ESRI shp/shx shapefiles.
  3. Copyright (C) 2003 Robert Lipe, robertlipe+source@gpsbabel.org
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  15. */
  16. #include "defs.h"
  17. #include "shapelib/shapefil.h"
  18. #include <stdlib.h>
  19. #if SHAPELIB_ENABLED
  20. static SHPHandle ihandle;
  21. static DBFHandle ihandledb;
  22. static SHPHandle ohandle;
  23. #define MYNAME "shape"
  24. static unsigned poly_count;
  25. static double* polybufx;
  26. static double* polybufy;
  27. static double* polybufz;
  28. static QString ofname;
  29. static int nameidx;
  30. static int urlidx;
  31. static char* opt_name = NULL;
  32. static char* opt_url = NULL;
  33. static
  34. arglist_t shp_args[] = {
  35. {
  36. "name", &opt_name, "Index of name field in .dbf",
  37. NULL, ARGTYPE_STRING, "0", NULL
  38. },
  39. {
  40. "url", &opt_url, "Index of URL field in .dbf",
  41. NULL, ARGTYPE_INT, "0", NULL
  42. },
  43. ARG_TERMINATOR
  44. };
  45. static void
  46. my_rd_init(const QString& fname)
  47. {
  48. ihandle = SHPOpen(qPrintable(fname), "rb");
  49. if (ihandle == NULL) {
  50. fatal(MYNAME ":Cannot open shp file %s for reading\n", qPrintable(fname));
  51. }
  52. ihandledb = DBFOpen(qPrintable(fname), "rb");
  53. if (ihandledb == NULL) {
  54. fatal(MYNAME ":Cannot open dbf file %s for reading\n", qPrintable(fname));
  55. }
  56. if (opt_name) {
  57. if (opt_name[0] == '?') {
  58. int nFields = 0;
  59. int i = 0;
  60. char name[12];
  61. char* txt = xstrdup(" Database fields\n");
  62. nFields = DBFGetFieldCount(ihandledb);
  63. for (i = 0; i < nFields; i++) {
  64. char txtName[50];
  65. DBFGetFieldInfo(ihandledb, i, name, NULL, NULL);
  66. sprintf(txtName,"%2d %s\n", i, name);
  67. txt = xstrappend(txt, txtName);
  68. }
  69. txt = xstrappend(txt, "\n");
  70. fatal("%s", txt);
  71. }
  72. if (strchr(opt_name, '+')) {
  73. nameidx = -2;
  74. } else if (opt_name[0] >= '0' && opt_name[0] <= '9') {
  75. nameidx = atoi(opt_name);
  76. } else {
  77. nameidx = DBFGetFieldIndex(ihandledb, opt_name);
  78. if (nameidx == -1) {
  79. fatal(MYNAME ":dbf file for %s doesn't have '%s' field.\n", qPrintable(fname), opt_name);
  80. }
  81. }
  82. } else {
  83. nameidx = DBFGetFieldIndex(ihandledb, "NAME");
  84. if (nameidx == -1) {
  85. // fatal(MYNAME ":dbf file for %s doesn't have 'NAME' field.\n Please specify the name index with the 'name' option.\n", qPrintable(fname));
  86. }
  87. }
  88. if (opt_url) {
  89. if (opt_url[0] >= '0' && opt_url[0] <= '9') {
  90. urlidx = atoi(opt_url);
  91. } else {
  92. urlidx = DBFGetFieldIndex(ihandledb, opt_url);
  93. }
  94. } else {
  95. urlidx = DBFGetFieldIndex(ihandledb, "URL");
  96. }
  97. }
  98. void
  99. my_read(void)
  100. {
  101. int npts;
  102. const char* etype = "unknown";
  103. SHPGetInfo(ihandle, &npts, NULL, NULL, NULL);
  104. while (npts) {
  105. SHPObject* shp;
  106. Waypoint* wpt;
  107. const char* name = "";
  108. const char* url;
  109. char* tmpName = NULL;
  110. char* tmpIndex = opt_name;
  111. shp = SHPReadObject(ihandle, npts-1);
  112. if (nameidx >0) {
  113. name = DBFReadStringAttribute(ihandledb, npts-1, nameidx);
  114. } else {
  115. if (nameidx == -1) {
  116. name = "";
  117. } else if (nameidx == -2) {
  118. tmpName = xstrdup("");
  119. tmpIndex = opt_name;
  120. while (tmpIndex) {
  121. char* tmp2 = tmpIndex;
  122. tmpIndex = strchr(tmpIndex,'+');
  123. if (tmpIndex) {
  124. *tmpIndex = '\0';
  125. tmpIndex++;
  126. }
  127. if (tmp2[0]>='0' && tmp2[0]<='9') {
  128. name = DBFReadStringAttribute(
  129. ihandledb, npts-1, atoi(tmp2));
  130. } else {
  131. int idx = 0;
  132. idx = DBFGetFieldIndex(ihandledb, tmp2);
  133. if (idx >= 0) {
  134. name = DBFReadStringAttribute(
  135. ihandledb, npts-1, idx);
  136. }
  137. }
  138. tmpName = xstrappend(tmpName, name);
  139. if (tmpIndex) {
  140. tmpName = xstrappend(tmpName, " / ");
  141. }
  142. }
  143. name = tmpName;
  144. }
  145. }
  146. if (urlidx > 0) {
  147. url = DBFReadStringAttribute(ihandledb, npts-1, urlidx);
  148. } else {
  149. url = NULL;
  150. }
  151. switch (shp->nSHPType) {
  152. case SHPT_ARC: {
  153. int j;
  154. route_head* routehead = route_head_alloc();
  155. routehead->rte_name = name;
  156. route_add_head(routehead);
  157. for (j = 0; j < shp->nVertices; j++) {
  158. wpt = new Waypoint;
  159. wpt->latitude = shp->padfY[j];
  160. wpt->longitude = shp->padfX[j];
  161. wpt->altitude = shp->padfZ[j];
  162. route_add_wpt(routehead, wpt);
  163. }
  164. }
  165. break;
  166. case SHPT_POINT:
  167. wpt = new Waypoint;
  168. wpt->latitude = shp->dfYMin;
  169. wpt->longitude = shp->dfXMin;
  170. wpt->shortname = name;
  171. if (url) {
  172. wpt->AddUrlLink(url);
  173. }
  174. waypt_add(wpt);
  175. break;
  176. case SHPT_POLYGON:
  177. etype = "polygon";
  178. goto err;
  179. case SHPT_MULTIPOINT:
  180. etype = "multipoint";
  181. goto err;
  182. case SHPT_POINTZ:
  183. etype = "pointz" ;
  184. goto err;
  185. case SHPT_ARCZ:
  186. etype = "arcz" ;
  187. goto err;
  188. case SHPT_POLYGONZ:
  189. etype = "polygonz" ;
  190. goto err;
  191. case SHPT_MULTIPOINTZ:
  192. etype = "multipointz" ;
  193. goto err;
  194. case SHPT_POINTM:
  195. etype = "pointm" ;
  196. goto err;
  197. case SHPT_ARCM:
  198. etype = "arcm" ;
  199. goto err;
  200. case SHPT_POLYGONM:
  201. etype = "polygonm" ;
  202. goto err;
  203. case SHPT_MULTIPOINTM:
  204. etype = "multipointm" ;
  205. goto err;
  206. case SHPT_MULTIPATCH:
  207. etype = "multipatch" ;
  208. goto err;
  209. default:
  210. err:
  211. warning("This file contains shapefile geometry type %s that does not naturally convert\nCustom programming is likely required.\n",
  212. etype);
  213. break;
  214. }
  215. SHPDestroyObject(shp);
  216. npts--;
  217. if (tmpName) {
  218. xfree(tmpName);
  219. tmpName = NULL;
  220. }
  221. }
  222. }
  223. void
  224. my_rd_deinit(void)
  225. {
  226. SHPClose(ihandle);
  227. }
  228. void
  229. my_wr_init(const QString& fname)
  230. {
  231. ofname = fname;
  232. }
  233. void
  234. my_wr_deinit(void)
  235. {
  236. SHPClose(ohandle);
  237. ofname.clear();
  238. }
  239. void
  240. my_write_wpt(const Waypoint* wpt)
  241. {
  242. SHPObject* shpobject;
  243. shpobject = SHPCreateSimpleObject(SHPT_POINT, 1,
  244. (double*)(void*)&wpt->longitude,
  245. (double*)(void*)&wpt->latitude,
  246. (double*)(void*)&wpt->altitude);
  247. SHPWriteObject(ohandle, -1, shpobject);
  248. SHPDestroyObject(shpobject);
  249. }
  250. void
  251. poly_init(const route_head* h)
  252. {
  253. int ct = track_waypt_count();
  254. polybufx = (double*) xcalloc(ct, sizeof(double));
  255. polybufy = (double*) xcalloc(ct, sizeof(double));
  256. polybufz = (double*) xcalloc(ct, sizeof(double));
  257. }
  258. void
  259. poly_point(const Waypoint* wpt)
  260. {
  261. polybufx[poly_count] = wpt->longitude;
  262. polybufy[poly_count] = wpt->latitude;
  263. polybufz[poly_count] = wpt->altitude;
  264. poly_count++;
  265. }
  266. void
  267. poly_deinit(const route_head* h)
  268. {
  269. SHPObject* shpobject;
  270. shpobject = SHPCreateSimpleObject(SHPT_ARC, track_waypt_count(),
  271. polybufx, polybufy, polybufz);
  272. SHPWriteObject(ohandle, -1, shpobject);
  273. SHPDestroyObject(shpobject);
  274. xfree(polybufx);
  275. xfree(polybufy);
  276. xfree(polybufz);
  277. fprintf(stderr, "Done\n");
  278. poly_count = 0;
  279. }
  280. void
  281. my_write(void)
  282. {
  283. switch (global_opts.objective) {
  284. case wptdata:
  285. case unknown_gpsdata:
  286. ohandle = SHPCreate(qPrintable(ofname), SHPT_POINT);
  287. if (ohandle == NULL) {
  288. fatal(MYNAME ":Cannot open %s for writing\n",
  289. qPrintable(ofname));
  290. }
  291. waypt_disp_all(my_write_wpt);
  292. break;
  293. case trkdata:
  294. ohandle = SHPCreate(qPrintable(ofname), SHPT_ARC);
  295. if (ohandle == NULL) {
  296. fatal(MYNAME ":Cannot open %s for writing\n",
  297. qPrintable(ofname));
  298. }
  299. route_disp_all(poly_init, poly_deinit, poly_point);
  300. break;
  301. case rtedata:
  302. fatal(MYNAME ": Routes are not supported\n");
  303. break;
  304. case posndata:
  305. fatal(MYNAME ": Realtime positioning not supported\n");
  306. break;
  307. }
  308. }
  309. ff_vecs_t shape_vecs = {
  310. ff_type_internal,
  311. FF_CAP_RW_ALL,
  312. my_rd_init,
  313. my_wr_init,
  314. my_rd_deinit,
  315. my_wr_deinit,
  316. my_read,
  317. my_write,
  318. NULL,
  319. shp_args,
  320. CET_CHARSET_ASCII, 0 /* CET-REVIEW */
  321. };
  322. #endif /* SHAPELIB_ENABLED */