Ejemplo n.º 1
0
    def compute(
        self,
        shape,
        quality,
        angular_tolerance,
        tessellate=True,
        compute_edges=True,
        normals_len=0,
        debug=False,
    ):
        self.shape = shape
        self.normals_len = normals_len
        self.edges = []

        count = self.number_solids(shape)
        with Timer(debug, "", f"mesh incrementally {'(parallel)' if count > 1 else ''}", 3):
            # Remove previous mesh data
            BRepTools.Clean_s(shape)
            BRepMesh_IncrementalMesh(shape, quality, False, angular_tolerance, count > 1)

        if tessellate:
            with Timer(debug, "", "get nodes, triangles and normals", 3):
                self.tessellate()

        if compute_edges:
            with Timer(debug, "", "get edges", 3):
                self.compute_edges()
Ejemplo n.º 2
0
    def collect_shapes(
        self,
        loc,
        quality,
        deviation,
        angular_tolerance,
        edge_accuracy,
        render_edges,
        render_normals,
        progress=None,
        timeit=False,
    ):

        # A first rough estimate of the bounding box.
        # Will be too large, but is sufficient for computing the quality
        with Timer(timeit, self.name, "compute quality:", 2) as t:
            bb = bounding_box(self.shape, loc=loc, optimal=False)
            quality = compute_quality(bb, deviation=deviation)
            t.info = str(bb)

        normals_len = 0 if render_normals is False else quality / deviation * 5

        with Timer(timeit, self.name, "tessellate:     ", 2) as t:
            mesh = tessellate(
                self.shape,
                quality=quality,
                angular_tolerance=angular_tolerance,
                normals_len=normals_len,
                debug=timeit,
                compute_edges=render_edges,
            )
            t.info = f"{{quality:{quality:.4f}, angular_tolerance:{angular_tolerance:.2f}}}"

        # After meshing the non optimal bounding box is much more exact
        with Timer(timeit, self.name, "bounding box:   ", 2) as t:
            bb2 = bounding_box(self.shape, loc=loc, optimal=False)
            bb2.update(bb, minimize=True)
            t.info = str(bb2)

        if progress:
            progress.update()

        color = [c.web_color for c in self.color] if isinstance(
            self.color, tuple) else self.color.web_color

        return {
            "id": self.id,
            "type": "shapes",
            "name": self.name,
            "shape": mesh,
            "color": color,
            "bb": bb2.to_dict(),
        }
Ejemplo n.º 3
0
    def collect_shapes(
        self,
        path,
        loc,
        deviation,
        angular_tolerance,
        edge_accuracy,
        render_edges,
        parallel=False,
        progress=None,
        timeit=False,
    ):
        self.id = f"{path}/{self.name}"

        with Timer(timeit, self.name, "bounding box:", 2) as t:
            bb = bounding_box(self.shape, loc=wrapped_or_None(loc))
            quality = compute_quality(bb, deviation=deviation)
            deflection = quality / 100 if edge_accuracy is None else edge_accuracy
            t.info = str(bb)

        with Timer(timeit, self.name, "discretize:  ", 2):
            edges = []
            for edge in self.shape:
                edges.extend(discretize_edge(edge, deflection))
            edges = np.asarray(edges)

        if progress:
            progress.update()

        color = [c.web_color for c in self.color] if isinstance(
            self.color, tuple) else self.color.web_color

        return {
            "id": self.id,
            "type": "edges",
            "name": self.name,
            "shape": edges,
            "color": color,
            "width": self.width,
            "bb": bb.to_dict(),
        }
Ejemplo n.º 4
0
    def collect_shapes(
        self,
        loc,
        quality,
        deviation,
        angular_tolerance,
        edge_accuracy,
        render_edges,
        render_normals,
        progress=None,
        timeit=False,
    ):
        with Timer(timeit, self.name, "bounding box:", 2) as t:
            bb = bounding_box(self.shape, loc=loc)
            quality = compute_quality(bb, deviation=deviation)
            deflection = quality / 100 if edge_accuracy is None else edge_accuracy
            t.info = str(bb)

        with Timer(timeit, self.name, "discretize:  ", 2):
            edges = flatten(
                [discretize_edge(edge, deflection) for edge in self.shape])

        if progress:
            progress.update()

        color = [c.web_color for c in self.color] if isinstance(
            self.color, tuple) else self.color.web_color

        return {
            "id": self.id,
            "type": "edges",
            "name": self.name,
            "shape": edges,
            "color": color,
            "bb": bb,
        }
