#!/usr/bin/env python

# In this example vtkClipPolyData is used to cut a polygonal model
# of a cow in half. In addition, the open clip is closed by triangulating
# the resulting complex polygons.
#
# However it has been switched to use the more pythonic tvtk instead of vtk.
# The use of tvtk traits also has the benefit of line consolidation.

from tvtk.api import tvtk
from tvtk.api import colors

import sys
sys.path.append('/home/landisb/PycharmProjects/PythonScripts/Morphing')
import myVTK


ren = tvtk.Renderer(background=colors.white)

stlFile = '/home/landisb/PycharmProjects/Data/cow.stl'

# First start by reading a cow model. We also generate surface normals for
# prettier rendering.
cow = tvtk.STLReader(file_name=stlFile)
cowNormals = tvtk.PolyDataNormals(input_connection=cow.output_port)

# myVTK.MakeStl(ren, '/home/landisb/PycharmProjects/Data/cow.stl')

# We clip with an implicit function. Here we use a plane positioned near
# the center of the cow model and oriented at an arbitrary angle.
origin = (0, 0, 1)
normal=(-1, -1, 0)

plane = tvtk.Plane(origin=origin, normal=normal)
# myVTK.DrawPlane(ren, origin, normal, size=8, color=colors.cyan, opacity=0.4)
# myVTK.DrawPlane(ren, (-0.3,-0.3,1), normal, size=8, color=colors.yellow, opacity=0.7)

# myVTK.MakeArrowVector(ren, origin, normal)

# vtkClipPolyData requires an implicit function to define what it is to
# clip with. Any implicit function, including complex boolean combinations
# can be used. Notice that we can specify the value of the implicit function
# with the SetValue method.
clipper = tvtk.ClipPolyData(input_connection=cowNormals.output_port, clip_function=plane, generate_clipped_output=True)
clipper.generate_clip_scalars = False	# can add inline in initial call
clipMapper = tvtk.PolyDataMapper(input_connection=clipper.output_port)
clipProp = tvtk.Property(color=colors.peacock, opacity=1)
clipActor = tvtk.Actor(mapper=clipMapper, property=clipProp)


# Here we are cutting the cow. Cutting creates lines where the cut
# function intersects the model. (Clipping removes a portion of the
# model but the dimension of the data does not change.)
#
# The reason we are cutting is to generate a closed polygon at the
# boundary of the clipping process. The cutter generates line
# segments, the stripper then puts them together into polylines. We
# then pull a trick and define polygons using the closed line
# segements that the stripper created.
cutEdges = tvtk.Cutter(input_connection=cowNormals.output_port, cut_function=plane, generate_cut_scalars=False)
cutStrips = tvtk.Stripper(input_connection=cutEdges.output_port)
cutStrips.update()
cutPoly = tvtk.PolyData(points=cutStrips.output.points, polys=cutStrips.output.lines)

########## Ben adding to visualize the cut line, ie cutStrips  ####################
import numpy as np

mapper = tvtk.PolyDataMapper(input_connection=cutStrips.output_port)
prop = tvtk.Property(color=colors.green, opacity=1, line_width=5)
actor = tvtk.Actor(mapper=mapper, property=prop)
ren.add_actor(actor)
######### Done ####################################################################

# Triangle filter is robust enough to ignore the duplicate point at
# the beginning and end of the polygons and triangulate them.
cutTriangles = tvtk.TriangleFilter()
cutTriangles.set_input_data(cutPoly)
cutMapper = tvtk.PolyDataMapper(input_connection=cutTriangles.output_port)
cutMapper.set_input_data(cutPoly)
cutProp = tvtk.Property(color=colors.yellow, edge_color=colors.red, edge_visibility=True)
cutActor = tvtk.Actor(mapper=cutMapper, property=cutProp)


# The clipped part of the cow is rendered wireframe.
restMapper = tvtk.PolyDataMapper(input_connection=clipper.clipped_output_port)
restProp = tvtk.Property(representation='wireframe')

# print restProp.class_editable_traits()
restActor = tvtk.Actor(mapper=restMapper, property=restProp)


# Create graphics stuff

renWin = tvtk.RenderWindow(size=(400, 400))
renWin.add_renderer(ren)
iren = tvtk.RenderWindowInteractor(render_window=renWin)

# Add the actors to the renderer, set the background and size
ren.add_actor(clipActor)
ren.add_actor(cutActor)
ren.add_actor(restActor)

ren.reset_camera()
cam = ren.active_camera
cam.azimuth(30)
cam.elevation(30)
cam.dolly(1.5)
ren.reset_camera_clipping_range()

import os
import inspect

iren.initialize()
renWin.render()
renWin.window_name = os.path.basename(inspect.stack()[0][1]).replace('.py', '')
iren.start()

# print restProp.class_editable_traits()