# -*- coding: utf-8 -*-

import FreeCAD
from FreeCAD import Placement, Rotation, Vector
import matplotlib

doc=FreeCAD.newDocument("Seifendose")

O_Len = 110.0           # Länge des Oberteils
O_Breite = 75.0         # Breite des Oberteils
O_Hoehe = 55.0          # Höhe des Oberteils
O_Dicke = 2.0           # Wandstärke des Oberteils

U_Hoehe = 10.0          # Höhe des Unterteils
U_Bodendicke = 2.0      # Dicke des Bodens des Unterteils
E_Dicke = 2.0           # Wandstärke des Einlegers
FE_Hoehe = 2.0          # Höhe des Fußes des Einlegers in der Mitte

Rad_V = 15.0            # Radius außen zum Abrunden der vertikalen Kanten
Rad_H = 20.0            # Radius außen zum Abrunden der horizontalen Kanten
Rad_E = 350.0           # Biegeradius der Einlegeplatte
Rad_B = 1.5             # Radius der Bohrungen im Einleger
Rad_A = 0.5             # Radius zum Abrunden des Einlegers
BA = 8                  # Randabstand der Bohrungen
BX = 12                 # Anzahl der Bohrungen in X-Richtung
BY = 8                  # Anzahl der Bohrungen in Y-Richtung

Spiel = 0.25            # Spiel zwischen Oberteil und Unterteil, umlaufend
Spiel_E = 0.5           # Spiel zwischen Einlegeplatte und Unterteil, umlaufend

vec0=Vector(0,0,0)      # Nullvektor
vecx=Vector(1,0,0)      # Drehachse x
vecy=Vector(0,1,0)      # Drehachse y
vecz=Vector(0,0,1)      # Drehachse z

# Farben
Farbe_Unterteil = matplotlib.colors.to_rgb('royalblue')
Farbe_Oberteil  = matplotlib.colors.to_rgb('lightsteelblue')
Farbe_Einleger  = matplotlib.colors.to_rgb('pink')

def Abrunden_vertikal(part, rad):
# vertikale Kanten zum Abrunden auswählen
   edges=[]
   edgecount = len(part.Edges)
   for i in range (0,edgecount):
      thisEdge = part.Edges[i]
      tan = thisEdge.tangentAt(0.0)
      if tan == Vector(0,0,1):
         edges.append(thisEdge)

# ...und abrunden
   if ((len(edges) > 0) & (rad > 0)):
      part = part.makeFillet(rad, edges)
   return(part)

# Basisformen generieren
U_Boden  = Part.makeBox(O_Len, O_Breite, U_Bodendicke)     # Boden des Unterteils
U_Aussen = Part.makeBox(O_Len-2*O_Dicke-2*Spiel, O_Breite-2*O_Dicke-2*Spiel, U_Hoehe).translate(Vector(O_Dicke+Spiel,O_Dicke+Spiel,U_Bodendicke))          # Außenbox des Randes des Unterteils
U_Innen  = Part.makeBox(O_Len-4*O_Dicke-2*Spiel, O_Breite-4*O_Dicke-2*Spiel, U_Hoehe).translate(Vector(2*O_Dicke+Spiel,2*O_Dicke+Spiel,U_Bodendicke))      # Innenbox des Unterteils

E_Breite = O_Breite-4*O_Dicke-2*Spiel-2*Spiel_E
E_Len = O_Len-4*O_Dicke-2*Spiel-2*Spiel_E
E_Pos = Vector(2*O_Dicke+Spiel+Spiel_E,2*O_Dicke+Spiel+Spiel_E,0)
E_Schnitt = Part.makeBox(E_Len, E_Breite, 2*U_Hoehe).translate(E_Pos)       # Außenbox des Einlegers (zum Schneiden)
E_Innen  = Part.makeBox(E_Len-2*E_Dicke, E_Breite-2*E_Dicke, 2*U_Hoehe).translate(Vector(E_Pos.x+E_Dicke,E_Pos.y+E_Dicke,0)) # Innenbox des Einlegers

O_Aussen = Part.makeBox(O_Len, O_Breite, O_Hoehe)          # Außenbox Oberteil
O_Innen  = Part.makeBox(O_Len-2*O_Dicke, O_Breite-2*O_Dicke, O_Hoehe).translate(Vector(O_Dicke,O_Dicke,O_Dicke))   # Innenbox Oberteil