Ejemplo n.º 5
0
def _show(part_group, **kwargs):
    for k in kwargs:
        if get_default(k, "n/a") == "n/a":
            raise KeyError(f"Paramater {k} is not a valid argument for show()")

    if kwargs.get("cad_width") is not None and kwargs.get("cad_width") < 640:
        warn("cad_width has to be >= 640, setting to 640")
        kwargs["cad_width"] = 640

    if kwargs.get("height") is not None and kwargs.get("height") < 400:
        warn("height has to be >= 400, setting to 400")
        kwargs["height"] = 400

    if kwargs.get("tree_width") is not None and kwargs.get("tree_width") < 250:
        warn("tree_width has to be >= 250, setting to 250")
        kwargs["tree_width"] = 250

    if kwargs.get("quality") is not None:
        warn(
            "quality is ignored. Use deviation to control smoothness of edges")
        del kwargs["quality"]

    sidecar_backup = None

    # if kwargs.get("parallel") is not None:
    #     if kwargs["parallel"] and platform.system() != "Linux":
    #         warn("parallel=True only works on Linux. Setting parallel=False")
    #         kwargs["parallel"] = False

    timeit = preset("timeit", kwargs.get("timeit"))

    with Timer(timeit, "", "overall"):

        if part_group is None:

            import base64  # pylint:disable=import-outside-toplevel
            import pickle  # pylint:disable=import-outside-toplevel
            from jupyter_cadquery.logo import LOGO_DATA  # pylint:disable=import-outside-toplevel

            logo = pickle.loads(base64.b64decode(LOGO_DATA))

            config = add_shape_args(logo["config"])

            defaults = get_defaults()
            config["cad_width"] = defaults["cad_width"]
            config["tree_width"] = defaults["tree_width"]
            config["height"] = defaults["height"]
            config["glass"] = defaults["glass"]
            config["title"] = defaults["viewer"]

            for k, v in create_args(kwargs).items():
                config[k] = v

            shapes = logo["data"]["shapes"]
            states = logo["data"]["states"]
            bb = _combined_bb(shapes).to_dict()
            # add global bounding box
            shapes["bb"] = bb

        else:

            config = apply_defaults(**kwargs)

            if config.get("viewer") == "":
                # If viewer is "" (the show default), then the default sidecar should be taken into account
                config["viewer"] = None
            elif config.get("viewer") is None:
                # if viewer is None (explicitely set), then ignore the default sidecar, i.e. back it up and set to None
                sidecar_backup = get_default_sidecar()
                _set_default_sidecar(None)

            if config.get("reset_camera") is False:  #  could be None
                if config.get("zoom") is not None:
                    del config["zoom"]
                if config.get("position") is not None:
                    del config["position"]
                if config.get("quaternion") is not None:
                    del config["quaternion"]

            parallel = preset("parallel", config.get("parallel"))
            with Timer(timeit, "", "tessellate", 1):
                num_shapes = part_group.count_shapes()
                progress_len = 2 * num_shapes if parallel else num_shapes
                progress = None if num_shapes < 2 else Progress(progress_len)

                if parallel:
                    init_pool()
                    keymap.reset()

                shapes, states = _tessellate_group(part_group,
                                                   tessellation_args(config),
                                                   progress, timeit)

                if parallel:
                    mp_get_results(shapes, progress)
                    close_pool()

                bb = _combined_bb(shapes).to_dict()
                # add global bounding box
                shapes["bb"] = bb

                if progress is not None:
                    progress.done()

            # Calculate normal length

            config["normal_len"] = get_normal_len(
                preset("render_normals", config.get("render_normals")),
                shapes,
                preset("deviation", config.get("deviation")),
            )

            show_bbox = preset("show_bbox", kwargs.get("show_bbox"))
            if show_bbox:
                insert_bbox(show_bbox, shapes, states)

        with Timer(timeit, "", "show shapes", 1):
            cv = viewer_show(shapes, states, **show_args(config))

            # If we forced to ignore the default sidecar, restore it
            if sidecar_backup is not None:
                _set_default_sidecar(sidecar_backup)

    return cv
