root/trunk/clustr/shapefile.cpp

Revision 617, 5.5 kB (checked in by aaron, 8 months ago)

update to 0.21: patch from mattb to make multi-tags files work

Line 
1 /*
2 Clustr.  Copyright (c) 2007-2009 Yahoo! Inc.
3
4 All rights reserved.  This code is free software; you can redistribute it
5 and/or modify it under the terms of the GNU General Public License (GPL),
6 version 2 only.  This code is distributed WITHOUT ANY WARRANTY, whether
7 express or implied. See the GNU GPL for more details
8 (http://www.gnu.org/licenses/gpl.html)
9
10 AS A SPECIAL EXCEPTION, YOU HAVE PERMISSION TO LINK THIS PROGRAM WITH THE
11 CGAL LIBRARY AND DISTRIBUTE EXECUTABLES, AS LONG AS YOU FOLLOW THE REQUIREMENTS
12 OF THE GNU GPL VERSION 2 IN REGARD TO ALL OF THE SOFTWARE IN THE EXECUTABLE
13 ASIDE FROM CGAL.
14 */
15
16 #include "shapefile.h"
17 #include <algorithm>
18 #include <iterator>
19 #include <vector>
20 #include <stdexcept>
21 #include <stdlib.h>
22 #include <cassert>
23
24 using namespace std;
25
26 namespace Clustr {
27     Shapefile::Shapefile (string const filename, GeometryType layer_type, bool append)
28     {
29         name = filename.substr(0, filename.find_last_of('.'));
30         geom_type = layer_type;
31         layer = NULL;
32
33         OGRRegisterAll();
34         driver = OGRGetDriverByName(driver_name.c_str());
35         if( driver == NULL ) {
36             throw runtime_error( driver_name + " driver not available." );
37         }
38
39         ds = OGR_Dr_Open(driver, filename.c_str(), NULL);
40         if (ds != NULL && !append) {
41             OGR_DS_Destroy(ds);
42             unlink(filename.c_str());
43         }
44         if (ds == NULL || !append) {
45             ds = OGR_Dr_CreateDataSource(driver, filename.c_str(), NULL);
46             if( ds == NULL ) {
47                 throw runtime_error(filename + " datasource creation failed.");
48             }
49         }
50
51         layer = OGR_DS_GetLayer(ds, 0);
52         if (layer != NULL && !append) {
53             if (OGR_DS_DeleteLayer(ds, 0) != OGRERR_NONE) {
54                 throw runtime_error(filename + " existing layer can't be deleted.");
55             }
56         }
57         if (layer == NULL) {
58             layer = OGR_DS_CreateLayer(ds, name.c_str(), NULL, layer_type, NULL);
59             if( layer == NULL ) {
60                 throw runtime_error(filename + " layer creation failed.");
61             }
62         }
63     }
64
65     void Shapefile::add_field (const char *field_name, OGRFieldType type, int width, int precision) {
66         OGRFieldDefnH fld = OGR_Fld_Create(field_name, type);
67         OGR_Fld_SetWidth(fld, width);
68         OGR_Fld_SetPrecision(fld, precision);
69         if( OGR_L_CreateField( layer, fld, 1 ) != OGRERR_NONE ) {
70             throw runtime_error(name + " field creation failed.");
71         }
72         OGR_Fld_Destroy(fld);
73     }
74
75     void Shapefile::add_feature (const Feature &feature) {
76         if( OGR_L_CreateFeature( layer, feature.handle() ) != OGRERR_NONE ) {
77             throw runtime_error(name + " feature creation failed.");
78         }
79     }
80
81     Feature::Feature (const Shapefile &shape) {
82         geom_type = shape.geometry_type();
83         defn = shape.definition();
84         feat = OGR_F_Create(defn);
85     }
86
87     int Feature::index (const char *name) {
88         int i = OGR_FD_GetFieldIndex(defn, name);
89         if (i == -1) {
90             throw runtime_error(string(name) + " field not found on feature.");
91         }
92         return i;
93     }
94
95     void Feature::set (const Geometry &geom) {
96         assert(geom.geometry_type() == geom_type);
97         if (OGR_F_SetGeometry(feat, geom.handle()) != OGRERR_NONE) {
98             throw runtime_error("Couldn't set geometry on feature.");
99         }
100     }
101
102     void Feature::set (const char *name, const char *val) {
103         OGR_F_SetFieldString(feat, index(name), val);
104     }
105
106     void Feature::set (const char *name, long int val) {
107         OGR_F_SetFieldInteger(feat, index(name), val);
108     }
109
110     void Feature::set (const char *name, double val) {
111         OGR_F_SetFieldDouble(feat, index(name), val);
112     }
113
114     Geometry::Geometry(GeometryType geom_type) : geom_type(geom_type) {
115         outer = inner = OGR_G_CreateGeometry(geom_type);
116         if (geom_type == wkbPolygon) add_ring();
117     }
118
119     void Geometry::add_ring (void) {
120         assert(geom_type == wkbPolygon);
121         OGRGeometryH ring = OGR_G_CreateGeometry(wkbLinearRing);
122         if (OGR_G_AddGeometryDirectly(outer, ring) != OGRERR_NONE) {
123             throw runtime_error("Couldn't add ring to polygon");
124         }
125         inner = ring;
126     }
127
128     void Geometry::push_back (double x, double y) {
129         OGR_G_AddPoint_2D(inner, x, y);
130     }
131    
132     void Geometry::push_back (const Point& pt) {
133         OGR_G_AddPoint_2D(inner, pt.x(), pt.y());
134     }
135
136     template <typename Iterator>
137     void Geometry::insert (Iterator begin, Iterator end) {
138         for (Iterator it = begin; it != end; it++) {
139             push_back(*it);
140         }
141         if (geom_type == wkbPolygon || geom_type == wkbMultiPolygon) {
142             push_back(*begin);
143         }
144     }
145
146     /* necessary to keep the linker from blowing up */
147     template void Geometry::insert<Ring::iterator>(Ring::iterator, Ring::iterator);
148
149     void Geometry::insert_rings (Polygon::iterator begin,  Polygon::iterator end) {
150         assert(geom_type == wkbPolygon);
151         for (Polygon::iterator it = begin; it != end; it++) {
152             if (it != begin) add_ring();
153             insert(it->begin(), it->end());
154         }
155     }
156
157     void MultiGeometry::push_back (const Geometry& geom) {
158         if (OGR_G_AddGeometry(outer, geom.handle()) != OGRERR_NONE) {
159             throw runtime_error("Couldn't add geometry to multigeometry");
160         }
161     }
162
163     void MultiGeometry::insert (Polygon::iterator begin, Polygon::iterator end) {
164         Geometry geom(wkbPolygon);
165         geom.insert_rings(begin, end);
166         push_back(geom);
167     }
168 }
169
Note: See TracBrowser for help on using the browser.