Example #1
0
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)
Example #2
0
    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.")
Example #3
0
    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)
Example #4
0
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")
Example #5
0
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