shapefuncs.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. /*
  2. * Local function prototypes
  3. */
  4. static int _calc_shapelen (
  5. GeomType type,
  6. int numpoints,
  7. int numparts
  8. );
  9. static void _get_extrema (
  10. int num_points,
  11. Point *pt,
  12. double *z,
  13. double *m,
  14. double *xy_bnd,
  15. double *z_bnd,
  16. double *m_bnd
  17. );
  18. static int _get_shp_parts (
  19. char *cp,
  20. int swap_bytes,
  21. Geometry *geom
  22. );
  23. static int _get_shp_multipoint (
  24. char *cp,
  25. int swap_bytes,
  26. Geometry *geom
  27. );
  28. static int _get_shp_point (
  29. char *cp,
  30. int swap_bytes,
  31. Geometry *geom
  32. );
  33. /***************************************************************************
  34. *
  35. * geom_to_shape - takes a geometry and converts it into a shape
  36. * representation.
  37. *
  38. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  39. *
  40. * Purpose:
  41. * Converts a geometry into its ESRI shape representation.
  42. *
  43. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  44. *
  45. * Parameters:
  46. * geom <Input> == (Geometry *) The geometry object
  47. * max_alloced <In/Out> == (int *) The maximum number of bytes
  48. * allocated to the binary array.
  49. * data_len <Output> == (int *) The number of bytes in the shape.
  50. * binary <Output> == (char **) The shape binary.
  51. *
  52. * RETURN <Output> == (void)
  53. *
  54. ****************************************************************************/
  55. void geom_to_shape (
  56. Geometry *geom,
  57. int *max_alloced,
  58. int *data_len,
  59. char **binary
  60. )
  61. {
  62. char *cp;
  63. double xy_bnd[4];
  64. double z_bnd[2];
  65. double m_bnd[2];
  66. int i;
  67. int swap;
  68. int npoints = geom->num_points;
  69. int nparts = geom->num_parts;
  70. Point *pt = geom->pt;
  71. double *m = geom->m;
  72. double *z = geom->z;
  73. ShpType type;
  74. ENDIAN_TEST (i); /* Sets i = 0 if big-endian, 1 if little-endian */
  75. swap = 1 - i;
  76. /* Calculate data_len. */
  77. *data_len = _calc_shapelen (geom->type, npoints, nparts);
  78. /* Allocate memory to the binary character array, set max_alloced
  79. equal to data_len if this is the first call to put_shape.
  80. Otherwise, if the data_len is larger then max_alloced,
  81. reallocate the larger data_len to the binary character array. */
  82. if (*max_alloced == 0)
  83. {
  84. *binary = (char *)malloc (*data_len);
  85. *max_alloced = *data_len;
  86. }
  87. else if (*max_alloced < *data_len)
  88. {
  89. *binary = (char *) realloc (*binary, *data_len);
  90. *max_alloced = *data_len;
  91. }
  92. /* Copy the address of the binary character array to the
  93. character pointer cp. */
  94. cp = *binary;
  95. /* The put_integer function byte swaps an integer value if necessary,
  96. and advances the cp character pointer after the interger value
  97. just added.
  98. The put_xy and put_double functions operate in the same manner as
  99. put_integer does, except they add an array of double precision
  100. numbers. */
  101. switch (geom->type)
  102. {
  103. case geomEmpty:
  104. /* Geometry is empty so the buffer only contains its datatype */
  105. type = shpNil;
  106. put_integer (&cp, swap, 1, (int *)&type);
  107. break;
  108. case geomPoint: /* Point */
  109. type = shpPoint;
  110. put_integer (&cp, swap, 1, (int *)&type);
  111. put_xy (&cp, swap, 1, pt); /* Add the X, Y coordinate */
  112. break;
  113. case geomPointM: /* Point with measure */
  114. type = shpPointM;
  115. put_integer (&cp, swap, 1, (int *)&type);
  116. put_xy (&cp, swap, 1, pt); /* Add the X, Y coordinate */
  117. put_double (&cp, swap, 1, m); /* Add the measure */
  118. break;
  119. case geomPointZ: /* Point with Z coordinate */
  120. type = shpPointZ;
  121. put_integer (&cp, swap, 1, (int *)&type);
  122. put_xy (&cp, swap, 1, pt); /* Add the X, Y coordinate */
  123. put_double (&cp, swap, 1, z); /* Add the Z coordinate */
  124. break;
  125. case geomPointZM: /* Point with Z coordinate and measure. */
  126. type = shpPointZM;
  127. put_integer (&cp, swap, 1, (int *)&type);
  128. put_xy (&cp, swap, 1, pt); /* Add the X, Y coordinate */
  129. put_double (&cp, swap, 1, z); /* Add the Z coordinate */
  130. put_double (&cp, swap, 1, m); /* Add the measure */
  131. break;
  132. case geomMultiPoint: /* Multipoint. */
  133. type = shpMultiPoint;
  134. put_integer (&cp, swap, 1, (int *)&type);
  135. /* Calculate the extreme X, Y. */
  136. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  137. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  138. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  139. put_xy (&cp, swap, npoints, pt); /* Add the X, Y coords */
  140. break;
  141. case geomMultiPointM: /* Multipoint with measure. */
  142. type = shpMultiPointM;
  143. put_integer (&cp, swap, 1, (int *)&type);
  144. /* Calculate the extreme X, Y and measures */
  145. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  146. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  147. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  148. put_xy (&cp, swap, npoints, pt); /* Add the X, Y coords */
  149. put_double (&cp, swap, 2, m_bnd); /* Add the extreme measures */
  150. put_double (&cp, swap, npoints, m); /* Add the measures */
  151. break;
  152. case geomMultiPointZ: /* Multipoint with Z ordinates */
  153. type = shpMultiPointZ;
  154. put_integer (&cp, swap, 1, (int *)&type);
  155. /* Calculate the extreme X, Y, Z and measures. */
  156. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  157. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  158. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  159. put_xy (&cp, swap, npoints, pt); /* Add the X, Y coordinates */
  160. put_double (&cp, swap, 2, z_bnd); /* Add the Z extrema */
  161. put_double (&cp, swap, npoints, z); /* Add the Z ordinates */
  162. break;
  163. case geomMultiPointZM: /* Multipoint with Z ordinates and measures */
  164. type = shpMultiPointZM;
  165. put_integer (&cp, swap, 1, (int *)&type);
  166. /* Calculate the extreme X, Y, Z and measures. */
  167. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  168. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  169. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  170. put_xy (&cp, swap, npoints, pt); /* Add the X, Y coords */
  171. put_double (&cp, swap, 2, z_bnd); /* Add the Z extreme */
  172. put_double (&cp, swap, npoints, z); /* Add the Z ordinates */
  173. put_double (&cp, swap, 2, m_bnd); /* Add the extreme measures */
  174. put_double (&cp, swap, npoints, m); /* Add the measures */
  175. break;
  176. case geomLineString:
  177. case geomMultiLineString:
  178. type = shpPolyline;
  179. put_integer (&cp, swap, 1, (int *)&type);
  180. /* Calculate the extreme X, Y. */
  181. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  182. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  183. put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
  184. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  185. if (nparts > 1)
  186. {
  187. /* There is more that one part; add the part offsets array */
  188. put_integer (&cp, swap, nparts, geom->offsets);
  189. }
  190. else
  191. {
  192. /* There is only one part; set the part offsets array to 0. */
  193. memset (cp, 0, sizeof (int));
  194. cp += sizeof (int); /* Advance the character pointer cp */
  195. }
  196. put_xy (&cp, swap, npoints, pt); /* Add the point array */
  197. break;
  198. case geomLineStringM:
  199. case geomMultiLineStringM:
  200. type = shpPolylineM;
  201. put_integer (&cp, swap, 1, (int *)&type);
  202. /* Calculate the extreme X, Y and measures. */
  203. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  204. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  205. put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
  206. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  207. if (nparts > 1)
  208. {
  209. /* There is more that one part; add the part offsets array */
  210. put_integer (&cp, swap, nparts, geom->offsets);
  211. }
  212. else
  213. {
  214. /* There is only one part; set the part offsets array to 0. */
  215. memset (cp, 0, sizeof (int));
  216. cp += sizeof (int); /* Advance the character pointer cp */
  217. }
  218. put_xy (&cp, swap, npoints, pt); /* Add the points array */
  219. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  220. put_double (&cp, swap, 2, m_bnd); /* Add the measure extremes */
  221. put_double (&cp, swap, npoints, m); /* Add the measures array */
  222. break;
  223. case geomLineStringZ:
  224. case geomMultiLineStringZ:
  225. type = shpPolylineZ;
  226. put_integer (&cp, swap, 1, (int *)&type);
  227. /* Calculate the extreme X, Y, Z and measures. */
  228. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  229. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  230. put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
  231. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  232. if (nparts > 1)
  233. {
  234. /* There is more that one part; add the part offsets array */
  235. put_integer (&cp, swap, nparts, geom->offsets);
  236. }
  237. else
  238. {
  239. /* There is only one part; set the part offsets array to 0. */
  240. memset (cp, 0, sizeof (int));
  241. cp += sizeof (int); /* Advance the character pointer cp */
  242. }
  243. put_xy (&cp, swap, npoints, pt); /* Add the no. of points */
  244. put_double (&cp, swap, 2, z_bnd); /* Add the Z extremes */
  245. put_double (&cp, swap, npoints, z); /* Add the Z array */
  246. break;
  247. case geomLineStringZM:
  248. case geomMultiLineStringZM:
  249. type = shpPolylineZM;
  250. put_integer (&cp, swap, 1, (int *)&type);
  251. /* Calculate the extreme X, Y, Z and measures. */
  252. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  253. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  254. put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
  255. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  256. if (nparts > 1)
  257. {
  258. /* There is more that one part; add the part offsets array */
  259. put_integer (&cp, swap, nparts, geom->offsets);
  260. }
  261. else
  262. {
  263. /* There is only one part; set the part offsets array to 0. */
  264. memset (cp, 0, sizeof (int));
  265. cp += sizeof (int); /* Advance the character pointer cp */
  266. }
  267. put_xy (&cp, swap, npoints, pt); /* Add the no. of points */
  268. put_double (&cp, swap, 2, z_bnd); /* Add the Z extemes */
  269. put_double (&cp, swap, npoints, z); /* Add the Z array */
  270. put_double (&cp, swap, 2, m_bnd); /* Add the measure extremes */
  271. put_double (&cp, swap, npoints, m); /* Add the measure array */
  272. break;
  273. case geomPolygon:
  274. case geomMultiPolygon:
  275. type = shpPolygon;
  276. put_integer (&cp, swap, 1, (int *)&type);
  277. /* Calculate the extreme X, Y. */
  278. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  279. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  280. put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
  281. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  282. if (nparts > 1)
  283. {
  284. /* There is more that one part; add the part offsets array */
  285. put_integer (&cp, swap, nparts, geom->offsets);
  286. }
  287. else
  288. {
  289. /* There is only one part; set the part offsets array to 0. */
  290. memset (cp, 0, sizeof (int));
  291. cp += sizeof (int); /* Advance the character pointer cp */
  292. }
  293. put_xy (&cp, swap, npoints, pt); /* Add the point array */
  294. break;
  295. case geomPolygonM:
  296. case geomMultiPolygonM:
  297. type = shpPolygonM;
  298. put_integer (&cp, swap, 1, (int *)&type);
  299. /* Calculate the extreme X, Y and measures. */
  300. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  301. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  302. put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
  303. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  304. if (nparts > 1)
  305. {
  306. /* There is more that one part; add the part offsets array */
  307. put_integer (&cp, swap, nparts, geom->offsets);
  308. }
  309. else
  310. {
  311. /* There is only one part; set the part offsets array to 0. */
  312. memset (cp, 0, sizeof (int));
  313. cp += sizeof (int); /* Advance the character pointer cp */
  314. }
  315. put_xy (&cp, swap, npoints, pt); /* Add the points array */
  316. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  317. put_double (&cp, swap, 2, m_bnd); /* Add the measure extremes */
  318. put_double (&cp, swap, npoints, m); /* Add the measures array */
  319. break;
  320. case geomPolygonZ:
  321. case geomMultiPolygonZ:
  322. type = shpPolygonZ;
  323. put_integer (&cp, swap, 1, (int *)&type);
  324. /* Calculate the extreme X, Y, Z and measures. */
  325. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  326. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  327. put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
  328. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  329. if (nparts > 1)
  330. {
  331. /* There is more that one part; add the part offsets array */
  332. put_integer (&cp, swap, nparts, geom->offsets);
  333. }
  334. else
  335. {
  336. /* There is only one part; set the part offsets array to 0. */
  337. memset (cp, 0, sizeof (int));
  338. cp += sizeof (int); /* Advance the character pointer cp */
  339. }
  340. put_xy (&cp, swap, npoints, pt); /* Add the no. of points */
  341. put_double (&cp, swap, 2, z_bnd); /* Add the Z extremes */
  342. put_double (&cp, swap, npoints, z); /* Add the Z array */
  343. break;
  344. case geomPolygonZM:
  345. case geomMultiPolygonZM:
  346. type = shpPolygonZM;
  347. put_integer (&cp, swap, 1, (int *)&type);
  348. /* Calculate the extreme X, Y, Z and measures. */
  349. _get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
  350. put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
  351. put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
  352. put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
  353. if (nparts > 1)
  354. {
  355. /* There is more that one part; add the part offsets array */
  356. put_integer (&cp, swap, nparts, geom->offsets);
  357. }
  358. else
  359. {
  360. /* There is only one part; set the part offsets array to 0. */
  361. memset (cp, 0, sizeof (int));
  362. cp += sizeof (int); /* Advance the character pointer cp */
  363. }
  364. put_xy (&cp, swap, npoints, pt); /* Add the no. of points */
  365. put_double (&cp, swap, 2, z_bnd); /* Add the Z extemes */
  366. put_double (&cp, swap, npoints, z); /* Add the Z array */
  367. put_double (&cp, swap, 2, m_bnd); /* Add the measure extremes */
  368. put_double (&cp, swap, npoints, m); /* Add the measure array */
  369. break;
  370. }
  371. }
  372. /***************************************************************************
  373. *
  374. * _calc_shapelen - Calculates the number of bytes in the shape.
  375. *
  376. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  377. *
  378. * Purpose:
  379. * Calculate the number of bytes in the shape.
  380. *
  381. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  382. *
  383. * Parameters:
  384. * type <Input> == (GeomType) The geometry data type.
  385. * num_points <Input> == (int) The number of points in the geometry.
  386. * num_parts <Input> == (int) The number of parts into the geometry.
  387. *
  388. * RETURN <Output> == (void)
  389. *
  390. ****************************************************************************/
  391. static int _calc_shapelen (
  392. GeomType type,
  393. int numpoints,
  394. int numparts
  395. )
  396. {
  397. int data_len;
  398. data_len = sizeof (int); /* Add the size of the data type */
  399. switch (type)
  400. {
  401. case geomEmpty: /* Shape is empty. */
  402. break;
  403. case geomPoint: /* Shape is a point. */
  404. data_len += (2 * sizeof (double));
  405. break;
  406. case geomPointZ: /* Shape is a point with a Z coordinate */
  407. case geomPointM: /* Shape is a point with a measure. */
  408. data_len += (3 * sizeof (double));
  409. break;
  410. case geomPointZM: /* Shape is a point with a Z coordinate and a measure */
  411. data_len += (4 * sizeof (double));
  412. break;
  413. case geomMultiPoint: /* Shape is a multipoint. */
  414. data_len += ((2 * numpoints) + 4) * sizeof(double) + sizeof (int);
  415. break;
  416. case geomMultiPointZ: /* Shape is a multipoint with Z coordinates. */
  417. case geomMultiPointM: /* Shape is a multipoint with measures. */
  418. data_len += ((3 * numpoints) + 6) * sizeof(double) + sizeof (int);
  419. break;
  420. case geomMultiPointZM: /* Shape is a multipoint with Z coords and measures */
  421. data_len += ((4 * numpoints) + 8) * sizeof(double) + sizeof (int);
  422. break;
  423. case geomLineString: /* Shape is a polyline or polygon. */
  424. case geomMultiLineString:
  425. case geomPolygon:
  426. case geomMultiPolygon:
  427. data_len += (2 + numparts) * sizeof (int);
  428. data_len += ((2 * numpoints) + 4) * sizeof(double);
  429. break;
  430. case geomLineStringM: /* Shape is a polyline or polygon with measures. */
  431. case geomMultiLineStringM:
  432. case geomPolygonM:
  433. case geomMultiPolygonM:
  434. case geomLineStringZ: /* Shape is a polyline or polygon with Z coords. */
  435. case geomMultiLineStringZ:
  436. case geomPolygonZ:
  437. case geomMultiPolygonZ:
  438. data_len += (2 + numparts) * sizeof (int);
  439. data_len += ((3 * numpoints) + 6) * sizeof(double);
  440. break;
  441. case geomLineStringZM: /* Shape is a polyline or polygon with */
  442. case geomPolygonZM: /* Z coordinates and measures. */
  443. case geomMultiLineStringZM:
  444. case geomMultiPolygonZM:
  445. data_len += (2 + numparts) * sizeof (int);
  446. data_len += ((4 * numpoints) + 8) * sizeof(double);
  447. break;
  448. }
  449. return data_len;
  450. }
  451. /***************************************************************************
  452. *
  453. * _get_extrema - Calculates the extremes of the X, Y, Z and measures.
  454. *
  455. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  456. *
  457. * Purpose:
  458. * Calculates the extremes of the X, Y, Z and measures.
  459. *
  460. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  461. *
  462. * Parameters:
  463. * num_points <Input> == (int) The number of points in the geometry.
  464. * pt <Input> == (Point *) Array of X, Y coordinates.
  465. * z <Input> == (double *) Array of Z ordinates.
  466. * m <Input> == (double *) Array of measures.
  467. * xy_bnd <Output> == (double *) X, Y coordinate extremes.
  468. * z_bnd <Output> == (double *) Z ordinate extremes.
  469. * m_bnd <Output> == (double *) Measure extremes.
  470. *
  471. * RETURN <Output> == (void)
  472. *
  473. ****************************************************************************/
  474. static void _get_extrema (
  475. int num_points,
  476. Point *pt,
  477. double *z,
  478. double *m,
  479. double *xy_bnd,
  480. double *z_bnd,
  481. double *m_bnd
  482. )
  483. {
  484. int i;
  485. /* Initialize the extremes */
  486. xy_bnd[0] = xy_bnd[1] = DBL_MAX; /* min x, min y */
  487. xy_bnd[2] = xy_bnd[3] = -DBL_MAX; /* max x, max y */
  488. z_bnd[0] = m_bnd[0] = DBL_MAX; /* min z, min m */
  489. z_bnd[1] = m_bnd[1] = -DBL_MAX; /* max z, max m */
  490. for (i = 0; i < num_points; i++)
  491. {
  492. /* Find the min & max values */
  493. if (pt[i].x < xy_bnd[0])
  494. xy_bnd[0] = pt[i].x;
  495. if (pt[i].y < xy_bnd[1])
  496. xy_bnd[1] = pt[i].y;
  497. if (pt[i].x > xy_bnd[2])
  498. xy_bnd[2] = pt[i].x;
  499. if (pt[i].y > xy_bnd[3])
  500. xy_bnd[3] = pt[i].y;
  501. if (z)
  502. {
  503. if (z[i] < z_bnd[0])
  504. z_bnd[0] = z[i];
  505. if (z[i] > z_bnd[1])
  506. z_bnd[1] = z[i];
  507. }
  508. if (m)
  509. {
  510. if (m[i] < m_bnd[0])
  511. m_bnd[0] = m[i];
  512. if (m[i] > m_bnd[1])
  513. m_bnd[1] = m[i];
  514. }
  515. }
  516. }
  517. /***************************************************************************
  518. *
  519. * geom_to_shape - takes a geometry and converts it into a shape
  520. * representation.
  521. *
  522. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  523. *
  524. * Purpose:
  525. * Converts a geometry into a shape.
  526. *
  527. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  528. *
  529. * Parameters:
  530. * binary <Input> == (char **) The shape binary.
  531. *
  532. * RETURN <Output> == (int) Error code
  533. *
  534. ****************************************************************************/
  535. int shape_to_geom (
  536. char *binary,
  537. Geometry *geom
  538. )
  539. {
  540. ShpType shape_type;
  541. int rc;
  542. char *cp;
  543. int swap_bytes;
  544. int i;
  545. ENDIAN_TEST (i); /* Sets i = 0 if big-endian, 1 if little-endian */
  546. swap_bytes = 1 - i;
  547. cp = binary;
  548. get_integer (&cp, swap_bytes, 1, (int *) &shape_type);
  549. switch (shape_type)
  550. {
  551. /* copy the points based on shape type */
  552. case shpNil:
  553. /* Nothing to do, we already made the shape nil */
  554. break;
  555. case shpPoint:
  556. geom->type = geomPoint;
  557. rc = _get_shp_point (cp, swap_bytes, geom);
  558. break;
  559. case shpPointM:
  560. geom->type = geomPointM;
  561. rc = _get_shp_point (cp, swap_bytes, geom);
  562. break;
  563. case shpPointZ:
  564. geom->type = geomPointZ;
  565. rc = _get_shp_point (cp, swap_bytes, geom);
  566. break;
  567. case shpPointZM:
  568. geom->type = geomPointZM;
  569. rc = _get_shp_point (cp, swap_bytes, geom);
  570. break;
  571. case shpMultiPoint:
  572. geom->type = geomMultiPoint;
  573. rc = _get_shp_multipoint (cp, swap_bytes, geom);
  574. break;
  575. case shpMultiPointM:
  576. geom->type = geomMultiPoint;
  577. rc = _get_shp_multipoint (cp, swap_bytes, geom);
  578. break;
  579. case shpMultiPointZ:
  580. geom->type = geomMultiPointZ;
  581. rc = _get_shp_multipoint (cp, swap_bytes, geom);
  582. break;
  583. case shpMultiPointZM:
  584. geom->type = geomMultiPointZM;
  585. rc = _get_shp_multipoint (cp, swap_bytes, geom);
  586. break;
  587. case shpPolyline:
  588. geom->type = geomLineString;
  589. rc = _get_shp_parts (cp, swap_bytes, geom);
  590. break;
  591. case shpPolygon:
  592. geom->type = geomPolygon;
  593. rc = _get_shp_parts (cp, swap_bytes, geom);
  594. break;
  595. case shpPolylineM:
  596. geom->type = geomLineStringM;
  597. rc = _get_shp_parts (cp, swap_bytes, geom);
  598. break;
  599. case shpPolygonM:
  600. geom->type = geomPolygonM;
  601. rc = _get_shp_parts (cp, swap_bytes, geom);
  602. break;
  603. case shpPolylineZ:
  604. geom->type = geomLineStringZ;
  605. rc = _get_shp_parts (cp, swap_bytes, geom);
  606. break;
  607. case shpPolygonZ:
  608. geom->type = geomPolygonZ;
  609. rc = _get_shp_parts (cp, swap_bytes, geom);
  610. break;
  611. case shpPolylineZM:
  612. geom->type = geomLineStringZM;
  613. rc = _get_shp_parts (cp, swap_bytes, geom);
  614. break;
  615. case shpPolygonZM:
  616. geom->type = geomPolygonZM;
  617. rc = _get_shp_parts (cp, swap_bytes, geom);
  618. break;
  619. default:
  620. rc = GEOM_INVALID_SHP_TYPE;
  621. }
  622. return rc;
  623. }
  624. /***************************************************************************
  625. *
  626. * _get_shp_parts - Extracts polygon or polyline parts from the
  627. * ESRI binary shape representation of a geometry.
  628. *
  629. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  630. *
  631. * Purpose:
  632. * This function builds a polygon or polyline shape from the ESRI binary
  633. * shape representation of a geometry. Since it is a common routine for
  634. * lines and polygons, and the "multi" equivalents, it does not set
  635. * set the geometry, or verify the geometry. This is the caller's
  636. * responsibility. This function just fills in the numofpts, pt, zpt,
  637. * and mval fields.
  638. *
  639. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  640. *
  641. *A Parameters:
  642. * cp <In/Out> == (char *) a pointer into the binary buffer
  643. * swap_bytes <Input> == (int) 1 if bytes need to be swapped
  644. * geom <In/Out> == (Geometry *) The geometry object
  645. *
  646. * RETURN <Output> == (int) Error code
  647. *
  648. ****************************************************************************/
  649. static int _get_shp_parts (
  650. char *cp,
  651. int swap_bytes,
  652. Geometry *geom
  653. )
  654. {
  655. int rc;
  656. int num_points;
  657. int num_parts;
  658. int has_m = geom->type & 0x01;
  659. int has_z = geom->type & 0x02;
  660. int prev_offset;
  661. int i;
  662. /* Skip over the double precision bounding box, we will
  663. calculate the envelope when needed */
  664. cp += 4 * sizeof(double);
  665. /* Get the number of parts */
  666. get_integer (&cp, swap_bytes, 1, &num_parts);
  667. if (num_parts <= 0)
  668. return GEOM_INVALID_NUM_PARTS;
  669. /* Get the total number of points */
  670. get_integer (&cp, swap_bytes, 1, &num_points);
  671. if (num_points <= 0)
  672. return GEOM_TOO_FEW_POINTS;
  673. /* Allocate the parts offsets, then extract them */
  674. if (geom->offsets != NULL)
  675. free (geom->offsets);
  676. geom->offsets = malloc (num_parts * sizeof(int));
  677. if (NULL == geom->offsets)
  678. return GEOM_OUT_OF_MEMORY;
  679. get_integer (&cp, swap_bytes, num_parts, geom->offsets);
  680. /* make sure each part offset is legal */
  681. prev_offset = 0;
  682. if (geom->offsets[0] != 0)
  683. return GEOM_INVALID_PART_OFFSET;
  684. for (i = 1; i < num_parts; i++)
  685. {
  686. if (geom->offsets[i] < prev_offset + 2)
  687. {
  688. /* Offsets should be monotonically increasing,
  689. and each part needs at least 2 points */
  690. return GEOM_INVALID_PART_OFFSET;
  691. }
  692. prev_offset = geom->offsets[i];
  693. }
  694. /* Check the last offset */
  695. if (num_points < prev_offset + 2)
  696. return GEOM_INVALID_PART_OFFSET;
  697. /* Allocate space for the geometry points. */
  698. rc = geom_allocate (geom, num_points);
  699. if (rc != GEOM_SUCCESS)
  700. return rc;
  701. geom->num_points = num_points;
  702. get_xy (&cp, swap_bytes, num_points, geom->pt);
  703. if (has_z)
  704. {
  705. cp += 2 * sizeof(double); /* Skip over Z extrema */
  706. get_double (&cp, swap_bytes, num_points, geom->z);
  707. }
  708. if (has_m)
  709. {
  710. cp += 2 * sizeof(double); /* Skip over M extrema */
  711. get_double (&cp, swap_bytes, num_points, geom->m);
  712. }
  713. return GEOM_SUCCESS;
  714. }
  715. /***************************************************************************
  716. *
  717. * _get_shp_multipoint - Extracts a multipoint shape from the ESRI binary
  718. *
  719. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  720. *
  721. * Purpose:
  722. * This function builds a multipoint shape from the ESRI binary shape
  723. * representation of a geometry.
  724. *
  725. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  726. *
  727. * Parameters:
  728. * cp <In/Out> == (char *) a pointer into the binary buffer
  729. * swap_bytes <Input> == (int) 1 if bytes need to be swapped
  730. * geom <In/Out> == (Geometry *) The geometry object
  731. *
  732. * RETURN <Output> == (int) Error code
  733. *
  734. ****************************************************************************/
  735. static int _get_shp_multipoint (
  736. char *cp,
  737. int swap_bytes,
  738. Geometry *geom
  739. )
  740. {
  741. int rc;
  742. int num_points;
  743. int has_m = geom->type & 0x01;
  744. int has_z = geom->type & 0x02;
  745. /* Skip over the double precision bounding box, we will
  746. calculate the envelope when needed */
  747. cp += 4 * sizeof(double);
  748. get_integer (&cp, swap_bytes, 1, &num_points);
  749. if (num_points <= 0)
  750. return GEOM_TOO_FEW_POINTS;
  751. /* Allocate space for the shape points. */
  752. rc = geom_allocate(geom, num_points);
  753. if (rc != GEOM_SUCCESS)
  754. return rc;
  755. geom->num_points = num_points;
  756. /* Get an array of xy points */
  757. get_xy (&cp, swap_bytes, num_points, geom->pt);
  758. if (has_z)
  759. {
  760. /* Skip over the double precision Z extrema */
  761. cp += 2 * sizeof(double);
  762. /* Get the Z values */
  763. get_double (&cp, swap_bytes, num_points, geom->z);
  764. }
  765. if (has_m)
  766. {
  767. /* Skip over the double precision M extrema */
  768. cp += 2 * sizeof(double);
  769. /* Get the measure values */
  770. get_double (&cp, swap_bytes, num_points, geom->m);
  771. }
  772. return GEOM_SUCCESS;
  773. }
  774. /***************************************************************************
  775. *
  776. * _get_shp_point - Extracts a point shape from the ESRI binary
  777. *
  778. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  779. *
  780. * Purpose:
  781. * This function builds a point shape from the ESRI binary shape
  782. * representation of a shape.
  783. *
  784. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  785. *
  786. * Parameters:
  787. * swap_bytes <Input> == (int) 1 if bytes need to be swapped
  788. * cp <In/Out> == (char *) a pointer into the binary buffer
  789. * geom <Output> == (Geometry *) The geometry object
  790. *
  791. * RETURN <Output> == (int) Error code
  792. *
  793. ****************************************************************************/
  794. static int _get_shp_point (
  795. char *cp,
  796. int swap_bytes,
  797. Geometry *geom
  798. )
  799. {
  800. int rc;
  801. int has_m = geom->type & 0x01;
  802. int has_z = geom->type & 0x02;
  803. /* Allocate space for the shape point */
  804. rc = geom_allocate(geom, 1);
  805. if (rc != GEOM_SUCCESS)
  806. return rc;
  807. geom->num_points = 1;
  808. /* Get a single xy point, followed by the Z and/or M values */
  809. get_xy (&cp, swap_bytes, 1, geom->pt);
  810. if (has_z)
  811. get_double (&cp, swap_bytes, 1, geom->z);
  812. if (has_m)
  813. get_double (&cp, swap_bytes, 1, geom->m);
  814. return GEOM_SUCCESS;
  815. }