# SPDX-License-Identifier: LGPL-2.1-or-later

# Copyright (c) 2005 Berthold Grupp
# License: LGPL


"""Python Module for building solid regular geometric objects.

Return value are list of vectors, 3 vectors define a facet.

Sample code for creating a mesh:
        facets = Cube(3.0, 4.0, 5.0)
        m = Mesh.newMesh()
        m.addFacets(facets)
"""


import math


def Sphere(radius, count):
    """Creates a sphere with a given radius.

    bla bla bla

    """
    return Ellipsoid(radius, radius, count)


def Ellipsoid(lenX, lenY, count):
    polyline = []
    step = math.pi / count
    i = 0.0
    while i < math.pi + step / 10.0:
        x = math.cos(i) * lenX
        y = math.sin(i) * lenY
        polyline.append([x, y])
        i = i + step

    return RotationBody(polyline, count)


def Cylinder(radius, len, closed, edgelen, count):
    return Cone(radius, radius, len, closed, edgelen, count)


def Cone(radius1, radius2, len, closed, edgelen, count):
    polyline = []
    if closed:
        try:
            step = radius2 / math.ceil(radius2 / edgelen)
        except ZeroDivisionError:
            pass
        else:
            i = 0.0
            while i < radius2 - step / 2.0:
                polyline.append([len, i])
                i = i + step

    ct = math.ceil(len / edgelen)
    step = len / ct
    rstep = (radius1 - radius2) / ct
    i = len
    r = radius2
    while i > 0.0 + step / 2.0:
        polyline.append([i, r])
        i = i - step
        r = r + rstep
    polyline.append([0.0, radius1])

    if closed:
        try:
            step = radius1 / math.ceil(radius1 / edgelen)
        except ZeroDivisionError:
            pass
        else:
            i = radius1 - step
            while i > 0.0 + step / 2.0:
                polyline.append([0.0, i])
                i = i - step
            polyline.append([0.0, 0.0])

    return RotationBody(polyline, count)


def Toroid(radius1, radius2, count):
    polyline = []

    step = math.pi * 2.0 / count
    i = -math.pi
    while i < math.pi + step / 10.0:
        x = radius1 + math.cos(i) * radius2
        y = radius1 + math.sin(i) * radius2
        polyline.append([x, y])
        i = i + step

    return RotationBody(polyline, count)


def RotationBody(polyline, count):
    """Build a rotation body from a given (closed) polyline, rotation axis is the X-Axis.

    Parameter: polyline: list of tuple of 2 floats (2d vector)

    """
    facets = []

    step = math.pi * 2.0 / count
    i = -math.pi
    while i < math.pi - step / 10.0:
        li = i + step
        for j in range(0, len(polyline) - 1):
            v1 = polyline[j]
            v2 = polyline[j + 1]

            x1 = v1[0]
            y1 = v1[1] * math.cos(i)
            z1 = v1[1] * math.sin(i)
            x2 = v2[0]
            y2 = v2[1] * math.cos(i)
            z2 = v2[1] * math.sin(i)
            x3 = v1[0]
            y3 = v1[1] * math.cos(li)
            z3 = v1[1] * math.sin(li)
            x4 = v2[0]
            y4 = v2[1] * math.cos(li)
            z4 = v2[1] * math.sin(li)

            if v1[1] != 0.0:
                facets.append([x1, y1, z1])
                facets.append([x2, y2, z2])
                facets.append([x3, y3, z3])

            if v2[1] != 0.0:
                facets.append([x2, y2, z2])
                facets.append([x4, y4, z4])
                facets.append([x3, y3, z3])

        i = i + step

    return facets


def Cube(lenX, lenY, lenZ):
    hx = lenX / 2.0
    hy = lenY / 2.0
    hz = lenZ / 2.0

    facets = []

    facets.append([-hx, -hy, -hz])
    facets.append([hx, -hy, -hz])
    facets.append([hx, -hy, hz])

    facets.append([-hx, -hy, -hz])
    facets.append([hx, -hy, hz])
    facets.append([-hx, -hy, hz])

    facets.append([-hx, hy, -hz])
    facets.append([hx, hy, hz])
    facets.append([hx, hy, -hz])

    facets.append([-hx, hy, -hz])
    facets.append([-hx, hy, hz])
    facets.append([hx, hy, hz])

    facets.append([-hx, -hy, -hz])
    facets.append([-hx, hy, hz])
    facets.append([-hx, hy, -hz])

    facets.append([-hx, -hy, -hz])
    facets.append([-hx, -hy, hz])
    facets.append([-hx, hy, hz])

    facets.append([hx, -hy, -hz])
    facets.append([hx, hy, -hz])
    facets.append([hx, hy, hz])

    facets.append([hx, -hy, -hz])
    facets.append([hx, hy, hz])
    facets.append([hx, -hy, hz])

    facets.append([-hx, -hy, -hz])
    facets.append([-hx, hy, -hz])
    facets.append([hx, hy, -hz])

    facets.append([-hx, -hy, -hz])
    facets.append([hx, hy, -hz])
    facets.append([hx, -hy, -hz])

    facets.append([-hx, -hy, hz])
    facets.append([hx, hy, hz])
    facets.append([-hx, hy, hz])

    facets.append([-hx, -hy, hz])
    facets.append([hx, -hy, hz])
    facets.append([hx, hy, hz])

    return facets


