src/terralib/postgis/EWKBReader.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/postgis/EWKBReader.cpp
22 
23  \brief An utility class for reading a PostGIS EWKB.
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 "../geometry.h"
32 #include "EWKBReader.h"
33 #include "Exception.h"
34 #include "Utils.h"
35 
36 // STL
37 #include <cassert>
38 #include <cstring>
39 
40 namespace te
41 {
42  namespace pgis
43  {
44  template<class T> inline T* GetCoordSequence(const char* ewkb, const char** endptr, unsigned int gType, char byteOrder)
45  {
46  assert(ewkb && endptr);
47 
48  unsigned int nPts = 0;
49  int srid = 0;
50 
51  if(gType & TE_EWKB_SRID_FLAG)
52  {
53  memcpy(&srid, ewkb, 4);
54  memcpy(&nPts, ewkb + 4, 4);
55  ewkb += 8;
56  }
57  else
58  {
59  memcpy(&nPts, ewkb, 4);
60  ewkb += 4;
61  }
62 
64  {
67  }
68 
69  Convert2OGCWKBType(gType);
70 
71  T* cs = new T(nPts, (te::gm::GeomType)gType, srid, nullptr);
72 
73  switch(gType)
74  {
76  memcpy(cs->getCoordinates(), ewkb, 16 * nPts);
77  ewkb += nPts * 16;
78  break;
79 
81  for(unsigned int i = 0; i < nPts; ++i)
82  {
83  memcpy(&(cs->getCoordinates()[i]), ewkb, 16);
84  memcpy(&(cs->getZ()[i]), ewkb + 16, 8);
85  ewkb += 24;
86  }
87  break;
88 
90  for(unsigned int i = 0; i < nPts; ++i)
91  {
92  memcpy(&(cs->getCoordinates()[i]), ewkb, 16);
93  memcpy(&(cs->getM()[i]), ewkb + 16, 8);
94  ewkb += 24;
95  }
96  break;
97 
99  for(unsigned int i = 0; i < nPts; ++i)
100  {
101  memcpy(&(cs->getCoordinates()[i]), ewkb, 16);
102  memcpy(&(cs->getZ()[i]), ewkb + 16, 8);
103  memcpy(&(cs->getM()[i]), ewkb + 24, 8);
104  ewkb += 32;
105  }
106  break;
107  }
108 
110  {
111  for(unsigned int i = 0; i < nPts; ++i)
112  {
113  te::common::SwapBytes(cs->getCoordinates()[i].x);
114  te::common::SwapBytes(cs->getCoordinates()[i].y);
115  }
116 
117  if(cs->getZ())
118  for(unsigned int i = 0; i < nPts; ++i)
119  te::common::SwapBytes(cs->getZ()[i]);
120 
121  if(cs->getM())
122  for(unsigned int i = 0; i < nPts; ++i)
123  te::common::SwapBytes(cs->getM()[i]);
124  }
125 
126  *endptr = ewkb;
127 
128  return cs;
129 
130  }
131  }
132 }
133 
135 {
136  const char* aux = ewkb;
137 
138  return getGeometry(ewkb, &aux);
139 }
140 
142 {
143  char* ewkb = te::core::Hex2Binary(hewkb);
144 
146 
147  delete [] ewkb;
148 
149  return g;
150 }
151 
152 te::gm::Geometry* te::pgis::EWKBReader::getGeometry(const char* ewkb, const char** endptr)
153 {
154  assert(ewkb && endptr);
155 
156  char byteOrder = 0;
157  unsigned int gType = 0;
158 
159  memcpy(&byteOrder, ewkb, 1);
160  memcpy(&gType, ewkb + 1, 4);
161 
163  te::common::SwapBytes(gType);
164 
165  Convert2OGCWKBType(gType);
166 
167  switch(gType)
168  {
169  case te::gm::PointType:
170  case te::gm::PointZType:
171  case te::gm::PointMType:
172  case te::gm::PointZMType:
173  return getPoint(ewkb, endptr);
174 
179  return getLineString(ewkb, endptr);
180 
181  case te::gm::PolygonType:
185  return getPolygon(ewkb, endptr);
186 
207  return getGeometryCollection(ewkb, endptr);
208 
209  /*case TriangleType:
210  case te::gm::TriangleZType:
211  case te::gm::TriangleMType:
212  case te::gm::TriangleZMType:
213  return getPolygon(ewkb, endptr);
214 
215  case te::gm::TINType:
216  case te::gm::TINZType:
217  case te::gm::TINMType:
218  case te::gm::TINZMType:
219  case te::gm::PolyhedralSurfaceType:
220  case te::gm::PolyhedralSurfaceZType:
221  case te::gm::PolyhedralSurfaceMType:
222  case te::gm::PolyhedralSurfaceZMType:
223  return getPolyhedralSurface(ewkb, endptr);*/
224 
225  default:
226  assert(false);
227  break;
228  }
229 
230  return nullptr;
231 }
232 
233 te::gm::Point* te::pgis::EWKBReader::getPoint(const char* ewkb, const char** endptr)
234 {
235  assert(ewkb && 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, ewkb, 1);
246  memcpy(&gType, ewkb + 1, 4);
247 
249  te::common::SwapBytes(gType);
250 
251  ewkb += 5;
252 
253  if(gType & TE_EWKB_SRID_FLAG)
254  {
255  memcpy(&srid, ewkb, 4);
256  ewkb += 4;
257  }
258 
259  Convert2OGCWKBType(gType);
260 
261  memcpy(&x, ewkb, 8);
262  memcpy(&y, ewkb + 8, 8);
263 
264  ewkb += 16;
265 
266  if(gType != te::gm::PointType)
267  {
268  switch(gType)
269  {
270  case te::gm::PointZType:
271  memcpy(&z, ewkb, 8);
272  ewkb += 8;
273  break;
274 
275  case te::gm::PointMType:
276  memcpy(&m, ewkb, 8);
277  ewkb += 8;
278  break;
279 
280  default: // zm
281  assert(gType == te::gm::PointZMType);
282  memcpy(&z, ewkb, 8);
283  memcpy(&m, ewkb + 8, 8);
284  ewkb += 16;
285  }
286  }
287 
288  *endptr = ewkb;
289 
291  {
292  te::common::SwapBytes(srid);
297  }
298 
299  switch(gType)
300  {
301  te::gm::Point* p;
302 
303  case te::gm::PointType:
304  p = new te::gm::Point(x, y, srid);
305  return p;
306 
307  case te::gm::PointZType:
308  p = new te::gm::Point(srid, te::gm::PointZType);
309  p->setX(x);
310  p->setY(y);
311  p->setZ(z);
312  return p;
313 
314  case te::gm::PointMType:
315  p = new te::gm::Point(srid, te::gm::PointMType);
316  p->setX(x);
317  p->setY(y);
318  p->setM(m);
319  return p;
320 
321  default: // zm
322  assert(gType == te::gm::PointZMType);
323  p = new te::gm::Point(srid, te::gm::PointZMType);
324  p->setX(x);
325  p->setY(y);
326  p->setZ(z);
327  p->setM(m);
328  return p;
329  }
330 }
331 
332 te::gm::LineString* te::pgis::EWKBReader::getLineString(const char* ewkb, const char** endptr)
333 {
334  assert(ewkb && endptr);
335 
336  char byteOrder = 0;
337  unsigned int gType = 0;
338 
339  memcpy(&byteOrder, ewkb, 1);
340  memcpy(&gType, ewkb + 1, 4);
341 
342  ewkb += 5;
343 
345  te::common::SwapBytes(gType);
346 
347  te::gm::LineString* l = GetCoordSequence<te::gm::LineString>(ewkb, endptr, gType, byteOrder);
348 
349  return l;
350 }
351 
352 te::gm::LinearRing* te::pgis::EWKBReader::getLinearRing(const char* ewkb, te::gm::GeomType t, int srid, char wkbByteOrder, const char** endptr)
353 {
354  assert(ewkb && endptr);
355 
356  te::gm::LinearRing* r = GetCoordSequence<te::gm::LinearRing>(ewkb, endptr, t, wkbByteOrder);
357  r->setSRID(srid);
358 
359  return r;
360 }
361 
362 te::gm::Polygon* te::pgis::EWKBReader::getPolygon(const char* ewkb, const char** endptr)
363 {
364  assert(ewkb && endptr);
365 
366  char byteOrder = 0;
367  unsigned int gType = 0;
368  int srid = 0;
369  unsigned int nRings = 0;
370 
371  memcpy(&byteOrder, ewkb, 1);
372  memcpy(&gType, ewkb + 1, 4);
373 
375  te::common::SwapBytes(gType);
376 
377  if(gType & TE_EWKB_SRID_FLAG)
378  {
379  memcpy(&srid, ewkb + 5, 4);
380  memcpy(&nRings, ewkb + 9, 4);
381  ewkb += 13;
382  }
383  else
384  {
385  memcpy(&nRings, ewkb + 5, 4);
386  ewkb += 9;
387  }
388 
390  {
391  te::common::SwapBytes(srid);
392  te::common::SwapBytes(nRings);
393  }
394 
395  Convert2OGCWKBType(gType);
396 
397  te::gm::Polygon* p = nullptr;
398 
400 
401  switch(gType)
402  {
403  case te::gm::PolygonType:
404  rType = te::gm::LineStringType;
405  p = new te::gm::Polygon(nRings, te::gm::PolygonType, srid, nullptr);
406  break;
407 
409  rType = te::gm::LineStringZType;
410  p = new te::gm::Polygon(nRings, te::gm::PolygonZType, srid, nullptr);
411  break;
412 
414  rType = te::gm::LineStringMType;
415  p = new te::gm::Polygon(nRings, te::gm::PolygonMType, srid, nullptr);
416  break;
417 
419  rType = te::gm::LineStringZMType;
420  p = new te::gm::Polygon(nRings, te::gm::PolygonZMType, srid, nullptr);
421  break;
422 
423  default:
424  assert(false);
425  break;
426  }
427 
428  *endptr = ewkb;
429 
430  if(p == nullptr)
431  return nullptr;
432 
433  for(unsigned int i = 0; i < nRings; ++i)
434  {
435  te::gm::LinearRing* r = getLinearRing(ewkb, rType, srid, byteOrder, endptr);
436  ewkb = *endptr;
437  p->getRings()[i] = r;
438  }
439 
440  return p;
441 }
442 
444 {
445  assert(ewkb && endptr);
446 
447  char byteOrder = 0;
448  unsigned int gType = 0;
449  int srid = 0;
450  unsigned int nGeoms = 0;
451 
452  memcpy(&byteOrder, ewkb, 1);
453  memcpy(&gType, ewkb + 1, 4);
454 
456  te::common::SwapBytes(gType);
457 
458  if(gType & TE_EWKB_SRID_FLAG)
459  {
460  memcpy(&srid, ewkb + 5, 4);
461  memcpy(&nGeoms, ewkb + 9, 4);
462  ewkb += 13;
463  }
464  else
465  {
466  memcpy(&nGeoms, ewkb + 5, 4);
467  ewkb += 9;
468  }
469 
471  {
472  te::common::SwapBytes(srid);
473  te::common::SwapBytes(nGeoms);
474  }
475 
476  Convert2OGCWKBType(gType);
477 
478  te::gm::GeometryCollection* gc = nullptr;
479 
480  switch(gType)
481  {
486  gc = new te::gm::MultiPolygon(nGeoms, (te::gm::GeomType)gType, srid, nullptr);
487  break;
488 
493  gc = new te::gm::MultiPoint(nGeoms, (te::gm::GeomType)gType, srid, nullptr);
494  break;
495 
500  gc = new te::gm::MultiLineString(nGeoms, (te::gm::GeomType)gType, srid, nullptr);
501  break;
502 
507  gc = new te::gm::GeometryCollection(nGeoms, (te::gm::GeomType)gType, srid, nullptr);
508  break;
509 
510  default:
511  assert(false);
512  break;
513  }
514 
515  *endptr = ewkb;
516 
517  if(gc == nullptr)
518  return nullptr;
519 
520  for(unsigned int i = 0; i < nGeoms; ++i)
521  {
522  te::gm::Geometry* g = getGeometry(ewkb, endptr);
523  g->setSRID(srid);
524  ewkb = *endptr;
525  gc->getGeometries()[i] = g;
526  }
527 
528  return gc;
529 }
static te::gm::LineString * getLineString(const char *ewkb, const char **endptr)
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
static te::gm::Geometry * readHex(const char *hewkb)
It returns a valid geometry from a given hex-encoded EWKB.
static te::gm::Geometry * read(const char *ewkb)
It returns a valid geometry from a given EWKB.
std::vector< Curve * > & getRings()
It returns the polygon rings.
Definition: CurvePolygon.h:294
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
static te::gm::Geometry * getGeometry(const char *ewkb, const char **endptr)
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
static te::gm::Polygon * getPolygon(const char *ewkb, const char **endptr)
Utility functions for PostgreSQL.
static const MachineByteOrder sm_machineByteOrder
A flag that indicates the machine byte order (Big Endian or Little Endian).
#define TE_EWKB_SRID_FLAG
te::gm::GeometryCollection * gc
A LinearRing is a LineString that is both closed and simple.
Definition: LinearRing.h:53
An exception class for the PostGIS driver.
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
A point with x and y coordinate values.
Definition: Point.h:50
void setM(const double &m)
It sets the Point m-coordinate value.
Definition: Point.h:187
static te::gm::LinearRing * getLinearRing(const char *ewkb, te::gm::GeomType t, int srid, char wkbByteOrder, const char **endptr)
URI C++ Library.
Definition: Attributes.h:37
te::gm::Polygon * p
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
static te::gm::GeometryCollection * getGeometryCollection(const char *ewkb, const char **endptr)
static te::gm::Point * getPoint(const char *ewkb, const char **endptr)
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
void setX(const double &x)
It sets the Point x-coordinate value.
Definition: Point.h:145
void Convert2OGCWKBType(unsigned int &gType)
It converts the PostGIS geometry type to a pure OGC WKB code.
const std::vector< Geometry * > & getGeometries() const
It returns a reference to the internal list of geometries.
T * GetCoordSequence(const char *ewkb, const char **endptr, unsigned int gType, char byteOrder)
virtual void setSRID(int srid) _NOEXCEPT_OP(true)=0
It sets the Spatial Reference System ID of the geometry and all its parts if it is a GeometryCollecti...
void setSRID(int srid)
It sets the Spatial Reference System ID of the linestring.
An utility class for reading a PostGIS EWKB.
void setY(const double &y)
It sets the Point y-coordinate value.
Definition: Point.h:159
It is a collection of other geometric objects.
void SwapBytes(T &v)
It swaps the bytes in local.
void setZ(const double &z)
It sets the Point z-coordinate value.
Definition: Point.h:173