• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 //
3 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
4 //
5 // Use, modification and distribution is subject to the Boost Software License,
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 // Boost.Geometry (aka GGL, Generic Geometry Library)
9 // SOCI example
10 
11 // c: using WKB to retrieve geometries
12 
13 // SOCI is a generic C++ template interface to access relational databases
14 
15 // To build and run this example, see comments in example a
16 // Alternatively compile composing and executing compiler command directoy in examples directory,
17 //    for example using GCC compiler:
18 //    g++ -I../../../boost -I/home/mloskot/usr/include/soci \
19 //        -I /home/mloskot/usr/include/soci/postgresql -I/usr/include/postgresql \
20 //        -L/home/mloskot/usr/lib -lsoci_core-gcc-3_0 -lsoci_postgresql-gcc-3_0 x03_c_soci_example.cpp
21 
22 #include <soci.h>
23 #include <soci-postgresql.h>
24 
25 #include <exception>
26 #include <iostream>
27 #include <iterator>
28 #include <string>
29 #include <vector>
30 
31 #include <boost/geometry/geometry.hpp>
32 #include <boost/geometry/geometries/geometries.hpp>
33 #include <boost/geometry/extensions/gis/io/wkb/read_wkb.hpp>
34 #include <boost/geometry/extensions/gis/io/wkb/utility.hpp>
35 #include <boost/geometry/io/wkt/wkt.hpp>
36 
37 // user-defined type with GGL geometry
38 struct tree
39 {
40     int id;
41     boost::geometry::model::point<float, 2, boost::geometry::cs::geographic<boost::geometry::degree> > location;
42 };
43 
44 // conversion of row of result to user-defined type - performs WKB parsing
45 namespace soci
46 {
47     template <>
48     struct type_conversion<tree>
49     {
50         typedef soci::values base_type;
51 
from_basesoci::type_conversion52         static void from_base(base_type const& v, soci::indicator ind, tree& value)
53         {
54             try
55             {
56                 value.id = v.get<int>("id");
57 
58                 // intermediate step: hex-encoded binary string to raw WKB
59                 std::string const& hex = v.get<std::string>("wkb");
60                 std::vector<unsigned char> wkb;
61                 if (!boost::geometry::hex2wkb(hex, std::back_inserter(wkb)))
62                     throw std::runtime_error("hex2wkb translation failed");
63 
64                 // parse WKB and construct point geometry
65                 if (!boost::geometry::read_wkb(wkb.begin(), wkb.end(), value.location))
66                     throw std::runtime_error("read_wkb failed");
67             }
68             catch(const std::exception& e)
69             {
70                 std::cout << e.what() << std::endl;
71             }
72         }
73 
to_basesoci::type_conversion74         static void to_base(tree const& value, base_type& v, soci::indicator& ind)
75         {
76             throw std::runtime_error("todo: wkb writer not yet implemented");
77         }
78     };
79 }
80 
main()81 int main()
82 {
83     try
84     {
85         // establish database connection
86         soci::session sql(soci::postgresql, "dbname=ggl user=ggl password=ggl");
87 
88         // construct schema of table for trees (point geometries)
89         sql << "DELETE FROM geometry_columns WHERE f_table_name = 'trees'";
90         sql << "DROP TABLE IF EXISTS trees CASCADE";
91         sql << "CREATE TABLE trees (id INTEGER)";
92         sql << "SELECT AddGeometryColumn('trees', 'geom', -1, 'POINT', 2)";
93 
94         // insert sample data using plain WKT input
95         sql << "INSERT INTO trees VALUES(1, ST_GeomFromText('POINT(1.23 2.34)', -1))";
96         sql << "INSERT INTO trees VALUES(2, ST_GeomFromText('POINT(3.45 4.56)', -1))";
97         sql << "INSERT INTO trees VALUES(3, ST_GeomFromText('POINT(5.67 6.78)', -1))";
98         sql << "INSERT INTO trees VALUES(4, ST_GeomFromText('POINT(7.89 9.01)', -1))";
99 
100         // query data in WKB form and read to geometry object
101         typedef std::vector<tree> trees_t;
102         soci::rowset<tree> rows = (sql.prepare << "SELECT id, encode(ST_AsBinary(geom), 'hex') AS wkb FROM trees");
103         trees_t trees;
104         std::copy(rows.begin(), rows.end(), std::back_inserter(trees));
105 
106         // print trees output
107         for (trees_t::const_iterator it = trees.begin(); it != trees.end(); ++it)
108         {
109             std::cout << "Tree #" << it->id << " located at\t" << boost::geometry::wkt(it->location) << std::endl;
110         }
111     }
112     catch (std::exception const &e)
113     {
114         std::cerr << "Error: " << e.what() << '\n';
115     }
116     return 0;
117 }
118 
119