#######################################################################
#
# $Id: GeometryScene.py,v 1.5 2008-03-28 06:25:37 lorenz Exp $
# 
# Copyright (C) 2004-2008 Petr Lorenz
# All rights reserved.
# 
# ##### BEGIN LICENSE BLOCK #####
#
# Version: MPL 1.1 / GPL 2.0 / LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.1 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
# 
# The Original Code is Petr Lorenz emGine Graphical User Interface (GUI).
# 
# The Initial Developer of the Original Code is Petr Lorenz.
# Portions created by the Initial Developer are Copyright (C) 2004-2008.
# All Rights Reserved.
# 
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the  "GPL"), or the
# GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
# case the provisions of the GPL or the LGPL are applicable instead of those
# above.  If you wish to allow use of your version of this file only under the
# terms of either the GPL or the LGPL and not to allow others to use your
# version of this file under the MPL, indicate your decision by deleting the
# provisions above and replace them with the notice and other provisions
# required by the GPL or LGPL.  If you do not delete the provisions above, a
# recipient may use your version of this file under the terms of any one of the
# MPL License, the GPL or the LGPL.
#
# ##### END LICENSE BLOCK #####
#
#######################################################################
# 
# $Log: GeometryScene.py,v $
# Revision 1.5  2008-03-28 06:25:37  lorenz
# - Perspective/Orthogonal view
# - Top/Bottom/Front/Back/Left/Right views
# - Boundary conditions setup
# - Platform Info
#
# Revision 1.4  2008-02-07 05:45:25  lorenz
# * Fixed 'Simulation Boundary View' check problem
#   when closing a project.
#
# * Fixed Bounding Box problems when moving/editing a geometry.
#
# Revision 1.3  2008-02-01 05:16:57  lorenz
# Construction plane resolution changed.
#
# Revision 1.2  2008-01-28 16:15:15  lorenz
# Windows related changes (e.g., refreshing).
#
# Revision 1.1.1.1  2008-01-28 06:15:35  lorenz
# Import emGine GUI v. 0.7.1
#
# Revision 1.4  2007-07-02 06:37:17  lorenz
# Clean up of old code.
#
# Revision 1.3  2007-06-14 06:31:51  lorenz
# Added emGine settings handling.
# Better handling of GUI state through GUIState class.
#
# Revision 1.2  2007-06-11 06:17:58  lorenz
# Construction plane handling added (during IMS2007, HAWAII + airplane)
#
# Revision 1.1.1.1  2007-05-08 06:22:35  lorenz
# Initial Import
#
#######################################################################

# July 2006 - March 2008
import wx

import vtk
from vtk.wx.wxVTKRenderWindow import wxVTKRenderWindow

import consts

class emGine_wxVTKRenderWindow(wxVTKRenderWindow):
  def __init__(self, parent, ID, *args, **kw):
    wxVTKRenderWindow.__init__(self, parent, ID, args, kw)

