

def main():
    ''' uncomment functions to test them 
    you can uncomment the display functions the respective functions to view the geometries
    '''
    # BRepFeat_SplitShape_example()       # works to split faces - how to get a Geom_Surface?
    
    # BRepAlgoAPI_Cut_example()           # no split results
    
    GEOMAlgo_Splitter_example()       # segmentation fault example
    
    
    
    

def BRepFeat_SplitShape_example():
    """ example using BRepFeat_SplitShape_example"""
    # create geometry
    handle_splitterCurve, aProjCurveShape, aSectionCurveShape, handle_sweptSurface_trimmed_bsplinesurf, handle_sweptSurface_cutter_trimmed_bsplinesurf = geometry()
    
    from OCC.BRepFeat import BRepFeat_SplitShape
    from OCC.BRep import BRep_Tool
    from OCC.Utils.Topology import Topo
    from OCC.TopTools import TopTools_ListOfShape
    from OCC.TopoDS import TopoDS
    
    # make a face and an edge for the splitter from the geometric entities
    aFace_orig = makeFace(handle_sweptSurface_trimmed_bsplinesurf)    
    topologyOfCurve = Topo(aSectionCurveShape)
    aEdge_cutter = topologyOfCurve.edges().next() 
    
    # instantiate the splitter and add the cutter
    splitter = BRepFeat_SplitShape(aFace_orig)
    splitter.Add(aEdge_cutter,aFace_orig)        
    # build result
    splitter.Build()
    # iterator for the result objects
    iter = TopTools_ListOfShape()
    iter.Set(splitter.Modified(aFace_orig))
    #
    # get the results
    shape = iter.First()
    shape_other_edge = iter.Last()
    
    ### DISPLAY for debug
    # shapes_to_display = [shape]
    # shapes_to_display = [shape_other_edge]
    # shapes_to_display = [shape_other_edge,shape]
    # display_shape(shapes_to_display)
    
    # #############################
    # Now try to convert result to a surface
    # #############################
    
    # convert a shape to a face
    face_shape_other_edge = TopoDS.face(shape_other_edge)   # this face is splitted
    # generate a surface from the shape
    surf = BRep_Tool.Surface(face_shape_other_edge) # this surface is like the original surface
    
    ### DISPLAY for debug
    shapes_to_display = [surf]
    display_shape(shapes_to_display)
    
    
def BRepAlgoAPI_Cut_example():
    """ example using BRepAlgoAPI_Cut"""
    # create geometry
    handle_splitterCurve, aProjCurveShape, aSectionCurveShape, handle_sweptSurface_trimmed_bsplinesurf, handle_sweptSurface_cutter_trimmed_bsplinesurf = geometry()
    
    
    from OCC.BRepAlgoAPI import BRepAlgoAPI_Cut
    # make a face and cutter Face for the cutter from the geometric entities
    aFace_orig = makeFace(handle_sweptSurface_trimmed_bsplinesurf)
    aFace_cutter = makeFace(handle_sweptSurface_cutter_trimmed_bsplinesurf)
    
    # instantiate the cutter
    cutter = BRepAlgoAPI_Cut(aFace_orig,aFace_cutter)
    
    # ##### operations:
    # BOP_SECTION 
    # BOP_COMMON 
    # BOP_FUSE 
    # BOP_CUT 
    # BOP_CUT21 
    
    # set the cut operation
    cutter.SetOperation(4)
    print "Operation",cutter.Operation()
    # generate results
    cutter.Build()
    # get the result
    ResultShape = cutter.Shape()
    
    ### DISPLAY for debug
    shapes_to_display = [ResultShape,aFace_orig]
    display_shape(shapes_to_display)
    
