Ejemplo n.º 1
0
def test_bounds_sphere_boundingbox_middle():
    r"""Test the determination of the bounding box middle"""
    # occutils.mesh.mesh(box)
    bb = BoundingBox(sphere_)
    assert bb.centre.X() < tol / 10.
    assert bb.centre.Y() < tol / 10.
    assert bb.centre.Z() < tol / 10.
Ejemplo n.º 2
0
def test_bounds_box():
    r"""Test the bounding box on a box shape"""
    # mesh(box)
    bb = BoundingBox(box_)
    assert box_dim_x <= bb.x_span < box_dim_x + 2.001 * tol
    assert box_dim_y <= bb.y_span < box_dim_y + 2.001 * tol
    assert box_dim_z <= bb.z_span < box_dim_z + 2.001 * tol
Ejemplo n.º 3
0
def convert_brep_file(brep_filename, target_folder, remove_original=True):
    r"""Convert a BREP file (.brep, .brp) for web display

    Parameters
    ----------
    brep_filename : str
        Full path to the BREP file
    target_folder : str
        Full path to the target folder for the conversion
    remove_original : bool
        Should the input file be deleted after conversion?
        It should be deleted on a web platform to save disk space, but, for
        testing, it might be useful not to delete it.

    Returns
    -------
    Nothing, it is a procedure

    """
    if not isdir(target_folder):
        mkdir(target_folder)
    shape = BrepImporter(brep_filename).shape
    converted_filename = _conversion_filename(brep_filename, target_folder, 0)
    converted_basenames = [basename(converted_filename)]
    _convert_shape(shape, converted_filename)

    _write_descriptor(
        BoundingBox(shape).max_dimension, converted_basenames,
        _descriptor_filename(target_folder, basename(brep_filename)))
    if remove_original is True:
        remove(brep_filename)
Ejemplo n.º 4
0
def test_bounds_sphere():
    r"""Test the bounding box on a sphere"""
    # mesh(box)
    bb = BoundingBox(sphere_)
    assert 2 * sphere_radius <= bb.x_span < 2 * sphere_radius + 2.001 * tol
    assert 2 * sphere_radius <= bb.y_span < 2 * sphere_radius + 2.001 * tol
    assert 2 * sphere_radius <= bb.z_span < 2 * sphere_radius + 2.001 * tol
Ejemplo n.º 5
0
def mesh(shape, factor=4000., use_min_dim=False):
    r"""Mesh a shape

    Parameters
    ----------
    shape : OCC.TopoDS.TopoDS_Shape
        Shape to mesh
    factor : float
        The higher, the finer the mesh
    use_min_dim : bool (optional)
        Use minimum bounding box dimension to compute the linear deflection.
        The default is False (i.e. use max dimension)
        This is useful for long and thin objects where using the max dimension
        would result in a very coarse linear deflection in the other directions.

    """
    bb = BoundingBox(shape)
    if use_min_dim:
        linear_deflection = bb.min_dimension / factor
        logger.info("Linear deflection : %f" % linear_deflection)
        OCC.BRepMesh.BRepMesh_IncrementalMesh(shape, linear_deflection)
    else:
        linear_deflection = bb.max_dimension / factor
        logger.info("Linear deflection : %f" % linear_deflection)
        OCC.BRepMesh.BRepMesh_IncrementalMesh(shape, linear_deflection)
Ejemplo n.º 6
0
def test_with_box():
    r"""Test the bounding box workaround with a box"""
    dx = 10.0
    dy = 20.0
    dz = 30.0

    # Make a box with a corner at 0,0,0 and the other dx,dy,dz
    box = BRepPrimAPI_MakeBox(dx, dy, dz).Shape()
    bb = BoundingBox(box)
    increment = 0.01

    bbw_x_min = real_bb_position("X", "MIN", bb.x_min, box, increment=increment)
    bbw_x_max = real_bb_position("X", "MAX", bb.x_max, box, increment=increment)

    bbw_y_min = real_bb_position("Y", "MIN", bb.y_min, box, increment=increment)
    bbw_y_max = real_bb_position("Y", "MAX", bb.y_max, box, increment=increment)

    bbw_z_min = real_bb_position("Z", "MIN", bb.z_min, box, increment=increment)
    bbw_z_max = real_bb_position("Z", "MAX", bb.z_max, box, increment=increment)

    assert bb.x_min < 0.
    assert bb.x_max > dx

    assert bb.y_min < 0.
    assert bb.y_max > dy

    assert bb.z_min < 0.
    assert bb.z_max > dz

    assert bbw_x_min <= 0.
    assert abs(bbw_x_min) <= increment

    assert bbw_x_max >= dx
    assert abs(bbw_x_max - dx) <= increment

    assert bbw_y_min <= 0.
    assert abs(bbw_y_min) <= increment

    assert bbw_y_max >= dy
    assert abs(bbw_y_max - dy) <= increment

    assert bbw_z_min <= 0.
    assert abs(bbw_z_min) <= increment

    assert bbw_z_max >= dz
    assert abs(bbw_z_max - dz) <= increment
