All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
WKBReader.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/geometry/WKBReader.cpp
22 
23  \brief A class that deserializes a geometry from a valid WKB.
24 */
25 
26 // TerraLib
27 #include "../common/ByteSwapUtils.h"
28 #include "../common/Globals.h"
29 #include "../common/HexUtils.h"
30 #include "../common/Translator.h"
31 #include "Exception.h"
32 #include "GeometryCollection.h"
33 #include "LinearRing.h"
34 #include "MultiCurve.h"
35 #include "MultiLineString.h"
36 #include "MultiPoint.h"
37 #include "MultiPolygon.h"
38 #include "PointM.h"
39 #include "PointZ.h"
40 #include "PointZM.h"
41 #include "Polygon.h"
42 #include "PolyhedralSurface.h"
43 #include "TIN.h"
44 #include "Triangle.h"
45 #include "WKBReader.h"
46 
47 // STL
48 #include <cstring>
49 
51 {
52  const char* aux = wkb;
53 
54  return getGeometry(wkb, &aux);
55 }
56 
58 {
59  char* wkb = te::common::Hex2Binary(hwkb);
60 
62 
63  delete [] wkb;
64 
65  return g;
66 }
67 
68 te::gm::Geometry* te::gm::WKBReader::getGeometry(const char* wkb, const char** endptr)
69 {
70  assert(wkb && endptr);
71 
72  char byteOrder = 0;
73  unsigned int gType = 0;
74 
75  memcpy(&byteOrder, wkb, 1);
76  memcpy(&gType, wkb + 1, 4);
77 
78  //wkb += 5; -> not skipping now!
79 
80  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
81  te::common::SwapBytes(gType);
82 
83  switch(gType)
84  {
85  case te::gm::PointType:
86  return getPoint(wkb, endptr);
87 
88  case te::gm::PointZType:
89  return getPointZ(wkb, endptr);
90 
91  case te::gm::PointMType:
92  return getPointM(wkb, endptr);
93 
95  return getPointZM(wkb, endptr);
96 
97 
102  return getLineString(wkb, endptr);
103 
104  case te::gm::PolygonType:
111  return getPolygon(wkb, endptr);
112 
129  return getGeometryCollection(wkb, endptr);
130 
131  case te::gm::TINType:
132  case te::gm::TINZType:
133  case te::gm::TINMType:
134  case te::gm::TINZMType:
139  return getPolyhedralSurface(wkb, endptr);
140 
141  default:
142  throw Exception(TE_TR("Could not read WKB due to an invalid geometry type!"));
143  }
144 }
145 
146 te::gm::Point* te::gm::WKBReader::getPoint(const char* wkb, const char** endptr)
147 {
148  assert(wkb && endptr);
149 
150  char byteOrder = 0;
151 //unsigned int gType = 0;
152  double x = 0.0;
153  double y = 0.0;
154 
155  memcpy(&byteOrder, wkb, 1);
156 //memcpy(&gType, wkb + 1, 4);
157 
158  memcpy(&x, wkb + 5, 8);
159  memcpy(&y, wkb + 13, 8);
160 
161  wkb += 21;
162 
163  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
164  {
165 // te::common::SwapBytes(gType);
168  }
169 
170  *endptr = wkb;
171 
172  return new Point(x, y, 0, 0);
173 }
174 
175 te::gm::PointZ* te::gm::WKBReader::getPointZ(const char* wkb, const char** endptr)
176 {
177  assert(wkb && endptr);
178 
179  char byteOrder = 0;
180 //unsigned int gType = 0;
181  double x = 0.0;
182  double y = 0.0;
183  double z = 0.0;
184 
185  memcpy(&byteOrder, wkb, 1);
186 //memcpy(&gType, wkb + 1, 4);
187  memcpy(&x, wkb + 5, 8);
188  memcpy(&y, wkb + 13, 8);
189  memcpy(&z, wkb + 21, 8);
190 
191  *endptr = wkb + 29;
192 
194  {
195 // te::common::SwapBytes(gType);
199  }
200 
201  return new PointZ(x, y, z, 0, 0);
202 }
203 
204 te::gm::PointM* te::gm::WKBReader::getPointM(const char* wkb, const char** endptr)
205 {
206  assert(wkb && endptr);
207 
208  char byteOrder = 0;
209 //unsigned int gType = 0;
210  double x = 0.0;
211  double y = 0.0;
212  double m = 0.0;
213 
214  memcpy(&byteOrder, wkb, 1);
215 //memcpy(&gType, wkb + 1, 4);
216  memcpy(&x, wkb + 5, 8);
217  memcpy(&y, wkb + 13, 8);
218  memcpy(&m, wkb + 21, 8);
219 
220  *endptr = wkb + 29;
221 
222  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
223  {
224 // te::common::SwapBytes(gType);
228  }
229 
230  return new PointM(x, y, m, 0, 0);
231 }
232 
233 te::gm::PointZM* te::gm::WKBReader::getPointZM(const char* wkb, const char** endptr)
234 {
235  assert(wkb && endptr);
236 
237  char byteOrder = 0;
238 //unsigned int gType = 0;
239 //int srid = 0;
240  double x = 0.0;
241  double y = 0.0;
242  double z = 0.0;
243  double m = 0.0;
244 
245  memcpy(&byteOrder, wkb, 1);
246 //memcpy(&gType, wkb + 1, 4);
247  memcpy(&x, wkb + 5, 8);
248  memcpy(&y, wkb + 13, 8);
249  memcpy(&z, wkb + 21, 8);
250  memcpy(&m, wkb + 29, 8);
251 
252  *endptr = wkb + 37;
253 
254 
255  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
256  {
257 // te::common::SwapBytes(gType);
262  }
263 
264  return new PointZM(x, y, z, m, 0, 0);
265 }
266 
267 te::gm::LineString* te::gm::WKBReader::getLineString(const char* wkb, const char** endptr)
268 {
269  assert(wkb && endptr);
270 
271  char byteOrder = 0;
272  unsigned int gType = 0;
273  int srid = 0;
274  unsigned int nPts = 0;
275 
276  memcpy(&byteOrder, wkb, 1);
277  memcpy(&gType, wkb + 1, 4);
278  memcpy(&nPts, wkb + 5, 4);
279 
280  wkb += 9;
281 
282  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
283  {
284  te::common::SwapBytes(gType);
285  te::common::SwapBytes(nPts);
286  }
287 
288  LineString* l = new LineString(nPts, static_cast<GeomType>(gType), srid, 0);
289 
290  Coord2D* coords = l->getCoordinates();
291 
292  double* zA = l->getZ();
293 
294  double* mA = l->getM();
295 
296  switch(gType)
297  {
298  case LineStringType :
299  memcpy(coords, wkb, 16 * nPts);
300  wkb += nPts * 16;
301  break;
302 
303  case LineStringZType :
304  for(unsigned int i = 0; i < nPts; ++i)
305  {
306  memcpy(&(coords[i]), wkb, 16);
307  memcpy(&(zA[i]), wkb + 16, 8);
308  wkb += 24;
309  }
310  break;
311 
312  case LineStringMType :
313  for(unsigned int i = 0; i < nPts; ++i)
314  {
315  memcpy(&(coords[i]), wkb, 16);
316  memcpy(&(mA[i]), wkb + 16, 8);
317  wkb += 24;
318  }
319  break;
320 
321  case LineStringZMType :
322  for(unsigned int i = 0; i < nPts; ++i)
323  {
324  memcpy(&(coords[i]), wkb, 16);
325  memcpy(&(zA[i]), wkb + 16, 8);
326  memcpy(&(mA[i]), wkb + 24, 8);
327  wkb += 32;
328  }
329  break;
330 
331  default:
332  throw Exception(TE_TR("Could not read WKB due to an invalid line string type!"));
333  }
334 
335  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
336  {
337  for(unsigned int i = 0; i < nPts; ++i)
338  {
339  te::common::SwapBytes(coords[i].x);
340  te::common::SwapBytes(coords[i].y);
341  }
342 
343  if(zA)
344  for(unsigned int i = 0; i < nPts; ++i)
345  te::common::SwapBytes(zA[i]);
346 
347  if(mA)
348  for(unsigned int i = 0; i < nPts; ++i)
349  te::common::SwapBytes(mA[i]);
350  }
351 
352  *endptr = wkb;
353 
354  return l;
355 }
356 
357 te::gm::LinearRing* te::gm::WKBReader::getLinearRing(const char* wkb, const char** endptr, te::common::MachineByteOrder byteOrder, GeomType gType)
358 {
359  assert(wkb && endptr);
360 
361  unsigned int nPts = 0;
362 
363  memcpy(&nPts, wkb, 4);
364  wkb += 4;
365 
367  te::common::SwapBytes(nPts);
368 
369  LinearRing* r = new LinearRing(nPts, gType, 0, 0);
370 
371  Coord2D* coords = r->getCoordinates();
372 
373  double* zA = r->getZ();
374 
375  double* mA = r->getM();
376 
377  switch(gType)
378  {
379  case LineStringType :
380  memcpy(coords, wkb, 16 * nPts);
381  wkb += nPts * 16;
382  break;
383 
384  case LineStringZType :
385  for(unsigned int i = 0; i < nPts; ++i)
386  {
387  memcpy(&(coords[i]), wkb, 16);
388  memcpy(&(zA[i]), wkb + 16, 8);
389  wkb += 24;
390  }
391  break;
392 
393  case LineStringMType :
394  for(unsigned int i = 0; i < nPts; ++i)
395  {
396  memcpy(&(coords[i]), wkb, 16);
397  memcpy(&(mA[i]), wkb + 16, 8);
398  wkb += 24;
399  }
400  break;
401 
402  case LineStringZMType :
403  for(unsigned int i = 0; i < nPts; ++i)
404  {
405  memcpy(&(coords[i]), wkb, 16);
406  memcpy(&(zA[i]), wkb + 16, 8);
407  memcpy(&(mA[i]), wkb + 24, 8);
408  wkb += 32;
409  }
410  break;
411 
412  default:
413  throw Exception(TE_TR("Could not read WKB due to an invalid linear ring type!"));
414  }
415 
417  {
418  for(unsigned int i = 0; i < nPts; ++i)
419  {
420  te::common::SwapBytes(coords[i].x);
421  te::common::SwapBytes(coords[i].y);
422  }
423 
424  if(zA)
425  for(unsigned int i = 0; i < nPts; ++i)
426  te::common::SwapBytes(zA[i]);
427 
428  if(mA)
429  for(unsigned int i = 0; i < nPts; ++i)
430  te::common::SwapBytes(mA[i]);
431  }
432 
433  *endptr = wkb;
434 
435  return r;
436 }
437 
438 te::gm::Polygon* te::gm::WKBReader::getPolygon(const char* wkb, const char** endptr)
439 {
440  assert(wkb && endptr);
441 
443  unsigned int gType = 0;
444  unsigned int nRings = 0;
445 
446  memcpy(&byteOrder, wkb, 1);
447  memcpy(&gType, wkb + 1, 4);
448  memcpy(&nRings, wkb + 5, 4);
449 
450  wkb += 9;
451 
453  {
454  te::common::SwapBytes(gType);
455  te::common::SwapBytes(nRings);
456  }
457 
458  Polygon* p = 0;
459 
461 
462  switch(gType)
463  {
464  case PolygonType:
465  rType = LineStringType;
466  p = new Polygon(nRings, PolygonType, 0, 0);
467  break;
468 
469  case PolygonZType:
470  rType = LineStringZType;
471  p = new Polygon(nRings, PolygonZType, 0, 0);
472  break;
473 
474  case PolygonMType:
475  rType = LineStringMType;
476  p = new Polygon(nRings, PolygonMType, 0, 0);
477  break;
478 
479  case PolygonZMType:
480  rType = LineStringZMType;
481  p = new Polygon(nRings, PolygonZMType, 0, 0);
482  break;
483 
484  case TriangleType:
485  rType = LineStringType;
486 
487  if(nRings != 1)
488  return 0;
489 
490  p = new Triangle(TriangleType, 0, 0);
491  break;
492 
493  case TriangleZType:
494  rType = LineStringZType;
495 
496  if(nRings != 1)
497  return 0;
498 
499  p = new Triangle(TriangleZType, 0, 0);
500  break;
501 
502  case TriangleMType:
503  rType = LineStringMType;
504 
505  if(nRings != 1)
506  return 0;
507 
508  p = new Triangle(TriangleMType, 0, 0);
509  break;
510 
511  case TriangleZMType:
512  rType = LineStringZMType;
513 
514  if(nRings != 1)
515  return 0;
516 
517  p = new Triangle(TriangleZMType, 0, 0);
518  break;
519 
520  default:
521  throw Exception(TE_TR("Could not read WKB due to an invalid polygon type!"));
522  }
523 
524  *endptr = wkb;
525 
526  if(p == 0)
527  return 0;
528 
529  for(unsigned int i = 0; i < nRings; ++i)
530  {
531  LinearRing* r = getLinearRing(wkb, endptr, byteOrder, rType);
532  wkb = *endptr;
533  p->setRingN(i, r);
534  }
535 
536  return p;
537 }
538 
540 {
541  assert(wkb && endptr);
542 
544  unsigned int gType = 0;
545  unsigned int nGeoms = 0;
546 
547  memcpy(&byteOrder, wkb, 1);
548  memcpy(&gType, wkb + 1, 4);
549  memcpy(&nGeoms, wkb + 5, 4);
550 
552  {
553  te::common::SwapBytes(gType);
554  te::common::SwapBytes(nGeoms);
555  }
556 
557  wkb += 9;
558 
559  GeometryCollection* gc = 0;
560 
561  switch(gType)
562  {
563  case MultiPolygonType:
564  case MultiPolygonZType:
565  case MultiPolygonMType:
566  case MultiPolygonZMType:
567  gc = new MultiPolygon(nGeoms, static_cast<GeomType>(gType));
568  break;
569 
570  case MultiPointType:
571  case MultiPointZType:
572  case MultiPointMType:
573  case MultiPointZMType:
574  gc = new MultiPoint(nGeoms, static_cast<GeomType>(gType));
575  break;
576 
577  case MultiLineStringType:
581  gc = new MultiLineString(nGeoms, static_cast<GeomType>(gType));
582  break;
583 
588  gc = new GeometryCollection(nGeoms, static_cast<GeomType>(gType));
589  break;
590 
591  default:
592  throw Exception(TE_TR("Could not read WKB due to an invalid geometry collection type!"));
593  }
594 
595  *endptr = wkb;
596 
597  if(gc == 0)
598  throw Exception(TE_TR("Could not create geometry collection from wkb!"));
599 
600  for(unsigned int i = 0; i < nGeoms; ++i)
601  {
602  Geometry* g = getGeometry(wkb, endptr);
603  wkb = *endptr;
604  gc->setGeometryN(i, g);
605  }
606 
607  return gc;
608 }
609 
611 {
612  assert(wkb && endptr);
613 
615  unsigned int gType = 0;
616  unsigned int nPols = 0;
617 
618  memcpy(&byteOrder, wkb, 1);
619  memcpy(&gType, wkb + 1, 4);
620  memcpy(&nPols, wkb + 5, 4);
621 
623  {
624  te::common::SwapBytes(gType);
625  te::common::SwapBytes(nPols);
626  }
627 
628  wkb += 9;
629 
630  PolyhedralSurface* ph = 0;
631 
632  switch(gType)
633  {
638  ph = new PolyhedralSurface(nPols, static_cast<GeomType>(gType), 0, 0);
639  break;
640 
641  case TINType:
642  case TINZType:
643  case TINMType:
644  case TINZMType:
645  ph = new TIN(nPols, static_cast<GeomType>(gType), 0, 0);
646  break;
647 
648  default:
649  throw Exception(TE_TR("Could not read WKB due to an invalid polyhedral surface type!"));
650  }
651 
652  *endptr = wkb;
653 
654  if(ph == 0)
655  throw Exception(TE_TR("Could not create polyhedral surface from wkb!"));
656 
657  for(unsigned int i = 0; i < nPols; ++i)
658  {
659  Polygon* gptr = getPolygon(wkb, endptr);
660  wkb = *endptr;
661  ph->setPatchN(i ,gptr);
662  }
663 
664  return ph;
665 }
PolyhedralSurface is a contiguous collection of polygons, which share common boundary segments...
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
Definition: Enums.h:41
A LinearRing is a LineString that is both closed and simple.
Coord2D * getCoordinates() const
It returns a pointer to the internal array of coordinates.
Definition: LineString.h:456
static Geometry * readHex(const char *hwkb)
It returns a valid geometry from a given hex-encoded WKB.
Definition: WKBReader.cpp:57
static const MachineByteOrder sm_machineByteOrder
A flag that indicates the machine byte order (Big Endian or Little Endian).
Definition: Globals.h:54
static te::gm::Point * getPoint(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:146
static te::gm::Polygon * getPolygon(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:438
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:347
PolyhedralSurface is a contiguous collection of polygons, which share common boundary segments...
static te::gm::Geometry * getGeometry(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:68
MultiPoint is a GeometryCollection whose elements are restricted to points.
A point with a z-coordinate value and an associated measurement.
Definition: PointZM.h:51
A point with an associated measure.
Definition: PointM.h:51
TIN (triangulated irregular network) is a PolyhedralSurface consisting only of Triangle patches...
Definition: TIN.h:50
A LinearRing is a LineString that is both closed and simple.
Definition: LinearRing.h:53
MultiPoint is a GeometryCollection whose elements are restricted to points.
Definition: MultiPoint.h:50
A point with z-coordinate value.
Definition: PointZ.h:51
LineString is a curve with linear interpolation between points.
Definition: LineString.h:62
static te::gm::LinearRing * getLinearRing(const char *wkb, const char **endptr, te::common::MachineByteOrder byteOrder, GeomType gType)
Definition: WKBReader.cpp:357
Triangle is a polygon with 3 distinct, non-collinear vertices and no interior boundary.
Triangle is a polygon with 3 distinct, non-collinear vertices and no interior boundary.
Definition: Triangle.h:50
A point with x and y coordinate values.
Definition: Point.h:50
static te::gm::GeometryCollection * getGeometryCollection(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:539
MultiLineString is a MultiCurve whose elements are LineStrings.
MultiPolygon is a MultiSurface whose elements are Polygons.
MultiCurve is a class that represents a 1-dimensional GeometryCollection whose elements are curves...
static te::gm::PointM * getPointM(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:204
static te::gm::LineString * getLineString(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:267
MachineByteOrder
Endianness.
Definition: Enums.h:116
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Definition: Geometry.h:73
static te::gm::PolyhedralSurface * getPolyhedralSurface(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:610
An exception class for the Geometry module.
TIN (triangulated irregular network) is a PolyhedralSurface consisting only of Triangle patches...
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
MultiLineString is a MultiCurve whose elements are LineStrings.
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Definition: Polygon.h:50
A class that deserializes a geometry from a valid WKB.
static te::gm::PointZM * getPointZM(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:233
static te::gm::PointZ * getPointZ(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:175
char * Hex2Binary(const char *hex)
It converts each pair of hex characters from a NULL-terminated string of hex characters into a binary...
Definition: HexUtils.h:469
void setGeometryN(std::size_t i, Geometry *g)
It sets the n-th geometry in this geometry collection.
const double & getZ(std::size_t i) const
It returns the n-th z coordinate value.
Definition: LineString.cpp:397
const double & getM(std::size_t i) const
It returns the n-th m measure value.
Definition: LineString.cpp:403
void setPatchN(std::size_t i, Polygon *p)
It sets the informed position polygon to the new one.
It is a collection of other geometric objects.
A point with z-coordinate value.
A point with a z-coordinate value and an associated measurement.
A point with an associated measure.
void SwapBytes(T &v)
It swaps the bytes in local.
It is a collection of other geometric objects.
static Geometry * read(const char *wkb)
It returns a valid geometry from a given WKB.
Definition: WKBReader.cpp:50
void setRingN(std::size_t i, Curve *r)
It sets the informed position ring to the new one.