def serialize_fenics_function(mesh, fenics_function): def _write_fenics_file(data, path): fn.File(path) << data serial_mesh = store_serial(mesh, _write_fenics_file, "xml") serial_function = store_serial(fenics_function, _write_fenics_file, "xml") return SerialFenicsFunctionData(serial_mesh, serial_function)
def set_data(self, data_name: str, data: Any, scratch_dir: Optional[str] = None): """Set data to a serial format that is easily portable. Parameters ---------- data_name : str "fcdoc" freeCAD document "mesh" fenics mesh "rmf" fenics region marker function data : The corresponding data that we would like to set. scratch_dir : str Optional existing temporary (fast) storage location. (Default value = None) Returns ------- None """ if data_name == "fcdoc": def _save_fct(doc, path): doc.saveAs(path) self.serial_fcdoc = store_serial(data, _save_fct, "fcstd", scratch_dir=scratch_dir) elif data_name == "mesh" or data_name == "rmf": def _save_fct(data, path): fn.File(path) << data if data_name == "mesh": self.serial_mesh = store_serial(data, _save_fct, "xml", scratch_dir=scratch_dir) if data_name == "rmf": self.serial_region_marker = store_serial( data, _save_fct, "xml", scratch_dir=scratch_dir) else: raise ValueError(f"{data_name} was not a valid data_name.")
def set_data(self, data: Any, scratch_dir: Optional[str] = None): """Set data to a serial format that is easily portable. Parameters ---------- data : The corresponding data that we would like to set. scratch_dir : str Optional existing temporary (fast) storage location. (Default value = None) Returns ------- None """ def _save_fct(doc, path): doc.saveAs(path) self.serial_fcdoc = store_serial(data, _save_fct, "fcstd", scratch_dir=scratch_dir)
def test_store_serial(datadir, fix_FCDoc): """Test serialisation to memory.""" import FreeCAD # Serialise document obj = fix_FCDoc.addObject("App::FeaturePython", "some_content") serial_data = store_serial(fix_FCDoc, lambda d, p: d.saveAs(p), "fcstd") # Write to a file file_path = os.path.join(datadir, "test.fcstd") data = codecs.decode(serial_data.encode(), "base64") with open(file_path, "wb") as of: of.write(data) # Load back and check doc = FreeCAD.newDocument("instance") FreeCAD.setActiveDocument("instance") doc.load(file_path) assert doc.getObject("some_content") is not None FreeCAD.closeDocument("instance")
def build(opts): """Build the 3D geometry in FreeCAD. Parameters ---------- opts : dict Options dict in the QMT Geometry3D.__init__ input format. Options dict in the QMT Geometry3D.__init__ input format. Returns ------- Geo3DData object. """ doc = FreeCAD.ActiveDocument geo = Geo3DData(opts.get("lunit", None)) # Schedule for deletion all objects not explicitly selected by the user input_parts_names = [] for part in opts["input_parts"]: if part.fc_name is None: obj_list = doc.getObjectsByLabel(part.label) if len(obj_list) != 1: msg = f"Part labeled {part.label} returned object list {obj_list}" raise KeyError(msg) fc_name = obj_list[0].Name part.fc_name = fc_name else: fc_name = part.fc_name input_parts_names += [fc_name] blacklist = [] for obj in doc.Objects: if (obj.Name not in input_parts_names) and (obj.TypeId != "Spreadsheet::Sheet"): blacklist.append(obj) # Update the model parameters if "params" in opts: # Extend params dictionary to original parts schema fcdict = { key: (value, "freeCAD") for (key, value) in opts["params"].items() } set_params(doc, fcdict) doc.recompute( ) # recompute here to update any sketches that change due to parameters if "built_part_names" not in opts: opts["built_part_names"] = {} if "serial_stp_parts" not in opts: opts["serial_stp_parts"] = {} # Build the parts info_holder = DummyInfo() # temporary workaround to support old litho code built_parts = [] for input_part in opts["input_parts"]: if isinstance(input_part, part_3d.ExtrudePart): part = build_extrude(input_part) elif isinstance(input_part, part_3d.SAGPart): part = build_sag(input_part) elif isinstance(input_part, part_3d.WirePart): part = build_wire(input_part) elif isinstance(input_part, part_3d.WireShellPart): part = build_wire_shell(input_part) elif isinstance(input_part, part_3d.LithographyPart): part = build_lithography(input_part, opts, info_holder) elif isinstance(input_part, part_3d.Geo3DPart): part = build_pass(input_part) else: raise ValueError( f"{input_part} is not a recognized Geo3DPart type") assert part is not None doc.recompute() built_parts.append(part) # needed for litho steps opts["built_part_names"][input_part.label] = part.Name # Cleanup if not DBG_OUT: collect_garbage(info_holder) for obj in blacklist: delete(obj) doc.recompute() # Subtraction (removes the need for subtractlists) for i, (input_part, part) in enumerate(zip(opts["input_parts"], built_parts)): if input_part.virtual: continue for other_input_part, other_part in zip(opts["input_parts"][0:i], built_parts[0:i]): if other_input_part.virtual: continue if checkOverlap([part, other_part]): cut = subtract( part, copy_move(other_part), consumeInputs=True if not DBG_OUT else False, ) simple_copy = doc.addObject("Part::Feature", "simple_copy") # no solid, just its shape (can be disjoint) simple_copy.Shape = cut.Shape delete(cut) part = simple_copy built_parts[i] = simple_copy # Update names and store the built parts built_parts_dict = {} # dict for cross sections for input_part, built_part in zip(opts["input_parts"], built_parts): built_part.Label = input_part.label # here it's collision free output_part = deepcopy(input_part) output_part.serial_stp = store_serial([built_part], exportCAD, "stp") output_part.serial_stl = store_serial([built_part], exportMeshed, "stl") output_part.built_fc_name = built_part.Name geo.add_part(output_part.label, output_part) # dict for cross sections built_parts_dict[input_part.label] = built_part # Build cross sections: for xsec_name in opts["xsec_dict"]: axis = opts["xsec_dict"][xsec_name]["axis"] distance = opts["xsec_dict"][xsec_name]["distance"] polygons = buildCrossSection(xsec_name, axis, distance, built_parts_dict) geo.add_xsec(xsec_name, polygons, axis=axis, distance=distance) # Store the FreeCAD document geo.set_data(doc) return geo