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 "../core/utils/HexUtils.h"
30 #include "../core/translator/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 "Point.h"
39 #include "Polygon.h"
40 #include "PolyhedralSurface.h"
41 #include "TIN.h"
42 #include "Triangle.h"
43 #include "WKBReader.h"
44 
45 // STL
46 #include <cstring>
47 
49 {
50  const char* aux = wkb;
51 
52  return getGeometry(wkb, &aux);
53 }
54 
56 {
57  char* wkb = te::core::Hex2Binary(hwkb);
58 
60 
61  delete [] wkb;
62 
63  return g;
64 }
65 
66 te::gm::Geometry* te::gm::WKBReader::getGeometry(const char* wkb, const char** endptr)
67 {
68  assert(wkb && endptr);
69 
70  char byteOrder = 0;
71  unsigned int gType = 0;
72 
73  memcpy(&byteOrder, wkb, 1);
74  memcpy(&gType, wkb + 1, 4);
75 
76  //wkb += 5; -> not skipping now!
77 
78  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
79  te::common::SwapBytes(gType);
80 
81  switch(gType)
82  {
83  case te::gm::PointType:
84  return getPoint(wkb, endptr);
85  case te::gm::PointZType:
86  return getPointZ(wkb, endptr);
87  case te::gm::PointMType:
88  return getPointM(wkb, endptr);
90  return getPointZM(wkb, endptr);
91 
92 
97  return getLineString(wkb, endptr);
98 
106  return getPolygon(wkb, endptr);
107 
128  return getGeometryCollection(wkb, endptr);
129 
130  case te::gm::TINType:
131  case te::gm::TINZType:
132  case te::gm::TINMType:
133  case te::gm::TINZMType:
138  return getPolyhedralSurface(wkb, endptr);
139 
140  default:
141  throw Exception(TE_TR("Could not read WKB due to an invalid geometry type!"));
142  }
143 }
144 
145 te::gm::Point* te::gm::WKBReader::getPoint(const char* wkb, const char** endptr)
146 {
147  assert(wkb && endptr);
148 
149  char byteOrder = 0;
150 //unsigned int gType = 0;
151  double x = 0.0;
152  double y = 0.0;
153 
154  memcpy(&byteOrder, wkb, 1);
155 //memcpy(&gType, wkb + 1, 4);
156 
157  memcpy(&x, wkb + 5, 8);
158  memcpy(&y, wkb + 13, 8);
159 
160  wkb += 21;
161 
162  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
163  {
164 // te::common::SwapBytes(gType);
167  }
168 
169  *endptr = wkb;
170 
171  return new Point(x, y);
172 }
173 
174 te::gm::Point* te::gm::WKBReader::getPointZ(const char* wkb, const char** endptr)
175 {
176  assert(wkb && endptr);
177 
178  char byteOrder = 0;
179 //unsigned int gType = 0;
180  double x = 0.0;
181  double y = 0.0;
182  double z = 0.0;
183 
184  memcpy(&byteOrder, wkb, 1);
185 //memcpy(&gType, wkb + 1, 4);
186  memcpy(&x, wkb + 5, 8);
187  memcpy(&y, wkb + 13, 8);
188  memcpy(&z, wkb + 21, 8);
189 
190  *endptr = wkb + 29;
191 
193  {
194 // te::common::SwapBytes(gType);
198  }
199 
200  Point* p = new Point(0, PointZType);
201  p->setX(x);
202  p->setY(y);
203  p->setZ(z);
204 
205  return p;
206 }
207 
208 te::gm::Point* te::gm::WKBReader::getPointM(const char* wkb, const char** endptr)
209 {
210  assert(wkb && endptr);
211 
212  char byteOrder = 0;
213 //unsigned int gType = 0;
214  double x = 0.0;
215  double y = 0.0;
216  double m = 0.0;
217 
218  memcpy(&byteOrder, wkb, 1);
219 //memcpy(&gType, wkb + 1, 4);
220  memcpy(&x, wkb + 5, 8);
221  memcpy(&y, wkb + 13, 8);
222  memcpy(&m, wkb + 21, 8);
223 
224  *endptr = wkb + 29;
225 
226  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
227  {
228 // te::common::SwapBytes(gType);
232  }
233 
234  Point* p = new Point(0, PointMType);
235  p->setX(x);
236  p->setY(y);
237  p->setM(m);
238 
239  return p;
240 }
241 
242 te::gm::Point* te::gm::WKBReader::getPointZM(const char* wkb, const char** endptr)
243 {
244  assert(wkb && endptr);
245 
246  char byteOrder = 0;
247 //unsigned int gType = 0;
248 //int srid = 0;
249  double x = 0.0;
250  double y = 0.0;
251  double z = 0.0;
252  double m = 0.0;
253 
254  memcpy(&byteOrder, wkb, 1);
255 //memcpy(&gType, wkb + 1, 4);
256  memcpy(&x, wkb + 5, 8);
257  memcpy(&y, wkb + 13, 8);
258  memcpy(&z, wkb + 21, 8);
259  memcpy(&m, wkb + 29, 8);
260 
261  *endptr = wkb + 37;
262 
263 
264  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
265  {
266 // te::common::SwapBytes(gType);
271  }
272 
273  Point* p = new Point(0, PointZMType);
274  p->setX(x);
275  p->setY(y);
276  p->setZ(z);
277  p->setM(m);
278 
279  return p;
280 }
281 
282 te::gm::LineString* te::gm::WKBReader::getLineString(const char* wkb, const char** endptr)
283 {
284  assert(wkb && endptr);
285 
286  char byteOrder = 0;
287  unsigned int gType = 0;
288  int srid = 0;
289  unsigned int nPts = 0;
290 
291  memcpy(&byteOrder, wkb, 1);
292  memcpy(&gType, wkb + 1, 4);
293  memcpy(&nPts, wkb + 5, 4);
294 
295  wkb += 9;
296 
297  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
298  {
299  te::common::SwapBytes(gType);
300  te::common::SwapBytes(nPts);
301  }
302 
303  LineString* l = new LineString(nPts, static_cast<GeomType>(gType), srid, nullptr);
304 
305  Coord2D* coords = l->getCoordinates();
306 
307  double* zA = l->getZ();
308 
309  double* mA = l->getM();
310 
311  switch(gType)
312  {
313  case LineStringType :
314  memcpy(coords, wkb, 16 * nPts);
315  wkb += nPts * 16;
316  break;
317 
318  case LineStringZType :
319  for(unsigned int i = 0; i < nPts; ++i)
320  {
321  memcpy(&(coords[i]), wkb, 16);
322  memcpy(&(zA[i]), wkb + 16, 8);
323  wkb += 24;
324  }
325  break;
326 
327  case LineStringMType :
328  for(unsigned int i = 0; i < nPts; ++i)
329  {
330  memcpy(&(coords[i]), wkb, 16);
331  memcpy(&(mA[i]), wkb + 16, 8);
332  wkb += 24;
333  }
334  break;
335 
336  case LineStringZMType :
337  for(unsigned int i = 0; i < nPts; ++i)
338  {
339  memcpy(&(coords[i]), wkb, 16);
340  memcpy(&(zA[i]), wkb + 16, 8);
341  memcpy(&(mA[i]), wkb + 24, 8);
342  wkb += 32;
343  }
344  break;
345 
346  default:
347  throw Exception(TE_TR("Could not read WKB due to an invalid line string type!"));
348  }
349 
350  if(te::common::Globals::sm_machineByteOrder != static_cast<te::common::MachineByteOrder>(byteOrder))
351  {
352  for(unsigned int i = 0; i < nPts; ++i)
353  {
354  te::common::SwapBytes(coords[i].x);
355  te::common::SwapBytes(coords[i].y);
356  }
357 
358  if(zA)
359  for(unsigned int i = 0; i < nPts; ++i)
360  te::common::SwapBytes(zA[i]);
361 
362  if(mA)
363  for(unsigned int i = 0; i < nPts; ++i)
364  te::common::SwapBytes(mA[i]);
365  }
366 
367  *endptr = wkb;
368 
369  return l;
370 }
371 
372 te::gm::LinearRing* te::gm::WKBReader::getLinearRing(const char* wkb, const char** endptr, te::common::MachineByteOrder byteOrder, GeomType gType)
373 {
374  assert(wkb && endptr);
375 
376  unsigned int nPts = 0;
377 
378  memcpy(&nPts, wkb, 4);
379  wkb += 4;
380 
382  te::common::SwapBytes(nPts);
383 
384  LinearRing* r = new LinearRing(nPts, gType, 0, nullptr);
385 
386  Coord2D* coords = r->getCoordinates();
387 
388  double* zA = r->getZ();
389 
390  double* mA = r->getM();
391 
392  switch(gType)
393  {
394  case LineStringType :
395  memcpy(coords, wkb, 16 * nPts);
396  wkb += nPts * 16;
397  break;
398 
399  case LineStringZType :
400  for(unsigned int i = 0; i < nPts; ++i)
401  {
402  memcpy(&(coords[i]), wkb, 16);
403  memcpy(&(zA[i]), wkb + 16, 8);
404  wkb += 24;
405  }
406  break;
407 
408  case LineStringMType :
409  for(unsigned int i = 0; i < nPts; ++i)
410  {
411  memcpy(&(coords[i]), wkb, 16);
412  memcpy(&(mA[i]), wkb + 16, 8);
413  wkb += 24;
414  }
415  break;
416 
417  case LineStringZMType :
418  for(unsigned int i = 0; i < nPts; ++i)
419  {
420  memcpy(&(coords[i]), wkb, 16);
421  memcpy(&(zA[i]), wkb + 16, 8);
422  memcpy(&(mA[i]), wkb + 24, 8);
423  wkb += 32;
424  }
425  break;
426 
427  default:
428  throw Exception(TE_TR("Could not read WKB due to an invalid linear ring type!"));
429  }
430 
432  {
433  for(unsigned int i = 0; i < nPts; ++i)
434  {
435  te::common::SwapBytes(coords[i].x);
436  te::common::SwapBytes(coords[i].y);
437  }
438 
439  if(zA)
440  for(unsigned int i = 0; i < nPts; ++i)
441  te::common::SwapBytes(zA[i]);
442 
443  if(mA)
444  for(unsigned int i = 0; i < nPts; ++i)
445  te::common::SwapBytes(mA[i]);
446  }
447 
448  *endptr = wkb;
449 
450  return r;
451 }
452 
453 te::gm::Polygon* te::gm::WKBReader::getPolygon(const char* wkb, const char** endptr)
454 {
455  assert(wkb && endptr);
456 
458  unsigned int gType = 0;
459  unsigned int nRings = 0;
460 
461  memcpy(&byteOrder, wkb, 1);
462  memcpy(&gType, wkb + 1, 4);
463  memcpy(&nRings, wkb + 5, 4);
464 
465  wkb += 9;
466 
468  {
469  te::common::SwapBytes(gType);
470  te::common::SwapBytes(nRings);
471  }
472 
473  Polygon* p = nullptr;
474 
476 
477  switch(gType)
478  {
479  case PolygonType:
480  rType = LineStringType;
481  p = new Polygon(nRings, PolygonType, 0, nullptr);
482  break;
483 
484  case PolygonZType:
485  rType = LineStringZType;
486  p = new Polygon(nRings, PolygonZType, 0, nullptr);
487  break;
488 
489  case PolygonMType:
490  rType = LineStringMType;
491  p = new Polygon(nRings, PolygonMType, 0, nullptr);
492  break;
493 
494  case PolygonZMType:
495  rType = LineStringZMType;
496  p = new Polygon(nRings, PolygonZMType, 0, nullptr);
497  break;
498 
499  case TriangleType:
500  rType = LineStringType;
501 
502  if(nRings != 1)
503  return nullptr;
504 
505  p = new Triangle(TriangleType, 0, nullptr);
506  break;
507 
508  case TriangleZType:
509  rType = LineStringZType;
510 
511  if(nRings != 1)
512  return nullptr;
513 
514  p = new Triangle(TriangleZType, 0, nullptr);
515  break;
516 
517  case TriangleMType:
518  rType = LineStringMType;
519 
520  if(nRings != 1)
521  return nullptr;
522 
523  p = new Triangle(TriangleMType, 0, nullptr);
524  break;
525 
526  case TriangleZMType:
527  rType = LineStringZMType;
528 
529  if(nRings != 1)
530  return nullptr;
531 
532  p = new Triangle(TriangleZMType, 0, nullptr);
533  break;
534 
535  default:
536  throw Exception(TE_TR("Could not read WKB due to an invalid polygon type!"));
537  }
538 
539  *endptr = wkb;
540 
541  if(p == nullptr)
542  return nullptr;
543 
544  for(unsigned int i = 0; i < nRings; ++i)
545  {
546  LinearRing* r = getLinearRing(wkb, endptr, byteOrder, rType);
547  wkb = *endptr;
548  p->setRingN(i, r);
549  }
550 
551  return p;
552 }
553 
555 {
556  assert(wkb && endptr);
557 
559  unsigned int gType = 0;
560  unsigned int nGeoms = 0;
561 
562  memcpy(&byteOrder, wkb, 1);
563  memcpy(&gType, wkb + 1, 4);
564  memcpy(&nGeoms, wkb + 5, 4);
565 
567  {
568  te::common::SwapBytes(gType);
569  te::common::SwapBytes(nGeoms);
570  }
571 
572  wkb += 9;
573 
574  GeometryCollection* gc = nullptr;
575 
576  switch(gType)
577  {
578  case MultiPolygonType:
579  case MultiPolygonZType:
580  case MultiPolygonMType:
581  case MultiPolygonZMType:
582  gc = new MultiPolygon(nGeoms, static_cast<GeomType>(gType));
583  break;
584 
585  case MultiPointType:
586  case MultiPointZType:
587  case MultiPointMType:
588  case MultiPointZMType:
589  gc = new MultiPoint(nGeoms, static_cast<GeomType>(gType));
590  break;
591 
592  case MultiLineStringType:
596  gc = new MultiLineString(nGeoms, static_cast<GeomType>(gType));
597  break;
598 
599  case MultiSurfaceType:
600  case MultiSurfaceZType:
601  case MultiSurfaceMType:
602  case MultiSurfaceZMType:
603  gc = new MultiSurface(nGeoms, static_cast<GeomType>(gType));
604  break;
605 
610  gc = new GeometryCollection(nGeoms, static_cast<GeomType>(gType));
611  break;
612 
613  default:
614  throw Exception(TE_TR("Could not read WKB due to an invalid geometry collection type!"));
615  }
616 
617  *endptr = wkb;
618 
619  if(gc == nullptr)
620  throw Exception(TE_TR("Could not create geometry collection from wkb!"));
621 
622  for(unsigned int i = 0; i < nGeoms; ++i)
623  {
624  Geometry* g = getGeometry(wkb, endptr);
625  wkb = *endptr;
626  gc->setGeometryN(i, g);
627  }
628 
629  return gc;
630 }
631 
633 {
634  assert(wkb && endptr);
635 
637  unsigned int gType = 0;
638  unsigned int nPols = 0;
639 
640  memcpy(&byteOrder, wkb, 1);
641  memcpy(&gType, wkb + 1, 4);
642  memcpy(&nPols, wkb + 5, 4);
643 
645  {
646  te::common::SwapBytes(gType);
647  te::common::SwapBytes(nPols);
648  }
649 
650  wkb += 9;
651 
652  PolyhedralSurface* ph = nullptr;
653 
654  switch(gType)
655  {
660  ph = new PolyhedralSurface(nPols, static_cast<GeomType>(gType), 0, nullptr);
661  break;
662 
663  case TINType:
664  case TINZType:
665  case TINMType:
666  case TINZMType:
667  ph = new TIN(nPols, static_cast<GeomType>(gType), 0, nullptr);
668  break;
669 
670  default:
671  throw Exception(TE_TR("Could not read WKB due to an invalid polyhedral surface type!"));
672  }
673 
674  *endptr = wkb;
675 
676  if(ph == nullptr)
677  throw Exception(TE_TR("Could not create polyhedral surface from wkb!"));
678 
679  for(unsigned int i = 0; i < nPols; ++i)
680  {
681  Polygon* gptr = getPolygon(wkb, endptr);
682  wkb = *endptr;
683  ph->setPatchN(i ,gptr);
684  }
685 
686  return ph;
687 }
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.
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
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
Base exception class for plugin module.
A point with x and y coordinate values.
static Geometry * readHex(const char *hwkb)
It returns a valid geometry from a given hex-encoded WKB.
Definition: WKBReader.cpp:55
static const MachineByteOrder sm_machineByteOrder
A flag that indicates the machine byte order (Big Endian or Little Endian).
static te::gm::Point * getPoint(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:145
static te::gm::Polygon * getPolygon(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:453
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:242
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:66
MultiPoint is a GeometryCollection whose elements are restricted to points.
te::gm::GeometryCollection * gc
A LinearRing is a LineString that is both closed and simple.
Definition: LinearRing.h:53
static te::gm::Point * getPointM(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:208
MultiPoint is a GeometryCollection whose elements are restricted to points.
Definition: MultiPoint.h:50
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:372
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:554
MultiLineString is a MultiCurve whose elements are LineStrings.
void setM(const double &m)
It sets the Point m-coordinate value.
Definition: Point.h:187
te::gm::Polygon * p
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::LineString * getLineString(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:282
MachineByteOrder
Endianness.
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
static te::gm::PolyhedralSurface * getPolyhedralSurface(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:632
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.
void setX(const double &x)
It sets the Point x-coordinate value.
Definition: Point.h:145
MultiSurface is a class that represents a 2-dimensional GeometryCollection whose elements are surface...
Definition: MultiSurface.h:54
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.
const double & getM(std::size_t i) const
It returns the n-th m measure value.
void setPatchN(std::size_t i, Polygon *p)
It sets the informed position polygon to the new one.
void setY(const double &y)
It sets the Point y-coordinate value.
Definition: Point.h:159
It is a collection of other geometric objects.
An exception class for the Geometry module.
static te::gm::Point * getPointZ(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:174
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:48
void setZ(const double &z)
It sets the Point z-coordinate value.
Definition: Point.h:173
static te::gm::Point * getPointZM(const char *wkb, const char **endptr)
Definition: WKBReader.cpp:242
void setRingN(std::size_t i, Curve *r)
It sets the informed position ring to the new one.