Voor wat het waard is, geef ik hier vast een ‘werkende’ op_get_bag.py code. Leg hem gerust naast de oude code, het is een stuk kleiner omdat er minder wordt gebruikt, ik heb wel zoveel mogelijk er in laten staan.
Probleem met deze code is dus dat de huisjes een heeeel eind vanaf de AHN map in Blender worden geladen,… je zult ze er dus zelf heen moeten slepen en dat lukt mij niet (ik ben erg onhandig in Blender)
Dit heeft mogelijk te maken met de diverse Spatial Systems. Wellicht dat de auteur @thomaskole van deze plugin er iets over kan zeggen. Het meeste fix werk is al gedaan, mocht ik nog iets moeten doen, dan hoor ik het graag…
import bpy
import urllib.request
import json
import zipfile
import os
import bmesh
from bpy.types import Operator
from . import utils
from bpy.props import (
StringProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
EnumProperty,
)
tileset = {}
# Functie voor ophalen tiles binnen de basemap-bbox
def get_tiles_in_basemap(error_margin):
get_tileset()
global tileset
bboxes = list()
basemap = utils.get_basemap_obj()
shiftLon = basemap.location.x
shiftLat = basemap.location.y
lon = bpy.context.scene["longitude"]
lat = bpy.context.scene["latitude"]
rd = utils.Rijksdriehoek()
rd.from_wgs(lat, lon)
lon = rd.rd_x + shiftLon
lat = rd.rd_y + shiftLat
sscale = utils.get_scene_scale_m()
error = error_margin
worldRect = [lon - sscale[0]/2 - error, lat - sscale[1]/2 - error, lon + sscale[0]/2 + error, lat + sscale[1]/2 + error]
# Pas de nieuwe structuur aan
for feature in tileset.get('features', []):
bbox = feature["bbox"]
uri = feature["properties"].get("obj_download", "")
if isRectangleOverlap(bbox, worldRect):
bboxes.append([bbox, uri])
return bboxes
# Nieuwe get_tileset functie om de bounding box API aan te roepen
def get_tileset():
global tileset
if tileset:
print("Tileset already cached")
else:
print("Fetching tileset with new bbox API")
# Bounding box ophalen en API-request met bbox
basemap = utils.get_basemap_obj()
lon, lat = bpy.context.scene["longitude"], bpy.context.scene["latitude"]
rd = utils.Rijksdriehoek()
rd.from_wgs(lat, lon)
lon, lat = rd.rd_x + basemap.location.x, rd.rd_y + basemap.location.y
sscale = utils.get_scene_scale_m()
bbox = f"{lon - sscale[0]/2},{lat - sscale[1]/2},{lon + sscale[0]/2},{lat + sscale[1]/2}"
# URL samenstellen voor nieuwe API-oproep
url = f"https://data.3dbag.nl/api/BAG3D/wfs?version=1.1.0&request=GetFeature&typename=BAG3D:Tiles&outputFormat=application/json&srsname=EPSG:28992&bbox={bbox},EPSG:28992"
try:
req = urllib.request.Request(url, None, utils.get_request_header())
handle = urllib.request.urlopen(req, timeout=10)
data = handle.read()
handle.close()
tileset = json.loads(data)
except Exception as e:
print(f"Error fetching tileset: {e}")
tileset = {}
# Functie om overlapping te controleren
def isRectangleOverlap(R1, R2):
return not (R1[0] >= R2[2] or R1[2] <= R2[0] or R1[3] <= R2[1] or R1[1] >= R2[3])
class op_get_bag(Operator):
bl_idname = "gis.get_bag"
bl_label = "Get 3D BAG"
bl_description = "Download 3D buildings to match your existing basemap"
bl_options = {'REGISTER', 'UNDO'}
bag_lod: EnumProperty(
name="Detail",
description="3D BAG in verschillende levels.",
items=(
('lod12', "LOD 1.2 (laag detail)", ""),
('lod13', "LOD 1.3 (medium detail)", ""),
('lod22', "LOD 2.2 (hoog detail)", "")
),
default='lod22',
)
excess_cleanup: EnumProperty(
name="Excess",
description="Hoe te verwerken buiten de basemap-grenzen?",
items=(
('CUT', "Cut away", "Verwijdert buiten basemap-grenzen"),
('INCLUDE', "Inclusief overhang", "Houdt gebouwen die grenzen aan basemap"),
('EXCLUDE', "Exclusief overhang", "Verwijdert gebouwen niet geheel binnen de basemap"),
('NOTHING', "Niets doen", "Behoudt alle tiles")
),
default='CUT',
)
error_margin: FloatProperty(
name="Excess",
description="Gebruik dit om grenzen nauwkeurig aan te passen.",
default=500,
)
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self, width=250)
def draw(self, context):
layout = self.layout
row = layout.row()
if(utils.is_scene_georef()):
row = layout.row()
row.scale_y = 0.6
row.label(text="Get Dutch 3D buildings to", icon='INFO')
row = layout.row()
row.scale_y = 0.6
row.label(text="match your existing basemap")
layout.separator()
layout.row()
layout.row()
row = layout.row()
row.label(text="Download:", icon='URL')
row = layout.row()
row.prop(self, "bag_lod")
row = layout.row()
row.prop(self, "error_margin")
numtiles = len(get_tiles_in_basemap(self.error_margin))
row = layout.row()
row.scale_y = 0.6
row.label(text="Tiles in basemap: " + str(numtiles))
layout.row()
layout.row()
row = layout.row()
row.label(text="Mesh:", icon='MOD_DISPLACE')
row = layout.row()
row.prop(self, "excess_cleanup")
else:
row = layout.row()
row.scale_y = 0.6
row.label(text="Scene has no basemap!", icon='ERROR')
row = layout.row()
row.scale_y = 0.6
row.label(text="use (GIS > Web geodata > Basemap)")
def execute(self, context):
print("\n\n########## BLENDER HOOGTEDATA ADDON ##########\n\n")
utils.ensure_basemap_scale()
bboxes = get_tiles_in_basemap(self.error_margin)
print("Number of tiles in search: " + str(len(bboxes)))
for b in bboxes:
# Gebruik alleen het laatste deel van de URI als id
id = os.path.basename(b[1]).replace("-obj.zip", "")
print(f"\n\nGetting 3D BAG tile: {b[1]}")
try:
req = urllib.request.Request(b[1], None, utils.get_request_header())
handle = urllib.request.urlopen(req, timeout=10)
data = handle.read()
handle.close()
file_path = os.path.join(utils.get_tmp_path(), f"bag3d_{id}.zip")
print(f"Debugging file_path path: {file_path}")
tmpzipfolder = os.path.join(utils.get_tmp_path(), f"bag3d_{id}/")
print(f"Debugging tmpzipfolder path: {tmpzipfolder}")
print(f"utils.get_tmp_path(): {utils.get_tmp_path()}")
# Zorg ervoor dat het tijdelijke pad bestaat
os.makedirs(tmpzipfolder, exist_ok=True)
print(f"Created temporary folder if it didn't exist: {tmpzipfolder}")
with open(file_path, 'wb') as zip_file:
zip_file.write(data)
print(f"Selected LOD: {self.bag_lod}") # Debug de geselecteerde LOD
with zipfile.ZipFile(file_path, 'r') as zip_ref:
zip_ref.extractall(tmpzipfolder)
for obj_file in os.listdir(tmpzipfolder):
print(f"Checking file: {obj_file}") # Debug de bestandsnaam
if str(self.bag_lod.lower()) in obj_file.lower() and obj_file.lower().endswith('obj'):
# Oude Blender 2.x en 3.x methode::
#bpy.ops.import_scene.obj(filepath=os.path.join(tmpzipfolder, obj_file), use_split_objects=False, use_split_groups=False, axis_forward='Y', axis_up='Z')
# Nieuwe Blender 4.x methode:
bpy.ops.wm.obj_import(filepath=os.path.join(tmpzipfolder, obj_file))
except Exception as e:
print(f"Error with tile {id}: {e}")
print("\n\n########## # ##########\n\n")
return {'FINISHED'}