# Kanten abrunden
U_Boden  = Abrunden_vertikal(U_Boden,  Rad_V)                                   # vertikale Kanten des Bodens des Unterteils abrunden
U_Aussen = Abrunden_vertikal(U_Aussen, Rad_V-O_Dicke-Spiel)                     # vertikale Kanten der Außenseite des Randes des Unterteils abrunden
U_Innen  = Abrunden_vertikal(U_Innen,  Rad_V-2*O_Dicke-Spiel)                   # vertikale Kanten der Innenseite des Randes des Unterteils abrunden
O_Aussen = Abrunden_vertikal(O_Aussen, Rad_V)                                   # vertikale Kanten der Außenseite des Oberteils abrunden
O_Innen  = Abrunden_vertikal(O_Innen,  Rad_V-O_Dicke)                           # vertikale Kanten der Innenseite des Oberteils abrunden
E_Schnitt = Abrunden_vertikal(E_Schnitt, Rad_V-2*O_Dicke-Spiel-Spiel_E)         # vertikale Kanten der Außenseite des Einlegers abrunden
E_Innen = Abrunden_vertikal(E_Innen, Rad_V-2*O_Dicke-E_Dicke-Spiel-Spiel_E)     # vertikale Kanten der Innenseite des Einlegers abrunden
E_Fuss = E_Schnitt.cut(E_Innen).translate(Vector(0,0,U_Bodendicke))             # Fuß des Einlegers umlaufend

# Einleger zusammenbauen und passend für das Unterteil verschieben
trl = Vector(O_Len/2,(O_Breite-E_Breite)/2,Rad_E+U_Bodendicke+FE_Hoehe)
Einleger = Part.makeCylinder(Rad_E, E_Breite, vec0, vecy, 360).translate(trl).fuse(E_Fuss)
Einleger = Einleger.cut(Part.makeCylinder(Rad_E-E_Dicke, E_Breite, vec0, vecy, 360).translate(trl))
Einleger = E_Schnitt.common(Einleger)

# Einleger perforieren
Bohrung = Part.makeCylinder(Rad_B, O_Hoehe)
BX_D = (E_Len-2*BA) / (BX-1)               # Abstand der Bohrungen in X-Richtung
BY_D = (E_Breite-2*BA) / (BY-1)            # Abstand der Bohrungen in Y-Richtung

for i in range (0,BX):
   for j in range (0,BY):
      Einleger = Einleger.cut(Bohrung.copy().translate(Vector(E_Pos.x+BA+BX_D*i,E_Pos.y+BA+BY_D*j,0)))
#      print(i,j)

# alle Kanten des Einlegers zum Abrunden auswählen
edges=[]
edgecount = len(Einleger.Edges)
for i in range (0,edgecount):
      thisEdge = Einleger.Edges[i]
      edges.append(thisEdge)

# ...und abrunden
if (len(edges) > 0):
   Einleger = Einleger.makeFillet(Rad_A, edges)

# horizontale Kanten der Außenseite des Oberteils zum Abrunden auswählen
edges=[]
edgecount = len(O_Aussen.Edges)
for i in range (0,edgecount):
      thisEdge = O_Aussen.Edges[i]
      if thisEdge.tangentAt(0.0) == vecy and thisEdge.valueAt(0).z < O_Hoehe/2:
         edges.append(thisEdge)
#         print(thisEdge.valueAt(0))

# ...und abrunden
if ((len(edges) > 0) & (Rad_H > 0)):
   O_Aussen = O_Aussen.makeFillet(Rad_H, edges)

# horizontale Kanten der Innenseite des Oberteils zum Abrunden auswählen
edges=[]
edgecount = len(O_Innen.Edges)
for i in range (0,edgecount):
      thisEdge = O_Innen.Edges[i]
      if thisEdge.tangentAt(0.0) == vecy and thisEdge.valueAt(0).z < O_Hoehe/2:
         edges.append(thisEdge)
#         print(thisEdge.valueAt(0))

# ...und abrunden
if ((len(edges) > 0) & (Rad_H > O_Dicke)):
   O_Innen = O_Innen.makeFillet(Rad_H-O_Dicke, edges)

# Unterteil zusammenbauen
Unterteil = U_Aussen.cut(U_Innen).fuse(U_Boden)

# Oberteil zusammenbauen, drehen und passend für das Unterteil verschieben
Oberteil = O_Aussen.cut(O_Innen).rotate(vec0, vecx, 180).translate(Vector(0,O_Breite,O_Hoehe+U_Bodendicke))

# Namen und Farben zuweisen
p1=doc.addObject("Part::Feature")
p1.Shape = Unterteil
p1.ViewObject.ShapeColor=Farbe_Unterteil
p1.Label="Unterteil"

p1=doc.addObject("Part::Feature")
p1.Shape = Oberteil
p1.ViewObject.ShapeColor=Farbe_Oberteil
p1.Label="Oberteil"

p1=doc.addObject("Part::Feature")
p1.Shape = Einleger
p1.ViewObject.ShapeColor=Farbe_Einleger
p1.Label="Einleger"

view = FreeCADGui.ActiveDocument.ActiveView
view.fitAll()

doc.recompute()

# Macro End



