# Toilet: a close-coupled pan lofted through level sections, its bowl cut out by a second loft,
# a seat ring and a lid that lifts on its hinges (each an object of its own), a cistern with a
# dual-flush button, in a tiled corner with a paper holder on the wall.
from math import *
units("mm")

china, chrome, grout = "#f4f4f1", "#d6d9de", "#9a958d"
floor_tile, wall_tile = "#d8d3cb", "#b9c6ba"
WALL = 700                       # the wall behind (the toilet faces -y, the viewer)
RIM = 400                        # the rim's height
HINGE = 530                      # where the seat and lid turn
S = 48                           # facets round the ellipses

# ---------- the pan: outer form, the deck behind the bowl, the bowl cut in ----------
outer = loft([ellipse(0, 400, 110, 150, offset=0, sides=S),
              ellipse(0, 370, 120, 185, offset=140, sides=S),
              ellipse(0, 345, 160, 215, offset=280, sides=S),
              ellipse(0, 335, 180, 215, offset=RIM, sides=S)], name="pan", color=china)
deck = box(330, 260, RIM, at=(-165, 430, 0))
deck.fillet(50, edges="vertical")
pan = outer + deck
bowl = loft([ellipse(0, 345, 48, 55, offset=170, sides=S),
             ellipse(0, 335, 72, 85, offset=220, sides=S),
             ellipse(0, 320, 128, 150, offset=330, sides=S),
             ellipse(0, 320, 148, 180, offset=RIM + 1, sides=S)])
pan = pan - bowl
pan.paint(china)
water = ellipse(0, 334, 76, 92, offset=236, sides=S).pull(2, name="water", color="#bcdbe6")

# ---------- the seat and the lid: rings and a cover, the lid lifted ----------
ring = ellipse(0, 330, 183, 200, offset=RIM, sides=S).pull(22) - ellipse(0, 318, 125, 150, offset=RIM, sides=S).pull(22)
ring.paint(china)
ring.name = "seat ring"
ring.fillet(5, edges="top")
seat = group([ring], name="seat")
cover = ellipse(0, 330, 183, 200, offset=RIM + 22, sides=S).pull(18, name="lid", color=china)
cover.fillet(5, edges="top")
cover.rotate(-84, axis="x", about=(0, HINGE, RIM + 22))
lid = group([cover], name="lid")
hinges = [cylinder(10, 34, at=(x, HINGE - 4, RIM + 14), axis="x", name="hinge", color=chrome, sides=20) for x in (-92, 58)]

# ---------- the cistern, its lid and the dual-flush button ----------
tank = box(370, 135, 360, at=(-185, 560, RIM), name="cistern", color=china)
tank.fillet(30, edges="vertical")
tank_lid = box(380, 145, 22, at=(-190, 555, RIM + 360), name="cistern lid", color=china)
tank_lid.fillet(30, edges="vertical")
tank_lid.chamfer(4, edges="top")
TOP = RIM + 382
plate = cylinder(32, 2, at=(0, 627, TOP), name="flush plate", color=chrome, sides=40)
half = [(26 * cos(radians(a)), 26 * sin(radians(a))) for a in range(-90, 91, 12)]
buttons = [prism([(1.5 + x, 627 + y) for x, y in half], 4, offset=TOP + 2, name="full flush", color=chrome),
           prism([(-1.5 - x, 627 + y) for x, y in half], 4, offset=TOP + 2, name="half flush", color=chrome)]
toilet = group([pan, water, tank, tank_lid, plate] + buttons + hinges + [seat, lid], name="toilet")

# ---------- the corner: floor and wall tiles on grout, a paper holder ----------
floor_grout = box(900, 900, 6, at=(-450, WALL - 900, -10), name="grout", color=grout)
tiles = [box(297, 297, 4, at=(-450 + 300 * i + 1.5, WALL - 900 + 300 * j + 1.5, -4), name="floor tile", color=floor_tile) for i in range(3) for j in range(3)]
wall_grout = box(900, 20, 1200, at=(-450, WALL + 4, -10), name="grout", color=grout)
wall_tiles = [box(297, 4, 297, at=(-450 + 300 * i + 1.5, WALL, -10 + 300 * k + 1.5), name="wall tile", color=wall_tile) for i in range(3) for k in range(4)]
corner = group([floor_grout, wall_grout] + tiles + wall_tiles, name="tiles")

roll = cylinder(55, 100, at=(255, 630, 640), axis="x", name="paper roll", color="#f7f6f2", sides=40) - cylinder(20, 100, at=(255, 630, 640), axis="x", sides=24)
roll.paint("#f7f6f2")
rose = cylinder(24, 8, at=(240, WALL - 8, 640), axis="y", name="wall plate", color=chrome, sides=32)
arm = pipe([(240, WALL - 8, 640), (240, 630, 640), (370, 630, 640)], 6, name="holder arm", color=chrome, sides=16)
holder = group([rose, arm, roll], name="paper holder")
