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