def GEOMAlgo_Splitter_example():
    """ example using GEOMAlgo_Splitter
    
    segmetation fault at Perform()
    
    versions:
        OCE-12
        pythonOCC master - also tried with 0.6-dev and 0.6-beta
    """
    # create geometry
    handle_splitterCurve, aProjCurveShape, aSectionCurveShape,handle_sweptSurface_trimmed_bsplinesurf,handle_sweptSurface_cutter_trimmed_bsplinesurf = geometry()
    
    from OCC.GEOMAlgo import GEOMAlgo_Splitter
    from OCC.Utils.Topology import Topo
    
    # make a face and cutter Face for the Splitter from the geometric entities
    aFace_orig = makeFace(handle_sweptSurface_trimmed_bsplinesurf)
    aFace_cutter = makeFace(handle_sweptSurface_cutter_trimmed_bsplinesurf)
    #
    # alternative cutter
    topologyOfCurve = Topo(aSectionCurveShape)
    aEdge_cutter = topologyOfCurve.edges().next()   
    
    ### DISPLAY for debug
    # shapes_to_display = [aFace_orig,aFace_cutter]
    # display_shape(shapes_to_display)
    
    # instantiate the Splitter
    splitter_Algo = GEOMAlgo_Splitter()
    # add the shape to be split
    splitter_Algo.AddShape(aFace_orig)
    # add the shape that works as a cutter
    splitter_Algo.AddTool(aFace_cutter)
    # splitter_Algo.AddTool(aEdge_cutter) # alternative cutter
    # run splitter
    splitter_Algo.Perform()                 # segmentation fault here
    
    # resulting shape
    result_shape = splitter_Algo.Shape()
    

# #################################
# geometry function
# #################################
    
def geometry():
    
    """ Create an arbitrary shell and a projected curve on this shell"""
    
    from OCC.gp import gp_Ax2
    from OCC.gp import gp_Circ    
    from OCC.gp import gp_Dir
    from OCC.gp import gp_Pnt
    from OCC.gp import gp_Vec
    from OCC.GC import GC_MakeArcOfCircle
    from OCC.Geom import Geom_SurfaceOfLinearExtrusion
    from OCC.Geom import Geom_RectangularTrimmedSurface
    from OCC.GeomConvert import GeomConvert_SurfaceToBSplineSurface
    from OCC.GeomAPI import GeomAPI_PointsToBSpline
    from OCC.Utils.Common import point_list_to_TColgp_Array1OfPnt
    
    from OCC.BRepAlgo import BRepAlgo_NormalProjection
    from OCC.BRepAlgoAPI import BRepAlgoAPI_Section
    #
    #
    radius = 300.
    length = 600.    
    pi = 3.14159265359
    angle_of_segment = pi/2.
    
    # ######################
    # Surface
    # ######################
    aAx2 = gp_Ax2(gp_Pnt(0,0,0), gp_Dir(0,1,0)) # in y direction
    aCircle = gp_Circ(aAx2,radius)
    
    # Trim arc to 90 degree arc
    aCurve = GC_MakeArcOfCircle(aCircle,0,angle_of_segment,1).Operator()
    
    handle_sweptSurface = Geom_SurfaceOfLinearExtrusion(aCurve, gp_Dir(gp_Vec(gp_Pnt(0,0,0),gp_Pnt(0,1,0)))).GetHandle()  # in y direction
    handle_sweptSurface_trimmed = Geom_RectangularTrimmedSurface(handle_sweptSurface,0,angle_of_segment,0,length/2.).GetHandle()            
    #
    handle_sweptSurface_trimmed_bsplinesurf = GeomConvert_SurfaceToBSplineSurface(handle_sweptSurface_trimmed)
            
    # ######################
    # Curve
    # ######################
    P1 = gp_Pnt(240,400,100)
    P2 = gp_Pnt(150,-100,100)
        
    handle_splitterCurve = GeomAPI_PointsToBSpline(point_list_to_TColgp_Array1OfPnt([P1,P2])).Curve()
    
    # ######################
    # extruded Surface from curve 
    # ######################
    handle_sweptSurface_cutter = Geom_SurfaceOfLinearExtrusion(handle_splitterCurve, gp_Dir(gp_Vec(gp_Pnt(0,0,0),gp_Pnt(0,0,1)))).GetHandle()  # in z direction
    handle_sweptSurface_cutter_trimmed = Geom_RectangularTrimmedSurface(handle_sweptSurface_cutter,0,500,0,1).GetHandle()
    
    #
    handle_sweptSurface_cutter_trimmed_bsplinesurf = GeomConvert_SurfaceToBSplineSurface(handle_sweptSurface_cutter_trimmed)
    
    # ######################
    # Curve projection on surface or curve intersection of the two surfaces
    # ######################
        
        # normal PROJECTION is not equal to intersection depending on extrusion direction!
    aFace = makeFace(handle_sweptSurface_trimmed_bsplinesurf)
    aEdge = makeEdge(handle_splitterCurve)
    #
    projection = BRepAlgo_NormalProjection(aFace)
    projection.Add(aEdge)
    projection.Build()
    if projection.IsDone():
        aProjCurveShape = projection.Projection()
        
        
        # INTERSECTION
    aFace_orig = makeFace(handle_sweptSurface_trimmed_bsplinesurf)
    aFace_cutter = makeFace(handle_sweptSurface_cutter_trimmed_bsplinesurf)
    aSectionGenerator = BRepAlgoAPI_Section(aFace_orig,aFace_cutter,False)
    aSectionGenerator.ComputePCurveOn1(True)
    aSectionGenerator.Approximation(True)
    aSectionGenerator.Build()
    if aSectionGenerator.IsDone():
        aSectionCurveShape = aSectionGenerator.Shape()
        
        
    # ###############
    # Display geometry for debug
    # ###############
    # shapes_to_display = [aProjCurveShape,handle_sweptSurface_trimmed_bsplinesurf,aSectionCurveShape,handle_sweptSurface_cutter_trimmed_bsplinesurf]
    # shapes_to_display = [aProjCurveShape,handle_sweptSurface_trimmed_bsplinesurf,handle_splitterCurve,handle_sweptSurface_cutter_trimmed_bsplinesurf]
    # display_shape(shapes_to_display)
    
    return handle_splitterCurve, aProjCurveShape, aSectionCurveShape,handle_sweptSurface_trimmed_bsplinesurf,handle_sweptSurface_cutter_trimmed_bsplinesurf

