From 4c38f8df36f5d6b47acb475263189683994f2f84 Mon Sep 17 00:00:00 2001 From: krande Date: Thu, 7 Nov 2024 19:38:06 +0100 Subject: [PATCH] added xml export support --- examples/scripts/gxml_develop/flat_plate.py | 18 +++++--- src/ada/cadit/gxml/write/write_beams.py | 3 +- src/ada/cadit/gxml/write/write_plates.py | 41 +++++++++++++++++++ .../cadit/gxml/write/write_sat_embedded.py | 23 ++--------- src/ada/cadit/gxml/write/write_xml.py | 37 ++++++++++++++--- src/ada/cadit/sat/write/writer.py | 2 +- 6 files changed, 90 insertions(+), 34 deletions(-) create mode 100644 src/ada/cadit/gxml/write/write_plates.py diff --git a/examples/scripts/gxml_develop/flat_plate.py b/examples/scripts/gxml_develop/flat_plate.py index ca76cdad0..f596b86c7 100644 --- a/examples/scripts/gxml_develop/flat_plate.py +++ b/examples/scripts/gxml_develop/flat_plate.py @@ -11,10 +11,13 @@ def main(): - output_dir = pathlib.Path("temp") + output_dir = pathlib.Path("temp").resolve().absolute() output_dir.mkdir(exist_ok=True) dest_sat_file = output_dir / "flat_plate_sesam_10x10.sat" + dest_gxml_file = output_dir / "flat_plate_sesam_10x10.xml" + exported_flat = output_dir / "exported_flat_plate_10x10.xml" + res = ada.from_genie_xml(exported_flat) startup_js_file = output_dir / 'startup.js' workspace = output_dir / "workspace/flat_plate_sesam_10x10" workspace.mkdir(parents=True, exist_ok=True) @@ -22,14 +25,17 @@ def main(): pl = ada.Plate("pl", [(0, 0), (10, 0), (10, 10), (0, 10)], 0.1) pl2 = ada.Plate("pl2", [(0, 0), (10, 0), (10, 10), (0, 10)], 0.1, origin=(10, 10, 0)) pl3 = ada.Plate("pl3", [(0, 0), (10, 0), (10, 2), (8, 2), (8, 4), (10, 4),(10,10), (0, 10)], 0.1, origin=(0, 0, 2)) + plates = [pl] #, pl2, pl3] + a = ada.Assembly() / plates + a.to_genie_xml(dest_gxml_file, embed_sat=True) - a = ada.Assembly() / (pl, pl3, pl2) sw = part_to_sat_writer(a) sw.write(dest_sat_file) + xml_import = f'XmlImporter = ImportConceptXml();\nXmlImporter.DoImport("{dest_gxml_file.as_posix()}");' + sat_import = f'SatImporter = ImportGeometrySat();\nSatImporter.DoImport("{dest_sat_file.as_posix()}");' with open(startup_js_file, 'w') as f: - f.write("SatImporter = ImportGeometrySat();\n") - f.write(f'SatImporter.DoImport("{dest_sat_file.resolve().absolute().as_posix()}");') + f.write(xml_import) genie_exe = os.getenv("ADA_GENIE_EXE") if genie_exe is None: @@ -37,10 +43,10 @@ def main(): return args = f"\"{genie_exe}\" {workspace.absolute().as_posix()} /new /com={startup_js_file.resolve().absolute().as_posix()}" - subprocess.run(args, shell=True) + #subprocess.run(args, shell=True) # If you want to start an external process, you can use the following line: - # os.system(args) + os.system(args) if __name__ == '__main__': diff --git a/src/ada/cadit/gxml/write/write_beams.py b/src/ada/cadit/gxml/write/write_beams.py index 31a185ef2..fcd0a140c 100644 --- a/src/ada/cadit/gxml/write/write_beams.py +++ b/src/ada/cadit/gxml/write/write_beams.py @@ -4,12 +4,13 @@ from typing import TYPE_CHECKING from .write_utils import add_local_system +from ...sat.write.writer import SatWriter if TYPE_CHECKING: from ada import Beam, Part -def add_beams(root: ET.Element, part: Part, sat_map: dict): +def add_beams(root: ET.Element, part: Part, sw: SatWriter = None): from ada import Beam for beam in part.get_all_physical_objects(by_type=Beam): diff --git a/src/ada/cadit/gxml/write/write_plates.py b/src/ada/cadit/gxml/write/write_plates.py new file mode 100644 index 000000000..11592ccad --- /dev/null +++ b/src/ada/cadit/gxml/write/write_plates.py @@ -0,0 +1,41 @@ +from __future__ import annotations + +import xml.etree.ElementTree as ET +from typing import TYPE_CHECKING + +from .write_utils import add_local_system +from ...sat.write.writer import SatWriter + +if TYPE_CHECKING: + from ada import Part, Plate + +def add_plate(plate: Plate, thck_name: str, structures_elem, sw: SatWriter): + structure = ET.SubElement(structures_elem, "structure") + flat_plate = ET.SubElement(structure, "flat_plate", {"name": plate.name, "thickness_ref": thck_name, "material_ref": plate.material.name}) + local_sys = ET.SubElement(flat_plate, "local_system") + ET.SubElement(local_sys, "vector", {"x": str(plate.poly.normal[0]), "y": str(plate.poly.normal[1]), "z": str(plate.poly.normal[2]), "dir": "z"}) + ET.SubElement(flat_plate, "front") + ET.SubElement(flat_plate, "back") + ET.SubElement(flat_plate, "segmentation") + geometry = ET.SubElement(flat_plate, "geometry") + sheet = ET.SubElement(geometry, "sheet") + sat_reference = ET.SubElement(sheet, "sat_reference") + ET.SubElement(sat_reference, "face", {"face_ref": sw.face_map.get(plate.guid)}) + +def add_plates(structure_domain: ET.Element, part: Part, sw: SatWriter): + from ada import Plate + + thickness = {} + properties = structure_domain.find("./properties") + thickness_elem = ET.SubElement(properties, "thicknesses") + structures_elem = structure_domain.find("./structures") + + for plate in part.get_all_physical_objects(by_type=Plate): + if plate.t not in thickness: + thickness[plate.t] = f"Tck{len(thickness)+1}" + tck_elem = ET.Element("thickness", {"name": thickness[plate.t], "default": "true"}) + tck_elem.append(ET.Element("constant_thickness", {"th": str(plate.t)})) + thickness_elem.append(tck_elem) + + thck_name = thickness[plate.t] + add_plate(plate, thck_name, structures_elem, sw) \ No newline at end of file diff --git a/src/ada/cadit/gxml/write/write_sat_embedded.py b/src/ada/cadit/gxml/write/write_sat_embedded.py index 28778edb0..00b2ab62a 100644 --- a/src/ada/cadit/gxml/write/write_sat_embedded.py +++ b/src/ada/cadit/gxml/write/write_sat_embedded.py @@ -2,31 +2,14 @@ import base64 import xml.etree.ElementTree as ET -from typing import TYPE_CHECKING -from ada.cadit.sat.utils import create_sat_from_beams -if TYPE_CHECKING: - from ada import Part - - -def embed_sat_geometry(root: ET.Element, part: Part) -> dict: +def embed_sat_geometry(root: ET.Element) -> None: geom = ET.SubElement(root, "geometry") sat_embedded = ET.SubElement(geom, "sat_embedded", dict(encoding="base64", compression="zip", tag_name="dnvscp")) - # Encode and compress the string - sat_map = dict() - beams_sat = create_sat_from_beams(part) - sat_map.update(beams_sat.sat_map) - - data = create_sesam_sat_bytes(beams_sat.sat_text) - - encoded_data = base64.b64encode(data).decode() - - # Add the encoded data to the element using CDATA - sat_embedded.text = "" - - return sat_map + # Temporary placeholder text for CDATA + sat_embedded.text = "__CDATA_PLACEHOLDER__" def create_sesam_sat_bytes(sat_body_str: str) -> bytes: diff --git a/src/ada/cadit/gxml/write/write_xml.py b/src/ada/cadit/gxml/write/write_xml.py index 5f76c16ea..7872667ae 100644 --- a/src/ada/cadit/gxml/write/write_xml.py +++ b/src/ada/cadit/gxml/write/write_xml.py @@ -1,16 +1,21 @@ from __future__ import annotations +import base64 import os import pathlib import xml.etree.ElementTree as ET +import zipfile +from io import BytesIO from typing import TYPE_CHECKING, Callable from .write_bcs import add_boundary_conditions from .write_beams import add_beams from .write_masses import add_masses from .write_materials import add_materials +from .write_plates import add_plates from .write_sat_embedded import embed_sat_geometry from .write_sections import add_sections +from ...sat.write.writer import part_to_sat_writer if TYPE_CHECKING: from ada import Part @@ -41,18 +46,38 @@ def write_xml(part: Part, xml_file, embed_sat=False, writer_postprocessor: Calla add_materials(properties, part) # Add SAT geometry (maybe only applicable for plate geometry) - sat_map = dict() + sw = None if embed_sat: - sat_map = embed_sat_geometry(structure_domain, part) + sw = part_to_sat_writer(part) + embed_sat_geometry(structure_domain) # Add structural elements - add_beams(structures_elem, part, sat_map) + add_beams(structures_elem, part, sw) + add_plates(structure_domain, part, sw) add_boundary_conditions(structures_elem, part) add_masses(structures_elem, part) if writer_postprocessor: writer_postprocessor(root, part) - # Write the modified XML back to the file - os.makedirs(xml_file.parent, exist_ok=True) - tree.write(str(xml_file)) + xml_file.parent.mkdir(exist_ok=True) + if embed_sat: + # Compress the SAT data + sat_bytes = bytes(sw.to_str(), encoding="utf-8") + compressed_io = BytesIO() + with zipfile.ZipFile(compressed_io, mode="w", compression=zipfile.ZIP_DEFLATED) as zipf: + zipf.writestr("b64temp.sat", sat_bytes) + compressed_data = compressed_io.getvalue() + + # Encode the compressed data in base64 + encoded_data = base64.b64encode(compressed_data).decode() + xml_str = ET.tostring(tree.getroot(), encoding="unicode") + cdata_section = f"" + xml_str = xml_str.replace("__CDATA_PLACEHOLDER__", cdata_section) + + # Write the modified XML string to the file + with open(xml_file, "w", encoding="utf-8") as file: + file.write(xml_str) + else: + # Write the modified XML back to the file + tree.write(str(xml_file), encoding="utf-8") diff --git a/src/ada/cadit/sat/write/writer.py b/src/ada/cadit/sat/write/writer.py index 25f32b6db..040000909 100644 --- a/src/ada/cadit/sat/write/writer.py +++ b/src/ada/cadit/sat/write/writer.py @@ -32,7 +32,7 @@ def part_to_sat_writer(part: Part | Assembly) -> SatWriter: # Plates for face_id, pl in enumerate(part.get_all_physical_objects(by_type=Plate), start=1): face_name = f"FACE{face_id:08d}" - sw.face_map[face_name] = pl.guid + sw.face_map[pl.guid] = face_name new_entities = plate_to_sat_entities(pl, face_name, GeomRepr.SHELL, sw) for entity in new_entities: sw.add_entity(entity)