mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
Add experimental support for gbxml - make importer import spaces, as it is very important for energy modeling
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import bpy
|
||||
import uuid
|
||||
import math
|
||||
import sys
|
||||
#sys.path.append('C:\Program Files\Python37\Lib\site-packages')
|
||||
import bspy
|
||||
from bspy import Gbxml
|
||||
|
||||
class GbxmlExporter():
|
||||
def __init__(self):
|
||||
self.gbxml = Gbxml()
|
||||
self.campus = None
|
||||
|
||||
def export(self):
|
||||
print('# Start export')
|
||||
self.campus = self.gbxml.add_element(self.gbxml.root(), 'Campus')
|
||||
self.campus.set('id', 'campus-1')
|
||||
name = self.gbxml.add_element(self.campus, 'Name', 'My project')
|
||||
|
||||
location = self.gbxml.add_element(self.campus, 'Location')
|
||||
self.gbxml.add_element(location, 'ZipcodeOrPostalCode', 'G20 0SP')
|
||||
self.gbxml.add_element(location, 'Name', 'London/Heathrow')
|
||||
self.gbxml.add_element(location, 'Latitude', '51.480000')
|
||||
self.gbxml.add_element(location, 'Longitude', '-0.450000')
|
||||
self.gbxml.add_element(location, 'Elevation', '24.000000')
|
||||
|
||||
building = self.gbxml.add_element(self.campus, 'Building')
|
||||
building.set('id', str(uuid.uuid4()))
|
||||
building.set('buildingType', 'Office')
|
||||
|
||||
for object in bpy.context.selected_objects:
|
||||
self.create_space(object, building)
|
||||
|
||||
# hardcoded test
|
||||
construction = self.gbxml.add_element(self.gbxml.root(), 'Construction')
|
||||
construction.set('id', 'defaultconstruction')
|
||||
self.gbxml.add_element(construction, 'Name', 'test construction name')
|
||||
u_value = self.gbxml.add_element(construction, 'U-value', '0.42')
|
||||
u_value.set('unit', 'WPerSquareMeterK')
|
||||
layer = self.gbxml.add_element(construction, 'LayerId')
|
||||
layer.set('layerIdRef', 'defaultlayer')
|
||||
|
||||
layer = self.gbxml.add_element(self.gbxml.root(), 'Layer')
|
||||
layer.set('id', 'defaultlayer')
|
||||
material = self.gbxml.add_element(layer, 'MaterialId')
|
||||
material.set('materialIdRef', 'defaultmaterial')
|
||||
|
||||
material = self.gbxml.add_element(self.gbxml.root(), 'Material')
|
||||
material.set('id', 'defaultmaterial')
|
||||
thickness = self.gbxml.add_element(material, 'Thickness', '0.2')
|
||||
thickness.set('unit', 'Meters')
|
||||
self.gbxml.add_element(material, 'Name', 'test material name')
|
||||
r_value = self.gbxml.add_element(material, 'R-value', '0.13')
|
||||
r_value.set('unit', 'SquareMeterKPerW')
|
||||
|
||||
self.gbxml.write('C:/cygwin64/home/moud308/Projects/New Folder/out.xml')
|
||||
print('# Validation results: {}'.format(self.gbxml.validate()))
|
||||
print('# Finish export')
|
||||
|
||||
def create_space(self, object, building):
|
||||
space = self.gbxml.add_element(building, 'Space')
|
||||
space.set('id', object.name)
|
||||
calculated_area = 0
|
||||
|
||||
shell_geometry = self.gbxml.add_element(space, 'ShellGeometry')
|
||||
shell_geometry.set('id', 'shellid')
|
||||
closed_shell = self.gbxml.add_element(shell_geometry, 'ClosedShell')
|
||||
for polygon in object.data.polygons:
|
||||
calculated_area += polygon.area
|
||||
self.create_poly_loop(object, polygon, closed_shell)
|
||||
self.create_space_boundary(object, polygon, space)
|
||||
self.create_surface(object, polygon)
|
||||
self.gbxml.add_element(space, 'Area', str(calculated_area))
|
||||
self.gbxml.add_element(space, 'Volume', str(self.get_volume(object)))
|
||||
|
||||
def create_space_boundary(self, object, polygon, parent):
|
||||
space_boundary = self.gbxml.add_element(parent, 'SpaceBoundary')
|
||||
space_boundary.set('isSecondLevelBoundary', 'true')
|
||||
space_boundary.set('surfaceIdRef', 'surface-{}-{}'.format(object.name, polygon.index))
|
||||
planar_geometry = self.gbxml.add_element(space_boundary, 'PlanarGeometry')
|
||||
self.create_poly_loop(object, polygon, planar_geometry)
|
||||
|
||||
def create_surface(self, object, polygon):
|
||||
surface = self.gbxml.add_element(self.campus, 'Surface')
|
||||
surface.set('id', 'surface-{}-{}'.format(object.name, polygon.index))
|
||||
surface.set('surfaceType', 'ExteriorWall')
|
||||
surface.set('constructionIdRef', 'defaultconstruction')
|
||||
adjacent_space_id = self.gbxml.add_element(surface, 'AdjacentSpaceId')
|
||||
adjacent_space_id.set('spaceIdRef', object.name)
|
||||
rectangular_geometry = self.gbxml.add_element(surface, 'RectangularGeometry')
|
||||
self.gbxml.add_element(
|
||||
rectangular_geometry, 'Azimuth',
|
||||
str(math.degrees(math.atan2(polygon.normal[0], polygon.normal[1]))))
|
||||
self.gbxml.add_element(
|
||||
rectangular_geometry, 'Tilt',
|
||||
str(math.degrees(math.atan2(polygon.normal[2], polygon.normal[1])) - 90))
|
||||
planar_geometry = self.gbxml.add_element(surface, 'PlanarGeometry')
|
||||
self.create_poly_loop(object, polygon, planar_geometry)
|
||||
|
||||
def create_poly_loop(self, object, polygon, parent):
|
||||
poly_loop = self.gbxml.add_element(parent, 'PolyLoop')
|
||||
for vertice in polygon.vertices:
|
||||
cartesian_point = self.gbxml.add_element(poly_loop, 'CartesianPoint')
|
||||
for coord in [0, 1, 2]:
|
||||
coordinate = self.gbxml.add_element(cartesian_point, 'Coordinate')
|
||||
coordinate.text = str(object.data.vertices[vertice].co[coord])
|
||||
|
||||
def get_volume(self, o):
|
||||
volume = 0
|
||||
ob_mat = o.matrix_world
|
||||
me = o.data
|
||||
me.calc_loop_triangles()
|
||||
for tf in me.loop_triangles:
|
||||
tfv = tf.vertices
|
||||
if len(tf.vertices) == 3:
|
||||
tf_tris = (me.vertices[tfv[0]], me.vertices[tfv[1]], me.vertices[tfv[2]]),
|
||||
else:
|
||||
tf_tris = (me.vertices[tfv[0]], me.vertices[tfv[1]], me.vertices[tfv[2]]),\
|
||||
(me.vertices[tfv[2]], me.vertices[tfv[3]], me.vertices[tfv[0]])
|
||||
|
||||
for tf_iter in tf_tris:
|
||||
v1 = ob_mat @ tf_iter[0].co
|
||||
v2 = ob_mat @ tf_iter[1].co
|
||||
v3 = ob_mat @ tf_iter[2].co
|
||||
|
||||
volume += v1.dot(v2.cross(v3)) / 6.0
|
||||
return volume
|
||||
|
||||
gbxml_exporter = GbxmlExporter()
|
||||
gbxml_exporter.export()
|
||||
@@ -15,7 +15,7 @@ class ImportIFC():
|
||||
def execute(self):
|
||||
self.load_file()
|
||||
n = 0
|
||||
elements = self.file.by_type('IfcElement')
|
||||
elements = self.file.by_type('IfcElement') + self.file.by_type('IfcSpace')
|
||||
for element in elements:
|
||||
self.create_object(element)
|
||||
n += 1
|
||||
|
||||
Reference in New Issue
Block a user