75 std::string layerName,
79 std::string tempFolder,
87 std::string rastProj = p_raster->
getDataset()->GetProjectionRef();
88 OGRSpatialReference rastSRS;
89 rastSRS.importFromWkt(rastProj.c_str());
90 OGRLayer *p_inputLayer = p_vector->
getLayer(layerName.c_str());
91 const OGRSpatialReference *p_vectSRS = p_inputLayer->GetSpatialRef();
92 if (!rastSRS.IsSame(p_vectSRS)) {
93 throw std::runtime_error(
"access vector and raster do not have the same spatial reference system.");
97 OGRMultiPolygon *buffInnerPolygons =
new OGRMultiPolygon;
98 OGRMultiPolygon *buffOuterPolygons =
new OGRMultiPolygon;
99 OGRGeometry *p_polygonMask;
106 buffOuter = buffOuter - pixelSize / 50;
107 buffInner = buffInner == 0 ? 0 : buffInner + pixelSize / 50;
110 for (
const auto& p_feature : *p_vector->
getLayer(layerName.c_str())) {
111 OGRGeometry *p_geometry = p_feature->GetGeometryRef();
113 throw std::runtime_error(std::format(
"an invalid geometry was encountered in the {} layer.", layerName));
116 OGRwkbGeometryType type = wkbFlatten(p_geometry->getGeometryType());
119 case OGRwkbGeometryType::wkbLineString: {
120 OGRGeometry *p_outer = p_geometry->Buffer(buffOuter);
121 buffOuterPolygons->addGeometry(p_outer);
122 OGRGeometryFactory::destroyGeometry(p_outer);
124 if (buffInner != 0) {
125 OGRGeometry *p_inner = p_geometry->Buffer(buffInner);
126 buffInnerPolygons->addGeometry(p_inner);
127 OGRGeometryFactory::destroyGeometry(p_inner);
131 case OGRwkbGeometryType::wkbMultiLineString: {
132 for (
const auto& p_lineString : *p_geometry->toMultiLineString()) {
133 OGRGeometry *p_outer = p_lineString->Buffer(buffOuter);
134 buffOuterPolygons->addGeometry(p_outer);
135 OGRGeometryFactory::destroyGeometry(p_outer);
137 if (buffInner != 0) {
138 OGRGeometry *p_inner = p_lineString->Buffer(buffInner);
139 buffInnerPolygons->addGeometry(p_inner);
140 OGRGeometryFactory::destroyGeometry(p_inner);
147 throw std::runtime_error(
"geometry type must be LineString or MultiLineString");
153 if (buffInner == 0) {
154 p_polygonMask = buffOuterPolygons->UnionCascaded();
157 OGRGeometry *buffOuterUnion = buffOuterPolygons->UnionCascaded();
158 OGRGeometry *buffInnerUnion = buffInnerPolygons->UnionCascaded();
159 p_polygonMask = buffOuterUnion->Difference(buffInnerUnion);
160 OGRGeometryFactory::destroyGeometry(buffOuterUnion);
161 OGRGeometryFactory::destroyGeometry(buffInnerUnion);
163 delete buffOuterPolygons;
164 delete buffInnerPolygons;
169 OGRGeometry *p_polygonWithinExtent;
170 OGRwkbGeometryType geomtype = p_polygonMask->getGeometryType();
171 if (geomtype == wkbPolygon) {
172 p_polygonWithinExtent = p_polygonMask->toPolygon()->Intersection(&extent);
174 else if (geomtype == wkbMultiPolygon) {
175 p_polygonWithinExtent = p_polygonMask->toMultiPolygon()->Intersection(&extent);
178 throw std::runtime_error(
"p_polygonMask is not a polygon or a multipolygon!");
181 geomtype = p_polygonWithinExtent->getGeometryType();
182 if (geomtype == wkbPolygon) {
183 this->area += p_polygonWithinExtent->toPolygon()->toUpperClass()->get_Area();
185 else if (geomtype == wkbMultiPolygon) {
186 for (
const auto& p_polygon : *p_polygonWithinExtent->toMultiPolygon()) {
187 this->area += p_polygon->toUpperClass()->get_Area();
191 throw std::runtime_error(
"taking the intersection of polygons somehow resulted in something not a polygon! This is a bug.");
195 OGRGeometry *p_invertedMask = extent.Difference(p_polygonMask);
198 GDALDataset *p_accessPolygonDataset = GetGDALDriverManager()->GetDriverByName(
"MEM")->Create(
207 OGRLayer *p_layer = p_accessPolygonDataset->CreateLayer(
209 p_vector->
getLayer(layerName.c_str())->GetSpatialRef(),
210 p_invertedMask->getGeometryType(),
213 OGRFieldDefn field(
"index", OFTInteger);
214 p_layer->CreateField(&field);
217 OGRFeature *p_feature = OGRFeature::CreateFeature(p_layer->GetLayerDefn());
218 p_feature->SetField(
"index", 0);
219 p_feature->SetGeometry(p_invertedMask);
220 p_layer->CreateFeature(p_feature);
221 OGRFeature::DestroyFeature(p_feature);
223 std::filesystem::path path = tempFolder;
224 path = path /
"access.tif";
227 char **argv =
nullptr;
230 argv = CSLAddString(argv,
"-at");
233 argv = CSLAddString(argv,
"-burn");
234 argv = CSLAddString(argv, std::to_string(1).c_str());
237 argv = CSLAddString(argv,
"-l");
238 argv = CSLAddString(argv,
"access");
241 argv = CSLAddString(argv,
"-te");
242 argv = CSLAddString(argv, std::to_string(p_raster->
getXMin()).c_str());
243 argv = CSLAddString(argv, std::to_string(p_raster->
getYMin()).c_str());
244 argv = CSLAddString(argv, std::to_string(p_raster->
getXMax()).c_str());
245 argv = CSLAddString(argv, std::to_string(p_raster->
getYMax()).c_str());
248 argv = CSLAddString(argv,
"-ts");
249 argv = CSLAddString(argv, std::to_string(p_raster->
getWidth()).c_str());
250 argv = CSLAddString(argv, std::to_string(p_raster->
getHeight()).c_str());
253 argv = CSLAddString(argv,
"-ot");
254 argv = CSLAddString(argv,
"Int8");
256 GDALRasterizeOptions *options = GDALRasterizeOptionsNew(argv,
nullptr);
259 this->p_dataset = GDALDataset::FromHandle(GDALRasterize(
260 path.string().c_str(),
262 p_accessPolygonDataset,
267 this->band.
p_band = this->p_dataset->GetRasterBand(1);
268 this->band.
type = GDT_Int8;
269 this->band.
size =
sizeof(int8_t);
270 this->band.
p_band->GetBlockSize(&this->band.
xBlockSize, &this->band.yBlockSize);
273 GDALRasterizeOptionsFree(options);
275 GDALClose(GDALDataset::ToHandle(p_accessPolygonDataset));
276 OGRGeometryFactory::destroyGeometry(p_polygonMask);
277 OGRGeometryFactory::destroyGeometry(p_polygonWithinExtent);
278 OGRGeometryFactory::destroyGeometry(p_invertedMask);