Ejemplo n.º 7
0
def point_in_boundingbox(shape, pnt, tolerance=OCCUTILS_DEFAULT_TOLERANCE):
    r"""Is pnt inside the bounding box of solid?

    This is a much speedier test than checking the TopoDS_Solid

    Parameters
    ----------
    shape : TopoDS_Shape
    pnt : OCC.gp.gp_Pnt
    tolerance : float

    Returns
    -------
    bool
        True if pnt lies in boundingbox, False otherwise

    """
    return not BoundingBox(shape, tolerance).bnd_box.IsOut(pnt)
Ejemplo n.º 8
0
def test_with_sphere():
    r"""Test the bounding box workaround with a sphere"""
    radius = 10.0
    sphere = BRepPrimAPI_MakeSphere(radius).Shape()
    bb = BoundingBox(sphere)
    increment = 0.01

    bbw_x_min = real_bb_position("X", "MIN", bb.x_min, sphere, increment=increment)
    bbw_x_max = real_bb_position("X", "MAX", bb.x_max, sphere, increment=increment)

    bbw_y_min = real_bb_position("Y", "MIN", bb.y_min, sphere, increment=increment)
    bbw_y_max = real_bb_position("Y", "MAX", bb.y_max, sphere, increment=increment)

    bbw_z_min = real_bb_position("Z", "MIN", bb.z_min, sphere, increment=increment)
    bbw_z_max = real_bb_position("Z", "MAX", bb.z_max, sphere, increment=increment)

    assert bb.x_min < -radius
    assert bb.x_max > radius

    assert bb.y_min < -radius
    assert bb.y_max > radius

    assert bb.z_min < -radius
    assert bb.z_max > radius

    assert bbw_x_min <= - radius
    assert abs(bbw_x_min - (-radius)) <= increment

    assert bbw_x_max >= radius
    assert abs(bbw_x_max - radius) <= increment

    assert bbw_y_min <= - radius
    assert abs(bbw_y_min - (-radius)) <= increment

    assert bbw_y_max >= radius
    assert abs(bbw_y_max - radius) <= increment

    assert bbw_z_min <= - radius
    assert abs(bbw_z_min - (-radius)) <= increment

    assert bbw_z_max >= radius
    assert abs(bbw_z_max - radius) <= increment
Ejemplo n.º 9
0
def convert_py_file_part(py_filename, target_folder, remove_original=True):
    r"""Convert an OsvCad Python file that contains a part for web display

    The Python file contains the definition of a part.

    Parameters
    ----------
    py_filename : str
        Full path to the Python file
    target_folder : str
        Full path to the target folder for the conversion
    remove_original : bool
        Should the input file be deleted after conversion?
        It should be deleted on a web platform to save disk space, but, for
        testing, it might be useful not to delete it.

    Returns
    -------
    Nothing, it is a procedure

    Raises
    ------
    ValueError if not a part definition

    """
    if not isdir(target_folder):
        mkdir(target_folder)
    part = Part.from_py_script(py_filename)
    shape = part.node_shape.shape
    converted_filename = _conversion_filename(py_filename,
                                              target_folder,
                                              0)
    converted_basenames = [basename(converted_filename)]
    _convert_shape(shape, converted_filename)

    _write_descriptor(BoundingBox(shape).max_dimension,
                      converted_basenames,
                      _descriptor_filename(target_folder,
                                           basename(py_filename)))
    if remove_original is True:
        remove(py_filename)
