TECA
The Toolkit for Extreme Climate Analysis
teca_shape_file_util.h
Go to the documentation of this file.
1 #ifndef teca_shape_file_util_h
2 #define teca_shape_file_util_h
3 
4 #include "teca_binary_stream.h"
5 #include "teca_geometry.h"
6 #include "teca_mpi.h"
7 
8 #include <string>
9 #include <vector>
10 #include <ostream>
11 #include <shapefil.h>
12 
13 /// @file
14 
15 namespace teca_shape_file_util
16 {
17 /// Get a string with the name of the shape type
18 const char *shape_type_name(int shpt);
19 
20 /// Send the shape object to the stream in a human readable form
21 std::ostream &operator<<(std::ostream &os, const SHPObject &obj);
22 
23 /// Read polygons from the given file.
24 template<typename coord_t>
25 int load_polygons(const std::string &filename,
26  std::vector<teca_geometry::polygon<coord_t>> &polys,
27  int verbose = 0)
28 {
29  if (verbose)
30  TECA_STATUS("Opening shape file \"" << filename << "\"")
31 
32  SHPHandle h = SHPOpen(filename.c_str(), "rb");
33  if (h == nullptr)
34  {
35  TECA_ERROR("Failed to open shape file \"" << filename << "\"")
36  return -1;
37  }
38 
39  int n_shapes = 0;
40  int types = 0;
41  double x0[4] = {0.0};
42  double x1[4] = {0.0};
43 
44  SHPGetInfo(h, &n_shapes, &types, x0, x1);
45 
46  if (verbose)
47  TECA_STATUS("Found " << n_shapes << " shapes of type "
48  << shape_type_name(types))
49 
50  if (types != SHPT_POLYGON)
51  {
52  TECA_ERROR("The shapes contained in \"" << filename
53  << "\" are not polygons.")
54  SHPClose(h);
55  return -1;
56  }
57 
58  polys.reserve(n_shapes);
59 
60  for (int i = 0; i < n_shapes; ++i)
61  {
62  if (verbose > 1)
63  std::cerr << "Reading object " << i << " ... " << std::endl;
64 
65  SHPObject *obj = SHPReadObject(h, i);
66  if (obj == nullptr)
67  {
68  TECA_ERROR("Failed to read the " << i << "th polygon")
69  SHPClose(h);
70  return -1;
71  }
72 
73  if (verbose > 1)
74  std::cerr << "Object" << i << " = " << *obj << std::endl;
75 
76  // process each part
77  std::vector<int> starts(obj->panPartStart, obj->panPartStart + obj->nParts);
78  std::vector<int> ends(obj->panPartStart + 1, obj->panPartStart + obj->nParts);
79  ends.push_back(obj->nVertices);
80  for (int j = 0; j < obj->nParts; ++j)
81  {
82  // only process polygons.
83  if (obj->panPartType[j] != SHPT_POLYGON)
84  {
85  TECA_WARNING("Part " << j << " of object " << i << " is "
86  << shape_type_name(obj->panPartType[j])
87  << " but a SHPT_POLYGON is required")
88  continue;
89  }
90 
91  int start = starts[j];
92  int n_verts = ends[j] - start;
93 
94  // make a polygon
96  poly.copy(obj->padfX + start, obj->padfY + start, n_verts);
97  //poly.normalize_coordinates();
98 
99  // add it to the collection
100  polys.push_back(poly);
101  }
102 
103  SHPDestroyObject(obj);
104  }
105 
106  SHPClose(h);
107 
108  return 0;
109 }
110 
111 /** Read polygons from the given file. MPI rank 0 reads and broadcasts to the
112  * other ranks in the job
113  */
114 template<typename coord_t>
115 int load_polygons(MPI_Comm comm, const std::string &filename,
116  std::vector<teca_geometry::polygon<coord_t>> &polys,
117  int verbose = 0)
118 {
119  int rank = 0;
120 #if defined(TECA_HAS_MPI)
121  int is_init = 0;
122  MPI_Initialized(&is_init);
123  if (is_init)
124  {
125  MPI_Comm_rank(comm, &rank);
126  }
127 #endif
128 
130 
131  if (rank == 0)
132  {
133  // read the shape file
134  if (teca_shape_file_util::load_polygons(filename, polys, verbose))
135  {
136  TECA_ERROR("Failed to read polygons from \""
137  << filename << "\"")
138 
139  // returning here would introduce an MPI deadlock
140  }
141 
142  // serialize
143  size_t n_polys = polys.size();
144 
145  bs.pack(n_polys);
146 
147  for (size_t i = 0; i < n_polys; ++i)
148  polys[i].to_stream(bs);
149  }
150 
151  // distribute to all ranks
152  bs.broadcast(comm);
153 
154  if (rank != 0)
155  {
156  // deserialize
157  size_t n_polys = 0;
158  bs.unpack(n_polys);
159 
160  polys.resize(n_polys);
161 
162  for (size_t i = 0; i < n_polys; ++i)
163  polys[i].from_stream(bs);
164  }
165 
166  return 0;
167 }
168 
169 };
170 
171 #endif
teca_binary_stream
Serialize objects into a binary stream.
Definition: teca_binary_stream.h:15
teca_geometry::polygon::copy
void copy(const in_coord_t *in_vx, const in_coord_t *in_vy, unsigned long in_n_verts)
deep copy the vertices of the polygon.
Definition: teca_geometry.h:106
teca_shape_file_util::load_polygons
int load_polygons(const std::string &filename, std::vector< teca_geometry::polygon< coord_t >> &polys, int verbose=0)
Read polygons from the given file.
Definition: teca_shape_file_util.h:25
teca_shape_file_util::shape_type_name
const char * shape_type_name(int shpt)
Get a string with the name of the shape type.
teca_file_util::filename
std::string filename(const std::string &filename)
TECA_STATUS
#define TECA_STATUS(_msg)
Constructs a status message and sends it to the stderr stream.
Definition: teca_common.h:144
teca_geometry.h
teca_shape_file_util::load_polygons
int load_polygons(MPI_Comm comm, const std::string &filename, std::vector< teca_geometry::polygon< coord_t >> &polys, int verbose=0)
Definition: teca_shape_file_util.h:115
TECA_WARNING
#define TECA_WARNING(_msg)
Constructs a warning message and sends it to the stderr stream.
Definition: teca_common.h:141
operator<<
std::ostream & operator<<(std::ostream &os, const teca_calendar_util::time_point &tpt)
send the time_point to a stream in humnan readable form
TECA_ERROR
#define TECA_ERROR(_msg)
Constructs an error message and sends it to the stderr stream.
Definition: teca_common.h:138
teca_geometry::polygon
Definition: teca_geometry.h:71