Merge pull request #4125 from Krande/fix/convert-units

Proposal for updating IfcPatch ConvertLengthUnit.py for compatibility with boost>=1.82
This commit is contained in:
Kristoffer Andersen
2023-12-19 06:43:01 +01:00
committed by GitHub
6 changed files with 588 additions and 167 deletions
@@ -16,8 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
from math import pi
from fractions import Fraction
from math import pi
from typing import Tuple, Iterable, Any
import ifcopenshell
import ifcopenshell.api
prefixes = {
"EXA": 1e18,
@@ -214,12 +218,10 @@ si_conversions = {
"fahrenheit": 1.8,
}
si_offsets = {
"fahrenheit": -459.67,
}
imperial_types = {
"thou": "LENGTHUNIT",
"inch": "LENGTHUNIT",
@@ -260,7 +262,6 @@ imperial_types = {
"fahrenheit": "THERMODYNAMICTEMPERATUREUNIT",
}
prefix_symbols = {
"EXA": "E",
"PETA": "P",
@@ -558,13 +559,13 @@ def calculate_unit_scale(ifc_file):
def format_length(
value,
precision,
decimal_places=2,
suppress_zero_inches=True,
unit_system="imperial",
input_unit="foot",
output_unit="foot",
value,
precision,
decimal_places=2,
suppress_zero_inches=True,
unit_system="imperial",
input_unit="foot",
output_unit="foot",
):
"""Formats a length for readability and imperial formatting
@@ -624,3 +625,79 @@ def format_length(
elif unit_system == "metric":
rounded_val = round(value / precision) * precision
return f"{rounded_val:.{decimal_places}f}"
def is_attr_type(
content_type: ifcopenshell.ifcopenshell_wrapper.named_type | ifcopenshell.ifcopenshell_wrapper.type_declaration,
ifc_unit_type_name: str) -> ifcopenshell.ifcopenshell_wrapper.type_declaration | None:
cur_decl = content_type
while hasattr(cur_decl, "declared_type") is True:
cur_decl = cur_decl.declared_type()
if hasattr(cur_decl, "name") is False:
continue
if cur_decl.name() == ifc_unit_type_name:
return cur_decl
if isinstance(cur_decl, ifcopenshell.ifcopenshell_wrapper.aggregation_type):
res = cur_decl.type_of_element()
cur_decl = res.declared_type()
if hasattr(cur_decl, "name") and cur_decl.name() == ifc_unit_type_name:
return cur_decl
while hasattr(cur_decl, "declared_type") is True:
cur_decl = cur_decl.declared_type()
if hasattr(cur_decl, "name") is False:
continue
if cur_decl.name() == ifc_unit_type_name:
return cur_decl
return None
def iter_element_and_attributes_per_type(ifc_file: ifcopenshell.file, attr_type_name: str) -> Iterable[
Tuple[ifcopenshell.entity_instance, ifcopenshell.ifcopenshell_wrapper.attribute, Any, str]]:
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(ifc_file.schema)
for element in ifc_file:
entity = schema.declaration_by_name(element.is_a())
attrs = entity.all_attributes()
for i, (attr, val, is_derived) in enumerate(zip(attrs, list(element), entity.derived())):
if is_derived:
continue
# Get all methods and attributes of the element
attr_type = attr.type_of_attribute()
base_type = is_attr_type(attr_type, attr_type_name)
if base_type is None:
continue
if val is None:
continue
yield element, attr, val
def convert_file_length_units(ifc_file: ifcopenshell.file, target_units: str) -> ifcopenshell.file:
"""Converts all units in an IFC file to the specified target units. Returns a new file."""
prefix = "MILLI" if target_units == "MILLIMETERS" else None
# Copy all elements from the original file to the patched file
file_patched = ifcopenshell.file.from_string(ifc_file.wrapped_data.to_string())
unit_assignment = ifcopenshell.util.unit.get_unit_assignment(file_patched)
old_length = [u for u in unit_assignment.Units if getattr(u, "UnitType", None) == "LENGTHUNIT"][0]
new_length = ifcopenshell.api.run("unit.add_si_unit", file_patched, unit_type="LENGTHUNIT", prefix=prefix)
# Traverse all elements and their nested attributes in the file and convert them
for element, attr, val in iter_element_and_attributes_per_type(file_patched, "IfcLengthMeasure"):
if isinstance(val, tuple):
new_value = [ifcopenshell.util.unit.convert_unit(v, old_length, new_length) for v in val]
setattr(element, attr.name(), tuple(new_value))
else:
new_value = ifcopenshell.util.unit.convert_unit(val, old_length, new_length)
setattr(element, attr.name(), new_value)
file_patched.remove(old_length)
unit_assignment.Units = tuple([new_length, *unit_assignment.Units])
return file_patched
@@ -0,0 +1,426 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION((''),'2;1');
FILE_NAME('','2019-03-20T15:56:44',(''),(''),'BuildingSmart IfcKit by Constructivity','IfcDoc 12.0.0.0','');
FILE_SCHEMA(('IFC4x1'));
ENDSEC;
DATA;
#1= IFCBEAMTYPE('0juf4qyggSstrxA20Qwnsj',$,'IPE220','Beam type',$,$,$,$,$,.BEAM.);
#2= IFCRELDECLARES('3P3zL0KYv4C9D9h3OX$dey',$,$,$,#5,(#1,#6));
#3= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20Q49sj',$,$,$,(#1),#7);
#7= IFCMATERIALPROFILESET($,$,(#8),$);
#8= IFCMATERIALPROFILE('IPE220',$,#9,#10,$,$);
#9= IFCMATERIAL('S275J2',$,'Steel');
#10= IFCISHAPEPROFILEDEF(.AREA.,'IPE220',$,110.,220.,5.9,9.2,12.,$,$);
#4= IFCRELDEFINESBYTYPE('2aq$Crcs_xJvd69lbm2bMM',$,'beam typing',$,(#11,#12,#13,#14,#15,#16,#17,#18,#19),#1);
#5= IFCPROJECT('32DJhIf6esIeAOIlD4Xw2m',#20,'Test model for beam cardinal points',$,$,$,$,(#21),#22);
#20= IFCOWNERHISTORY(#24,#25,$,.NOTDEFINED.,$,$,$,1320688800);
#21= IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.0E-05,#26,$);
#22= IFCUNITASSIGNMENT((#63,#64,#65,#66,#67,#68,#69,#70));
#24= IFCPERSONANDORGANIZATION(#71,#72,$);
#25= IFCAPPLICATION(#72,'Unknown','SDS/2 Version 6.300 on NT','Unknown');
#26= IFCAXIS2PLACEMENT3D(#73,#74,#75);
#27= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#76));
#28= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#78));
#29= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#79));
#30= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#81));
#31= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#82));
#32= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#84));
#33= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#85));
#34= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#87));
#35= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#88));
#36= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#90));
#37= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#91));
#38= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#93));
#39= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#94));
#40= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#96));
#41= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#97));
#42= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#99));
#43= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#100));
#44= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#102));
#45= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#103));
#46= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#105));
#47= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#106));
#48= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#108));
#49= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#109));
#50= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#111));
#51= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#112));
#52= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#114));
#53= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#115));
#54= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#117));
#55= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#118));
#56= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#120));
#57= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#121));
#58= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#123));
#59= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#124));
#60= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#126));
#61= IFCSHAPEREPRESENTATION(#21,'Body','SweptSolid',(#127));
#62= IFCSHAPEREPRESENTATION(#21,'Axis','Curve3D',(#129));
#63= IFCSIUNIT($,.LENGTHUNIT.,.MILLI.,.METRE.);
#64= IFCSIUNIT($,.PLANEANGLEUNIT.,$,.RADIAN.);
#65= IFCSIUNIT($,.MASSUNIT.,.KILO.,.GRAM.);
#66= IFCSIUNIT($,.TIMEUNIT.,$,.SECOND.);
#67= IFCSIUNIT($,.AREAUNIT.,$,.SQUARE_METRE.);
#68= IFCSIUNIT($,.PRESSUREUNIT.,$,.PASCAL.);
#69= IFCSIUNIT($,.FORCEUNIT.,$,.NEWTON.);
#70= IFCSIUNIT($,.THERMODYNAMICTEMPERATUREUNIT.,$,.DEGREE_CELSIUS.);
#71= IFCPERSON($,'Liebich',$,$,$,$,$,$);
#72= IFCORGANIZATION($,'buildingSMART',$,$,$);
#73= IFCCARTESIANPOINT((0.,0.,0.));
#74= IFCDIRECTION((0.,0.,1.));
#75= IFCDIRECTION((1.,0.,0.));
#76= IFCEXTRUDEDAREASOLID(#10,#130,#131,2000.);
#77= IFCPRODUCTDEFINITIONSHAPE($,$,(#28,#27));
#78= IFCPOLYLINE((#132,#133));
#79= IFCEXTRUDEDAREASOLID(#10,#134,#135,2000.);
#80= IFCPRODUCTDEFINITIONSHAPE($,$,(#30,#29));
#81= IFCPOLYLINE((#136,#137));
#82= IFCEXTRUDEDAREASOLID(#10,#138,#139,2000.);
#83= IFCPRODUCTDEFINITIONSHAPE($,$,(#32,#31));
#84= IFCPOLYLINE((#140,#141));
#85= IFCEXTRUDEDAREASOLID(#10,#142,#143,2000.);
#86= IFCPRODUCTDEFINITIONSHAPE($,$,(#34,#33));
#87= IFCPOLYLINE((#144,#145));
#88= IFCEXTRUDEDAREASOLID(#10,#146,#147,2000.);
#89= IFCPRODUCTDEFINITIONSHAPE($,$,(#36,#35));
#90= IFCPOLYLINE((#148,#149));
#91= IFCEXTRUDEDAREASOLID(#10,#150,#151,2000.);
#92= IFCPRODUCTDEFINITIONSHAPE($,$,(#38,#37));
#93= IFCPOLYLINE((#152,#153));
#94= IFCEXTRUDEDAREASOLID(#10,#154,#155,2000.);
#95= IFCPRODUCTDEFINITIONSHAPE($,$,(#40,#39));
#96= IFCPOLYLINE((#156,#157));
#97= IFCEXTRUDEDAREASOLID(#10,#158,#159,2000.);
#98= IFCPRODUCTDEFINITIONSHAPE($,$,(#42,#41));
#99= IFCPOLYLINE((#160,#161));
#100= IFCEXTRUDEDAREASOLID(#10,#162,#163,2000.);
#101= IFCPRODUCTDEFINITIONSHAPE($,$,(#44,#43));
#102= IFCPOLYLINE((#164,#165));
#103= IFCEXTRUDEDAREASOLID(#166,#167,#168,3000.);
#104= IFCPRODUCTDEFINITIONSHAPE($,$,(#46,#45));
#105= IFCPOLYLINE((#170,#171));
#106= IFCEXTRUDEDAREASOLID(#166,#172,#173,3000.);
#107= IFCPRODUCTDEFINITIONSHAPE($,$,(#48,#47));
#108= IFCPOLYLINE((#175,#176));
#109= IFCEXTRUDEDAREASOLID(#166,#177,#178,3000.);
#110= IFCPRODUCTDEFINITIONSHAPE($,$,(#50,#49));
#111= IFCPOLYLINE((#180,#181));
#112= IFCEXTRUDEDAREASOLID(#166,#182,#183,3000.);
#113= IFCPRODUCTDEFINITIONSHAPE($,$,(#52,#51));
#114= IFCPOLYLINE((#185,#186));
#115= IFCEXTRUDEDAREASOLID(#166,#187,#188,3000.);
#116= IFCPRODUCTDEFINITIONSHAPE($,$,(#54,#53));
#117= IFCPOLYLINE((#190,#191));
#118= IFCEXTRUDEDAREASOLID(#166,#192,#193,3000.);
#119= IFCPRODUCTDEFINITIONSHAPE($,$,(#56,#55));
#120= IFCPOLYLINE((#195,#196));
#121= IFCEXTRUDEDAREASOLID(#166,#197,#198,3000.);
#122= IFCPRODUCTDEFINITIONSHAPE($,$,(#58,#57));
#123= IFCPOLYLINE((#200,#201));
#124= IFCEXTRUDEDAREASOLID(#166,#202,#203,3000.);
#125= IFCPRODUCTDEFINITIONSHAPE($,$,(#60,#59));
#126= IFCPOLYLINE((#205,#206));
#127= IFCEXTRUDEDAREASOLID(#166,#207,#208,3000.);
#128= IFCPRODUCTDEFINITIONSHAPE($,$,(#62,#61));
#129= IFCPOLYLINE((#210,#211));
#130= IFCAXIS2PLACEMENT3D(#212,$,$);
#131= IFCDIRECTION((0.,0.,1.));
#132= IFCCARTESIANPOINT((0.,0.,0.));
#133= IFCCARTESIANPOINT((0.,0.,2000.));
#134= IFCAXIS2PLACEMENT3D(#213,$,$);
#135= IFCDIRECTION((0.,0.,1.));
#136= IFCCARTESIANPOINT((0.,0.,0.));
#137= IFCCARTESIANPOINT((0.,0.,2000.));
#138= IFCAXIS2PLACEMENT3D(#214,$,$);
#139= IFCDIRECTION((0.,0.,1.));
#140= IFCCARTESIANPOINT((0.,0.,0.));
#141= IFCCARTESIANPOINT((0.,0.,2000.));
#142= IFCAXIS2PLACEMENT3D(#215,$,$);
#143= IFCDIRECTION((0.,0.,1.));
#144= IFCCARTESIANPOINT((0.,0.,0.));
#145= IFCCARTESIANPOINT((0.,0.,2000.));
#146= IFCAXIS2PLACEMENT3D(#216,$,$);
#147= IFCDIRECTION((0.,0.,1.));
#148= IFCCARTESIANPOINT((0.,0.,0.));
#149= IFCCARTESIANPOINT((0.,0.,2000.));
#150= IFCAXIS2PLACEMENT3D(#217,$,$);
#151= IFCDIRECTION((0.,0.,1.));
#152= IFCCARTESIANPOINT((0.,0.,0.));
#153= IFCCARTESIANPOINT((0.,0.,2000.));
#154= IFCAXIS2PLACEMENT3D(#218,$,$);
#155= IFCDIRECTION((0.,0.,1.));
#156= IFCCARTESIANPOINT((0.,0.,0.));
#157= IFCCARTESIANPOINT((0.,0.,2000.));
#158= IFCAXIS2PLACEMENT3D(#219,$,$);
#159= IFCDIRECTION((0.,0.,1.));
#160= IFCCARTESIANPOINT((0.,0.,0.));
#161= IFCCARTESIANPOINT((0.,0.,2000.));
#162= IFCAXIS2PLACEMENT3D(#220,$,$);
#163= IFCDIRECTION((0.,0.,1.));
#164= IFCCARTESIANPOINT((0.,0.,0.));
#165= IFCCARTESIANPOINT((0.,0.,2000.));
#166= IFCTSHAPEPROFILEDEF(.AREA.,'1/2IPE300',$,150.,150.,7.1,10.7,15.,$,$,$,$);
#167= IFCAXIS2PLACEMENT3D(#221,$,$);
#168= IFCDIRECTION((0.,0.,1.));
#170= IFCCARTESIANPOINT((0.,0.,0.));
#171= IFCCARTESIANPOINT((0.,0.,3000.));
#172= IFCAXIS2PLACEMENT3D(#222,$,$);
#173= IFCDIRECTION((0.,0.,1.));
#175= IFCCARTESIANPOINT((0.,0.,0.));
#176= IFCCARTESIANPOINT((0.,0.,3000.));
#177= IFCAXIS2PLACEMENT3D(#223,$,$);
#178= IFCDIRECTION((0.,0.,1.));
#180= IFCCARTESIANPOINT((0.,0.,0.));
#181= IFCCARTESIANPOINT((0.,0.,3000.));
#182= IFCAXIS2PLACEMENT3D(#224,$,$);
#183= IFCDIRECTION((0.,0.,1.));
#185= IFCCARTESIANPOINT((0.,0.,0.));
#186= IFCCARTESIANPOINT((0.,0.,3000.));
#187= IFCAXIS2PLACEMENT3D(#225,$,$);
#188= IFCDIRECTION((0.,0.,1.));
#190= IFCCARTESIANPOINT((0.,0.,0.));
#191= IFCCARTESIANPOINT((0.,0.,3000.));
#192= IFCAXIS2PLACEMENT3D(#226,$,$);
#193= IFCDIRECTION((0.,0.,1.));
#195= IFCCARTESIANPOINT((0.,0.,0.));
#196= IFCCARTESIANPOINT((0.,0.,3000.));
#197= IFCAXIS2PLACEMENT3D(#227,$,$);
#198= IFCDIRECTION((0.,0.,1.));
#200= IFCCARTESIANPOINT((0.,0.,0.));
#201= IFCCARTESIANPOINT((0.,0.,3000.));
#202= IFCAXIS2PLACEMENT3D(#228,$,$);
#203= IFCDIRECTION((0.,0.,1.));
#205= IFCCARTESIANPOINT((0.,0.,0.));
#206= IFCCARTESIANPOINT((0.,0.,3000.));
#207= IFCAXIS2PLACEMENT3D(#229,$,$);
#208= IFCDIRECTION((0.,0.,1.));
#210= IFCCARTESIANPOINT((0.,0.,0.));
#211= IFCCARTESIANPOINT((0.,0.,3000.));
#212= IFCCARTESIANPOINT((-55.,110.,0.));
#213= IFCCARTESIANPOINT((0.,110.,0.));
#214= IFCCARTESIANPOINT((55.,110.,0.));
#215= IFCCARTESIANPOINT((-55.,0.,0.));
#216= IFCCARTESIANPOINT((0.,0.,0.));
#217= IFCCARTESIANPOINT((55.,0.,0.));
#218= IFCCARTESIANPOINT((-55.,-110.,0.));
#219= IFCCARTESIANPOINT((0.,-110.,0.));
#220= IFCCARTESIANPOINT((55.,-110.,0.));
#221= IFCCARTESIANPOINT((-75.,75.,0.));
#222= IFCCARTESIANPOINT((0.,75.,0.));
#223= IFCCARTESIANPOINT((75.,75.,0.));
#224= IFCCARTESIANPOINT((-75.,0.,0.));
#225= IFCCARTESIANPOINT((0.,0.,0.));
#226= IFCCARTESIANPOINT((75.,0.,0.));
#227= IFCCARTESIANPOINT((-75.,-75.,0.));
#228= IFCCARTESIANPOINT((0.,-75.,0.));
#229= IFCCARTESIANPOINT((75.,-75.,0.));
#6= IFCBEAMTYPE('0juf4qyggSstrxA20Qdisj',$,'1/2IPE300','Beam type',$,$,$,$,$,.BEAM.);
#11= IFCBEAMSTANDARDCASE('0juf4qyggSI8rxA20Qwnsj',$,'A-1','IPE220','Beam',#232,#77,'A-1',$);
#232= IFCLOCALPLACEMENT(#235,#236);
#235= IFCLOCALPLACEMENT(#237,#26);
#236= IFCAXIS2PLACEMENT3D(#256,#257,#258);
#237= IFCLOCALPLACEMENT($,#26);
#239= IFCLOCALPLACEMENT(#235,#260);
#240= IFCLOCALPLACEMENT(#235,#261);
#241= IFCLOCALPLACEMENT(#235,#262);
#242= IFCLOCALPLACEMENT(#235,#263);
#243= IFCLOCALPLACEMENT(#235,#264);
#244= IFCLOCALPLACEMENT(#235,#265);
#245= IFCLOCALPLACEMENT(#235,#266);
#246= IFCLOCALPLACEMENT(#235,#267);
#247= IFCLOCALPLACEMENT(#235,#268);
#248= IFCLOCALPLACEMENT(#235,#269);
#249= IFCLOCALPLACEMENT(#235,#270);
#250= IFCLOCALPLACEMENT(#235,#271);
#251= IFCLOCALPLACEMENT(#235,#272);
#252= IFCLOCALPLACEMENT(#235,#273);
#253= IFCLOCALPLACEMENT(#235,#274);
#254= IFCLOCALPLACEMENT(#235,#275);
#255= IFCLOCALPLACEMENT(#235,#276);
#256= IFCCARTESIANPOINT((0.,0.,0.));
#257= IFCDIRECTION((1.,0.,0.));
#258= IFCDIRECTION((0.,1.,0.));
#260= IFCAXIS2PLACEMENT3D(#277,#278,#279);
#261= IFCAXIS2PLACEMENT3D(#280,#281,#282);
#262= IFCAXIS2PLACEMENT3D(#283,#284,#285);
#263= IFCAXIS2PLACEMENT3D(#286,#287,#288);
#264= IFCAXIS2PLACEMENT3D(#289,#290,#291);
#265= IFCAXIS2PLACEMENT3D(#292,#293,#294);
#266= IFCAXIS2PLACEMENT3D(#295,#296,#297);
#267= IFCAXIS2PLACEMENT3D(#298,#299,#300);
#268= IFCAXIS2PLACEMENT3D(#301,#302,#303);
#269= IFCAXIS2PLACEMENT3D(#304,#305,#306);
#270= IFCAXIS2PLACEMENT3D(#307,#308,#309);
#271= IFCAXIS2PLACEMENT3D(#310,#311,#312);
#272= IFCAXIS2PLACEMENT3D(#313,#314,#315);
#273= IFCAXIS2PLACEMENT3D(#316,#317,#318);
#274= IFCAXIS2PLACEMENT3D(#319,#320,#321);
#275= IFCAXIS2PLACEMENT3D(#322,#323,#324);
#276= IFCAXIS2PLACEMENT3D(#325,#326,#327);
#277= IFCCARTESIANPOINT((0.,1500.,0.));
#278= IFCDIRECTION((1.,0.,0.));
#279= IFCDIRECTION((0.,1.,0.));
#280= IFCCARTESIANPOINT((0.,3000.,0.));
#281= IFCDIRECTION((1.,0.,0.));
#282= IFCDIRECTION((0.,1.,0.));
#283= IFCCARTESIANPOINT((0.,4500.,0.));
#284= IFCDIRECTION((1.,0.,0.));
#285= IFCDIRECTION((0.,1.,0.));
#286= IFCCARTESIANPOINT((0.,6000.,0.));
#287= IFCDIRECTION((1.,0.,0.));
#288= IFCDIRECTION((0.,1.,0.));
#289= IFCCARTESIANPOINT((0.,7500.,0.));
#290= IFCDIRECTION((1.,0.,0.));
#291= IFCDIRECTION((0.,1.,0.));
#292= IFCCARTESIANPOINT((0.,9000.,0.));
#293= IFCDIRECTION((1.,0.,0.));
#294= IFCDIRECTION((0.,1.,0.));
#295= IFCCARTESIANPOINT((0.,10500.,0.));
#296= IFCDIRECTION((1.,0.,0.));
#297= IFCDIRECTION((0.,1.,0.));
#298= IFCCARTESIANPOINT((0.,12000.,0.));
#299= IFCDIRECTION((1.,0.,0.));
#300= IFCDIRECTION((0.,1.,0.));
#301= IFCCARTESIANPOINT((0.,0.,1500.));
#302= IFCDIRECTION((0.98,0.081,0.182));
#303= IFCDIRECTION((-0.0001,0.9138,-0.40616));
#304= IFCCARTESIANPOINT((0.,1500.,1500.));
#305= IFCDIRECTION((0.98,0.081,0.182));
#306= IFCDIRECTION((-0.0001,0.9138,-0.40616));
#307= IFCCARTESIANPOINT((0.,3000.,1500.));
#308= IFCDIRECTION((0.98,0.081,0.182));
#309= IFCDIRECTION((-0.0001,0.9138,-0.40616));
#310= IFCCARTESIANPOINT((0.,4500.,1500.));
#311= IFCDIRECTION((0.98,0.081,0.182));
#312= IFCDIRECTION((-0.0001,0.9138,-0.40616));
#313= IFCCARTESIANPOINT((0.,6000.,1500.));
#314= IFCDIRECTION((0.98,0.081,0.182));
#315= IFCDIRECTION((-0.0001,0.9138,-0.40616));
#316= IFCCARTESIANPOINT((0.,7500.,1500.));
#317= IFCDIRECTION((0.98,0.081,0.182));
#318= IFCDIRECTION((-0.0001,0.9138,-0.40616));
#319= IFCCARTESIANPOINT((0.,9000.,1500.));
#320= IFCDIRECTION((0.98,0.081,0.182));
#321= IFCDIRECTION((-0.0001,0.9138,-0.40616));
#322= IFCCARTESIANPOINT((0.,10500.,1500.));
#323= IFCDIRECTION((0.98,0.081,0.182));
#324= IFCDIRECTION((-0.0001,0.9138,-0.40616));
#325= IFCCARTESIANPOINT((0.,12000.,1500.));
#326= IFCDIRECTION((0.98,0.081,0.182));
#327= IFCDIRECTION((-0.0001,0.9138,-0.40616));
#12= IFCBEAMSTANDARDCASE('0juf4qyggSI8rxA20sznsj',$,'A-2','IPE220','Beam',#239,#80,'A-2',$);
#13= IFCBEAMSTANDARDCASE('0juf4qyggSI8s4A20sznsj',$,'A-3','IPE220','Beam',#240,#83,'A-3',$);
#14= IFCBEAMSTANDARDCASE('0juf4qyggSI8s4A20sznw6',$,'A-4','IPE220','Beam',#241,#86,'A-4',$);
#15= IFCBEAMSTANDARDCASE('0juf4qyggSI8rxA20Qwnab',$,'A-5','IPE220','Beam',#242,#89,'A-5',$);
#16= IFCBEAMSTANDARDCASE('0juf4qyggSI8rxA20Qwng1',$,'A-6','IPE220','Beam',#243,#92,'A-6',$);
#17= IFCBEAMSTANDARDCASE('0juf4qyggSI8rxA20Qwn3s',$,'A-7','IPE220','Beam',#244,#95,'A-7',$);
#18= IFCBEAMSTANDARDCASE('0juf4qyggSI8rxA20Qwnlq',$,'A-8','IPE220','Beam',#245,#98,'A-8',$);
#19= IFCBEAMSTANDARDCASE('0juf4qyggSI8s4A20sznrt',$,'A-9','IPE220','Beam',#246,#101,'A-9',$);
#23= IFCRELAGGREGATES('0ZdtoJM$VsHBqD_feRfxAg',$,$,$,#5,(#259));
#169= IFCBEAMSTANDARDCASE('3QbcAsYoB7Hvx$4VHzijYi',$,'B-1','1/2IPE300','Beam',#247,#104,'B-1',$);
#174= IFCBEAMSTANDARDCASE('3Qb5gsYoB7Hvx$4VHzijYi',$,'B-2','1/2IPE300','Beam',#248,#107,'B-2',$);
#179= IFCBEAMSTANDARDCASE('3QbcAsYsg7Hvx$4VHzijYi',$,'B-3','1/2IPE300','Beam',#249,#110,'B-3',$);
#184= IFCBEAMSTANDARDCASE('3QbcAsYsg7Hvx$4VHzijGT',$,'B-4','1/2IPE300','Beam',#250,#113,'B-4',$);
#189= IFCBEAMSTANDARDCASE('3QbcAsYsg7Hvx$4VHzijdF',$,'B-5','1/2IPE300','Beam',#251,#116,'B-5',$);
#194= IFCBEAMSTANDARDCASE('3QbcAsYsg7Hvx$4VHzij3V',$,'B-6','1/2IPE300','Beam',#252,#119,'B-6',$);
#199= IFCBEAMSTANDARDCASE('3QbcAsYsg7Hvx$4VHzij71',$,'B-7','1/2IPE300','Beam',#253,#122,'B-7',$);
#204= IFCBEAMSTANDARDCASE('3QbcAsYsg7Hvx$4VHzijvb',$,'B-8','1/2IPE300','Beam',#254,#125,'B-8',$);
#209= IFCBEAMSTANDARDCASE('3QbcAsYsg7Hvx$4VHzijp1',$,'B-9','1/2IPE300','Beam',#255,#128,'B-9',$);
#230= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20Q2fsj',$,$,$,(#6),#345);
#345= IFCMATERIALPROFILESET($,$,(#346),$);
#346= IFCMATERIALPROFILE('1/2IPE300',$,#347,#166,$,$);
#347= IFCMATERIAL('S275J2',$,'Steel');
#231= IFCRELDEFINESBYTYPE('2aq$Crcs_xJvN69lbm2bMM',$,'beam typing',$,(#169,#174,#179,#184,#189,#194,#199,#204,#209),#6);
#233= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20QfZsj',$,$,$,(#11),#348);
#348= IFCMATERIALPROFILESETUSAGE(#7,1,$);
#234= IFCRELCONTAINEDINSPATIALSTRUCTURE('2aq$Crcs_xJvtg9lbm2bMM',$,'Physical model',$,(#11,#12,#13,#14,#15,#16,#17,#18,#19,#169,#174,#179,#184,#189,#194,#199,#204,#209),#238);
#238= IFCBUILDING('0Xwup04AK2G8Mt0WNZVy_Z',$,'Building',$,$,#235,$,$,.ELEMENT.,$,$,$);
#259= IFCSITE('10cTefjFQoJexBQrSqFcWZ',$,'Site',$,$,#237,$,$,.ELEMENT.,$,$,$,$,$);
#328= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20QgAsj',$,$,$,(#12),#350);
#350= IFCMATERIALPROFILESETUSAGE(#7,2,$);
#329= IFCRELASSOCIATESMATERIAL('3x0gFSPAr5puQ5WI22xYOm',$,$,$,(#13),#351);
#351= IFCMATERIALPROFILESETUSAGE(#7,3,$);
#330= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20QOHsj',$,$,$,(#14),#352);
#352= IFCMATERIALPROFILESETUSAGE(#7,4,$);
#331= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20QRLsj',$,$,$,(#15),#353);
#353= IFCMATERIALPROFILESETUSAGE(#7,5,$);
#332= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20QMmsj',$,$,$,(#16),#354);
#354= IFCMATERIALPROFILESETUSAGE(#7,6,$);
#333= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20Qh4sj',$,$,$,(#17),#355);
#355= IFCMATERIALPROFILESETUSAGE(#7,7,$);
#334= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20QwKsj',$,$,$,(#18),#356);
#356= IFCMATERIALPROFILESETUSAGE(#7,8,$);
#335= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20QJksj',$,$,$,(#19),#357);
#357= IFCMATERIALPROFILESETUSAGE(#7,9,$);
#336= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20QbFsj',$,$,$,(#169),#358);
#358= IFCMATERIALPROFILESETUSAGE(#345,1,$);
#337= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20Qqlsj',$,$,$,(#174),#359);
#359= IFCMATERIALPROFILESETUSAGE(#345,2,$);
#338= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20Q7isj',$,$,$,(#179),#360);
#360= IFCMATERIALPROFILESETUSAGE(#345,3,$);
#339= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20Q4nsj',$,$,$,(#184),#361);
#361= IFCMATERIALPROFILESETUSAGE(#345,4,$);
#340= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20Q41sj',$,$,$,(#189),#362);
#362= IFCMATERIALPROFILESETUSAGE(#345,5,$);
#341= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20QURsj',$,$,$,(#194),#363);
#363= IFCMATERIALPROFILESETUSAGE(#345,6,$);
#342= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20Qw9sj',$,$,$,(#199),#364);
#364= IFCMATERIALPROFILESETUSAGE(#345,7,$);
#343= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20QOcsj',$,$,$,(#204),#365);
#365= IFCMATERIALPROFILESETUSAGE(#345,8,$);
#344= IFCRELASSOCIATESMATERIAL('0juf4qyggSstrxA20Qw6sj',$,$,$,(#209),#366);
#366= IFCMATERIALPROFILESETUSAGE(#345,9,$);
#349= IFCRELAGGREGATES('1FUTCayKJbIQqDNnZzXu07',$,$,$,#259,(#238));
ENDSEC;
END-ISO-10303-21;
@@ -0,0 +1,49 @@
# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
#
# This file is part of IfcOpenShell.
#
# IfcOpenShell is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IfcOpenShell 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import pathlib
import pytest
import ifcopenshell.util.unit
UNITS_FIXTURE_DIR = pathlib.Path(__file__).parent.parent / "fixtures" / "units"
@pytest.mark.parametrize("ifc_file", UNITS_FIXTURE_DIR.glob("*.ifc"))
def test_file_units_length_convert(ifc_file):
f = ifcopenshell.open(ifc_file)
project_unit = ifcopenshell.util.unit.get_project_unit(f, "LENGTHUNIT")
if project_unit.Prefix == "MILLI":
target_units = "METERS"
scale = 0.001
else:
target_units = "MILLIMETERS"
scale = 1000
new_f = ifcopenshell.util.unit.convert_file_length_units(f, target_units)
for element, attr, val in ifcopenshell.util.unit.iter_element_and_attributes_per_type(new_f, "IfcLengthMeasure"):
elem_id = element.id()
original_element = f.by_id(elem_id)
original_val = getattr(original_element, attr.name())
if isinstance(original_val, tuple):
# assert element is equal to original element times scale
assert val == tuple([v * scale for v in original_val])
else:
# assert element is equal to original element times scale
assert val == original_val * scale