########################
# Geometry scene object
########################
class GeometryScene:
  def __init__(self, master):
    ###
    # Dictionary of state of GeometryScene
    ###
    self.state = dict()

    ####
    # Dictionary of all actors in the visualization scene
    ####
    self.actors = dict()

    ###
    # Set defaults
    ###
    self.DEFAULT_LINE_WIDTH = 3
    
    ####
    # The visualization widget
    ####
    #vtk_render_widget = self.vtk_render_widget = wxVTKRenderWindow(master, -1)
    vtk_render_widget = self.vtk_render_widget = emGine_wxVTKRenderWindow(master, -1)
    self.vtk_render_widget.Bind(wx.EVT_ENTER_WINDOW, self.change_cursor)

    ren = self.ren = vtk.vtkRenderer()
    ren.SetBackground(1.00, 1.00, 1.00)
    self.rw = vtk_render_widget.GetRenderWindow()	# the render window
    self.rw.AddRenderer(ren)

    # Custom interactor; TODO: should be used the vtkInteractorStyle in future?
    self.iren = iren = vtk.vtkRenderWindowInteractor()
    iren.SetInteractorStyle(None)
    #iren.SetRenderWindow(self.rw)

    # create dummy object
    #cs = vtk.vtkConeSource()
    #cs.SetResolution(4)
    #map = vtk.vtkPolyDataMapper()
    #map.SetInputConnection(cs.GetOutputPort())
    #act = vtk.vtkActor()
    #act.SetMapper(map)
    #act.GetProperty().SetColor(0.7, 0.43, 0.49)

    #
    # The default Axes
    #
    axes = vtk.vtkAxes()
    axes.SetOrigin(0, 0, 0)
    axesMapper = vtk.vtkPolyDataMapper()
    axesMapper.SetInputConnection(axes.GetOutputPort())
    axesActor = vtk.vtkActor()
    axesActor.SetMapper(axesMapper)
    axesActor.GetProperty().SetLineWidth(2)
    #self.axes_act = axesActor


    #
    # The default plane
    #

    #plane2 = vtk.vtkPlaneSource()
    #plane2.SetXResolution(25)
    #plane2.SetYResolution(25)
    #plane2.SetPoint1(30, 0, 0)
    #plane2.SetPoint2(0, 0, 30)
    #plane2.SetCenter(0, 0, 0)
    #planeMapper = vtk.vtkPolyDataMapper()
    #planeMapper.SetInputConnection(plane2.GetOutputPort())
    #planeActor = vtk.vtkActor()
    #planeActor.SetMapper(planeMapper)
    #planeActor.GetProperty().SetColor(0.5, 0.5, 0.5)
    #planeActor.GetProperty().SetInterpolationToFlat()
    #planeActor.GetProperty().SetRepresentationToWireframe()
    #ren.AddActor(planeActor)

    #plane3 = vtk.vtkPlaneSource()
    #plane3.SetXResolution(25)
    #plane3.SetYResolution(25)
    #plane3.SetPoint1(0, 30, 0)
    #plane3.SetPoint2(0, 0, 30)
    #plane3.SetCenter(0, 0, 0)
    #planeMapper = vtk.vtkPolyDataMapper()
    #planeMapper.SetInputConnection(plane3.GetOutputPort())
    #planeActor = vtk.vtkActor()
    #planeActor.SetMapper(planeMapper)
    #planeActor.GetProperty().SetColor(0.5, 0.5, 0.5)
    #planeActor.GetProperty().SetInterpolationToFlat()
    #planeActor.GetProperty().SetRepresentationToWireframe()
    #ren.AddActor(planeActor)

    ren.AddActor(axesActor)

    #
    # The default Axes Annotation
    #
    x_text = vtk.vtkVectorText()
    x_text.SetText("x")
    x_text_mapper = vtk.vtkPolyDataMapper()
    x_text_mapper.SetInputConnection(x_text.GetOutputPort())
    x_text_actor = vtk.vtkFollower()
    x_text_actor.SetMapper(x_text_mapper)
    x_text_actor.GetProperty().SetColor(0, 0, 0)
    x_text_actor.SetScale(0.3, 0.3, 0.3)
    x_text_actor.AddPosition(1, 0, 0)
    ren.AddActor(x_text_actor)
    x_text_actor.SetCamera(ren.GetActiveCamera())

    y_text = vtk.vtkVectorText()
    y_text.SetText("y")
    y_text_mapper = vtk.vtkPolyDataMapper()
    y_text_mapper.SetInputConnection(y_text.GetOutputPort())
    y_text_actor = vtk.vtkFollower()
    y_text_actor.SetMapper(y_text_mapper)
    y_text_actor.GetProperty().SetColor(0, 0, 0)
    y_text_actor.SetScale(0.3, 0.3, 0.3)
    y_text_actor.AddPosition(0, 1, 0)
    ren.AddActor(y_text_actor)
    y_text_actor.SetCamera(ren.GetActiveCamera())

    z_text = vtk.vtkVectorText()
    z_text.SetText("z")
    z_text_mapper = vtk.vtkPolyDataMapper()
    z_text_mapper.SetInputConnection(z_text.GetOutputPort())
    z_text_actor = vtk.vtkFollower()
    z_text_actor.SetMapper(z_text_mapper)
    z_text_actor.GetProperty().SetColor(0, 0, 0)
    z_text_actor.SetScale(0.3, 0.3, 0.3)
    z_text_actor.AddPosition(0, 0, 1)
    ren.AddActor(z_text_actor)
    z_text_actor.SetCamera(ren.GetActiveCamera())

    self.set_to_initial_state()

    #ren.AddActor(act)
    #self.show()

  ### Set the widget to the initial state
  def set_to_initial_state(self):
    self.remove_all_actors()
    self.ren.ResetCamera((-15,15,-15,15,-15,15))
    #self.ren.ResetCameraClippingRange()

    #cam = self.ren.GetActiveCamera()
    #print cam.GetPosition()
    #self.ren.GetActiveCamera().Zoom(1.0)

  def set_perspective_projection(self):
    cam = self.ren.GetActiveCamera()
    cam.ParallelProjectionOff()
    self.rw.Render()                    # refresh the view

  def set_orthogonal_projection(self):
    cam = self.ren.GetActiveCamera()
    cam.ParallelProjectionOn()
    self.rw.Render()                    # refresh the view

  def set_view(self, pos_vect, view_vect):
    cam = self.ren.GetActiveCamera()
    cam.SetFocalPoint(0, 0, 0)
    cam.SetPosition(pos_vect[0], pos_vect[1], pos_vect[2])
    cam.ComputeViewPlaneNormal()
    cam.SetViewUp(view_vect[0], view_vect[1], view_vect[2])
    cam.OrthogonalizeViewUp()
    self.ren.SetActiveCamera(cam)
    self.ren.ResetCamera()
    self.rw.Render()                    # refresh the view

  def set_view_front(self):
    self.set_view((1, 0, 0), (0, 0, 1))

  def set_view_back(self):
    self.set_view((-1, 0, 0), (0, 0, 1))

  def set_view_top(self):
    self.set_view((0, 0, 1), (0, 1, 0))

  def set_view_bottom(self):
    self.set_view((0, 0, -1), (0, 1, 0))

  def set_view_left(self):
    self.set_view((0, 1, 0), (0, 0, 1))

  def set_view_right(self):
    self.set_view((0, -1, 0), (0, 0, 1))

  def change_cursor(self, evt):
    self.vtk_render_widget.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))

  def set_dimensions(self, x1, y1, x2, y2):
    self.vtk_render_widget.SetDimensions(x1, y1, x2, y2)

  def show(self):
    self.vtk_render_widget.Show(True)

  def hide(self):
    self.vtk_render_widget.Show(False)

  def add_actor(self, actor_name, actor):
    #print "GeometryScene::add_actor actor_name = ", actor_name
    self.ren.AddActor(actor)
    self.actors[actor_name] = actor     # add the actor to the list of actors
    self.rw.Render()                    # refresh the view

  # FIXME: ? Should the actors be released from memory ?
  def remove_actor(self, actor_name):
    if actor_name in self.actors.keys():
      if (self.actors[actor_name]):
	print "GeometryScene::remove_actor(" + actor_name + ")"
	self.ren.RemoveActor(self.actors[actor_name])
	self.rw.Render()

  def remove_all_actors(self):
    for actor in self.actors.keys():
      self.remove_actor(actor)

  def highlight_object(self, object_name):
    #print "Highlighting object: ", object_name
    if (object_name != None):
      default_opacity = 0.2
    else:
      default_opacity = 1.0

    for act_name in self.actors.keys():
      if (act_name != object_name):
        self.actors[act_name].GetProperty().SetOpacity(default_opacity)
      else:
        self.actors[act_name].GetProperty().SetOpacity(1.0)
    self.rw.Render()                    # refresh the view

  def show_simulation_boundary(self, bbox):
    [x1, y1, z1] = bbox[0]
    [x2, y2, z2] = bbox[1]

    bboxs = vtk.vtkCubeSource()
    bboxs.SetBounds(x1, x2, y1, y2, z1, z2)
    bboxMapper = vtk.vtkPolyDataMapper()
    bboxMapper.SetInputConnection(bboxs.GetOutputPort())
    bboxActor = vtk.vtkActor()
    bboxActor.SetMapper(bboxMapper)
    bboxActor.GetProperty().SetInterpolationToFlat()
    bboxActor.GetProperty().SetRepresentationToWireframe()
    bboxActor.GetProperty().SetLineWidth(6)
    bboxActor.GetProperty().SetColor(0, 1, 0)

    self.add_actor("Misc__Simulation_Boundary", bboxActor)
    self.state["SimulationBoundary"] = True

  def hide_simulation_boundary(self):
    self.remove_actor("Misc__Simulation_Boundary")
    self.state["SimulationBoundary"] = False

  def draw_construction_plane_xy(self, bbox2D, params = None, zlevel = 0):
    self.delete_construction_plane_xy()
    self.show_construction_plane_xy(bbox2D, params, zlevel)

  def show_construction_plane_xy(self, bbox2D, params = None, zlevel = 0):
    [x1, y1] = bbox2D[0]
    [x2, y2] = bbox2D[1]
    dx = x2 - x1
    dy = y2 - y1

    dl = dx
    if (dl < dy):
      dl = dy
    if (dl == 0):
      dl = 1

    # center points
    cent_x = 0.5 * (x1 + x2)
    cent_y = 0.5 * (y1 + y2)

    # default extension of the plane over the EM structure
    extend_par = 5 
    dl_ = extend_par * dl

    #print x1
    #print y1
    #print x2
    #print y2
    #print dx
    #print dy

    plane = vtk.vtkPlaneSource()
    # FIXME: On a battery powered notebook, the following code is too slow, why ?
    # plane.SetXResolution(100)
    # plane.SetYResolution(100)

    plane.SetXResolution(20)
    plane.SetYResolution(20)

    plane.SetOrigin(0, 0, zlevel)
    plane.SetPoint1(dl_, 0, zlevel)
    plane.SetPoint2(0, dl_, zlevel)
    plane.SetCenter(cent_x, cent_y, zlevel)
    planeMapper = vtk.vtkPolyDataMapper()
    planeMapper.SetInputConnection(plane.GetOutputPort())
    planeActor = vtk.vtkActor()
    planeActor.SetMapper(planeMapper)
    planeActor.GetProperty().SetColor(0.7, 0.7, 0.7)
    planeActor.GetProperty().SetInterpolationToFlat()
    planeActor.GetProperty().SetRepresentationToWireframe()

    self.add_actor("Misc__Construction_Plane_xy", planeActor)
    self.state["ConstructionPlaneXY"] = True

  #############################################
  ######## ADDING OBJECTS #####################
  #############################################
  def add_patch(self, patch):
    #print "GeometryScene::add_patch, data = ", data
    name_prefix = consts.XML_TAG_GEOMETRY + "__"	# prefix for actor name

    ## if isinstance(data, dict):
    ##   actor_name = data[consts.XML_ATTR_NAME]
    ##   x1 = float(data[consts.XML_TAG_X1])
    ##   y1 = float(data[consts.XML_TAG_Y1])
    ##   x2 = x1 + float(data[consts.XML_TAG_LENGTH_X])
    ##   y2 = y1 + float(data[consts.XML_TAG_LENGTH_Y])
    ##   z = float(data[consts.XML_TAG_Z1])
    ## else:
    ##   actor_name = data[0]
    ##   x1 = float(data[1])
    ##   y1 = float(data[2])
    ##   x2 = x1 + float(data[3])
    ##   y2 = y1 + float(data[4])
    ##   z = float(data[5])

    actor_name = name_prefix + patch.name
    [x1, y1, z] = patch.p1
    [x2, y2, z] = patch.p2

    off = 0.001
    bs = vtk.vtkCubeSource()
    bs.SetBounds(x1, x2, y1, y2, z - off, z + off)
    cubeMapper = vtk.vtkPolyDataMapper()
    cubeMapper.SetInputConnection(bs.GetOutputPort())
    patchActor = vtk.vtkActor()
    patchActor.SetMapper(cubeMapper)
    patchActor.GetProperty().SetColor(1, 0, 0)
    patchActor.GetProperty().SetLineWidth(self.DEFAULT_LINE_WIDTH)

    self.add_actor(actor_name, patchActor)

  def add_circle(self, circle):
    name_prefix = consts.XML_TAG_GEOMETRY + "__"	# prefix for actor name

    ## if isinstance(data, dict):
    ##   actor_name = data[consts.XML_ATTR_NAME]
    ##   x = float(data[consts.XML_TAG_X1])
    ##   y = float(data[consts.XML_TAG_Y1])
    ##   z = float(data[consts.XML_TAG_Z1])
    ##   radius = float(data[consts.XML_TAG_RADIUS])
    ## else:
    ##   actor_name = data[0]
    ##   x = float(data[1])
    ##   y = float(data[2])
    ##   radius = float(data[3])
    ##   z = float(data[4])

    actor_name = name_prefix + circle.name
    [x, y, z] = circle.p1
    radius = circle.radius

    off = 0.001

    #print z
    cylinder = vtk.vtkCylinderSource()
    cylinder.SetResolution(24)
    #cylinder.SetCenter(x, y, z - off)
    cylinder.SetRadius(radius)
    cylinder.SetHeight(2*off)
    cylinderMapper = vtk.vtkPolyDataMapper()
    cylinderMapper.SetInputConnection(cylinder.GetOutputPort())
    cylinderMapper.SetResolveCoincidentTopologyToPolygonOffset()
    cylinderActor = vtk.vtkActor()
    cylinderActor.SetMapper(cylinderMapper)
    cylinderActor.GetProperty().SetColor(1, 0, 0)
    cylinderActor.RotateX(90)
    cylinderActor.SetPosition(x, y, z - off)
    cylinderActor.GetProperty().SetLineWidth(self.DEFAULT_LINE_WIDTH)
    # TODO: Set the SetOrigin -- i.e., the axis of the actor

    self.add_actor(actor_name, cylinderActor)

  def add_polygon(self, polygon):
    name_prefix = consts.XML_TAG_GEOMETRY + "__"	# prefix for actor name
    actor_name = name_prefix + polygon.name

    points = polygon.points
    num_points = len(points)

    if num_points >= 3:
      # TODO polygon checking for correctness
      pcoords = vtk.vtkFloatArray()
      pcoords.SetNumberOfComponents(3)	# 3D points
      pcoords.SetNumberOfTuples(num_points)
      for ind in range(num_points):
	point = points[ind]
	pcoords.SetTuple3(ind, point[0], point[1], point[2])

      vpoints = vtk.vtkPoints()
      vpoints.SetData(pcoords)

      vpolygon = vtk.vtkCellArray()
      vpolygon.InsertNextCell(num_points)
      for ind in range(num_points):
	vpolygon.InsertCellPoint(ind)

      polydata = vtk.vtkPolyData()
      polydata.SetPoints(vpoints)
      polydata.SetPolys(vpolygon)

      polygon_mapper = vtk.vtkPolyDataMapper()
      polygon_mapper.SetInput(polydata)

      polygon_actor = vtk.vtkActor()
      polygon_actor.SetMapper(polygon_mapper)
      polygon_actor.GetProperty().SetColor(1, 0, 0)
      polygon_actor.GetProperty().SetLineWidth(self.DEFAULT_LINE_WIDTH)

      # XXX: Edge visibility seems to not be working.
      #      One should use vtkAssembly for doing this
      #      with one wireframe and one surface rendering ...
      #polygon_actor.GetProperty().SetEdgeColor(0, 0, 0)
      #polygon_actor.GetProperty().EdgeVisibilityOn()

      self.add_actor(actor_name, polygon_actor)

  def add_box(self, box):
    VIS_CORR_FACT1 = 0.01	# correction factor for visualization problems of overlapping geometries
    name_prefix = consts.XML_TAG_GEOMETRY + "__"	# prefix for actor name

    #if isinstance(data, dict):
    #  actor_name = name_prefix + data[consts.XML_ATTR_NAME]
    #  x1 = float(data[consts.XML_TAG_X1])
    #  y1 = float(data[consts.XML_TAG_Y1])
    #  z1 = float(data[consts.XML_TAG_Z1])

    #  x2 = x1 + float(data[consts.XML_TAG_LENGTH_X])
    #  y2 = y1 + float(data[consts.XML_TAG_LENGTH_Y])
    #  z2 = z1 + float(data[consts.XML_TAG_LENGTH_Z])
    #else:
    #  actor_name = name_prefix + data[0]
    #  x1 = float(data[1])
    #  y1 = float(data[2])
    #  z1 = float(data[3])

    #  x2 = x1 + float(data[4])
    #  y2 = y1 + float(data[5])
    #  z2 = z1 + float(data[6])

    actor_name = name_prefix + box.name
    [x1, y1, z1] = box.p1
    [x2, y2, z2] = box.p2
    #print x1, x2, y1, y2, z1, z2

    # FIXME: the correction offset relative to used units !
    dx_off = 0.5*VIS_CORR_FACT1
    dy_off = 0.5*VIS_CORR_FACT1
    dz_off = 0.5*VIS_CORR_FACT1

    bs = vtk.vtkCubeSource()
    bs.SetBounds(x1 + dx_off, x2 - dx_off, y1 + dy_off, y2 - dy_off, z1 + dz_off, z2 - dz_off)
    #print bs.GetCenter()
    cubeMapper = vtk.vtkPolyDataMapper()
    cubeMapper.SetInputConnection(bs.GetOutputPort())
    cubeActor = vtk.vtkActor()
    cubeActor.SetMapper(cubeMapper)
    cubeActor.GetProperty().SetColor(0, 0, 1)
    cubeActor.GetProperty().SetEdgeColor(0, 0, 0)
    cubeActor.GetProperty().SetLineWidth(self.DEFAULT_LINE_WIDTH)
    #cubeActor.GetProperty().EdgeVisibilityOn()

    self.add_actor(actor_name, cubeActor)

  def add_cylinder(self, cylinder):
    #print "GeometryScene::add_cylinder, data = ", data
    name_prefix = consts.XML_TAG_GEOMETRY + "__"	# prefix for actor name

    ## if isinstance(data, dict):
    ##   actor_name = name_prefix + data[consts.XML_ATTR_NAME]
    ##   x1 = float(data[consts.XML_TAG_X1])
    ##   y1 = float(data[consts.XML_TAG_Y1])
    ##   z1 = float(data[consts.XML_TAG_Z1])
    ##   radius = float(data[consts.XML_TAG_RADIUS])
    ##   height = float(data[consts.XML_TAG_HEIGHT])
    ## else:
    ##   actor_name = name_prefix + data[0]
    ##   x1 = float(data[1])
    ##   y1 = float(data[2])
    ##   z1 = float(data[3])
    ##   radius = float(data[4])
    ##   height = float(data[5])

    actor_name = name_prefix + cylinder.name
    [x1, y1, z1] = cylinder.center
    radius = cylinder.radius
    height = cylinder.height

    z1 = z1 + 0.5*height

    cylinder = vtk.vtkCylinderSource()
    cylinder.SetResolution(24)
    #cylinder.SetCenter(x1, y1, z1)
    cylinder.SetRadius(radius)
    cylinder.SetHeight(height)
    cylinderMapper = vtk.vtkPolyDataMapper()
    cylinderMapper.SetInputConnection(cylinder.GetOutputPort())
    cylinderMapper.SetResolveCoincidentTopologyToPolygonOffset()
    cylinderActor = vtk.vtkActor()
    cylinderActor.SetMapper(cylinderMapper)
    cylinderActor.GetProperty().SetColor(0, 1, 0)
    cylinderActor.RotateX(90)
    cylinderActor.SetPosition(x1, y1, z1)
    
    self.add_actor(actor_name, cylinderActor)

  def add_voltage_port(self, data):
    name_prefix = consts.XML_TAG_EXCITATION + "__"	# prefix for actor name

    if isinstance(data, dict):
      actor_name = name_prefix + data[consts.XML_ATTR_NAME]
      x1 = float(data[consts.XML_TAG_X1])
      y1 = float(data[consts.XML_TAG_Y1])
      z1 = float(data[consts.XML_TAG_Z1])
      x2 = float(data[consts.XML_TAG_X2])
      y2 = float(data[consts.XML_TAG_Y2])
      z2 = float(data[consts.XML_TAG_Z2])
    else:
      actor_name = name_prefix + data[0]
      x1 = float(data[1])
      y1 = float(data[2])
      z1 = float(data[3])
      x2 = float(data[4])
      y2 = float(data[5])
      z2 = float(data[6])

    line = vtk.vtkLineSource()
    line.SetResolution(30)
    line.SetPoint1(x1, y1, z1)
    line.SetPoint2(x2, y2, z2)
    lineMapper = vtk.vtkPolyDataMapper()
    lineMapper.SetInputConnection(line.GetOutputPort())
    lineActor = vtk.vtkActor()
    lineActor.SetMapper(lineMapper)
    lineActor.GetProperty().SetColor(1, 0.2, 0)
    lineActor.GetProperty().SetLineWidth(3)

    self.add_actor(actor_name, lineActor)

  #############################################
  ######## DELETING OBJECTS ###################
  #############################################
  def delete_geometry(self, name):
    name_prefix = consts.XML_TAG_GEOMETRY + "__"	# prefix for actor name
    self.remove_actor(name_prefix + name)
  
  def delete_excitation(self, name):
    name_prefix = consts.XML_TAG_EXCITATION + "__"	# prefix for actor name
    self.remove_actor(name_prefix + name)

  def delete_construction_plane_xy(self):
    self.remove_actor("Misc__Construction_Plane_xy")
    self.state["ConstructionPlaneXY"] = False

  #############################################
  ######## HIGHLIGHTING OBJECTS ###############
  #############################################
  def highlight_geometry(self, name):
    name_prefix = consts.XML_TAG_GEOMETRY + "__"	# prefix for actor name
    self.highlight_object(name_prefix + name)

  def highlight_excitation(self, name):
    name_prefix = consts.XML_TAG_EXCITATION + "__"	# prefix for actor name
    self.highlight_object(name_prefix + name)




###############################################
if __name__ == '__main__':
  print "Testing GeometryScene Module..."

  app = wx.PySimpleApp()
  frame = wx.Frame(None, -1, "Testing GeometryScene Module...", size = (800, 600))
  frame.Show(True)

  geom = GeometryScene(frame)
  bbox2d = [[-5,-5],[5,5]]
  geom.show_construction_plane_xy(bbox2d)
  #geom.set_orthogonal_projection()
  geom.set_view_right()

  #### root = Tk()
  #### geom = GeometryScene(root)
  #### #e1 = Entry(root)
  #### #e1.grid(row = 0, sticky = E+W)
  #### #txt = Label(root, text="Geometry Scene")
  #### #txt.grid(row=1, sticky = E+W+N+S)

  #### root.grid_rowconfigure(0, weight = 1)
  #### root.grid_columnconfigure(0, weight = 1)
  #### #root.grid_rowconfigure(1, weight = 1)
  #### 
  #### geom.add_patch(["Patch1",0,0,3,3,3])
  #### geom.add_patch(["Patch2",0,0,8,8,8])
  #### geom.add_patch(["Patch3",0,0,8,8,-1])
  #### geom.add_circle(["Circ1",0,0,1,0])
  #### #root.mainloop()

  app.MainLoop()
