1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
#include "shapefile.h"
namespace shapefile
{
ShapefileHeader::ShapefileHeader(std::istream &stream)
{
uint8_t buffer[100];
stream.read((char *)buffer, 100);
// Little endian
file_code = swap_endian<int32_t>(*((int32_t *)&buffer[0]));
unused1 = swap_endian<int32_t>(*((int32_t *)&buffer[4]));
unused2 = swap_endian<int32_t>(*((int32_t *)&buffer[8]));
unused3 = swap_endian<int32_t>(*((int32_t *)&buffer[12]));
unused4 = swap_endian<int32_t>(*((int32_t *)&buffer[16]));
unused5 = swap_endian<int32_t>(*((int32_t *)&buffer[20]));
file_length = swap_endian<int32_t>(*((int32_t *)&buffer[24])) * 2;
// Big endian
version = *((int32_t *)&buffer[28]);
shape_type = *((int32_t *)&buffer[32]);
bounding_box_xmin = *((double *)&buffer[36]);
bounding_box_ymin = *((double *)&buffer[44]);
bounding_box_xmax = *((double *)&buffer[52]);
bounding_box_ymax = *((double *)&buffer[60]);
bounding_box_zmin = *((double *)&buffer[68]);
bounding_box_zmax = *((double *)&buffer[76]);
bounding_box_mmin = *((double *)&buffer[84]);
bounding_box_mmax = *((double *)&buffer[92]);
}
RecordHeader::RecordHeader(std::istream &stream)
{
uint8_t buffer[12];
stream.read((char *)buffer, 12);
// Little endian
record_number = swap_endian<int32_t>(*((int32_t *)&buffer[0]));
content_length = swap_endian<int32_t>(*((int32_t *)&buffer[4])) * 2 - 4;
// Big endian
shape_type = *((int32_t *)&buffer[8]);
}
NullShapeRecord::NullShapeRecord(std::istream & /*stream*/, RecordHeader &header) : RecordHeader(header)
{
// Empty
}
PointRecord::PointRecord(std::istream &stream, RecordHeader &header) : RecordHeader(header)
{
if (header.content_length != 16)
throw std::runtime_error("Point record should be 16-bytes, but is " + std::to_string(header.content_length) + "!");
uint8_t buffer[16];
stream.read((char *)buffer, 16);
// Big endian
point = *((point_t *)&buffer[0]);
}
MultiPointRecord::MultiPointRecord(std::istream &stream, RecordHeader &header) : RecordHeader(header)
{
uint8_t *buffer = new uint8_t[header.content_length];
stream.read((char *)buffer, header.content_length);
// Big endian
box = *((box_t *)&buffer[0]);
point_number = *((int32_t *)&buffer[32]);
for (int i = 0; i < point_number; i++)
{
point_t p = *((point_t *)&buffer[36 + 8 * (i * 2)]);
points.push_back(p);
}
delete[] buffer;
}
PolyLineRecord::PolyLineRecord(std::istream &stream, RecordHeader &header) : RecordHeader(header)
{
uint8_t *buffer = new uint8_t[header.content_length];
stream.read((char *)buffer, header.content_length);
// Big endian
box = *((box_t *)&buffer[0]);
part_number = *((int32_t *)&buffer[32]);
point_number = *((int32_t *)&buffer[36]);
std::vector<int32_t> parts; // Parse all parts
for (int i = 0; i < part_number; i++)
{
int32_t part = *((int32_t *)&buffer[40 + 4 * i]);
parts.push_back(part);
}
std::vector<point_t> points; // Parse all points
for (int i = 0; i < point_number; i++)
{
point_t p = *((point_t *)&buffer[40 + 4 * part_number + 8 * (i * 2)]);
points.push_back(p);
}
// Now get all points for each part, except the last
for (int pn = 0; pn < part_number - 1; pn++)
{
std::vector<point_t> part_points;
int part_start = parts[pn];
int part_end = parts[pn + 1];
part_points.insert(part_points.end(), &points[part_start], &points[part_end]);
parts_points.push_back(part_points);
}
// And the last
{
std::vector<point_t> part_points;
int part_start = parts[part_number - 1];
part_points.insert(part_points.end(), &points[part_start], &points[points.size() - 1]);
parts_points.push_back(part_points);
}
delete[] buffer;
}
PolygonRecord::PolygonRecord(std::istream &stream, RecordHeader &header) : PolyLineRecord(stream, header)
{
}
Shapefile::Shapefile(std::istream &stream) : header(stream)
{
while (!stream.eof())
{
shapefile::RecordHeader recordHeader(stream);
if (stream.tellg() < 0) // Safety
continue;
if (recordHeader.shape_type == shapefile::Point)
{
shapefile::PointRecord pointRecord(stream, recordHeader);
point_records.push_back(pointRecord);
}
else if (recordHeader.shape_type == shapefile::MultiPoint)
{
shapefile::MultiPointRecord multiPointRecord(stream, recordHeader);
multipoint_records.push_back(multiPointRecord);
}
else if (recordHeader.shape_type == shapefile::PolyLine)
{
shapefile::PolyLineRecord polyLineRecord(stream, recordHeader);
polyline_records.push_back(polyLineRecord);
}
else if (recordHeader.shape_type == shapefile::Polygon)
{
shapefile::PolygonRecord polygonRecord(stream, recordHeader);
polygon_records.push_back(polygonRecord);
}
else
{
uint8_t *buffer = new uint8_t[recordHeader.content_length];
stream.read((char *)buffer, recordHeader.content_length);
delete[] buffer;
}
}
}
}
|