Fix #1956. One-button upgrade from IFC2X3 to IFC4.

This commit is contained in:
Dion Moult
2022-01-17 16:20:01 +11:00
parent 1a735c4bef
commit 9ebe0aaa95
18 changed files with 206 additions and 24 deletions
+3 -3
View File
@@ -102,7 +102,7 @@ classes = [
ui.BIM_UL_generic,
ui.BIM_UL_topics,
ui.BIM_ADDON_preferences,
#scene panel groups -->
# scene panel groups -->
ui.BIM_PT_project_setup,
ui.BIM_PT_utilities,
ui.BIM_PT_collaboration,
@@ -112,12 +112,12 @@ classes = [
ui.BIM_PT_services,
ui.BIM_PT_misc,
ui.BIM_PT_quality_control,
#object panel groups -->
# object panel groups -->
ui.BIM_PT_object_metadata,
ui.BIM_PT_geometry_object,
ui.BIM_PT_services_object,
ui.BIM_PT_utilities_object,
ui.BIM_PT_misc_object
ui.BIM_PT_misc_object,
]
for mod in modules.values():
+1 -1
View File
@@ -128,6 +128,6 @@ class IFCHeaderSpecs:
self.name = part
elif i == 3:
self.time_stamp = part
elif line.startswith("FILE_SCHEMA"):
elif line.startswith("FILE_SCHEMA"):
self.schema_name = line.split("'")[1]
break
@@ -433,7 +433,6 @@ class OverrideOutlinerDelete(bpy.types.Operator, OverrideDeleteTrait):
while queue:
collection = queue.pop()
for obj in collection.objects:
print('obj is', obj)
objects.add(obj)
queue.extend(collection.children)
children = children.union(collection.children)
@@ -20,9 +20,10 @@ import bpy
from . import ui, prop, operator
classes = (
operator.ExecuteIfcPatch,
operator.RunMigratePatch,
operator.SelectIfcPatchInput,
operator.SelectIfcPatchOutput,
operator.ExecuteIfcPatch,
operator.UpdateIfcPatchArguments,
prop.BIMPatchProperties,
ui.BIM_PT_patch,
@@ -19,6 +19,9 @@
import os
import bpy
import json
import blenderbim.tool as tool
import blenderbim.core.patch as core
import blenderbim.bim.handler
try:
import ifcpatch
@@ -114,3 +117,17 @@ class UpdateIfcPatchArguments(bpy.types.Operator):
new_attr.name = arg_name
new_attr.set_value(arg_info.get("default", new_attr.get_value_default()))
return {"FINISHED"}
class RunMigratePatch(bpy.types.Operator):
bl_idname = "bim.run_migrate_patch"
bl_label = "Execute IFCPatch"
infile: bpy.props.StringProperty()
outfile: bpy.props.StringProperty()
schema: bpy.props.StringProperty()
def execute(self, context):
core.run_migrate_patch(tool.Patch, infile=self.infile, outfile=self.outfile, schema=self.schema)
bpy.ops.file.refresh()
blenderbim.bim.handler.refresh_ui_data()
return {"FINISHED"}
+22 -12
View File
@@ -47,6 +47,16 @@ class IFCFileSelector:
split = box.split()
split.label(text=attr_name.title().replace("_", " "))
split.label(text=str(attr_value))
if (
attr_name.lower() == "schema_name"
and str(attr_value).lower() == "ifc2x3"
and filepath[-4:].lower() == ".ifc"
):
row = box.row()
op = row.operator("bim.run_migrate_patch")
op.infile = filepath
op.outfile = filepath[0:-4] + "-IFC4.ifc"
op.schema = "IFC4"
class BIM_PT_section_plane(Panel):
@@ -178,7 +188,7 @@ class BIM_PT_utilities(Panel):
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw(self, context):
pass
@@ -204,7 +214,7 @@ class BIM_PT_geometry(Panel):
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw(self, context):
pass
@@ -219,7 +229,7 @@ class BIM_PT_4D5D(Panel):
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw(self, context):
pass
@@ -234,7 +244,7 @@ class BIM_PT_structural(Panel):
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw(self, context):
pass
@@ -249,7 +259,7 @@ class BIM_PT_services(Panel):
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw(self, context):
pass
@@ -290,11 +300,11 @@ class BIM_PT_object_metadata(Panel):
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw(self, context):
pass
class BIM_PT_geometry_object(Panel):
bl_label = "IFC Geometry"
bl_space_type = "PROPERTIES"
@@ -305,7 +315,7 @@ class BIM_PT_geometry_object(Panel):
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw(self, context):
pass
@@ -320,7 +330,7 @@ class BIM_PT_services_object(Panel):
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw(self, context):
pass
@@ -335,7 +345,7 @@ class BIM_PT_utilities_object(Panel):
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw(self, context):
pass
@@ -350,6 +360,6 @@ class BIM_PT_misc_object(Panel):
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw(self, context):
pass
+21
View File
@@ -0,0 +1,21 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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/>.
def run_migrate_patch(patch, infile=None, outfile=None, schema=None):
patch.run_migrate_patch(infile, outfile, schema)
+5
View File
@@ -196,6 +196,11 @@ class Misc:
def split_objects_with_cutter(cls, objs, cutter): pass
@interface
class Patch:
def run_migrate_patch(cls, infile, outfile, schema): pass
@interface
class Owner:
def add_address_attribute(cls, name): pass
@@ -29,6 +29,7 @@ from blenderbim.tool.library import Library
from blenderbim.tool.material import Material
from blenderbim.tool.misc import Misc
from blenderbim.tool.owner import Owner
from blenderbim.tool.patch import Patch
from blenderbim.tool.pset import Pset
from blenderbim.tool.qto import Qto
from blenderbim.tool.root import Root
+34
View File
@@ -0,0 +1,34 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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 os
import bpy
import blenderbim.core.tool
import blenderbim.tool as tool
try:
import ifcpatch
except:
print("IfcPatch not available")
class Patch(blenderbim.core.tool.Patch):
@classmethod
def run_migrate_patch(cls, infile, outfile, schema):
log = os.path.join(bpy.context.scene.BIMProperties.data_dir, "process.log")
ifcpatch.execute({"input": infile, "output": outfile, "recipe": "Migrate", "arguments": [schema], "log": log})
@@ -9,3 +9,8 @@ Scenario: Execute IFC Patch
And I set "scene.BIMPatchProperties.ifc_patch_args" to "[123454321,0,0,0]"
When I press "bim.execute_ifc_patch"
Then the file "{cwd}/test/files/basic-patched.ifc" should contain "123454321"
Scenario: Run migrate patch
Given an empty Blender session
When I press "bim.run_migrate_patch(infile='{cwd}/test/files/ifc2x3.ifc', outfile='{cwd}/test/files/ifc2x3-migrated.ifc', schema='IFC4')"
Then the file "{cwd}/test/files/ifc2x3-migrated.ifc" should contain "IFC4"
+7
View File
@@ -112,6 +112,13 @@ def owner():
prophet.verify()
@pytest.fixture
def patch():
prophet = Prophecy(blenderbim.core.tool.Patch)
yield prophet
prophet.verify()
@pytest.fixture
def pset():
prophet = Prophecy(blenderbim.core.tool.Pset)
+3 -1
View File
@@ -122,7 +122,9 @@ class TestAddBrick:
brick.add_brick_from_element("element", "namespace", "brick_class").should_be_called().will_return("brick_uri")
brick.run_assign_brick_reference(element="element", library="library", brick_uri="brick_uri").should_be_called()
brick.run_refresh_brick_viewer().should_be_called()
subject.add_brick(ifc, brick, element="element", namespace="namespace", brick_class="brick_class", library="library")
subject.add_brick(
ifc, brick, element="element", namespace="namespace", brick_class="brick_class", library="library"
)
def test_adding_a_plain_brick(self, ifc, brick):
brick.add_brick("namespace", "brick_class").should_be_called()
+3 -1
View File
@@ -60,7 +60,9 @@ class TestEditTextProduct:
def test_run(self, ifc, drawing):
ifc.get_entity("obj").should_be_called().will_return("element")
drawing.get_text_product("element").should_be_called().will_return("existing_product")
ifc.run("drawing.unassign_product", relating_product="existing_product", related_object="element").should_be_called()
ifc.run(
"drawing.unassign_product", relating_product="existing_product", related_object="element"
).should_be_called()
ifc.run("drawing.assign_product", relating_product="product", related_object="element").should_be_called()
drawing.update_text_value("obj").should_be_called()
drawing.disable_editing_text_product("obj").should_be_called()
+26
View File
@@ -0,0 +1,26 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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.core.owner as subject
from test.core.bootstrap import patch
class TestRunMigratePatch:
def test_run(self, patch):
patch.run_migrate_patch("infile", "outfile", "schema").should_be_called()
assert subject.run_migrate_patch(patch, infile="infile", outfile="outfile", schema="schema")
+12
View File
@@ -0,0 +1,12 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
FILE_NAME('','2021-09-03T08:40:25',(),(),'IfcOpenShell 0.6.0b0','IfcOpenShell 0.6.0b0','');
FILE_SCHEMA(('IFC2X3'));
ENDSEC;
DATA;
#1=IFCPERSON($,$,$,$,$,$,$,$);
#2=IFCORGANIZATION('abc','Foobar','http://www.example.com',$,$);
#3=IFCPERSONANDORGANIZATION(#1,#2,$);
ENDSEC;
END-ISO-10303-21;
+4 -4
View File
@@ -37,12 +37,12 @@ class TestImplementsTool(NewFile):
class TestAddBrick(NewFile):
def test_run(self):
BrickStore.graph = brickschema.Graph()
result = subject.add_brick(
"http://example.org/digitaltwin#", "https://brickschema.org/schema/Brick#Equipment"
)
result = subject.add_brick("http://example.org/digitaltwin#", "https://brickschema.org/schema/Brick#Equipment")
assert "http://example.org/digitaltwin#" in result
assert list(
BrickStore.graph.triples((URIRef(result), RDF.type, URIRef("https://brickschema.org/schema/Brick#Equipment")))
BrickStore.graph.triples(
(URIRef(result), RDF.type, URIRef("https://brickschema.org/schema/Brick#Equipment"))
)
)
assert list(
BrickStore.graph.triples(
+40
View File
@@ -0,0 +1,40 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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 os
import bpy
import ifcopenshell
import blenderbim.core.tool
import blenderbim.tool as tool
from test.bim.bootstrap import NewFile
from blenderbim.tool.patch import Patch as subject
class TestImplementsTool(NewFile):
def test_run(self):
assert isinstance(subject(), blenderbim.core.tool.Patch)
class TestRunMigratePatch(NewFile):
def test_run(self):
cwd = os.path.dirname(os.path.realpath(__file__))
infile = os.path.join(cwd, "..", "files", "ifc2x3.ifc")
outfile = os.path.join(cwd, "..", "files", "ifc2x3-migrated.ifc")
subject.run_migrate_patch(infile, outfile, "IFC4")
ifc = ifcopenshell.open(outfile)
assert ifc.schema == "IFC4"