Ejemplo n.º 10
0
def convert_stepzip_file(stepzip_filename,
                         target_folder,
                         remove_original=True):
    r"""Convert an OsvCad Stepzip file for web display

    A Stepzip file contains a STEP geometry file and an anchors definition file
    zipped together

    Parameters
    ----------
    stepzip_filename : str
        Full path to the Stepzip file
    target_folder : str
        Full path to the target folder for the conversion
    remove_original : bool
        Should the input file be deleted after conversion?
        It should be deleted on a web platform to save disk space, but, for
        testing, it might be useful not to delete it.

    Returns
    -------
    Nothing, it is a procedure

    """
    if not isdir(target_folder):
        mkdir(target_folder)
    part = Part.from_stepzip(stepzip_filename)
    shape = part.node_shape.shape
    converted_filename = _conversion_filename(stepzip_filename, target_folder,
                                              0)
    converted_basenames = [basename(converted_filename)]
    _convert_shape(shape, converted_filename)

    _write_descriptor(
        BoundingBox(shape).max_dimension, converted_basenames,
        _descriptor_filename(target_folder, basename(stepzip_filename)))
    if remove_original is True:
        remove(stepzip_filename)
Ejemplo n.º 11
0
def convert_iges_file(iges_filename, target_folder, remove_original=True):
    r"""Convert an IGES file (.iges, .igs) for web display

    Parameters
    ----------
    iges_filename : str
        Full path to IGES file
    target_folder : str
        Full path to the target folder for the conversion
    remove_original : bool
        Should the input file be deleted after conversion?
        It should be deleted on a web platform to save disk space, but, for
        testing, it might be useful not to delete it.

    Returns
    -------
    Nothing, it is a procedure

    """
    if not isdir(target_folder):
        mkdir(target_folder)
    converted_basenames = []
    importer = IgesImporter(iges_filename)
    shapes = importer.shapes
    max_dim = BoundingBox(importer.compound).max_dimension
    for i, shape in enumerate(shapes):
        converted_filename = _conversion_filename(iges_filename, target_folder,
                                                  i)
        _convert_shape(shape, converted_filename)
        converted_basenames.append(basename(converted_filename))

    _write_descriptor(
        max_dim, converted_basenames,
        _descriptor_filename(target_folder, basename(iges_filename)))
    if remove_original is True:
        remove(iges_filename)
