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();
112 OGRwkbGeometryType type = wkbFlatten(p_geometry->getGeometryType());
115 case OGRwkbGeometryType::wkbLineString: {
116 OGRGeometry *p_outer = p_geometry->Buffer(buffOuter);
117 buffOuterPolygons->addGeometry(p_outer);
118 OGRGeometryFactory::destroyGeometry(p_outer);
120 if (buffInner != 0) {
121 OGRGeometry *p_inner = p_geometry->Buffer(buffInner);
122 buffInnerPolygons->addGeometry(p_inner);
123 OGRGeometryFactory::destroyGeometry(p_inner);
127 case OGRwkbGeometryType::wkbMultiLineString: {
128 for (
const auto& p_lineString : *p_geometry->toMultiLineString()) {
129 OGRGeometry *p_outer = p_lineString->Buffer(buffOuter);
130 buffOuterPolygons->addGeometry(p_outer);
131 OGRGeometryFactory::destroyGeometry(p_outer);
133 if (buffInner != 0) {
134 OGRGeometry *p_inner = p_lineString->Buffer(buffInner);
135 buffInnerPolygons->addGeometry(p_inner);
136 OGRGeometryFactory::destroyGeometry(p_inner);
143 throw std::runtime_error(
"geometry type must be LineString or MultiLineString");
149 if (buffInner == 0) {
150 p_polygonMask = buffOuterPolygons->UnionCascaded();
153 OGRGeometry *buffOuterUnion = buffOuterPolygons->UnionCascaded();
154 OGRGeometry *buffInnerUnion = buffInnerPolygons->UnionCascaded();
155 p_polygonMask = buffOuterUnion->Difference(buffInnerUnion);
156 OGRGeometryFactory::destroyGeometry(buffOuterUnion);
157 OGRGeometryFactory::destroyGeometry(buffInnerUnion);
159 delete buffOuterPolygons;
160 delete buffInnerPolygons;
165 OGRGeometry *p_polygonWithinExtent;
166 OGRwkbGeometryType geomtype = p_polygonMask->getGeometryType();
167 if (geomtype == wkbPolygon) {
168 p_polygonWithinExtent = p_polygonMask->toPolygon()->Intersection(&extent);
170 else if (geomtype == wkbMultiPolygon) {
171 p_polygonWithinExtent = p_polygonMask->toMultiPolygon()->Intersection(&extent);
174 throw std::runtime_error(
"p_polygonMask is not a polygon or a multipolygon!");
177 geomtype = p_polygonWithinExtent->getGeometryType();
178 if (geomtype == wkbPolygon) {
179 this->area += p_polygonWithinExtent->toPolygon()->toUpperClass()->get_Area();
181 else if (geomtype == wkbMultiPolygon) {
182 for (
const auto& p_polygon : *p_polygonWithinExtent->toMultiPolygon()) {
183 this->area += p_polygon->toUpperClass()->get_Area();
187 throw std::runtime_error(
"taking the intersection of polygons somehow resulted in something not a polygon! This is a bug.");
191 OGRGeometry *p_invertedMask = extent.Difference(p_polygonMask);
194 GDALDataset *p_accessPolygonDataset = GetGDALDriverManager()->GetDriverByName(
"MEM")->Create(
203 OGRLayer *p_layer = p_accessPolygonDataset->CreateLayer(
205 p_vector->
getLayer(layerName.c_str())->GetSpatialRef(),
206 p_invertedMask->getGeometryType(),
209 OGRFieldDefn field(
"index", OFTInteger);
210 p_layer->CreateField(&field);
213 OGRFeature *p_feature = OGRFeature::CreateFeature(p_layer->GetLayerDefn());
214 p_feature->SetField(
"index", 0);
215 p_feature->SetGeometry(p_invertedMask);
216 p_layer->CreateFeature(p_feature);
217 OGRFeature::DestroyFeature(p_feature);
219 std::filesystem::path path = tempFolder;
220 path = path /
"access.tif";
223 char **argv =
nullptr;
226 argv = CSLAddString(argv,
"-at");
229 argv = CSLAddString(argv,
"-burn");
230 argv = CSLAddString(argv, std::to_string(1).c_str());
233 argv = CSLAddString(argv,
"-l");
234 argv = CSLAddString(argv,
"access");
237 argv = CSLAddString(argv,
"-te");
238 argv = CSLAddString(argv, std::to_string(p_raster->
getXMin()).c_str());
239 argv = CSLAddString(argv, std::to_string(p_raster->
getYMin()).c_str());
240 argv = CSLAddString(argv, std::to_string(p_raster->
getXMax()).c_str());
241 argv = CSLAddString(argv, std::to_string(p_raster->
getYMax()).c_str());
244 argv = CSLAddString(argv,
"-ts");
245 argv = CSLAddString(argv, std::to_string(p_raster->
getWidth()).c_str());
246 argv = CSLAddString(argv, std::to_string(p_raster->
getHeight()).c_str());
249 argv = CSLAddString(argv,
"-ot");
250 argv = CSLAddString(argv,
"Int8");
252 GDALRasterizeOptions *options = GDALRasterizeOptionsNew(argv,
nullptr);
255 this->p_dataset = GDALDataset::FromHandle(GDALRasterize(
256 path.string().c_str(),
258 p_accessPolygonDataset,
263 this->band.
p_band = this->p_dataset->GetRasterBand(1);
264 this->band.
type = GDT_Int8;
265 this->band.
size =
sizeof(int8_t);
266 this->band.
p_band->GetBlockSize(&this->band.
xBlockSize, &this->band.yBlockSize);
269 GDALRasterizeOptionsFree(options);
271 GDALClose(GDALDataset::ToHandle(p_accessPolygonDataset));
272 OGRGeometryFactory::destroyGeometry(p_polygonMask);
273 OGRGeometryFactory::destroyGeometry(p_polygonWithinExtent);
274 OGRGeometryFactory::destroyGeometry(p_invertedMask);