# solidLib.assortment — solidLib documentation

# Source code for solidLib.assortment

    import numpy as np
    import solid as scad
    from . import primitives as slp
    import solidLib as sl

    from typing import Union, Iterable

    # import .primitives as slp

    def grid(
        x_dim: int,
        y: int,
        w: float = 3,
        h: float = 1.5,
        fillet: bool = False,
    ):
        """generate a grid of (flattened) triangles with or without fillet

        the generated grid is x by y in size with a gridspace of size dim,
        the triangles used for the base structure is given by their height and width

        .. image:: img/grid.png
           :alt: 2x3 grid with defaults
        """

        if w > h * 2:
            out = scad.polygon([[0, 0], [w / 2, 0], [w / 2 - h, h], [0, h]])
        else:
            out = scad.polygon([[0, 0], [w / 2, 0], [0, h]])
        out = scad.linear_extrude(sl.settings.raster)(out)
        out = scad.rotate([90, 0, 90])(out)

        if fillet:
            # scallop = scad.cube([dim - 2 * h - (w - 2 * h), 0.0001, 0.0001])
            # scallop = scad.minkowski()(scallop, scad.sphere(r=h, segments=segments))
            scallop = slp.pill(
                [
                    [0, 0, 0],
                    [dsl.settings.raster - 2 * h - (w - 2 * h), 0, 0],
                    # [0,0,h], [dim - 2 * h - (w - 2 * h),0,h]
                ],
                h,
                segments=sl.settings.segments,
            )
            scallop += scad.rotate((0, -90, 0))(scallop) + scad.translate([sl.settings.raster - w, 0, 0])(
                scad.rotate([0, -90, 0])(scallop)
            )
            scallop = scad.translate((w / 2, w / 2, h))(scallop)
            out -= scallop

        out += scad.translate((0, sl.settings.raster, 0))(scad.rotate((0, 0, -90))(out))
        out += scad.translate((sl.settings.raster, sl.settings.raster, 0))(scad.rotate((0, 0, 180))(out))

        result = out
        for dx in range(x_dim):
            for dy in range(y):
                result += scad.translate((sl.settings.raster * dx, sl.settings.raster * dy, 0))(out)

        return result

    def grid_inv(
        x: float,
        y: float,
        w: float = 3,
        h: float = 1.5,
        fillet: bool = False,
    ):
        g = grid(x, y, w, h, fillet, sl.settings.raster, sl.settings.segments)
        return scad.cube([x * sl.settings.raster, y * sl.settings.raster, h]) - g

    def bin(x: float, y: float, h: float = 67):
        """
        standardized container

        .. image:: img/bin.png
        """

        class dims:
            wall = 2
            r_in = 2
            r_out = r_in + wall

        bulk = slp.rfcube([sl.settings.raster * x, sl.settings.raster * y, h], sl.settings.raster.r_out)
        hole = slp.rcube([sl.settings.raster * x - dims.wall * 2, sl.settings.raster * y - dims.wall * 2, h], dims.r_in)
        hole = scad.translate([dims.wall, dims.wall, dims.wall])(hole)

        wall_o = scad.cylinder(r=dims.r_out, h=dims.r_out, segments=sl.settings.segments)

        g = grid(x, y)

        goverlay = grid(x, y, w=2 + 2 * dims.wall, h=dims.r_in, fillet=True)
        goverlay = scad.translate([0, 0, dims.wall])(goverlay)
        goverlay = scad.intersection()(goverlay, hole)

        return bulk - hole - g + goverlay

    def toolinlay1(
        height: float,
        *args,
        r_tool: float = 7,
        inset: float = 4,
        maxh: float = 67,
    ):
        """toolinlay1

        creates a tooltray for alex container bins (2x3)

        .. image:: img/toolinlay1.png

        :param height: height of inset above lower bin
        :param inset: depth of inset
        """
        x = 2
        y = 3
        wall = 2
        r_in = 2
        tool_ins = 3

        base = slp.rfcube([x * sl.settings.raster, y * sl.settings.raster, height + inset], r_in + wall)

        toolindent = 0.1
        toolindent_w = 2
        toolbase_l = sl.settings.raster * x - 2 * wall - 2 * r_tool
        toolbase_t = scad.cube([toolbase_l * (1 - toolindent), 0.001, tool_ins])
        toolbase_b = scad.translate([toolbase_l * (1 - toolindent), 0, 0])(
            scad.cube([toolbase_l * toolindent - toolindent_w, 0.001, tool_ins])
        )
        toolcutout = scad.minkowski()(
            toolbase_t, scad.sphere(r=r_tool, segments=sl.settings.segments)
        ) + scad.minkowski()(
            toolbase_b, scad.sphere(r=r_tool + toolindent_w, segments=sl.settings.segments)
        )

        toolcutout = scad.translate(
            [r_tool + wall, r_tool + wall + toolindent_w, maxh - tool_ins]
        )(toolcutout)

        toolcutouts = []
        for i in range((sl.settings.raster * y - 3 * wall) // (r_tool * 2 + 2 * toolindent_w)):
            toolcutouts.append(
                scad.translate([0, i * (2 * r_tool + 2 * toolindent_w + 1.4), 0])(
                    scad.color("yellow")(toolcutout)
                )
            )

        lower = bin(2, 3, h=maxh - height, dim=sl.settings.raster)
        lower = scad.color("red", 0.5)(lower)
        base = scad.translate([0, 0, maxh - height - inset])(base)

        return base - lower - toolcutouts

    def toolinlay2(
        height: float,
        r_tool: Union[float, Iterable[float]] = 7,
        inset: float = 4,
        inset_tool: float = 3,
        maxh: float = 67,
        wall: float = 2,
    ):
        """toolinlay2

        creates a tooltray for alex container bins (2x3)

        .. image:: img/toolinlay2.png

        :param height: height of inset above lower bin
        :param r_tool: toolspace radius as float or list of floats
        :param inset: depth of toolinlay inset
        :param inset_tool: depth of additional toolspace inset
        :param maxh: system height restriction
        """
        x_dim = 3
        r_in = 2

        base = slp.rfcube([x_dim * sl.settings.raster, y_dim * sl.settings.raster, height + inset], r_in + wall)

        toolindent = 0.1
        toolindent_w = 2

        toolcutouts = []
        tool_rs = []
        if not isinstance(r_tool, list):
            tool_rs = [r_tool] * (
                (sl.settings.raster * x_dim - 3 * wall) // (r_tool * 2 + 2 * toolindent_w) - 1
            )
        else:
            tool_rs = r_tool

        toolbase_l = sl.settings.raster * y_dim - 2 * wall - 2 * np.max(tool_rs)
        for i, r in enumerate(tool_rs):
            toolbase_t = scad.cube([0.001, toolbase_l * (1 - toolindent), inset_tool])
            # toolbase_b = scad.translate([0, toolbase_l * (1 - toolindent), 0])(
            # scad.cube([0.001, toolbase_l * toolindent - toolindent_w, tool_ins])
            # )
            toolcutout = slp.pill(
                np.array([[0, 0, 0], [0, toolbase_l, 0], [0, toolbase_l, 10], [0, 0, 10]])
                + [0, 0, -np.max(tool_rs) + r]
                + [i * (toolindent_w + 1.4) + np.sum(tool_rs[0:i]) * 2, 0, 0],
                r,
            )

            toolcutout = scad.translate(
                (
                    np.max(tool_rs) + wall + toolindent_w,
                    np.max(tool_rs) + wall,
                    maxh - inset_tool,
                )
            )(toolcutout)
            toolcutouts.append(scad.color("yellow")(toolcutout))

        toolcutouts.append(
            slp.pill(
                np.array(
                    [
                        [0, 0, 0],
                        [0, toolindent * toolbase_l, 0],
                        [sl.settings.raster * x_dim - 2 * wall - 2 * 9, 0, 0],
                        [sl.settings.raster * x_dim - 2 * wall - 2 * 9, toolindent * toolbase_l, 0],
                        [0, 0, 10],
                        [0, toolindent * toolbase_l, 10],
                        [sl.settings.raster * x_dim - 2 * wall - 2 * 9, 0, 10],
                        [sl.settings.raster * x_dim - 2 * wall - 2 * 9, toolindent * toolbase_l, 10],
                    ]
                )
                + [9 + wall, 9 + wall, maxh - inset_tool],
                9,
            )
        )
        toolcutouts.append(
            scad.translate((wall * 2, wall * 2, 0))(
                slp.rfcube(
                    [
                        toolindent * toolbase_l + 2 * 9,
                        toolindent * toolbase_l + 2 * 9 - wall,
                        100,
                    ],
                    9 - wall,
                )
            )
        )

        lower = bin(2, 3, h=maxh - height, dim=sl.settings.raster)
        lower = scad.color("red", 0.5)(lower)
        base = scad.translate([0, 0, maxh - height - inset])(base)

        return base - lower - toolcutouts