wkbfuncs.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <float.h>
  5. /*
  6. * Local function prototypes
  7. */
  8. static int _calc_wkblen (
  9. GeomType type,
  10. int num_points,
  11. int num_parts,
  12. int num_subparts
  13. );
  14. static int _get_wkb_polys (
  15. char *cp,
  16. int swap_bytes,
  17. Geometry *geom
  18. );
  19. static int _get_wkb_header (
  20. char **buf_ptr,
  21. int *swap_bytes,
  22. WkbType *wkb_type
  23. );
  24. static int _get_wkb_points (
  25. char *cp,
  26. int swap_bytes,
  27. Geometry *geom
  28. );
  29. static int _get_wkb_lines (
  30. char *cp,
  31. int swap_bytes,
  32. Geometry *geom
  33. );
  34. static int _get_wkb_polys (
  35. char *cp,
  36. int swap_bytes,
  37. Geometry *geom
  38. );
  39. /***************************************************************************
  40. *
  41. * geom_to_wkb - takes a geometry of any type and converts it
  42. * into a Well Known Binary representation.
  43. *
  44. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  45. *
  46. * Purpose:
  47. *
  48. * Converts a geometry of any type into a WKB buffer. Since the structure
  49. * of a geometry varies by data type, the parameters of this function do
  50. * as well. The parts are associated with the multilinestring, and
  51. * multipolygon datatypes where each part represents a linestring and
  52. * a polygon, respectively. Subparts are associated with various rings
  53. * of a polygon.
  54. *
  55. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  56. *
  57. * Parameters:
  58. * geom <Input> == (Geometry *) The geometry data
  59. * max_alloced <Output> == (int *)
  60. * data_len <Output> == (int *) The number of bytes in the WKB.
  61. * binary <Output> == (char **) The WKB buffer.
  62. *
  63. * RETURN <Output> == (void)
  64. *
  65. ***************************************************************************/
  66. void geom_to_wkb (
  67. Geometry *geom,
  68. int *max_alloced,
  69. int *data_len,
  70. char **binary
  71. )
  72. {
  73. int type;
  74. char *cp;
  75. int i, j;
  76. int tmp_num_subparts;
  77. int end_subparts;
  78. int tmp_num_points;
  79. unsigned char byte_order;
  80. /* Calculate data_len. */
  81. *data_len = _calc_wkblen (geom->type, geom->num_points,
  82. geom->num_parts, geom->num_subparts);
  83. /* Allocate memory to the binary character array, set max_alloced
  84. equal to data_len if this is the first call to put_wkb.
  85. Otherwise, if the data_len is larger then max_alloced,
  86. reallocate the larger data_len to the binary character array. */
  87. if (*max_alloced == 0)
  88. {
  89. *binary = (char *)malloc (*data_len);
  90. *max_alloced = *data_len;
  91. }
  92. else if (*max_alloced < *data_len)
  93. {
  94. *binary = (char *) realloc (*binary, *data_len);
  95. *max_alloced = *data_len;
  96. }
  97. cp = *binary;
  98. ENDIAN_TEST (i); /* Sets i = 0 if big-endian, 1 if little-endian */
  99. byte_order = (unsigned char) i;
  100. *cp = byte_order;
  101. cp++;
  102. switch (geom->type)
  103. {
  104. case geomPoint:
  105. type = wkbPoint;
  106. put_integer (&cp, 0, 1, (int *)&type);
  107. put_xy (&cp, 0, 1, geom->pt);
  108. break;
  109. case geomMultiPoint:
  110. type = wkbMultiPoint;
  111. put_integer (&cp, 0, 1, (int *)&type);
  112. put_integer (&cp, 0, 1, &geom->num_points);
  113. type = wkbPoint; /* Each part is a wkb point */
  114. for (i = 0; i < geom->num_points; i++)
  115. {
  116. *cp = byte_order;
  117. cp++;
  118. put_integer (&cp, 0, 1, (int *)&type);
  119. put_xy (&cp, 0, 1, &geom->pt[i]);
  120. }
  121. break;
  122. case geomLineString:
  123. type = wkbLineString;
  124. put_integer (&cp, 0, 1, (int *)&type);
  125. put_integer (&cp, 0, 1, &geom->num_points);
  126. put_xy (&cp, 0, geom->num_points, geom->pt);
  127. break;
  128. case geomMultiLineString:
  129. type = wkbMultiLineString;
  130. put_integer (&cp, 0, 1, (int *)&type);
  131. put_integer (&cp, 0, 1, &geom->num_parts);
  132. type = wkbLineString; /* Each part is a wkb line */
  133. for (i = 0; i < geom->num_parts; i++)
  134. {
  135. *cp = byte_order;
  136. cp++;
  137. put_integer (&cp, 0, 1, (int *)&type);
  138. if (i == geom->num_parts - 1)
  139. tmp_num_points = geom->num_points - geom->offsets[i];
  140. else
  141. tmp_num_points = geom->offsets[i+1] - geom->offsets[i];
  142. put_integer (&cp, 0, 1, &tmp_num_points);
  143. put_xy (&cp, 0, tmp_num_points, &geom->pt[geom->offsets[i]]);
  144. }
  145. break;
  146. case geomPolygon:
  147. type = wkbPolygon;
  148. put_integer (&cp, 0, 1, (int *)&type);
  149. put_integer (&cp, 0, 1, &geom->num_subparts);
  150. for (i = 0; i < geom->num_subparts; i++)
  151. {
  152. if (i == geom->num_subparts - 1)
  153. {
  154. if (NULL != geom->suboffsets)
  155. {
  156. tmp_num_points = geom->num_points - geom->suboffsets[i];
  157. }
  158. else
  159. tmp_num_points = geom->num_points;
  160. }
  161. else
  162. tmp_num_points = geom->suboffsets[i+1] - geom->suboffsets[i];
  163. put_integer (&cp, 0, 1, &tmp_num_points);
  164. put_xy (&cp, 0, tmp_num_points, &geom->pt[geom->suboffsets[i]]);
  165. }
  166. break;
  167. case geomMultiPolygon:
  168. type = wkbMultiPolygon;
  169. put_integer (&cp, 0, 1, (int *)&type);
  170. put_integer (&cp, 0, 1, &geom->num_parts);
  171. type = wkbPolygon; /* Each part is a wkb polygon */
  172. for (j = 0; j < geom->num_parts; j++)
  173. {
  174. *cp = byte_order;
  175. cp++;
  176. put_integer (&cp, 0, 1, (int *)&type);
  177. if (j == geom->num_parts - 1)
  178. end_subparts = geom->num_subparts;
  179. else
  180. end_subparts = geom->offsets[j+1];
  181. tmp_num_subparts = end_subparts - geom->offsets[j];
  182. put_integer (&cp, 0, 1, &tmp_num_subparts);
  183. for (i = geom->offsets[j]; i < end_subparts; i++)
  184. {
  185. if (i == geom->num_subparts - 1)
  186. tmp_num_points = geom->num_points - geom->suboffsets[i];
  187. else
  188. tmp_num_points = geom->suboffsets[i+1] - geom->suboffsets[i];
  189. put_integer (&cp, 0, 1, &tmp_num_points);
  190. put_xy (&cp, 0, tmp_num_points, &geom->pt[geom->suboffsets[i]]);
  191. }
  192. }
  193. break;
  194. }
  195. }
  196. /***************************************************************************
  197. *
  198. * _calc_wkblen - Calculates the number of bytes in the well-known
  199. * binary representation of a geometry.
  200. *
  201. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  202. *
  203. * Purpose:
  204. * Calculate the number of bytes in the shape.
  205. *
  206. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  207. *
  208. * Parameters:
  209. * type <Input> == (geomType) The geometry data type.
  210. * num_points <Input> == (int) The number of points in the geometry.
  211. * num_parts <Input> == (int) The number of parts in the geometry.
  212. * num_subparts <Input> == (int) The number of subparts in the geometry.
  213. *
  214. * RETURN <Output> == (int) The required binary size
  215. *
  216. ***************************************************************************/
  217. static int _calc_wkblen (
  218. GeomType type,
  219. int num_points,
  220. int num_parts,
  221. int num_subparts
  222. )
  223. {
  224. int data_len;
  225. data_len = 1 + sizeof (int); /* Add the size of the data type */
  226. switch (type)
  227. {
  228. case geomPoint:
  229. data_len += (2 * sizeof (double));
  230. break;
  231. case geomMultiPoint:
  232. /*
  233. * num_points + num_points * (byte order + type + (x,y))
  234. */
  235. data_len += sizeof(int);
  236. data_len += num_points * (1 + sizeof(int) + 2 * sizeof(double));
  237. break;
  238. case geomLineString:
  239. /*
  240. * num_points + num_points * (x,y)
  241. */
  242. data_len += sizeof(int);
  243. data_len += num_points * (2 * sizeof(double));
  244. break;
  245. case geomMultiLineString:
  246. /*
  247. * num_parts + num_parts * (byte order + type + num_points)
  248. * + num_points * (x,y)
  249. */
  250. data_len += sizeof(int);
  251. data_len += num_parts * (1 + 2 * sizeof(int));
  252. data_len += num_points * (2 * sizeof(double));
  253. break;
  254. case geomPolygon:
  255. /*
  256. * num_subparts + num_subparts * (num_points)
  257. * + num_points * (x,y)
  258. */
  259. data_len += sizeof(int);
  260. data_len += num_subparts * sizeof (int);
  261. data_len += num_points * (2 * sizeof(double));
  262. break;
  263. case geomMultiPolygon:
  264. /*
  265. * num_parts + num_parts * (byte order + type + num_subparts)
  266. * + num_subparts * (num_points) + num_points * (x,y)
  267. */
  268. data_len += sizeof(int);
  269. data_len += num_parts * (1 + 2 * sizeof (int));
  270. data_len += num_subparts * sizeof (int);
  271. data_len += num_points * (2 * sizeof(double));
  272. break;
  273. }
  274. return data_len;
  275. }
  276. /***************************************************************************
  277. *
  278. * _get_wkb_header - Gets the wkb byte order and shape type
  279. *
  280. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  281. *
  282. * Purpose:
  283. * This function extracts the byte order of the OGIS WKB
  284. * byte stream, as well as the shape type.
  285. * The pointer into the buffer will be advanced to the position
  286. * immediately following the shape type.
  287. *
  288. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  289. *
  290. * Parameters:
  291. * buf_ptr <In/Out> == (char **) Address of pointer into byte stream
  292. * swap_bytes <Output> == (int) Do bytes need to be swapped
  293. * wkb_type <Output> == (WkbType *) OGIS shape type
  294. *
  295. * RETURN <Output> == (int) Error code
  296. *
  297. ***************************************************************************/
  298. static int _get_wkb_header (
  299. char **buf_ptr,
  300. int *swap_bytes,
  301. WkbType *wkb_type
  302. )
  303. {
  304. int i;
  305. ByteOrder byte_order;
  306. switch ((*buf_ptr)[0])
  307. {
  308. case 0:
  309. byte_order = BigEndian;
  310. break;
  311. case 1:
  312. byte_order = LittleEndian;
  313. break;
  314. default:
  315. return GEOM_INVALID_WKB_BYTE_ORDER;
  316. }
  317. ENDIAN_TEST (i); /* Sets i = 0 if big-endian, 1 if little-endian */
  318. *swap_bytes = 1 - i;
  319. (*buf_ptr)++;
  320. get_integer (buf_ptr, *swap_bytes, 1, (int *) wkb_type);
  321. return GEOM_SUCCESS;
  322. }
  323. /***************************************************************************
  324. *
  325. * wkb_to_geom - Constructs a geometry from an OGIS byte stream
  326. *
  327. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  328. *
  329. * Purpose:
  330. * This function builds a shape from the OGIS compliant Well Known Binary
  331. * representation of a geometry.
  332. *
  333. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  334. *
  335. * Parameters:
  336. * binary <Input> == (char *) The geometry's wkb representation
  337. * geom <Output> == (Geometry *) A geometry object
  338. *
  339. * RETURN <Output> == (int) Error code
  340. *
  341. ***************************************************************************/
  342. int wkb_to_geom (
  343. char *binary,
  344. Geometry *geom
  345. )
  346. {
  347. WkbType wkb_type;
  348. int rc;
  349. char *cp;
  350. int swap_bytes;
  351. /* Get the byte order and geometry type */
  352. cp = binary;
  353. rc = _get_wkb_header (&cp, &swap_bytes, &wkb_type);
  354. if (rc != GEOM_SUCCESS)
  355. return rc;
  356. switch (wkb_type)
  357. {
  358. /* copy the points based on shape type */
  359. case wkbPoint:
  360. geom->type = geomPoint;
  361. geom->num_points = 1;
  362. /* Allocate space for the shape point. */
  363. rc = geom_allocate(geom, 1);
  364. if (rc != GEOM_SUCCESS)
  365. return rc;
  366. /* Get an xy point */
  367. get_xy (&cp, swap_bytes, 1, geom->pt);
  368. break;
  369. case wkbMultiPoint:
  370. geom->type = geomMultiPoint;
  371. _get_wkb_points (cp, swap_bytes, geom);
  372. break;
  373. case wkbLineString:
  374. geom->type = geomLineString;
  375. _get_wkb_lines (cp, swap_bytes, geom);
  376. break;
  377. case wkbMultiLineString:
  378. geom->type = geomMultiLineString;
  379. _get_wkb_lines (cp, swap_bytes, geom);
  380. break;
  381. case wkbPolygon:
  382. geom->type = geomPolygon;
  383. _get_wkb_polys (cp, swap_bytes, geom);
  384. break;
  385. case wkbMultiPolygon:
  386. geom->type = geomMultiPolygon;
  387. _get_wkb_polys (cp, swap_bytes, geom);
  388. break;
  389. case wkbCollection:
  390. return GEOM_UNSUPPORTED_WKB_TYPE;
  391. break;
  392. default:
  393. return GEOM_INVALID_WKB_TYPE;
  394. }
  395. return GEOM_SUCCESS;
  396. }
  397. /***************************************************************************
  398. *
  399. * _get_wkb_points - Extracts a point or multi shape from the WKB binary
  400. *
  401. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  402. *
  403. * Purpose:
  404. * This function builds a shape from the WKB binary point or multipoint
  405. * shape representation of a shape.
  406. *
  407. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  408. *
  409. * Parameters:
  410. * swap_bytes <Input> == (int) Do bytes need to be swapped
  411. * cp <In/Out> == (char *) a pointer into the binary buffer
  412. * geom <Output> == (Geometry *) A geometry object
  413. *
  414. * RETURN <Output> == (int) Error code
  415. *
  416. ***************************************************************************/
  417. static int _get_wkb_points (
  418. char *cp,
  419. int swap_bytes,
  420. Geometry *geom
  421. )
  422. {
  423. int rc;
  424. int npoints, i;
  425. WkbType wkb_type;
  426. get_integer (&cp, swap_bytes, 1, &npoints);
  427. if (npoints <= 0)
  428. return GEOM_TOO_FEW_POINTS;
  429. /* Allocate space for the geometry points. */
  430. rc = geom_allocate(geom, npoints);
  431. if (rc != GEOM_SUCCESS)
  432. return rc;
  433. geom->num_points = npoints;
  434. /* Loop through the list of wkbPoints */
  435. for (i = 0; i < npoints; i++)
  436. {
  437. rc = _get_wkb_header (&cp, &swap_bytes, &wkb_type);
  438. if (rc != GEOM_SUCCESS)
  439. return rc;
  440. if (wkb_type != wkbPoint)
  441. return GEOM_INVALID_WKB_TYPE;
  442. /* Get an xy point */
  443. get_xy (&cp, swap_bytes, 1, &geom->pt[i]);
  444. }
  445. return GEOM_SUCCESS;
  446. }
  447. /***************************************************************************
  448. *
  449. * _get_wkb_lines - Extracts polyline parts from the OGIS binary
  450. *
  451. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  452. *
  453. * Purpose:
  454. * This function builds a polyline shape from the OGIS Well
  455. * Known binary representation of a shape.
  456. *
  457. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  458. *
  459. * Parameters:
  460. * swap_bytes <Input> == (int) Do bytes need to be swapped
  461. * cp <In/Out> == (char *) a pointer into the binary buffer
  462. * geom <In/Out> == (Geometry *) Handle to a geometry object.
  463. *
  464. * RETURN <Output> == (int) Error code
  465. *
  466. ***************************************************************************/
  467. static int _get_wkb_lines (
  468. char *cp,
  469. int swap_bytes,
  470. Geometry *geom
  471. )
  472. {
  473. int rc;
  474. int current_pt = 0;
  475. int i, npoints, nlines;
  476. WkbType wkb_type;
  477. if (geom->type == geomMultiLineString)
  478. {
  479. /* Get the number of line elements */
  480. get_integer (&cp, swap_bytes, 1, &nlines);
  481. if (nlines < 1)
  482. return GEOM_INVALID_NUM_PARTS;
  483. /* Get the first line's header */
  484. rc = _get_wkb_header (&cp, &swap_bytes, &wkb_type);
  485. if (rc != GEOM_SUCCESS)
  486. return rc;
  487. if (wkb_type != wkbLineString)
  488. return GEOM_INVALID_WKB_TYPE;
  489. }
  490. else
  491. {
  492. nlines = 1;
  493. }
  494. geom->num_points = 0;
  495. geom->num_parts = nlines;
  496. geom->num_subparts = 0;
  497. geom->offsets = malloc (nlines * sizeof(int));
  498. /* Loop through each part and extract the points. */
  499. for (i = 0; i < nlines; i++)
  500. {
  501. geom->offsets[i] = current_pt;
  502. /* Get the number of points for this part */
  503. get_integer (&cp, swap_bytes, 1, &npoints);
  504. if (npoints < 2)
  505. return GEOM_TOO_FEW_POINTS;
  506. /* Allocate space for the geometry points for this line */
  507. rc = geom_allocate (geom, geom->num_points + npoints);
  508. if (rc != GEOM_SUCCESS)
  509. return rc;
  510. geom->num_points += npoints;
  511. /* Now, get the points for the line */
  512. get_xy (&cp, swap_bytes, npoints, &geom->pt[current_pt]);
  513. current_pt += npoints;
  514. if (i < nlines - 1)
  515. {
  516. /* Read the next line's header */
  517. rc = _get_wkb_header (&cp, &swap_bytes, &wkb_type);
  518. if (rc != GEOM_SUCCESS)
  519. return rc;
  520. if (wkb_type != wkbLineString)
  521. return GEOM_INVALID_WKB_TYPE;
  522. }
  523. } /* end for */
  524. return GEOM_SUCCESS;
  525. }
  526. /***************************************************************************
  527. *
  528. * _get_wkb_polys - Extracts polygon parts from the OGIS binary
  529. *
  530. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  531. *
  532. * Purpose:
  533. * This function builds a polygon shape from the OGIS Well
  534. * Known binary representation of a shape.
  535. *
  536. *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  537. *
  538. * Parameters:
  539. * cp <In/Out> == (char *) a pointer into the binary buffer
  540. * swap_bytes <Input> == (int) Do bytes need to be swapped
  541. * geom <Output> == (Geometry *) A geometry object
  542. *
  543. * RETURN <Output> == (int) Error code
  544. *
  545. ***************************************************************************/
  546. static int _get_wkb_polys (
  547. char *cp,
  548. int swap_bytes,
  549. Geometry *geom
  550. )
  551. {
  552. int current_pt = 0;
  553. int rc;
  554. int i, j, k;
  555. int npoints, npolys, nrings;
  556. WkbType wkb_type;
  557. if (geom->type == geomMultiPolygon)
  558. {
  559. /* Get the number of polygon elements */
  560. get_integer (&cp, swap_bytes, 1, &npolys);
  561. if (npolys < 1)
  562. return GEOM_INVALID_NUM_PARTS;
  563. /* Get the first polygon's header */
  564. rc = _get_wkb_header (&cp, &swap_bytes, &wkb_type);
  565. if (rc != GEOM_SUCCESS)
  566. return rc;
  567. if (wkb_type != wkbPolygon)
  568. return GEOM_INVALID_WKB_TYPE;
  569. }
  570. else
  571. {
  572. npolys = 1;
  573. }
  574. geom->num_points = 0;
  575. geom->num_parts = npolys;
  576. geom->num_subparts = 0;
  577. geom->offsets = malloc (npolys * sizeof(int));
  578. geom->suboffsets = malloc (3 * npolys * sizeof(int));
  579. geom->sub_allocsize = 3 * npolys;
  580. k = 0; /* suboffset array index */
  581. /* Loop through each part and extract the points. */
  582. for (i = 0; i < npolys; i++)
  583. {
  584. geom->offsets[i] = current_pt;
  585. /* Get the number of rings for this polygon */
  586. get_integer (&cp, swap_bytes, 1, &nrings);
  587. if (nrings < 1)
  588. return GEOM_INVALID_NUM_PARTS;
  589. /* Reallocate & grow the suboffsets array if necessary */
  590. if (geom->num_subparts + nrings >= geom->sub_allocsize)
  591. {
  592. int *newArray;
  593. geom->sub_allocsize = geom->num_subparts + 2 * nrings;
  594. newArray = malloc (geom->sub_allocsize * sizeof(int));
  595. memcpy (newArray, geom->suboffsets,
  596. geom->num_subparts * sizeof(int));
  597. free (geom->suboffsets);
  598. geom->suboffsets = newArray;
  599. }
  600. geom->num_subparts += nrings;
  601. /* Loop through each ring to get the points */
  602. for (j = 0; j < nrings; j++)
  603. {
  604. geom->suboffsets[k] = current_pt;
  605. k++;
  606. /* Get the number of points for this ring */
  607. get_integer (&cp, swap_bytes, 1, &npoints);
  608. if (npoints < 4)
  609. return GEOM_TOO_FEW_POINTS;
  610. else
  611. {
  612. /* Allocate space for the shape points. */
  613. rc = geom_allocate (geom, geom->num_points + npoints);
  614. if (rc != GEOM_SUCCESS)
  615. return rc;
  616. geom->num_points += npoints;
  617. /* Now, get the points for the ring */
  618. get_xy (&cp, swap_bytes, npoints, &geom->pt[current_pt]);
  619. current_pt += npoints;
  620. }
  621. } /* end ring loop */
  622. if (i < npolys - 1)
  623. {
  624. /* read the next polygon's header */
  625. rc = _get_wkb_header (&cp, &swap_bytes, &wkb_type);
  626. if (rc != GEOM_SUCCESS)
  627. return rc;
  628. if (wkb_type != wkbPolygon)
  629. return GEOM_INVALID_WKB_TYPE;
  630. }
  631. } /* end polygon loop */
  632. return GEOM_SUCCESS;
  633. }