From 89535e0b6a979ad4e833a5294afeeab0dde09927 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 3 Sep 2021 14:13:37 +1000 Subject: [PATCH] Manual import offsets now apply on object placements for efficiency. --- src/blenderbim/blenderbim/bim/import_ifc.py | 32 +++-- src/blenderbim/test/bim/test_operator.py | 32 +++++ .../test/files/manual-geolocation.ifc | 116 ++++++++++++++++++ 3 files changed, 163 insertions(+), 17 deletions(-) create mode 100644 src/blenderbim/test/bim/test_operator.py create mode 100644 src/blenderbim/test/files/manual-geolocation.ifc diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 0b174f0c77..6b3c6a1921 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -444,18 +444,22 @@ class IfcImporter: if props.has_blender_offset: if self.is_point_far_away((matrix[0, 3], matrix[1, 3], matrix[2, 3])): obj.BIMObjectProperties.blender_offset_type = "OBJECT_PLACEMENT" - return mathutils.Matrix( - ifcopenshell.util.geolocation.global2local( - matrix, - float(props.blender_eastings) * self.unit_scale, - float(props.blender_northings) * self.unit_scale, - float(props.blender_orthogonal_height) * self.unit_scale, - float(props.blender_x_axis_abscissa), - float(props.blender_x_axis_ordinate), - ).tolist() + matrix = ifcopenshell.util.geolocation.global2local( + matrix, + float(props.blender_eastings) * self.unit_scale, + float(props.blender_northings) * self.unit_scale, + float(props.blender_orthogonal_height) * self.unit_scale, + float(props.blender_x_axis_abscissa), + float(props.blender_x_axis_ordinate), ) else: obj.BIMObjectProperties.blender_offset_type = "CARTESIAN_POINT" + + if self.ifc_import_settings.should_offset_model: + matrix[0,3] += self.ifc_import_settings.model_offset_coordinates[0] + matrix[1,3] += self.ifc_import_settings.model_offset_coordinates[1] + matrix[2,3] += self.ifc_import_settings.model_offset_coordinates[2] + return mathutils.Matrix(matrix.tolist()) def find_decomposed_ifc_class(self, element, ifc_class): @@ -747,7 +751,7 @@ class IfcImporter: if shape: m = shape.transformation.matrix.data # We use numpy here because Blender mathutils.Matrix is not accurate enough - mat = np.matrix( + mat = np.array( ([m[0], m[3], m[6], m[9]], [m[1], m[4], m[7], m[10]], [m[2], m[5], m[8], m[11]], [0, 0, 0, 1]) ) obj.matrix_world = self.apply_blender_offset_to_matrix_world(obj, mat) @@ -1391,13 +1395,7 @@ class IfcImporter: num_vertex_indices = len(geometry.faces) mesh.vertices.add(num_vertices) - if self.ifc_import_settings.should_offset_model: - # Potentially, there is a smarter way to do this. See #1047 - v_index = cycle((0, 1, 2)) - verts = [v + self.ifc_import_settings.model_offset_coordinates[next(v_index)] for v in verts] - mesh.vertices.foreach_set("co", verts) - else: - mesh.vertices.foreach_set("co", verts) + mesh.vertices.foreach_set("co", verts) mesh.loops.add(num_vertex_indices) mesh.loops.foreach_set("vertex_index", geometry.faces) mesh.polygons.add(num_loops) diff --git a/src/blenderbim/test/bim/test_operator.py b/src/blenderbim/test/bim/test_operator.py new file mode 100644 index 0000000000..88446f10bf --- /dev/null +++ b/src/blenderbim/test/bim/test_operator.py @@ -0,0 +1,32 @@ +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2021 Dion Moult +# +# 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 . + +import bpy +import pytest +import test.bim.bootstrap +from blenderbim.bim.ifc import IfcStore + + +class TestImportIFC(test.bim.bootstrap.NewFile): + def test_manual_offset_of_object_placements(self): + bpy.ops.import_ifc.bim( + filepath="./test/files/manual-geolocation.ifc", + should_offset_model=True, + model_offset_coordinates="-268388.5, -5774506.0, -21.899999618530273", + ) + assert IfcStore.id_map[63].location.length < 1 diff --git a/src/blenderbim/test/files/manual-geolocation.ifc b/src/blenderbim/test/files/manual-geolocation.ifc new file mode 100644 index 0000000000..eac7e9f937 --- /dev/null +++ b/src/blenderbim/test/files/manual-geolocation.ifc @@ -0,0 +1,116 @@ +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('BSI','Bentley Systems, Incorporated','http://www.bentley.com',$,$); +#3=IFCPERSONANDORGANIZATION(#1,#2,$); +#4=IFCAPPLICATION(#2,'10.05.00.54','ProStructures','ProStructures 10.05.00.54'); +#5=IFCOWNERHISTORY(#3,#4,.READONLY.,.NOCHANGE.,1630562173,$,#4,1630562173); +#6=IFCCARTESIANPOINT((0.,0.,0.)); +#7=IFCDIRECTION((0.,0.,1.)); +#8=IFCDIRECTION((1.,0.,0.)); +#9=IFCAXIS2PLACEMENT3D(#6,#7,#8); +#10=IFCLOCALPLACEMENT($,#9); +#11=IFCCARTESIANPOINT((0.,0.,0.)); +#12=IFCDIRECTION((0.,0.,1.)); +#13=IFCDIRECTION((1.,0.,0.)); +#14=IFCAXIS2PLACEMENT3D(#11,#12,#13); +#15=IFCLOCALPLACEMENT(#10,#14); +#16=IFCELEMENTASSEMBLY('0QaHit1x9DPgfaDyJawBSp',#5,'Assembly','101363101363',$,#15,$,$,$,$); +#17=IFCBUILDING('38KGkNI31AtfPlaIcH6khF',#5,'','',$,#10,$,$,.ELEMENT.,0.,0.,$); +#18=IFCCARTESIANPOINT((0.,0.,0.)); +#19=IFCDIRECTION((0.,0.,1.)); +#20=IFCDIRECTION((1.,0.,0.)); +#21=IFCAXIS2PLACEMENT3D(#18,#19,#20); +#22=IFCDIRECTION((0.,1.)); +#23=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,0.1,#21,#22); +#24=IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.); +#25=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.); +#26=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.); +#27=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0); +#28=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.); +#29=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.0174532925199433),#28); +#30=IFCCONVERSIONBASEDUNIT(#27,.PLANEANGLEUNIT.,'DEGREE',#29); +#31=IFCSIUNIT(*,.TIMEUNIT.,$,.SECOND.); +#32=IFCSIUNIT(*,.MASSUNIT.,.KILO.,.GRAM.); +#33=IFCSIUNIT(*,.THERMODYNAMICTEMPERATUREUNIT.,$,.KELVIN.); +#34=IFCSIUNIT(*,.POWERUNIT.,$,.WATT.); +#35=IFCDERIVEDUNITELEMENT(#34,1); +#36=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.); +#37=IFCDERIVEDUNITELEMENT(#36,-1); +#38=IFCSIUNIT(*,.THERMODYNAMICTEMPERATUREUNIT.,$,.KELVIN.); +#39=IFCDERIVEDUNITELEMENT(#38,-1); +#40=IFCDERIVEDUNIT((#35,#37,#39),.THERMALTRANSMITTANCEUNIT.,$); +#41=IFCUNITASSIGNMENT((#24,#25,#26,#30,#31,#32,#33,#40)); +#42=IFCPROJECT('115OE$kfH0mRwCYc1flCyS',#5,'ExampleAU','System: ProStructures 10.05.00.54',$,'',$,(#23),#41); +#43=IFCCARTESIANPOINT((268388506.986707,5774506009.46504,21900.)); +#44=IFCDIRECTION((0.950176625079621,-0.311712016373349,0.)); +#45=IFCDIRECTION((0.311712016373349,0.950176625079621,0.)); +#46=IFCAXIS2PLACEMENT3D(#43,#44,#45); +#47=IFCLOCALPLACEMENT(#15,#46); +#48=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#23,1.,.MODEL_VIEW.,$); +#49=IFCCARTESIANPOINT((0.,0.)); +#50=IFCCARTESIANPOINT((1780.00001049042,0.)); +#51=IFCCARTESIANPOINT((1780.00001049042,5345.)); +#52=IFCCARTESIANPOINT((0.,5345.)); +#53=IFCPOLYLINE((#49,#50,#51,#52,#49)); +#54=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#53); +#55=IFCCARTESIANPOINT((-20992.5596790314,-64.9500000000407,-135.00004196167)); +#56=IFCDIRECTION((-2.03103162066398E-09,0.,1.00000000000038)); +#57=IFCDIRECTION((1.00000000000038,0.,2.03103167617513E-09)); +#58=IFCAXIS2PLACEMENT3D(#55,#56,#57); +#59=IFCDIRECTION((1.18813792138184E-10,0.,1.00000000580532)); +#60=IFCEXTRUDEDAREASOLID(#54,#58,#59,270.000001571459); +#61=IFCSHAPEREPRESENTATION(#48,'Body','SweptSolid',(#60)); +#62=IFCPRODUCTDEFINITIONSHAPE($,$,(#61)); +#63=IFCPLATE('0F$Pk9LP57qh205akVlNyn',#5,'1780 x 270 PRECAST WALL','None','PLATE',#47,#62,$); +#64=IFCCARTESIANPOINT((-10183.0595588684,2607.550000002,134.993501663208)); +#65=IFCDIRECTION((-1.00000000000033,0.,-2.35827894545793E-07)); +#66=IFCDIRECTION((-2.35827894490281E-07,0.,1.00000000000035)); +#67=IFCAXIS2PLACEMENT3D(#64,#65,#66); +#68=IFCLOCALPLACEMENT(#47,#67); +#69=IFCCARTESIANPOINT((-169.999938726425,1652.49999842624,0.)); +#70=IFCCARTESIANPOINT((-169.999938726425,1652.49999842624,20000.)); +#71=IFCCARTESIANPOINT((-416.894422292709,1652.49999842624,19999.9999990463)); +#72=IFCCARTESIANPOINT((-416.894422769547,1652.49999842624,-9.5367431640625E-07)); +#73=IFCPOLYLOOP((#69,#70,#71,#72)); +#74=IFCFACEOUTERBOUND(#73,.T.); +#75=IFCFACE((#74)); +#76=IFCCARTESIANPOINT((-416.894422292709,2832.19421503862,19999.9999990463)); +#77=IFCCARTESIANPOINT((-416.894422769547,2832.19421503862,-9.5367431640625E-07)); +#78=IFCPOLYLOOP((#76,#77,#72,#71)); +#79=IFCFACEOUTERBOUND(#78,.T.); +#80=IFCFACE((#79)); +#81=IFCCARTESIANPOINT((-169.999938726425,2832.19421503862,20000.)); +#82=IFCCARTESIANPOINT((-169.999938726425,2832.19421503862,0.)); +#83=IFCPOLYLOOP((#81,#82,#77,#76)); +#84=IFCFACEOUTERBOUND(#83,.T.); +#85=IFCFACE((#84)); +#86=IFCPOLYLOOP((#82,#81,#70,#69)); +#87=IFCFACEOUTERBOUND(#86,.T.); +#88=IFCFACE((#87)); +#89=IFCPOLYLOOP((#71,#70,#81,#76)); +#90=IFCFACEOUTERBOUND(#89,.T.); +#91=IFCFACE((#90)); +#92=IFCPOLYLOOP((#77,#82,#69,#72)); +#93=IFCFACEOUTERBOUND(#92,.T.); +#94=IFCFACE((#93)); +#95=IFCCLOSEDSHELL((#75,#80,#85,#88,#91,#94)); +#96=IFCFACETEDBREP(#95); +#97=IFCSHAPEREPRESENTATION(#48,'Body','Brep',(#96)); +#98=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Box','Model',*,*,*,*,#23,1.,.SKETCH_VIEW.,$); +#99=IFCCARTESIANPOINT((-416.894422769547,1652.49999842624,-9.5367431640625E-07)); +#100=IFCBOUNDINGBOX(#99,246.894484043121,1179.69421661238,20000.0000009537); +#101=IFCSHAPEREPRESENTATION(#98,'Box','BoundingBox',(#100)); +#102=IFCPRODUCTDEFINITIONSHAPE($,$,(#97,#101)); +#103=IFCOPENINGELEMENT('22TGcEeKjD7RG2nluv0jCh',#5,'Poly Cut','Polycut','Opening',#68,#102,$); +#104=IFCRELVOIDSELEMENT('3rwEh3UJ54rf7tGBMqmsM8',#5,$,$,#63,#103); +#105=IFCRELCONTAINEDINSPATIALSTRUCTURE('1w11zxbin7ofyN4XqMau2m',#5,$,$,(#16),#17); +#106=IFCRELAGGREGATES('18bhJupbH4qg7WQnIR8unA',#5,$,$,#42,(#17)); +#107=IFCRELAGGREGATES('1UBSdkyd9DtQ6wd4bUJ7Nj',#5,$,$,#16,(#63)); +ENDSEC; +END-ISO-10303-21;