from OCC.gp import *
from OCC.BRepBuilderAPI import *
from OCC.GC import *
from OCC.Geom import *
from OCC.Display.SimpleGui import init_display
from OCC.BRepPrimAPI import *
from OCC.BRepFilletAPI import *
from OCC.BRepOffsetAPI import *
from OCC.TopExp import *
from OCC.TopAbs import *
from OCC.Utils.Topology import *
from OCC.BRepAlgoAPI import *
from OCC.BRepLib import *
from OCC.BRep import BRep_Tool
from OCC.BRep import BRep_Builder
from OCC.TopTools import *
from OCC.TopoDS import *
from OCC.Geom2d import *
from OCC.GCE2d import *
import struct 
from OCC.MSH.Mesh import QuickTriangleMesh 

myWidth = 50
myHeight = 70
myThickness = 30

display, start_display, add_menu, add_function_to_menu = init_display()


aPnt1 = gp_Pnt(-myWidth / 2. , 0 , 0);
aPnt2 = gp_Pnt(-myWidth / 2. , -myThickness / 4. , 0);
aPnt3 = gp_Pnt(0 , -myThickness / 2. , 0);
aPnt4 = gp_Pnt(myWidth / 2. , -myThickness / 4. , 0);
aPnt5 = gp_Pnt(myWidth / 2. , 0 , 0);

aArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3 ,aPnt4);
aSegment1 = GC_MakeSegment(aPnt1 , aPnt2);
aSegment2 = GC_MakeSegment(aPnt4 , aPnt5);

aEdge1 = BRepBuilderAPI_MakeEdge(Handle_Geom_TrimmedCurve(aSegment1.Value()));
aEdge2 = BRepBuilderAPI_MakeEdge(Handle_Geom_TrimmedCurve(aArcOfCircle.Value()));
aEdge3 = BRepBuilderAPI_MakeEdge(Handle_Geom_TrimmedCurve(aSegment2.Value()));
aWire  = BRepBuilderAPI_MakeWire();
aWire.Add(aEdge1.Edge())
aWire.Add(aEdge2.Edge())
aWire.Add(aEdge3.Edge())

xAxis = gp_Ax1()
aTrsf = gp_Trsf()
aTrsf.SetMirror(xAxis)

aBRepTrsf = BRepBuilderAPI_Transform(aWire.Wire() , aTrsf)
aMirroredShape = aBRepTrsf.Shape()

#cast_object = TopoDS()
aMirroredWire = TopoDS().wire(aMirroredShape)

mkWire = BRepBuilderAPI_MakeWire()

mkWire.Add(aWire.Wire())
mkWire.Add(aMirroredWire)

myWireProfile = mkWire.Wire()

myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile);

aPrismVec = gp_Vec(0 , 0 , myHeight);

myBody = BRepPrimAPI_MakePrism(myFaceProfile.Shape() , aPrismVec, True);

mkFillet = BRepFilletAPI_MakeFillet(myBody.Shape())

t=Topo(myBody.Shape())

for aEdge in t.edges():
    mkFillet.Add(myThickness/8.,aEdge)
myBody = mkFillet;
neckLocation = gp_Pnt(0 , 0 , myHeight)

neckNormal = gp_Dir(0.,0.,1.)
neckAx2 = gp_Ax2(neckLocation , neckNormal)


myNeckRadius = myThickness / 4.
myNeckHeight = myHeight / 10.
neckLocation = gp_Pnt (0. , 0. , myHeight)
neckNormal = gp_Dir(0.,0.,1.)
neckAx2 = gp_Ax2(neckLocation , neckNormal)
            

MKCylinder = BRepPrimAPI_MakeCylinder(neckAx2 , myNeckRadius , myNeckHeight);

myNeck = MKCylinder.Shape();

myBody = BRepAlgoAPI_Fuse(myBody.Shape() , myNeck);


faceToRemove = None
zMax = -1;
t = Topo(myBody.Shape())
k=1
for  aFace in t.faces():
    
    aSurface = BRep_Tool().Surface(aFace)
    
    if aSurface.GetObject().IsInstance('Geom_Plane'):
        aPlane = Handle_Geom_Plane().DownCast(aSurface).GetObject()
        aPnt = aPlane.Location()
        aZ = aPnt.Z()
        if aZ>zMax:
            faceToRemove = aFace

facesToRemove = TopTools_ListOfShape()
facesToRemove.Append(faceToRemove);
myBody = BRepOffsetAPI_MakeThickSolid(myBody.Shape() , facesToRemove , -myThickness/9. , 1.e-3);


aCyl1 = Geom_CylindricalSurface(gp_Ax3(neckAx2) , myNeckRadius * 0.99);
aCyl2 = Geom_CylindricalSurface(gp_Ax3(neckAx2) , myNeckRadius * 1.05);

aPnt = gp_Pnt2d(2. * 3.141592 , myNeckHeight / 2.)
aDir = gp_Dir2d(2. * 3.141592 , myNeckHeight / 4.)
aAx2d = gp_Ax2d(aPnt , aDir)
        
aMajor = 2. * 3.141592
aMinor = myNeckHeight / 10.
    
anEllipse1 = Geom2d_Ellipse(aAx2d , aMajor , aMinor);
anEllipse2 = Geom2d_Ellipse(aAx2d , aMajor , aMinor / 4);

aArc2 = Geom2d_TrimmedCurve(anEllipse1.GetHandle() , 3.141592, 0.);
aArc1 = Geom2d_TrimmedCurve(anEllipse2.GetHandle() , 3.141592, 0.);

anEllipsePnt2 = anEllipse1.Value(0.)
anEllipsePnt1 = anEllipse1.Value(3.141592)
    
aSegment = GCE2d_MakeSegment(anEllipsePnt1 , anEllipsePnt2)

aEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(aArc1.GetHandle() , aCyl1.GetHandle())
aEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment.Value() , aCyl1.GetHandle())
aEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(aArc2.GetHandle() , aCyl2.GetHandle())
aEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment.Value() , aCyl2.GetHandle())
print dir(aEdge1OnSurf1)
threadingWire1 = BRepBuilderAPI_MakeWire(aEdge1OnSurf1.Edge() , aEdge2OnSurf1.Edge())
threadingWire2 = BRepBuilderAPI_MakeWire(aEdge1OnSurf2.Edge() , aEdge2OnSurf2.Edge())


BRepLib().BuildCurves3d(threadingWire1.Wire())
BRepLib().BuildCurves3d(threadingWire2.Wire())

aTool = BRepOffsetAPI_ThruSections(True)

aTool.AddWire(threadingWire1.Wire())
aTool.AddWire(threadingWire2.Wire())
aTool.CheckCompatibility(False)

myThreading = aTool.Shape()


aRes = TopoDS_Compound()

aBuilder = BRep_Builder()
aBuilder.MakeCompound (aRes)

aBuilder.Add (aRes, myBody.Shape())
aBuilder.Add (aRes, myThreading)


display.EraseAll()
print dir(display)
display.DisplayShape(aRes)

try:
    mesh = QuickTriangleMesh(DISPLAY_LIST = True)
    mesh.set_shape(aRes)
    mesh.set_precision(mesh.get_precision()/2.)
    mesh.compute()
    print mesh.get_faces()
    print mesh.get_vertices()
except:
    print "shit happens"
start_display()

