def mesh_mixed_shell_and_beams(p: Part): p.connections.find() with GmshSession(silent=True, options=GmshOptions(Mesh_Algorithm=8)) as gs: gmap = dict() for obj in p.get_all_physical_objects(): if type(obj) is Beam: li = gs.add_obj(obj, geom_repr="line", build_native_lines=False) gmap[obj] = li.entities elif type(obj) is Plate: pl = gs.add_obj(obj, geom_repr="shell") gmap[obj] = pl.entities beams = list(p.get_all_physical_objects(by_type=Beam)) gs.open_gui() for pl in p.get_all_physical_objects(by_type=Plate): intersecting_beams = [] for pl_dim, pl_ent in gmap[pl]: for bm in find_beams_connected_to_plate(pl, beams): for li_dim, li_ent in gmap[bm]: intersecting_beams.append(li_ent) gs.model.mesh.embed(1, intersecting_beams, 2, pl_ent) gs.model.geo.synchronize() gs.mesh(0.1) p.fem = gs.get_fem()
def build_test_beam(): a = Assembly('MyAssembly') p = Part('MyPart') p.add_beam(Beam('Bm', (0, 0, 0), (1, 0, 0), 'IPE300')) p.gmsh.mesh(0.5) a.add_part(p) return a
def test_simple_hinged_beam(test_dir): bm = Beam("MyBeam", (0, 0, 0), (1, 0, 0), "IPE400") bm.hinge_prop = HingeProp(end1=Hinge([1, 2, 3, 4, 6], Csys("MyBeam_hinge"))) p = Part("MyPart") / bm p.fem = p.to_fem_obj(0.1) convert_hinges_2_couplings(p.fem) assert len(p.fem.constraints.values()) == 1
def read_sesam_fem(bulk_str, part_name): """ Reads the content string of a Sesam input file and converts it to FEM objects :param bulk_str: :param part_name: Name of part :rtype: ada.Part """ from ada import Part part = Part(part_name) fem = part.fem fem._nodes = get_nodes(bulk_str, fem) fem._elements = get_elements(bulk_str, fem) fem.elements.build_sets() part._materials = get_materials(bulk_str, part) fem._sets = part.fem.sets + get_sets(bulk_str, fem) fem._sections = get_sections(bulk_str, fem) # part.fem._masses = get_mass(bulk_str, part.fem) fem._constraints += get_constraints(bulk_str, fem) fem._springs = get_springs(bulk_str, fem) fem._bcs += get_bcs(bulk_str, fem) print(8 * "-" + f'Imported "{fem.instance_name}"') return part
def build_test_beam(): a = Assembly("MyAssembly") p = Part("MyPart") p.add_beam(Beam("Bm", (0, 0, 0), (1, 0, 0), "IPE300")) p.gmsh.mesh(0.5) a.add_part(p) return a
def test_meter_to_millimeter(test_units_dir): p = Part( "MyTopSpatialLevel", metadata=dict(ifctype="storey", description="MyTopLevelSpace"), ) bm1 = Beam("bm1", n1=[0, 0, 0], n2=[2, 0, 0], sec="IPE220", colour="red") p2 = Part( "MySecondLevel", metadata=dict(ifctype="storey", description="MySecondLevelSpace"), ) bm2 = Beam("bm2", n1=[0, 0, 0], n2=[0, 2, 0], sec="IPE220", colour="blue") p3 = Part( "MyThirdLevel", metadata=dict(ifctype="storey", description="MyThirdLevelSpace"), ) bm3 = Beam("bm3", n1=[0, 0, 0], n2=[0, 0, 2], sec="IPE220", colour="green") pl1 = Plate( "pl1", [(0, 0, 0), (0, 0, 2), (0, 2, 2), (0, 2.0, 0.0)], 0.01, use3dnodes=True, ) a = Assembly("MySiteName", project="MyTestProject") / [ p / [bm1, p2 / [bm2, p3 / [bm3, pl1]]] ] # a.to_ifc(test_units_dir / "my_test_in_meter.ifc") a.units = "mm" assert tuple(bm3.n2.p) == (0, 0, 2000) assert pl1.t == 10
def test_2ifc_simple(self): a = Assembly("ExportedPlates") p = Part("MyPart") a.add_part(p) atts2 = dict(origin=(0, 0, 0), xdir=(1, 0, 0), normal=(0, -1, 0)) pl2 = Plate("MyPl2", [(0, 0, 0.2), (5, 0, 0.2), (5, 5), (0, 5)], 20e-3, **atts2) p.add_plate(pl2) a.to_ifc(test_folder / "my_plate_poly.ifc")
def test_fem(self): a = Assembly("MyAssembly") p = Part("MyPart") p.add_beam(Beam("Bm", (0, 0, 0), (1, 0, 0), "IPE300")) a.add_part(p) a.gmsh.mesh() a._repr_html_() a._renderer.toggle_mesh_visibility()
def test_material_ifc_roundtrip(materials_test_dir): ifc_path = materials_test_dir / "my_material.ifc" p = Part("MyPart") p.add_material(Material("my_mat")) a = Assembly("MyAssembly") / p fp = a.to_ifc(ifc_path, return_file_obj=True) b = ada.from_ifc(fp) assert len(b.materials) == 1
def test_pipe_straight(dummy_display): a = Assembly("MyTest") p = Part("MyPart") a.add_part(p) z = 3.2 y0 = -200e-3 pipe1 = Pipe("Pipe1", [(0, y0, 0), (0, y0, z)], Section("PSec", "PIPE", r=0.10, wt=5e-3)) p.add_pipe(pipe1) _ = a.to_ifc(test_dir / "pipe_straight.ifc", return_file_obj=True) dummy_display(a)
def test_pipe_straight(self): a = Assembly("MyTest") p = Part("MyPart") a.add_part(p) z = 3.2 y0 = -200e-3 pipe1 = Pipe("Pipe1", [(0, y0, 0), (0, y0, z)], Section("PSec", "PIPE", r=0.10, wt=5e-3)) p.add_pipe(pipe1) a.to_ifc(test_folder / "pipe_straight.ifc") a._repr_html_()
def test_material_ifc_roundtrip(self): ifc_name = 'my_material.ifc' a = Assembly('MyAssembly') p = Part('MyPart') p.add_material(Material('my_mat')) a.add_part(p) a.to_ifc(test_folder / ifc_name) b = Assembly('MyImport') b.read_ifc(test_folder / ifc_name)
def test_material_ifc_roundtrip(self): ifc_name = "my_material.ifc" a = Assembly("MyAssembly") p = Part("MyPart") p.add_material(Material("my_mat")) a.add_part(p) a.to_ifc(test_folder / ifc_name) b = Assembly("MyImport") b.read_ifc(test_folder / ifc_name)
def test_bbox_viz(): blist = [] ypos = 0 for sec in ["IPE300", "HP200x10", "TUB300x30", "TUB300/200x20"]: bm = Beam(sec, (0, ypos, 0), (0, ypos, 1), sec) blist += [ Part(sec + "_Z") / [ bm, PrimBox("Bbox_Z_" + sec, *bm.bbox.minmax, colour="red", opacity=0.5) ] ] bm = Beam(sec, (0, ypos, 2), (1, ypos, 2), sec) blist += [ Part(sec + "_X") / [ bm, PrimBox("Bbox_X_" + sec, *bm.bbox.minmax, colour="red", opacity=0.5) ] ] bm = Beam("bm_" + sec + "_Y", (ypos, 0, 3), (ypos, 1, 3), sec) blist += [ Part(sec + "_Y") / [ bm, PrimBox("Bbox_Y_" + sec, *bm.bbox.minmax, colour="red", opacity=0.5) ] ] bm = Beam("bm_" + sec + "_XYZ", (ypos, ypos, 4), (ypos + 1, ypos + 1, 5), sec) blist += [ Part(sec + "_XYZ") / [ bm, PrimBox("Bbox_XYZ_" + sec, *bm.bbox.minmax, colour="red", opacity=0.5) ] ] ypos += 1 a = Assembly() / blist _ = a.to_ifc(test_dir / "beam_bounding_box.ifc", return_file_obj=True)
def test_beam_directions(self): a = Assembly("AdaRotatedProfiles") p = Part("Part") a.add_part(p) props = dict(spre="/JSB_VA-DIN-SPEC/Y26IPE400", matr="/GR.355-II(Y26)_jsb_va") p.add_beam( Beam( "bm_test2X0", n1=[0, 0, 0], n2=[5, 0, 0], sec=section, angle=0, metadata=dict(props=props), ) ) p.add_beam( Beam( "bm_test2X90", n1=[0, 0, 1], n2=[5, 0, 1], sec=section, angle=90, metadata=dict(props=props), ) ) p.add_beam( Beam( "bm_test2Y0", n1=[0, 0, 2], n2=[0, 5, 2], sec=section, angle=0, metadata=dict(props=props), ) ) p.add_beam( Beam( "bm_test2Y90", n1=[0, 0, 3], n2=[0, 5, 3], sec=section, angle=90, metadata=dict(props=props), ) ) a.to_ifc(test_folder / "my_angled_profiles.ifc")
def create_ifc(name, up=(0, 0, 1)): a = Assembly("MyAssembly") p = Part(name) p.add_beam( Beam( "bm_up", n1=[0, 0, 0], n2=[2, 0, 0], sec="HP200x10", mat=Material("SteelMat", CarbonSteel("S420")), colour="red", up=up, )) a.add_part(p) a.to_ifc(test_folder / name)
def test_export_basic(ifc_test_dir): bm = Beam( "MyBeam", (0, 0, 0), (2, 0, 0), Section("MySec", from_str="BG300x200x10x20"), metadata=dict(hidden=True), ) bm1 = Beam("bm1", n1=[0, 0, 0], n2=[2, 0, 0], sec="IPE220", colour="red") bm2 = Beam("bm2", n1=[0, 0, 0], n2=[0, 2, 0], sec="IPE220", colour="blue") bm3 = Beam("bm3", n1=[0, 0, 0], n2=[0, 0, 2], sec="IPE220", colour="green") bm4 = Beam("bm4", n1=[0, 0, 0], n2=[2, 0, 2], sec="IPE220", colour="black") bm5 = Beam("bm5", n1=[0, 0, 2], n2=[2, 0, 2], sec="IPE220", colour="white") user = User(user_id="krande", org_id="ADA", org_name="Assembly Test") pl1 = Plate( "pl1", [(0, 0, 0), (0, 0, 2), (0, 2, 2), (0, 2.0, 0.0)], 0.01, use3dnodes=True, ) a = Assembly("MyFirstIfcFile", user=user) / ( Part("MyBldg", metadata=dict(ifctype="building")) / [bm, bm1, bm2, bm3, bm4, bm5, pl1] ) a.to_ifc(ifc_test_dir / "my_test.ifc", return_file_obj=True)
def test_wall_simple(self): points = [(0, 0, 0), (5, 0, 0), (5, 5, 0)] w = Wall("MyWall", points, 3, 0.15, offset="LEFT") wi = Window("MyWindow1", 1.5, 1, 0.15) wi2 = Window("MyWindow2", 2, 1, 0.15) door = Door("Door1", 1.5, 2, 0.2) w.add_insert(wi, 0, 1, 1.2) w.add_insert(wi2, 1, 1, 1.2) w.add_insert(door, 0, 3.25, 0) a = Assembly("MyAssembly") p = Part("MyPart") a.add_part(p) p.add_wall(w) a.to_ifc(test_folder / "my_wall_wDoorsWindows.ifc") a._repr_html_()
def test_poly_extrude(): bm = Beam("MyBeam", (0, 0, 0), (2, 0, 0), Section("myIPE", from_str="IPE400")) a = Assembly("Test") / [Part("MyPart") / bm] h = 0.2 r = 0.02 origin = np.array([0.1, 0.1, -0.1]) normal = np.array([0, -1, 0]) xdir = np.array([1, 0, 0]) points = [(0, 0, r), (0.1, 0, r), (0.05, 0.1, r)] bm.add_penetration(PrimExtrude("my_pen1", points, h, normal, origin, xdir)) origin += np.array([0.2, 0, 0]) points = [(0, 0, r), (0.1, 0, r), (0.1, 0.2, r), (0, 0.2, r)] bm.add_penetration(PrimExtrude("my_pen2", points, h, normal, origin, xdir)) origin += np.array([0.2, 0, 0]) points = [(0, 0, r), (0.2, 0, r), (0.25, 0.1, r), (0.25, 0.25, r), (0, 0.25, r)] bm.add_penetration(PrimExtrude("my_pen3", points, h, normal, origin, xdir)) origin += np.array([0.4, 0, 0]) points = [ (0, 0, r), (0.2, 0, r), (0.25, 0.1, r), (0.5, 0.0, r), (0.5, 0.25, r), (0, 0.25, r), ] bm.add_penetration(PrimExtrude("my_pen4", points, h, normal, origin, xdir)) _ = a.to_ifc(test_dir / "penetrations_poly.ifc", return_file_obj=True)
def test_beam_rotation_by_angle(): # Define beam rotations using vectors angles = [0, 90, 180, 270] vectorX = [(0, 0, 1), (0, -1, 0), (0, 0, -1), (0, 1, 0)] vectorY = [(0, 0, 1), (1, 0, 0), (0, 0, -1), (-1, 0, 0)] vectorZ = [(0, 1, 0), (-1, 0, 0), (0, -1, 0), (1, 0, 0)] a = Assembly("AdaRotatedProfiles") p = a.add_part(Part("RotatedBeams")) sec = "HP200x10" d1 = dict(n1=(0, 0, 0), n2=(5, 0, 0), sec=sec) d2 = dict(n1=(0, 0, 0), n2=(0, 5, 0), sec=sec) d3 = dict(n1=(0, 0, 0), n2=(0, 0, 5), sec=sec) for i, angle in enumerate(angles): # Along X-Axis bm = p.add_beam(Beam(f"bmX_n{i}_a", **d1, angle=angle)) assert all([x == y for x, y in zip(bm.up, vectorX[i])]) is True p.add_beam(Beam(f"bmX_n{i}_v", **d1, up=vectorX[i])) # Along Y-Axis bm = p.add_beam(Beam(f"bmY_n{i}_a", **d2, angle=angle)) assert all([x == y for x, y in zip(bm.up, vectorY[i])]) is True p.add_beam(Beam(f"bmY_n{i}_v", **d2, up=vectorY[i])) # Along Z-Axis bm = p.add_beam(Beam(f"bmZ_n{i}_a", **d3, angle=angle)) assert all([x == y for x, y in zip(bm.up, vectorZ[i])]) is True p.add_beam(Beam(f"bmZ_n{i}_v", **d3, up=vectorZ[i]))
def line_elem_to_beam(elem: Elem, parent: Part) -> Beam: """Convert FEM line element to Beam""" a = parent.get_assembly() n1 = elem.nodes[0] n2 = elem.nodes[-1] e1 = None e2 = None elem.fem_sec.material.parent = parent if a.convert_options.fem2concepts_include_ecc is True: if elem.eccentricity is not None: ecc = elem.eccentricity if ecc.end1 is not None and ecc.end1.node.id == n1.id: e1 = ecc.end1.ecc_vector if ecc.end2 is not None and ecc.end2.node.id == n2.id: e2 = ecc.end2.ecc_vector if elem.fem_sec.section.type == "GENBEAM": logging.error( f"Beam elem {elem.id} uses a GENBEAM which might not represent an actual cross section" ) return Beam( f"bm{elem.id}", n1, n2, elem.fem_sec.section, elem.fem_sec.material, up=elem.fem_sec.local_z, e1=e1, e2=e2, parent=parent, )
def test_cone_beam(self): s_o = [(375.0, 375.0, 375.0), (375.0, -375.0, 375.0), (-375.0, -375.0, 375.0), (-375.0, 375.0, 375.0)] s_i = [(325.0, 325.0, 325.0), (-325.0, 325.0, 325.0), (-325.0, -325.0, 325.0), (325.0, -325.0, 325.0)] e_o = [(525.0, 525.0, 525.0), (525.0, -525.0, 525.0), (-525.0, -525.0, 525.0), (-525.0, 525.0, 525.0)] e_i = [(475.0, 475.0, 475.0), (-475.0, 475.0, 475.0), (-475.0, -475.0, 475.0), (475.0, -475.0, 475.0)] poly_s_o = CurvePoly(s_o, (0, 0, 0), (0, 0, 1), (1, 0, 0)) poly_s_i = CurvePoly(s_i, (0, 0, 0), (0, 0, 1), (1, 0, 0)) section_s = Section('MyStartCrossSection', "poly", outer_poly=poly_s_o, inner_poly=poly_s_i, units="mm") poly_e_o = CurvePoly(e_o, (0, 0, 0), (0, 0, 1), (1, 0, 0)) poly_e_i = CurvePoly(e_i, (0, 0, 0), (0, 0, 1), (1, 0, 0)) section_e = Section('MyEndCrossSection', "poly", outer_poly=poly_e_o, inner_poly=poly_e_i, units="mm") bm = Beam('MyCone', (2, 2, 2), (4, 4, 4), sec=section_s, tap=section_e) a = Assembly( 'Level1', project='Project0', creator='krande', units='mm') / (Part('Level2') / bm) a.to_ifc(test_folder / 'cone_ex.ifc')
def test_bm_eigenfrequency_shell(self): bm = test_bm() p = Part("MyPart") a = Assembly("MyAssembly") / [p / bm] create_beam_mesh(bm, p.fem, "shell") fix_set = p.fem.add_set(FemSet("bc_nodes", get_beam_end_nodes(bm), "nset")) a.fem.add_bc(Bc("Fixed", fix_set, [1, 2, 3, 4, 5, 6])) a.fem.add_step(Step("Eigen", "eigenfrequency")) a.to_fem("Cantilever_CA_EIG_sh", "abaqus", overwrite=True) a.to_fem("Cantilever_CA_EIG_sh", "sesam", overwrite=True) res = a.to_fem("Cantilever_CA_EIG_sh", "code_aster", overwrite=True, execute=True) f = h5py.File(res.results_file_path) modes = f.get("CHA/modes___DEPL") for mname, m in modes.items(): mode = m.attrs["NDT"] freq = m.attrs["PDT"] print(mode, freq)
def penetration_check(part: Part): a = part.get_assembly() cog = part.nodes.vol_cog normal = part.placement.zdir for p in a.get_all_subparts(): for pipe in p.pipes: for segment in pipe.segments: if type(segment) is PipeSegStraight: assert isinstance(segment, PipeSegStraight) p1, p2 = segment.p1, segment.p2 v1 = (p1.p - cog) * normal v2 = (p2.p - cog) * normal if np.dot(v1, v2) < 0: part.add_penetration( PrimCyl(f"{p.name}_{pipe.name}_{segment.name}_pen", p1.p, p2.p, pipe.section.r + 0.1))
def test_export_layers(): bm = Beam( "MyBeam", (0, 0, 0), (2, 0, 0), Section("MySec", from_str="BG300x200x10x20"), metadata=dict(hidden=True), ) webh = bm.section.h - bm.section.t_fbtn * 2 pl1 = Plate( "Web1", [(0, 0), (2, 0), (2, webh), (0, webh)], bm.section.t_w, placement=Placement(origin=(0, -bm.section.w_btn / 2 + bm.section.t_w, -webh / 2), zdir=(0, -1, 0), xdir=(1, 0, 0)), ) pl2 = Plate( "Web2", [(0, 0), (2, 0), (2, webh), (0, webh)], bm.section.t_w, placement=Placement(origin=(0, bm.section.w_btn / 2, -webh / 2), zdir=(0, -1, 0), xdir=(1, 0, 0)), ) pl3 = Plate( "Fla1", [(0, 0), (2, 0), (2, bm.section.w_top), (0, bm.section.w_top)], bm.section.t_fbtn, placement=Placement(origin=(0, -bm.section.w_btn / 2, -bm.section.h / 2), zdir=(0, 0, 1), xdir=(1, 0, 0)), ) pl4 = Plate( "Fla2", [(0, 0), (2, 0), (2, bm.section.w_top), (0, bm.section.w_top)], bm.section.t_fbtn, placement=Placement( origin=(0, -bm.section.w_btn / 2, bm.section.h / 2 - bm.section.t_fbtn), zdir=(0, 0, 1), xdir=(1, 0, 0), ), ) p = Part("MyBldg", metadata=dict(ifctype="building")) a = Assembly("MySite", project="MyLayersProject") / (p / [bm, pl1, pl2, pl3, pl4]) ifc_name = "MyLayerTest.ifc" fp = a.to_ifc(test_dir / ifc_name, return_file_obj=True) print(a) b = ada.from_ifc(fp) print(b)
def get_part_from_bulk_str(name, bulk_str, parent, instance_name=None, metadata=None): from ada import Part metadata = dict(move=None, rotate=None) if metadata is None else metadata instance_name = name if instance_name is None else instance_name if instance_name is None: instance_name = "Temp" fem = FEM(name=instance_name, metadata=metadata) part = Part(name, fem=fem, parent=parent) fem._nodes = get_nodes_from_inp(bulk_str, fem) fem.nodes.move(move=fem.metadata["move"], rotate=fem.metadata["rotate"]) fem._elements = get_elem_from_inp(bulk_str, fem) fem.elements.build_sets() bulk_sets = get_sets_from_bulk(bulk_str, fem) fem._sets = fem.sets + bulk_sets fem._sections = get_sections_from_inp(bulk_str, fem) fem._bcs += get_bcs_from_bulk(bulk_str, fem) fem._masses = get_mass_from_bulk(bulk_str, fem) fem.surfaces.update(get_surfaces_from_bulk(bulk_str, fem)) fem._lcsys = get_lcsys_from_bulk(bulk_str, fem) fem._constraints = get_constraints_from_inp(bulk_str, fem) return part
def import_ifc_hierarchy(assembly: Assembly, product, ifc_ref: IfcRef): pr_type = product.is_a() pp = get_parent(product) if pp is None: return None, None # "IfcSpace", if pr_type not in ["IfcBuilding", "IfcBuildingStorey", "IfcSpatialZone"]: return None, None props = get_psets(product) name = product.Name if name is None: logging.debug( f'Name was not found for the IFC element "{product}". Will look for ref to name in props' ) name = resolve_name(props, product) new_part = Part( name, metadata=dict(original_name=name, props=props), guid=product.GlobalId, ifc_ref=ifc_ref, units=assembly.units, ) pp_name = pp.Name if pp_name is None: pp_name = resolve_name(get_psets(pp), pp) if pp_name is None: return None, None parent = assembly.get_by_name(pp_name) return parent, new_part
def test_beam_offset(self): bm1 = Beam( "bm1", n1=[0, 0, 0], n2=[2, 0, 0], sec="IPE300", mat=Material("SteelMat", CarbonSteel("S420")), colour="red", up=(0, 0, 1), e1=(0, 0, -0.1), e2=(0, 0, -0.1), ) bm2 = Beam( "bm2", n1=[0, 0, 0], n2=[2, 0, 0], sec="IPE300", mat=Material("SteelMat", CarbonSteel("S420")), colour="blue", up=(0, 0, -1), e1=(0, 0, -0.1), e2=(0, 0, -0.1), ) a = Assembly("Toplevel") / [Part("MyPart") / [bm1, bm2]] a.to_ifc(test_folder / "beams_offset.ifc")
def test_ex1(self): origin = [362237.0037951513, 100000.0, 560985.9095763591] csys = [ [0.0, -1.0, 0.0], [-0.4626617625735456, 0.0, 0.8865348799975894], [-0.8865348799975894, 0.0, -0.4626617625735456], ] local_points2d = [ [4.363213751783499e-11, 229.80445306040926], [1.4557793281525672e-11, -57.217605078163196], [2.912511939794014e-11, -207.22885580839431], [-330.0, -207.25, -4.518217213237464e-11], [-400.0, -122.2, 50.0], [-400.0, 42.79, 50.0], [-325.0, 267.83, 50.0], [-85.00004587126028, 650.0198678083951, 24.999999999931404], [-35.0, 650.02, -7.881391015070461e-12], [-35.0, 350.1], [-15.14, 261.52], ] thick = 30 pl = Plate("test", local_points2d, thick, origin=origin, normal=csys[2], xdir=csys[0], units="mm") a = Assembly() / [Part("te") / pl] a.to_ifc(test_folder / "error_plate.ifc")
def test_ex2(self): origin = [362857.44778571784, 100000.0, 561902.5557556185] csys = [ [0.0, 1.0, 0.0], [-0.9756456931466083, 0.0, 0.2193524138104576], [0.2193524138104576, 0.0, 0.9756456931466083], ] local_points2d = [ [-35.000000000029075, 246.8832348783828], [-15.0, 154.3], [6.4472604556706474e-15, 74.98044924694155], [0.0, -170.7], [-3.376144703353855e-14, -320.6997855533479], [-330.0, -320.7, -1.0189517968329821e-10], [-400.0, -235.7, 50.0], [-400.0, -70.7, 50.0], [-325.0, 154.3, 50.0], [-85.00004587117287, 500.03303441608927, 24.99999999997542], [-34.99999999999994, 500.0330344161669, -7.881391015070461e-12], ] thick = 30 pl = Plate("test2", local_points2d, thick, origin=origin, normal=csys[2], xdir=csys[0], units="mm") a = Assembly(units="mm") / [Part("te", units="mm") / pl] a.to_ifc(test_folder / "error_plate2.ifc")