Ejemplo n.º 12
0
    def on_selected_change(self, change):
        """Callback function for listener"""

        # TODO: investigate why importing Part
        # at top of file causes an app crash
        from cadracks_core.model import Part

        logger.debug("Selection changed")

        sel = self.model.selected

        logger.debug("sel : %s" % sel)

        if not isdir(sel):
            # what extension ?
            ext = splitext(sel)[1].lower()

            logger.info("File extension : %s" % ext)

            if ext == ".py":
                with open(sel) as f:
                    content = f.read()

                if is_valid_python(content) is True:
                    busy_info = wx.BusyInfo(
                        "Loading Python defined geometry ...")
                    try:
                        module_ = imp.load_source(sel, sel)

                        has_shape = hasattr(module_, "__shape__")
                        has_shapes = hasattr(module_, "__shapes__")
                        has_anchors = hasattr(module_, "__anchors__")
                        has_properties = hasattr(module_, "__properties__")
                        has_assembly = hasattr(module_, "__assembly__")
                        has_assemblies = hasattr(module_, "__assemblies__")

                        self.erase_all()

                        if has_shapes is True:
                            logger.info("%s has shapeS" % sel)
                            for i, shape in enumerate(module_.__shapes__):
                                self.display_shape(shape,
                                                   color_=colour_wx_to_occ(
                                                       color_from_sequence(
                                                           i, "colors")))

                        elif has_assembly is True:
                            logger.info("%s has assembly" % sel)
                            try:
                                self.display_assembly(module_.__assembly__)
                                self.viewer_display.FitAll()
                            except KeyError as ke:
                                self.erase_all()
                                logger.exception(ke)

                        elif has_assemblies is True:
                            logger.info("%s has assemblies" % sel)
                            try:
                                self.display_assemblies(module_.__assemblies__)
                                self.viewer_display.FitAll()
                            except KeyError as ke:
                                self.erase_all()
                                logger.exception(ke)
                        # elif has_shape is True and has_anchors is True:
                        elif has_shape is True:
                            if has_anchors is False:
                                logger.info("%s has shape" % sel)
                                self.display_shape(module_.__shape__)
                            else:
                                logger.info("%s has shape and anchors" % sel)
                                p = anchorable_part_from_py_script(sel)
                                self.display_part(p)
                            self.viewer_display.FitAll()
                        else:
                            self.erase_all()
                            logger.warning("Nothing to display")
                    except Exception as e:
                        logger.error(str(e))
                    finally:
                        del busy_info
                else:  # the file is not a valid Python file
                    logger.warning("Not a valid python file")
                    self.erase_all()

            elif ext in [".step", ".stp"]:
                self.erase_all()
                busy_info = wx.BusyInfo("Loading STEP ...")
                try:
                    shapes = StepImporter(sel).shapes
                    logger.info("%i shapes in %s" % (len(shapes), sel))
                    for shape in shapes:
                        color_255 = (255, 255, 255)
                        self.display_shape(shape,
                                           color_=colour_wx_to_occ(color_255),
                                           transparency=0.1)
                        self.viewer_display.FitAll()
                except Exception as e:
                    logger.error(str(e))
                finally:
                    del busy_info

            elif ext in [".iges", ".igs"]:
                self.erase_all()
                busy_info = wx.BusyInfo("Loading IGES ...")
                try:
                    shapes = IgesImporter(sel).shapes
                    logger.info("%i shapes in %s" % (len(shapes), sel))
                    for shape in shapes:
                        color_255 = (51, 255, 255)
                        self.display_shape(shape,
                                           color_=colour_wx_to_occ(color_255),
                                           transparency=0.1)
                        self.viewer_display.FitAll()
                except Exception as e:
                    logger.error(str(e))
                finally:
                    del busy_info

            elif ext == ".stl":
                self.erase_all()
                busy_info = wx.BusyInfo("Loading STL ...")
                try:
                    shape = StlImporter(sel).shape
                    color_255 = (0, 255, 0)
                    self.display_shape(shape,
                                       color_=colour_wx_to_occ(color_255),
                                       transparency=0.1)
                    self.viewer_display.FitAll()
                except Exception as e:
                    logger.error(str(e))
                finally:
                    del busy_info

            elif ext == ".json":  # parts library
                self.erase_all()

                is_library_file = False

                with open(sel) as json_file:
                    if "metadata" in json_file.read():
                        is_library_file = True

                if is_library_file is True:
                    busy_info = wx.BusyInfo("Loading parts library ...")
                    try:
                        with open(sel) as json_file:
                            json_file_content = json.load(json_file)
                            # print(json_file_content["data"].keys())
                            # find the biggest bounding box
                            biggest_bb = [0, 0, 0]
                            # smallest_bb = [0, 0, 0]
                            for i, k in enumerate(
                                    json_file_content["data"].keys()):
                                library_part = anchorable_part_from_library(
                                    sel, k)
                                bb = BoundingBox(library_part.shape)
                                if bb.x_span > biggest_bb[0]:
                                    biggest_bb[0] = bb.x_span
                                # if bb.x_span < smallest_bb[0]:
                                #     smallest_bb[0] = bb.x_span
                                if bb.y_span > biggest_bb[1]:
                                    biggest_bb[1] = bb.y_span
                                # if bb.y_span < smallest_bb[1]:
                                #     smallest_bb[1] = bb.y_span
                                if bb.z_span > biggest_bb[2]:
                                    biggest_bb[2] = bb.z_span
                                # if bb.z_span < smallest_bb[2]:
                                #     smallest_bb[2] = bb.y_span
                            biggest_dimension = max(biggest_bb)
                            # smallest_dimension = min(smallest_bb)

                            nb_per_row = int(
                                math.sqrt(len(
                                    json_file_content["data"].keys())))

                            for i, k in enumerate(
                                    json_file_content["data"].keys()):
                                library_part = anchorable_part_from_library(
                                    sel, k)
                                x_pos = biggest_dimension * 2 * (i %
                                                                 nb_per_row)
                                y_pos = biggest_dimension * 2 * (i //
                                                                 nb_per_row)

                                # Translate using an AnchorTransformation
                                library_part.add_matrix_generator(
                                    AnchorTransformation(
                                        Anchor(p=(0, 0, 0),
                                               u=(1, 0, 0),
                                               v=(0, 1, 0),
                                               name='a'),
                                        Anchor(p=(x_pos, y_pos, 0),
                                               u=(1, 0, 0),
                                               v=(0, 1, 0),
                                               name='b')))
                                self.display_part(library_part,
                                                  transparency=0.2,
                                                  anchor_names_height=10)
                                pnt_message = gp_Pnt(
                                    x_pos + biggest_dimension / 5,
                                    y_pos + biggest_dimension / 5, 0)
                                self.display_message(pnt_message,
                                                     k,
                                                     message_color=(1, 1, 1),
                                                     height=20)
                                self.viewer_display.FitAll()
                    except Exception as e:
                        logger.error(str(e))
                    finally:
                        del busy_info
            elif ext == ".stepzip":
                self.erase_all()
                busy_info = wx.BusyInfo("Loading STEPZIP ...")
                try:
                    self.display_part(anchorable_part_from_stepzip(sel),
                                      transparency=0.2)
                    self.viewer_display.FitAll()
                except Exception as e:
                    logger.error(str(e))
                finally:
                    del busy_info
            else:
                logger.error("File has an extension %s that is not "
                             "handled by the 3D panel" % ext)
                self.erase_all()

        else:  # a directory is selected
            self.erase_all()

        self.Layout()

        logger.debug("code change detected in 3D panel")
