All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 "../common/HexUtils.h"
30 #include "../common/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, 0);
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::common::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 
203  return getGeometryCollection(ewkb, endptr);
204 
205  /*case TriangleType:
206  case te::gm::TriangleZType:
207  case te::gm::TriangleMType:
208  case te::gm::TriangleZMType:
209  return getPolygon(ewkb, endptr);
210 
211  case te::gm::TINType:
212  case te::gm::TINZType:
213  case te::gm::TINMType:
214  case te::gm::TINZMType:
215  case te::gm::PolyhedralSurfaceType:
216  case te::gm::PolyhedralSurfaceZType:
217  case te::gm::PolyhedralSurfaceMType:
218  case te::gm::PolyhedralSurfaceZMType:
219  return getPolyhedralSurface(ewkb, endptr);*/
220 
221  default:
222  assert(false);
223  break;
224  }
225 
226  return 0;
227 }
228 
229 te::gm::Point* te::pgis::EWKBReader::getPoint(const char* ewkb, const char** endptr)
230 {
231  assert(ewkb && endptr);
232 
233  char byteOrder = 0;
234  unsigned int gType = 0;
235  int srid = 0;
236  double x = 0.0;
237  double y = 0.0;
238  double z = 0.0;
239  double m = 0.0;
240 
241  memcpy(&byteOrder, ewkb, 1);
242  memcpy(&gType, ewkb + 1, 4);
243 
245  te::common::SwapBytes(gType);
246 
247  ewkb += 5;
248 
249  if(gType & TE_EWKB_SRID_FLAG)
250  {
251  memcpy(&srid, ewkb, 4);
252  ewkb += 4;
253  }
254 
255  Convert2OGCWKBType(gType);
256 
257  memcpy(&x, ewkb, 8);
258  memcpy(&y, ewkb + 8, 8);
259 
260  ewkb += 16;
261 
262  if(gType != te::gm::PointType)
263  {
264  switch(gType)
265  {
266  case te::gm::PointZType:
267  memcpy(&z, ewkb, 8);
268  ewkb += 8;
269  break;
270 
271  case te::gm::PointMType:
272  memcpy(&m, ewkb, 8);
273  ewkb += 8;
274  break;
275 
276  default: // zm
277  assert(gType == te::gm::PointZMType);
278  memcpy(&z, ewkb, 8);
279  memcpy(&m, ewkb + 8, 8);
280  ewkb += 16;
281  }
282  }
283 
284  *endptr = ewkb;
285 
287  {
288  te::common::SwapBytes(srid);
293  }
294 
295  switch(gType)
296  {
297  case te::gm::PointType:
298  return new te::gm::Point(x, y, srid, 0);
299 
300  case te::gm::PointZType:
301  return new te::gm::PointZ(x, y, z, srid, 0);
302 
303  case te::gm::PointMType:
304  return new te::gm::PointM(x, y, m, srid, 0);
305 
306  default: // zm
307  assert(gType == te::gm::PointZMType);
308  return new te::gm::PointZM(x, y, z, m, srid, 0);
309  }
310 }
311 
312 te::gm::LineString* te::pgis::EWKBReader::getLineString(const char* ewkb, const char** endptr)
313 {
314  assert(ewkb && endptr);
315 
316  char byteOrder = 0;
317  unsigned int gType = 0;
318 
319  memcpy(&byteOrder, ewkb, 1);
320  memcpy(&gType, ewkb + 1, 4);
321 
322  ewkb += 5;
323 
325  te::common::SwapBytes(gType);
326 
327  te::gm::LineString* l = GetCoordSequence<te::gm::LineString>(ewkb, endptr, gType, byteOrder);
328 
329  return l;
330 }
331 
332 te::gm::LinearRing* te::pgis::EWKBReader::getLinearRing(const char* ewkb, te::gm::GeomType t, int srid, char wkbByteOrder, const char** endptr)
333 {
334  assert(ewkb && endptr);
335 
336  te::gm::LinearRing* r = GetCoordSequence<te::gm::LinearRing>(ewkb, endptr, t, wkbByteOrder);
337  r->setSRID(srid);
338 
339  return r;
340 }
341 
342 te::gm::Polygon* te::pgis::EWKBReader::getPolygon(const char* ewkb, const char** endptr)
343 {
344  assert(ewkb && endptr);
345 
346  char byteOrder = 0;
347  unsigned int gType = 0;
348  int srid = 0;
349  unsigned int nRings = 0;
350 
351  memcpy(&byteOrder, ewkb, 1);
352  memcpy(&gType, ewkb + 1, 4);
353 
355  te::common::SwapBytes(gType);
356 
357  if(gType & TE_EWKB_SRID_FLAG)
358  {
359  memcpy(&srid, ewkb + 5, 4);
360  memcpy(&nRings, ewkb + 9, 4);
361  ewkb += 13;
362  }
363  else
364  {
365  memcpy(&nRings, ewkb + 5, 4);
366  ewkb += 9;
367  }
368 
370  {
371  te::common::SwapBytes(srid);
372  te::common::SwapBytes(nRings);
373  }
374 
375  Convert2OGCWKBType(gType);
376 
377  te::gm::Polygon* p = 0;
378 
380 
381  switch(gType)
382  {
383  case te::gm::PolygonType:
384  rType = te::gm::LineStringType;
385  p = new te::gm::Polygon(nRings, te::gm::PolygonType, srid, 0);
386  break;
387 
389  rType = te::gm::LineStringZType;
390  p = new te::gm::Polygon(nRings, te::gm::PolygonZType, srid, 0);
391  break;
392 
394  rType = te::gm::LineStringMType;
395  p = new te::gm::Polygon(nRings, te::gm::PolygonMType, srid, 0);
396  break;
397 
399  rType = te::gm::LineStringZMType;
400  p = new te::gm::Polygon(nRings, te::gm::PolygonZMType, srid, 0);
401  break;
402 
403  default:
404  assert(false);
405  break;
406  }
407 
408  *endptr = ewkb;
409 
410  if(p == 0)
411  return 0;
412 
413  for(unsigned int i = 0; i < nRings; ++i)
414  {
415  te::gm::LinearRing* r = getLinearRing(ewkb, rType, srid, byteOrder, endptr);
416  ewkb = *endptr;
417  p->getRings()[i] = r;
418  }
419 
420  return p;
421 }
422 
424 {
425  assert(ewkb && endptr);
426 
427  char byteOrder = 0;
428  unsigned int gType = 0;
429  int srid = 0;
430  unsigned int nGeoms = 0;
431 
432  memcpy(&byteOrder, ewkb, 1);
433  memcpy(&gType, ewkb + 1, 4);
434 
436  te::common::SwapBytes(gType);
437 
438  if(gType & TE_EWKB_SRID_FLAG)
439  {
440  memcpy(&srid, ewkb + 5, 4);
441  memcpy(&nGeoms, ewkb + 9, 4);
442  ewkb += 13;
443  }
444  else
445  {
446  memcpy(&nGeoms, ewkb + 5, 4);
447  ewkb += 9;
448  }
449 
451  {
452  te::common::SwapBytes(srid);
453  te::common::SwapBytes(nGeoms);
454  }
455 
456  Convert2OGCWKBType(gType);
457 
459 
460  switch(gType)
461  {
466  gc = new te::gm::MultiPolygon(nGeoms, (te::gm::GeomType)gType, srid, 0);
467  break;
468 
473  gc = new te::gm::MultiPoint(nGeoms, (te::gm::GeomType)gType, srid, 0);
474  break;
475 
480  gc = new te::gm::MultiLineString(nGeoms, (te::gm::GeomType)gType, srid, 0);
481  break;
482 
487  gc = new te::gm::GeometryCollection(nGeoms, (te::gm::GeomType)gType, srid, 0);
488  break;
489 
490  default:
491  assert(false);
492  break;
493  }
494 
495  *endptr = ewkb;
496 
497  if(gc == 0)
498  return 0;
499 
500  for(unsigned int i = 0; i < nGeoms; ++i)
501  {
502  te::gm::Geometry* g = getGeometry(ewkb, endptr);
503  g->setSRID(srid);
504  ewkb = *endptr;
505  gc->getGeometries()[i] = g;
506  }
507 
508  return gc;
509 }
An utility class for reading a PostGIS EWKB.
static te::gm::LineString * getLineString(const char *ewkb, const char **endptr)
Definition: EWKBReader.cpp:312
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.
Definition: EWKBReader.cpp:141
static te::gm::Geometry * read(const char *ewkb)
It returns a valid geometry from a given EWKB.
Definition: EWKBReader.cpp:134
std::vector< Curve * > & getRings()
It returns the polygon rings.
Definition: CurvePolygon.h:300
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
Definition: Enums.h:41
#define TE_EWKB_SRID_FLAG
Definition: Config.h:163
static te::gm::Geometry * getGeometry(const char *ewkb, const char **endptr)
Definition: EWKBReader.cpp:152
static te::gm::Polygon * getPolygon(const char *ewkb, const char **endptr)
Definition: EWKBReader.cpp:342
static const MachineByteOrder sm_machineByteOrder
A flag that indicates the machine byte order (Big Endian or Little Endian).
Definition: Globals.h:54
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
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
A point with x and y coordinate values.
Definition: Point.h:50
Utility functions for PostgreSQL.
static te::gm::LinearRing * getLinearRing(const char *ewkb, te::gm::GeomType t, int srid, char wkbByteOrder, const char **endptr)
Definition: EWKBReader.cpp:332
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Definition: Geometry.h:73
static te::gm::GeometryCollection * getGeometryCollection(const char *ewkb, const char **endptr)
Definition: EWKBReader.cpp:423
static te::gm::Point * getPoint(const char *ewkb, const char **endptr)
Definition: EWKBReader.cpp:229
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
An exception class for the PostGIS driver.
void Convert2OGCWKBType(unsigned int &gType)
It converts the PostGIS geometry type to a pure OGC WKB code.
Definition: Utils.h:900
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)
Definition: EWKBReader.cpp:44
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 setSRID(int srid)
It sets the Spatial Reference System ID of the linestring.
Definition: LineString.cpp:176
It is a collection of other geometric objects.
virtual void setSRID(int srid)=0
It sets the Spatial Reference System ID of the geometry and all its parts if it is a GeometryCollecti...
void SwapBytes(T &v)
It swaps the bytes in local.