# #################################
# display functions
# #################################

def display_shape(shapes=[]):
    """displays geometry or shapes in list"""
    from OCC.Display.SimpleGui import init_display
    backend_str = "wx" 
    backend_str = "pyqt4"   #much preferred
    backend_str = "qt"
    display, start_display, add_menu, add_function_to_menu  = init_display(backend_str=backend_str)
    
    # convert entities to displayable shapes
    shapes_to_display = []
    for entity in shapes:
        # print entity
        shapes_to_display.append(convertGeomToShape(entity))
    display.DisplayShape(shapes_to_display)
    display.FitAll()
    start_display()

def convertGeomToShape(geom):
    """ converts geometric entities to shapes"""
    from OCC.TopoDS import TopoDS_Shape
    from OCC.Geom import Handle_Geom_BSplineSurface
    from OCC.Geom import Handle_Geom_BSplineCurve
    from OCC.Geom import Handle_Geom_Surface
    
    # #################
    # Shape types
    # #################
    if isinstance(geom,TopoDS_Shape):                
        return geom
    # #################
    # Surface types
    # #################
    elif isinstance(geom,Handle_Geom_BSplineSurface):            
        return makeFace(geom)
    elif isinstance(geom,Handle_Geom_Surface):            
        return makeFace(geom)
    # #################
    # Curve types
    # #################
    elif isinstance(geom,Handle_Geom_BSplineCurve):            
        return makeEdge(geom)
    
    else:
        raise Exception("-ERROR: instance not known. Can not convert to Shape. Instance of type %s" % (type(geom)))

def makeFace(surface):
    """
    Create a OCC face from a geometric surface. shape
    
    :Parameters:
        surface : OCC surface shape
    
    :Returns:
        face.Shape() : OCC face shape
    
    """
    from OCC.BRepBuilderAPI import BRepBuilderAPI_MakeFace
    tol_degen = 1e-6
    face = BRepBuilderAPI_MakeFace(surface, tol_degen)
    face.Build()
    return face.Face()
    
def makeEdge(curve):
    """
    Create a OCC edge from a geometric curve shape.
    
    :Parameters:
        curve : OCC curve shape
    
    :Returns:
        spline.Shape() : OCC spline shape
    
    """
    from OCC.BRepBuilderAPI import BRepBuilderAPI_MakeEdge
    edge = BRepBuilderAPI_MakeEdge(curve)
    edge.Build()
    return edge.Edge()
    




if __name__=='__main__':
    #
    main()