mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
Finish refactor georeference module
This commit is contained in:
@@ -25,14 +25,14 @@ classes = (
|
||||
operator.EditGeoreferencing,
|
||||
operator.SetIfcGridNorth,
|
||||
operator.SetBlenderGridNorth,
|
||||
# operator.SetIfcTrueNorth,
|
||||
# operator.SetBlenderTrueNorth,
|
||||
operator.SetIfcTrueNorth,
|
||||
operator.SetBlenderTrueNorth,
|
||||
operator.RemoveGeoreferencing,
|
||||
operator.AddGeoreferencing,
|
||||
# operator.ConvertLocalToGlobal,
|
||||
# operator.ConvertGlobalToLocal,
|
||||
# operator.GetCursorLocation,
|
||||
# operator.SetCursorLocation,
|
||||
operator.ConvertLocalToGlobal,
|
||||
operator.ConvertGlobalToLocal,
|
||||
operator.GetCursorLocation,
|
||||
operator.SetCursorLocation,
|
||||
prop.BIMGeoreferenceProperties,
|
||||
ui.BIM_PT_gis,
|
||||
ui.BIM_PT_gis_utilities,
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# ############################################################################ #
|
||||
|
||||
import blenderbim.tool as tool
|
||||
|
||||
def refresh():
|
||||
@@ -35,20 +33,6 @@ class GeoreferenceData:
|
||||
"true_north" : cls.true_north(),
|
||||
}
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def is_georeferenced(cls):
|
||||
ifc = tool.Ifc.get()
|
||||
if ifc.schema == "IFC2X3":
|
||||
return
|
||||
|
||||
map_conversions = []
|
||||
for context in ifc.by_type("IfcGeometricRepresentationContext", include_subtypes=False):
|
||||
if not context.HasCoordinateOperation:
|
||||
continue
|
||||
map_conversions.append(context)
|
||||
|
||||
return True if map_conversions else False
|
||||
|
||||
@classmethod
|
||||
def map_conversion(cls):
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
import bpy
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.core.georeference as core
|
||||
import blenderbim.bim.handler
|
||||
|
||||
class AddGeoreferencing(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_georeferencing"
|
||||
@@ -79,10 +78,85 @@ class SetBlenderGridNorth(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.set_blender_grid_north"
|
||||
bl_label = "Set Blender Grid North"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Set Blender grif north"
|
||||
bl_description = "Set Blender grid north"
|
||||
|
||||
def _execute(self, context):
|
||||
core.set_blender_grid_north()
|
||||
|
||||
class GetCursorLocation(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.get_cursor_location"
|
||||
bl_label = "Get Cursor Location"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Insert the current cursor coordinates"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context): #TODO is it right to use the poll method?
|
||||
file = tool.Ifc.get()
|
||||
return file and file.by_type("IfcUnitAssignment")
|
||||
|
||||
def _execute(self, context):
|
||||
core.get_cursor_location(tool.Georeference)
|
||||
|
||||
class SetCursorLocation(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.set_cursor_location"
|
||||
bl_label = "Set Cursor Location"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Set curson location to coordinates"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context): #TODO is it right to use the poll method?
|
||||
file = tool.Ifc.get()
|
||||
props = context.scene.BIMGeoreferenceProperties
|
||||
return file and file.by_type("IfcUnitAssignment") and props.coordinate_output.count(",") == 2
|
||||
|
||||
def _execute(self, context):
|
||||
core.set_cursor_location(tool.Georeference)
|
||||
|
||||
class SetIfcTrueNorth(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.set_ifc_true_north"
|
||||
bl_label = "Set IFC True North"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Set IFC True north"
|
||||
|
||||
def _execute(self, context):
|
||||
core.set_ifc_true_north(tool.Georeference)
|
||||
|
||||
class SetBlenderTrueNorth(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.set_blender_true_north"
|
||||
bl_label = "Set Blender True North"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Set Blender true north"
|
||||
|
||||
def _execute(self, context):
|
||||
core.set_blender_true_north(tool.Georeference)
|
||||
|
||||
class ConvertLocalToGlobal(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.convert_local_to_global"
|
||||
bl_label = "Convert Local To Global"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Convert local coordinate to global coordinate"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
file = tool.Ifc.get()
|
||||
props = context.scene.BIMGeoreferenceProperties
|
||||
return file and props.coordinate_input.count(",") == 2
|
||||
|
||||
def _execute(self, context):
|
||||
core.convert_local_to_global(tool.Georeference)
|
||||
|
||||
class ConvertGlobalToLocal(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.convert_global_to_local"
|
||||
bl_label = "Convert Global To Local"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Convert global coordinate to local coordinate"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
file = tool.Ifc.get()
|
||||
props = context.scene.BIMGeoreferenceProperties
|
||||
return file and file.by_type("IfcUnitAssignment") and props.coordinate_input.count(",") == 2
|
||||
|
||||
def _execute(self, context):
|
||||
core.convert_global_to_local(tool.Georeference)
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
import ifcopenshell.util.geolocation
|
||||
from bpy.types import Panel
|
||||
#from ifcopenshell.api.georeference.data import Data
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.helper import draw_attributes, draw_attribute
|
||||
from blenderbim.bim.module.georeference.data import GeoreferenceData
|
||||
@@ -73,8 +72,8 @@ class BIM_PT_gis(Panel):
|
||||
row.prop(props, "true_north_ordinate")
|
||||
if hasattr(context.scene, "sun_pos_properties"):
|
||||
row = self.layout.row(align=True)
|
||||
# row.operator("bim.set_ifc_true_north", text="Set IFC North")
|
||||
# row.operator("bim.set_blender_true_north", text="Set Blender North")
|
||||
row.operator("bim.set_ifc_true_north", text="Set IFC North")
|
||||
row.operator("bim.set_blender_true_north", text="Set Blender North")
|
||||
|
||||
|
||||
def draw_ui(self, context):
|
||||
@@ -83,7 +82,7 @@ class BIM_PT_gis(Panel):
|
||||
if not GeoreferenceData.data["projected_crs"]:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Not Georeferenced")
|
||||
if IfcStore.get_file().schema != "IFC2X3":
|
||||
if IfcStore.get_file().schema != "IFC2X3": #TODO Is it correct to use IfcStore.get_file() or is it better tool.Ifc.get()?
|
||||
row.operator("bim.add_georeferencing", icon="ADD", text="")
|
||||
|
||||
if props.has_blender_offset:
|
||||
@@ -179,16 +178,19 @@ class BIM_PT_gis_utilities(Panel):
|
||||
bl_category = "BlenderBIM"
|
||||
|
||||
def draw(self, context):
|
||||
if not GeoreferenceData.is_loaded:
|
||||
GeoreferenceData.load()
|
||||
|
||||
props = context.scene.BIMGeoreferenceProperties
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(props, "coordinate_input", text="Input")
|
||||
#row.operator("bim.get_cursor_location", text="", icon="TRACKER")
|
||||
row.operator("bim.get_cursor_location", text="", icon="TRACKER")
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(props, "coordinate_output", text="Output")
|
||||
#row.operator("bim.set_cursor_location", text="", icon="TRACKER")
|
||||
row.operator("bim.set_cursor_location", text="", icon="TRACKER")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
#row.operator("bim.convert_local_to_global", text="Local to Global")
|
||||
#row.operator("bim.convert_global_to_local", text="Global to Local")
|
||||
row.operator("bim.convert_local_to_global", text="Local to Global")
|
||||
row.operator("bim.convert_global_to_local", text="Global to Local")
|
||||
|
||||
|
||||
@@ -18,71 +18,60 @@
|
||||
|
||||
import bpy
|
||||
import blenderbim.bim.helper
|
||||
import ifcopenshell
|
||||
|
||||
from blenderbim.bim.module.georeference.data import GeoreferenceData
|
||||
|
||||
from math import radians, degrees, atan, tan, cos, sin
|
||||
|
||||
def add_georeferencing(ifc):
|
||||
ifc.run("georeference.add_georeferencing")
|
||||
|
||||
def enable_editing_georeferencing(georeference): #TODO simplify this function
|
||||
def enable_editing_georeferencing(georeference):
|
||||
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||
|
||||
georeference.clear_projected_crs()
|
||||
|
||||
blenderbim.bim.helper.import_attributes(
|
||||
"IfcProjectedCRS",
|
||||
bpy.context.scene.BIMGeoreferenceProperties.projected_crs,
|
||||
props.projected_crs,
|
||||
GeoreferenceData.data["projected_crs"],
|
||||
georeference.import_projected_crs_attributes,
|
||||
)
|
||||
|
||||
|
||||
georeference.clear_map_conversion()
|
||||
|
||||
|
||||
blenderbim.bim.helper.import_attributes(
|
||||
"IfcMapConversion",
|
||||
bpy.context.scene.BIMGeoreferenceProperties.map_conversion,
|
||||
props.map_conversion,
|
||||
GeoreferenceData.data["map_conversion"],
|
||||
georeference.import_map_conversion_attributes,
|
||||
)
|
||||
|
||||
bpy.context.scene.BIMGeoreferenceProperties.has_true_north = bool(GeoreferenceData.data["true_north"])
|
||||
|
||||
if GeoreferenceData.data["true_north"]:
|
||||
bpy.context.scene.BIMGeoreferenceProperties.true_north_abscissa = str(GeoreferenceData.data["true_north"][0])
|
||||
bpy.context.scene.BIMGeoreferenceProperties.true_north_ordinate = str(GeoreferenceData.data["true_north"][1])
|
||||
|
||||
bpy.context.scene.BIMGeoreferenceProperties.is_editing = True
|
||||
georeference.set_has_true_north_prop(GeoreferenceData.data["true_north"])
|
||||
georeference.set_true_north_prop(GeoreferenceData.data["true_north"])
|
||||
georeference.enable_editing()
|
||||
|
||||
def remove_georeferencing(ifc):
|
||||
ifc.run("georeference.remove_georeferencing")
|
||||
|
||||
def edit_georeferencing(ifc, georeference):
|
||||
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||
ifc_file = georeference.get_file()
|
||||
|
||||
projected_crs = blenderbim.bim.helper.export_attributes(props.projected_crs, georeference.export_crs_attributes)
|
||||
map_conversion = blenderbim.bim.helper.export_attributes(props.map_conversion, georeference.export_map_attributes)
|
||||
|
||||
true_north = None
|
||||
# if props.has_true_north:
|
||||
# try:
|
||||
# true_north = [float(props.true_north_abscissa), float(props.true_north_ordinate)]
|
||||
# except ValueError:
|
||||
# self.report({"ERROR"}, "True North Abscissa and Ordinate expect a number")
|
||||
|
||||
ifcopenshell.api.run( #TODO use ifc.run
|
||||
|
||||
true_north = georeference.get_true_north_props(props)
|
||||
|
||||
ifc.run(
|
||||
"georeference.edit_georeferencing",
|
||||
ifc_file,
|
||||
**{
|
||||
"map_conversion": map_conversion,
|
||||
"projected_crs": projected_crs,
|
||||
"true_north": true_north,
|
||||
}
|
||||
)
|
||||
|
||||
bpy.ops.bim.disable_editing_georeferencing()
|
||||
|
||||
def disable_editing_georeferencing(georeference):
|
||||
georeference.set_false_is_editing()
|
||||
|
||||
georeference.disable_editing()
|
||||
|
||||
def set_ifc_grid_north(georeference):
|
||||
georeference.set_ifc_grid_north()
|
||||
@@ -90,4 +79,21 @@ def set_ifc_grid_north(georeference):
|
||||
def set_blender_grid_north(georeference):
|
||||
georeference.set_blender_grid_north()
|
||||
|
||||
def get_cursor_location(georeference):
|
||||
georeference.get_cursor_location()
|
||||
|
||||
def set_cursor_location(georeference):
|
||||
georeference.set_cursor_location()
|
||||
|
||||
def set_ifc_true_north(georeference):
|
||||
georeference.set_ifc_true_north()
|
||||
|
||||
def set_blender_true_north(georeference):
|
||||
georeference.set_blender_true_north()
|
||||
|
||||
def convert_local_to_global(georeference):
|
||||
georeference.convert_local_to_global(GeoreferenceData.data["map_conversion"])
|
||||
|
||||
def convert_global_to_local(georeference):
|
||||
georeference.convert_global_to_local(GeoreferenceData.data["map_conversion"])
|
||||
|
||||
|
||||
@@ -250,15 +250,24 @@ class Geometry:
|
||||
class Georeference:
|
||||
def clear_projected_crs(cls): pass
|
||||
def clear_map_conversion(cls): pass
|
||||
def set_has_true_north_prop(cls, data): pass
|
||||
def set_true_north_prop(cls, data): pass
|
||||
def get_true_north_props(cls, props): pass
|
||||
def enable_editing(cls): pass
|
||||
def disable_editing(cls): pass
|
||||
def get_file(cls): pass
|
||||
def set_false_is_editing(cls): pass
|
||||
def import_projected_crs_attributes(cls, name, prop, data): pass
|
||||
def import_map_conversion_attributes(cls, name, prop, data): pass
|
||||
def export_crs_attributes(cls, attributes, prop): pass
|
||||
def export_map_attributes(cls, attributes, prop): pass
|
||||
def set_ifc_grid_north(cls): pass
|
||||
def set_blender_grid_north(cls): pass
|
||||
|
||||
def get_cursor_location(cls): pass
|
||||
def set_cursor_location(cls): pass
|
||||
def set_ifc_true_north(cls): pass
|
||||
def set_blender_true_north(cls): pass
|
||||
def convert_local_to_global(cls, map_conversion): pass
|
||||
def convert_global_to_local(cls, map_conversion): pass
|
||||
|
||||
@interface
|
||||
class Ifc:
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
|
||||
import bpy
|
||||
import json
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.tool as tool
|
||||
import ifcopenshell
|
||||
import blenderbim.bim.helper
|
||||
|
||||
from ifcopenshell.api.unit.data import Data as UnitData
|
||||
|
||||
@@ -35,6 +37,34 @@ class Georeference(blenderbim.core.tool.Georeference):
|
||||
def clear_map_conversion(cls):
|
||||
bpy.context.scene.BIMGeoreferenceProperties.map_conversion.clear()
|
||||
|
||||
@classmethod
|
||||
def set_has_true_north_prop(cls, data):
|
||||
bpy.context.scene.BIMGeoreferenceProperties.has_true_north = bool(data)
|
||||
|
||||
@classmethod
|
||||
def set_true_north_prop(cls, data):
|
||||
if data:
|
||||
bpy.context.scene.BIMGeoreferenceProperties.true_north_abscissa = str(data[0])
|
||||
bpy.context.scene.BIMGeoreferenceProperties.true_north_ordinate = str(data[1])
|
||||
|
||||
@classmethod
|
||||
def get_true_north_props(cls, props):
|
||||
true_north = None
|
||||
if props.has_true_north:
|
||||
try:
|
||||
true_north = [float(props.true_north_abscissa), float(props.true_north_ordinate)]
|
||||
except ValueError:
|
||||
self.report({"ERROR"}, "True North Abscissa and Ordinate expect a number") #TODO use the correct report method
|
||||
return true_north
|
||||
|
||||
@classmethod
|
||||
def enable_editing(cls):
|
||||
bpy.context.scene.BIMGeoreferenceProperties.is_editing = True
|
||||
|
||||
@classmethod
|
||||
def disable_editing(cls):
|
||||
bpy.context.scene.BIMGeoreferenceProperties.is_editing = False
|
||||
|
||||
@classmethod
|
||||
def get_file(cls):
|
||||
return tool.Ifc.get()
|
||||
@@ -63,7 +93,7 @@ class Georeference(blenderbim.core.tool.Georeference):
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def export_crs_attributes(cls, attributes, prop,):
|
||||
def export_crs_attributes(cls, attributes, prop):
|
||||
ifc_file = tool.Ifc.get()
|
||||
if not prop.is_null and prop.name == "MapUnit":
|
||||
attributes[prop.name] = ifc_file.by_id(int(prop.enum_value))
|
||||
@@ -76,11 +106,6 @@ class Georeference(blenderbim.core.tool.Georeference):
|
||||
attributes[prop.name] = float(prop.string_value)
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def set_false_is_editing(cls):
|
||||
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||
props.is_editing = False
|
||||
|
||||
@classmethod
|
||||
def set_ifc_grid_north(cls):
|
||||
x_angle = -bpy.context.scene.sun_pos_properties.north_offset
|
||||
@@ -96,4 +121,111 @@ class Georeference(blenderbim.core.tool.Georeference):
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_cursor_location(cls):
|
||||
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||
scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
project_coordinates = [o / scale for o in bpy.context.scene.cursor.location]
|
||||
props.coordinate_input = ",".join([str(o) for o in project_coordinates])
|
||||
|
||||
|
||||
@classmethod
|
||||
def set_cursor_location(cls):
|
||||
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||
scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
bpy.context.scene.cursor.location = [float(co) * scale for co in props.coordinate_output.split(",")]
|
||||
|
||||
@classmethod
|
||||
def set_ifc_true_north(cls):
|
||||
y_angle = -bpy.context.scene.sun_pos_properties.north_offset + radians(90)
|
||||
bpy.context.scene.BIMGeoreferenceProperties.true_north_abscissa = str(cos(y_angle))
|
||||
bpy.context.scene.BIMGeoreferenceProperties.true_north_ordinate = str(sin(y_angle))
|
||||
|
||||
@classmethod
|
||||
def set_blender_true_north(cls):
|
||||
bpy.context.scene.sun_pos_properties.north_offset = -radians(
|
||||
ifcopenshell.util.geolocation.yaxis2angle(
|
||||
float(context.scene.BIMGeoreferenceProperties.true_north_abscissa),
|
||||
float(context.scene.BIMGeoreferenceProperties.true_north_ordinate),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@classmethod
|
||||
def convert_local_to_global(cls, map_conversion):
|
||||
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||
x, y, z = [float(co) for co in props.coordinate_input.split(",")]
|
||||
|
||||
if props.has_blender_offset:
|
||||
results = ifcopenshell.util.geolocation.xyz2enh(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
float(props.blender_eastings),
|
||||
float(props.blender_northings),
|
||||
float(props.blender_orthogonal_height),
|
||||
float(props.blender_x_axis_abscissa),
|
||||
float(props.blender_x_axis_ordinate),
|
||||
1.0,
|
||||
)
|
||||
x, y, z = results
|
||||
|
||||
# TODO: what if the project CRS units and the project units are different?
|
||||
|
||||
if map_conversion:
|
||||
results = ifcopenshell.util.geolocation.xyz2enh(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
map_conversion["Eastings"],
|
||||
map_conversion["Northings"],
|
||||
map_conversion["OrthogonalHeight"],
|
||||
map_conversion.get("XAxisAbscissa", 1.0),
|
||||
map_conversion.get("XAxisOrdinate", 0.0),
|
||||
map_conversion.get("Scale", 1.0),
|
||||
)
|
||||
else:
|
||||
results = (x, y, z)
|
||||
|
||||
props.coordinate_output = ",".join([str(r) for r in results])
|
||||
bpy.context.scene.cursor.location = results
|
||||
|
||||
@classmethod
|
||||
def convert_global_to_local(cls, map_conversion):
|
||||
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||
|
||||
x, y, z = [float(co) for co in props.coordinate_input.split(",")]
|
||||
|
||||
if map_conversion:
|
||||
results = ifcopenshell.util.geolocation.enh2xyz(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
map_conversion["Eastings"],
|
||||
map_conversion["Northings"],
|
||||
map_conversion["OrthogonalHeight"],
|
||||
map_conversion.get("XAxisAbscissa", 1.0),
|
||||
map_conversion.get("XAxisOrdinate", 0.0),
|
||||
map_conversion.get("Scale", 1.0),
|
||||
)
|
||||
else:
|
||||
results = (x, y, z)
|
||||
|
||||
if props.has_blender_offset:
|
||||
results = ifcopenshell.util.geolocation.enh2xyz(
|
||||
results[0],
|
||||
results[1],
|
||||
results[2],
|
||||
float(props.blender_eastings),
|
||||
float(props.blender_northings),
|
||||
float(props.blender_orthogonal_height),
|
||||
float(props.blender_x_axis_abscissa),
|
||||
float(props.blender_x_axis_ordinate),
|
||||
1.0,
|
||||
)
|
||||
|
||||
props.coordinate_output = ",".join([str(r) for r in results])
|
||||
|
||||
scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
bpy.context.scene.cursor.location = [o * scale for o in results]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user