def FineCube(lenX, lenY, lenZ, edgelen):
    hx = lenX / 2.0
    hy = lenY / 2.0
    hz = lenZ / 2.0
    cx = int(max(lenX / edgelen, 1))
    dx = lenX / cx
    cy = int(max(lenY / edgelen, 1))
    dy = lenY / cy
    cz = int(max(lenZ / edgelen, 1))
    dz = lenZ / cz

    facets = []

    # z
    for i in range(0, cx):
        for j in range(0, cy):
            facets.append([-hx + (i + 0) * dx, -hy + (j + 0) * dy, -hz])
            facets.append([-hx + (i + 0) * dx, -hy + (j + 1) * dy, -hz])
            facets.append([-hx + (i + 1) * dx, -hy + (j + 1) * dy, -hz])

            facets.append([-hx + (i + 0) * dx, -hy + (j + 0) * dy, -hz])
            facets.append([-hx + (i + 1) * dx, -hy + (j + 1) * dy, -hz])
            facets.append([-hx + (i + 1) * dx, -hy + (j + 0) * dy, -hz])

            facets.append([-hx + (i + 0) * dx, -hy + (j + 0) * dy, hz])
            facets.append([-hx + (i + 1) * dx, -hy + (j + 1) * dy, hz])
            facets.append([-hx + (i + 0) * dx, -hy + (j + 1) * dy, hz])

            facets.append([-hx + (i + 0) * dx, -hy + (j + 0) * dy, hz])
            facets.append([-hx + (i + 1) * dx, -hy + (j + 0) * dy, hz])
            facets.append([-hx + (i + 1) * dx, -hy + (j + 1) * dy, hz])

    # y
    for i in range(0, cx):
        for j in range(0, cz):
            facets.append([-hx + (i + 0) * dx, -hy, -hz + (j + 0) * dz])
            facets.append([-hx + (i + 1) * dx, -hy, -hz + (j + 1) * dz])
            facets.append([-hx + (i + 0) * dx, -hy, -hz + (j + 1) * dz])

            facets.append([-hx + (i + 0) * dx, -hy, -hz + (j + 0) * dz])
            facets.append([-hx + (i + 1) * dx, -hy, -hz + (j + 0) * dz])
            facets.append([-hx + (i + 1) * dx, -hy, -hz + (j + 1) * dz])

            facets.append([-hx + (i + 0) * dx, hy, -hz + (j + 0) * dz])
            facets.append([-hx + (i + 0) * dx, hy, -hz + (j + 1) * dz])
            facets.append([-hx + (i + 1) * dx, hy, -hz + (j + 1) * dz])

            facets.append([-hx + (i + 0) * dx, hy, -hz + (j + 0) * dz])
            facets.append([-hx + (i + 1) * dx, hy, -hz + (j + 1) * dz])
            facets.append([-hx + (i + 1) * dx, hy, -hz + (j + 0) * dz])

    # x
    for i in range(0, cy):
        for j in range(0, cz):
            facets.append([-hx, -hy + (i + 0) * dy, -hz + (j + 0) * dz])
            facets.append([-hx, -hy + (i + 0) * dy, -hz + (j + 1) * dz])
            facets.append([-hx, -hy + (i + 1) * dy, -hz + (j + 1) * dz])

            facets.append([-hx, -hy + (i + 0) * dy, -hz + (j + 0) * dz])
            facets.append([-hx, -hy + (i + 1) * dy, -hz + (j + 1) * dz])
            facets.append([-hx, -hy + (i + 1) * dy, -hz + (j + 0) * dz])

            facets.append([hx, -hy + (i + 0) * dy, -hz + (j + 0) * dz])
            facets.append([hx, -hy + (i + 1) * dy, -hz + (j + 1) * dz])
            facets.append([hx, -hy + (i + 0) * dy, -hz + (j + 1) * dz])

            facets.append([hx, -hy + (i + 0) * dy, -hz + (j + 0) * dz])
            facets.append([hx, -hy + (i + 1) * dy, -hz + (j + 0) * dz])
            facets.append([hx, -hy + (i + 1) * dy, -hz + (j + 1) * dz])

    return facets


def main():
    Cylinder(10.0, 20.0, 1, 10, 10)


if __name__ == "__main__":
    main()
