diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 06919f5409..6a16d145c6 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -254,9 +254,11 @@ class IfcImporter: self.update_progress(100) bpy.context.window_manager.progress_end() - def is_element_far_away(self, element, is_meters=True): + def is_element_far_away(self, element): try: - return self.is_point_far_away(element.ObjectPlacement.RelativePlacement.Location, is_meters=is_meters) + placement = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement) + point = placement[:, 3][0:3] + return self.is_point_far_away(point, is_meters=False) except: pass @@ -373,24 +375,26 @@ class IfcImporter: else: project = self.file.by_type("IfcContext")[0] site = self.find_decomposed_ifc_class(project, "IfcSite") - if site and self.is_element_far_away(site[0], is_meters=False): - return self.guess_georeferencing(site[0]) + if site and self.is_element_far_away(site): + return self.guess_georeferencing(site) building = self.find_decomposed_ifc_class(project, "IfcBuilding") - if building and self.is_element_far_away(building[0], is_meters=False): - return self.guess_georeferencing(building[0]) + if building and self.is_element_far_away(building): + return self.guess_georeferencing(building) return self.guess_absolute_coordinate() def guess_georeferencing(self, element): - if not element.ObjectPlacement.is_a("IfcLocalPlacement"): + if not element.ObjectPlacement or not element.ObjectPlacement.is_a("IfcLocalPlacement"): return - placement = element.ObjectPlacement.RelativePlacement + placement = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement) props = bpy.context.scene.BIMGeoreferenceProperties - props.blender_eastings = str(placement.Location.Coordinates[0]) - props.blender_northings = str(placement.Location.Coordinates[1]) - props.blender_orthogonal_height = str(placement.Location.Coordinates[2]) - if placement.RefDirection: - props.blender_x_axis_abscissa = str(placement.RefDirection.DirectionRatios[0]) - props.blender_x_axis_ordinate = str(placement.RefDirection.DirectionRatios[1]) + props.blender_eastings = str(placement[0][3]) + props.blender_northings = str(placement[1][3]) + props.blender_orthogonal_height = str(placement[2][3]) + x_axis = mathutils.Vector(placement[:, 0][0:3]) + default_x_axis = mathutils.Vector((1, 0, 0)) + if (default_x_axis - x_axis).length > 0.01: + props.blender_x_axis_abscissa = str(placement[0][0]) + props.blender_x_axis_ordinate = str(placement[1][0]) props.has_blender_offset = True def guess_absolute_coordinate(self): diff --git a/src/blenderbim/blenderbim/tool/misc.py b/src/blenderbim/blenderbim/tool/misc.py index 39af0b96d8..d68f0d997c 100644 --- a/src/blenderbim/blenderbim/tool/misc.py +++ b/src/blenderbim/blenderbim/tool/misc.py @@ -131,4 +131,5 @@ class Misc(blenderbim.core.tool.Misc): bm.to_mesh(cutter_mesh) bm.free() + bm_flipped.free() return new_objs diff --git a/src/blenderbim/test/bim/feature/project.feature b/src/blenderbim/test/bim/feature/project.feature index a658a62659..1b40fe3f3d 100644 --- a/src/blenderbim/test/bim/feature/project.feature +++ b/src/blenderbim/test/bim/feature/project.feature @@ -256,7 +256,6 @@ Scenario: Load project elements - load with the spatial decomposition collection And the collection "IfcSpace/Space" is in the collection "IfcBuildingStorey/My Storey" And "scene.BIMProjectProperties.is_loading" is "False" - Scenario: Load project elements - manual offset of object placements Given an empty Blender session And I press "bim.load_project(filepath='{cwd}/test/files/manual-geolocation.ifc', is_advanced=True)" @@ -265,6 +264,11 @@ Scenario: Load project elements - manual offset of object placements And I press "bim.load_project_elements" Then the object "IfcPlate/1780 x 270 PRECAST WALL" is at "0,0,0" +Scenario: Load project elements - auto offset of object placements + Given an empty Blender session + When I press "bim.load_project(filepath='{cwd}/test/files/auto-geolocation.ifc')" + Then the object "IfcPlate/1780 x 270 PRECAST WALL" is at "0,0,0" + Scenario: Unload project Given an empty Blender session When I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" diff --git a/src/blenderbim/test/files/auto-geolocation.ifc b/src/blenderbim/test/files/auto-geolocation.ifc new file mode 100644 index 0000000000..50bbe6535b --- /dev/null +++ b/src/blenderbim/test/files/auto-geolocation.ifc @@ -0,0 +1,114 @@ +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(#43,#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); +#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(#6,#44,#45); +#47=IFCLOCALPLACEMENT(#10,#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,$,$,(#63),#17); +#106=IFCRELAGGREGATES('18bhJupbH4qg7WQnIR8unA',#5,$,$,#42,(#17)); +ENDSEC; +END-ISO-10303-21;