Ejemplo n.º 13
0
def convert_freecad_file(freecad_filename,
                         target_folder,
                         remove_original=True):
    r"""Convert a FreeCAD file (.fcstd) for web display

    Parameters
    ----------
    freecad_filename : str
        Full path to FreeCAD file
    target_folder : str
        Full path to the target folder for the conversion
    remove_original : bool
        Should the input file be deleted after conversion?
        It should be deleted on a web platform to save disk space, but, for
        testing, it might be useful not to delete it.

    Returns
    -------
    Nothing, it is a procedure

    """
    logger.info("Starting FreeCAD conversion")

    folder_unzipping = join(target_folder,
                            splitext(basename(freecad_filename))[0])

    extract_fcstd(freecad_filename, folder_unzipping)
    name_file_visibility_tuples = \
        name_file_visibility_from_unzipping_folder(folder_unzipping)

    extremas = []
    converted_basenames = []

    for i, (n, f, v) in enumerate(name_file_visibility_tuples):
        if v is True:
            brep_filename = "%s/%s" % (folder_unzipping, f)
            converted_filename = _conversion_filename(brep_filename,
                                                      target_folder,
                                                      i)
            converted_basenames.append(basename(converted_filename))
            try:
                importer = BrepImporter(brep_filename)
                extremas.append(BoundingBox(importer.shape).as_tuple)
                _convert_shape(importer.shape, converted_filename)
            except (RuntimeError, AssertionError):
                # An AssertionError is raised if one of the BREPs contained
                # in the FCSTD file contains a NULL shape
                logger.error("RuntimeError for %s" % brep_filename)

    x_min = min([extrema[0] for extrema in extremas])
    y_min = min([extrema[1] for extrema in extremas])
    z_min = min([extrema[2] for extrema in extremas])
    x_max = max([extrema[3] for extrema in extremas])
    y_max = max([extrema[4] for extrema in extremas])
    z_max = max([extrema[5] for extrema in extremas])

    max_dim = max([x_max - x_min, y_max - y_min, z_max - z_min])

    _write_descriptor(max_dim,
                      converted_basenames,
                      _descriptor_filename(target_folder,
                                           basename(freecad_filename)))

    # Cleanup of files that are not needed anymore
    if remove_original is True:
        remove(freecad_filename)
    rmtree(folder_unzipping, ignore_errors=True)
Ejemplo n.º 14
0
def _characteristic_dimension(shape):
    from aocutils.analyze.bounds import BoundingBox
    bb = BoundingBox(shape)
    return (bb.x_span + bb.y_span + bb.z_span) / 3.
Ejemplo n.º 15
0
#!/usr/bin/env python
# coding: utf-8

r"""Hull FFD example with IGES"""

from aocxchange.iges import IgesImporter
from aocutils.analyze.bounds import BoundingBox

import pygem as pg
from pygem.utils import write_bounding_box

# Bounding box
hull_shape_compound = \
    IgesImporter(filename="./example_hull_iges/SYSSER01_Z0WL.igs").compound
bb = BoundingBox(hull_shape_compound)

print("X min : %f" % bb.x_min)
print("X max : %f" % bb.x_max)
print("Y min : %f" % bb.y_min)
print("Y max : %f" % bb.y_max)
print("Z min : %f" % bb.z_min)
print("Z max : %f" % bb.z_max)

assert abs(abs(bb.y_min) - abs(bb.y_max)) <= 1e-6

# Initial file loading and visualization
iges_handler = pg.igeshandler.IgesHandler()
mesh_points = iges_handler.parse('./example_hull_iges/SYSSER01_Z0WL.igs')
iges_handler.check_topology()

# Display the unmodified hull in 2 possible ways