Ejemplo n.º 6
0
    def collect_shapes(
        self,
        path,
        loc,
        deviation,
        angular_tolerance,
        edge_accuracy,
        render_edges,
        parallel=False,
        progress=None,
        timeit=False,
    ):
        self.id = f"{path}/{self.name}"

        # A first rough estimate of the bounding box.
        # Will be too large, but is sufficient for computing the quality
        with Timer(timeit, self.name, "compute quality:", 2) as t:
            bb = bounding_box(self.shape,
                              loc=wrapped_or_None(loc),
                              optimal=False)
            quality = compute_quality(bb, deviation=deviation)
            t.info = str(bb)

        with Timer(timeit, self.name, "tessellate:     ", 2) as t:
            func = mp_tessellate if parallel else tessellate
            result = func(
                self.shape,
                loc_to_tq(wrapped_or_None(loc)),
                deviation=deviation,
                quality=quality,
                angular_tolerance=angular_tolerance,
                debug=timeit,
                compute_edges=render_edges,
            )

            t.info = f"{{quality:{quality:.4f}, angular_tolerance:{angular_tolerance:.2f}}}"

            if parallel and is_apply_result(result):
                mesh = result
                bb = {}
            else:
                mesh, bb = result

        if progress is not None:
            progress.update()

        if isinstance(self.color, tuple):
            color = [c.web_color for c in self.color]  # pylint: disable=not-an-iterable
        else:
            color = self.color.web_color

        return {
            "id": self.id,
            "type": "shapes",
            "name": self.name,
            "shape": mesh,
            "color": color,
            "renderback": self.renderback,
            "accuracy": quality,
            "bb": bb,
        }
Ejemplo n.º 7
0
def _show(part_group, **kwargs):
    for k in kwargs:
        if get_default(k, "n/a") == "n/a":
            raise KeyError(f"Paramater {k} is not a valid argument for show()")

    if kwargs.get("cad_width") is not None and kwargs.get("cad_width") < 640:
        warn("cad_width has to be >= 640, setting to 640")
        kwargs["cad_width"] = 640

    if kwargs.get("height") is not None and kwargs.get("height") < 400:
        warn("height has to be >= 400, setting to 400")
        kwargs["height"] = 400

    if kwargs.get("tree_width") is not None and kwargs.get("tree_width") < 250:
        warn("tree_width has to be >= 250, setting to 250")
        kwargs["tree_width"] = 250

    # remove all tessellation and view parameters
    create_args, add_shape_args = split_args(kwargs)

    preset = lambda key, value: get_default(key) if value is None else value

    timeit = preset("timeit", kwargs.get("timeit"))

    with Timer(timeit, "", "overall"):

        with Timer(timeit, "", "setup display", 1):
            num_shapes = part_group.count_shapes()
            d = get_or_create_display(**create_args)
            d.init_progress(2 * num_shapes)

        with Timer(timeit, "", "tessellate", 1):

            mapping = part_group.to_state()
            shapes = part_group.collect_mapped_shapes(
                mapping,
                quality=preset("quality", kwargs.get("quality")),
                deviation=preset("deviation", kwargs.get("deviation")),
                angular_tolerance=preset("angular_tolerance",
                                         kwargs.get("angular_tolerance")),
                edge_accuracy=preset("edge_accuracy",
                                     kwargs.get("edge_accuracy")),
                render_edges=preset("render_edges",
                                    kwargs.get("render_edges")),
                render_normals=preset("render_normals",
                                      kwargs.get("render_normals")),
                progress=d.progress,
                timeit=timeit,
            )
            tree = part_group.to_nav_dict()

        with Timer(timeit, "", "show shapes", 1):
            d.add_shapes(shapes=shapes,
                         mapping=mapping,
                         tree=tree,
                         bb=_combined_bb(shapes),
                         **add_shape_args)

    d.info.version_msg(__version__)
    d.info.ready_msg(d.cq_view.grid.step)

    sidecar = has_sidecar()
    if sidecar is not None:
        print(f"Done, using side car '{sidecar.title()}'")

    return d