#######################################################################
#
# $Id: Mesh.py,v 1.3 2008-02-28 05:05:01 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: Mesh.py,v $
# Revision 1.3  2008-02-28 05:05:01  lorenz
# Zero rounding for too small distances in dl calculation.
#
# Revision 1.2  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.1.1.1  2008-01-28 06:15:35  lorenz
# Import emGine GUI v. 0.7.1
#
# Revision 1.5  2007-07-02 06:37:18  lorenz
# Clean up of old code.
#
# Revision 1.4  2007-06-14 06:31:51  lorenz
# Added emGine settings handling.
# Better handling of GUI state through GUIState class.
#
# Revision 1.3  2007-06-11 06:17:58  lorenz
# Construction plane handling added (during IMS2007, HAWAII + airplane)
#
# Revision 1.2  2007-05-18 16:37:01  lorenz
# Work on 'surrounding space' simbox and
#  'emgine_gui' tag
#
# Revision 1.1.1.1  2007-05-08 06:22:35  lorenz
# Initial Import
#
#######################################################################

# July 2006 - February 2008

import consts

# TODO: speed-up all computations here by using NumPy !!!! -PL-

class Mesh:
  def __init__(self):
    self.clear_all()

  def clear_all(self):
    self.x_points = list()
    self.y_points = list()
    self.z_points = list()
    self.simbox = [ [None, None, None], [None, None, None] ]
    self.dl = 0

  def add_xpoint(self, x):
    if not self.x_points.count(x):
      self.x_points.append(x)

  def add_ypoint(self, y):
    if not self.y_points.count(y):
      self.y_points.append(y)

  def add_zpoint(self, z):
    if not self.z_points.count(z):
      self.z_points.append(z)

  def add_point(self, point):
    [x, y, z] = point
    if not self.x_points.count(x):
      self.x_points.append(x)

    if not self.y_points.count(y):
      self.y_points.append(y)

    if not self.z_points.count(z):
      self.z_points.append(z)

  def add_points(self, points):
    for point in points:
      self.add_point(point)

  def set_dl(self, dl_):
    self.dl = dl_

  def get_dl(self):
    return self.dl

  def get_min_dl(self):
    if ((len(self.x_points) <= 1) and (len(self.y_points) <= 1) and (len(self.z_points) <= 1)):
      return None

    self.x_points.sort()
    self.y_points.sort()
    self.z_points.sort()

    dl = list()

    for i in range(1,len(self.x_points)):
      dl.append(self.x_points[i] - self.x_points[i-1])

    for i in range(1,len(self.y_points)):
      dl.append(self.y_points[i] - self.y_points[i-1])

    for i in range(1,len(self.z_points)):
      dl.append(self.z_points[i] - self.z_points[i-1])

    # return the smallest non-zero dl
    dl.sort()
    print dl
    ret_val = None
    for dl_ret in dl:
      if dl_ret >= consts.EMGINE_ROUND_ZERO_MESH_THRESHOLD:
	ret_val = dl_ret
	break
    return ret_val

  def get_bbox(self):
    if (len(self.x_points) == 0) or (len(self.y_points) == 0) or (len(self.z_points) == 0):
      if self.simbox != [[None, None, None], [None, None, None]]:
	return self.simbox
      else:
	return ((None, None, None), (None, None, None))

    self.x_points.sort()
    self.y_points.sort()
    self.z_points.sort()

    p1 = [self.x_points[0], self.y_points[0], self.z_points[0]]
    p2 = [self.x_points[-1], self.y_points[-1], self.z_points[-1]]

    # test if simbox is not greater
    if self.simbox:
      for ii in range(3):
	if self.simbox[0][ii] != None:
	  if self.simbox[0][ii] < p1[ii]:
	    p1[ii] = self.simbox[0][ii]

      for ii in range(3):
	if self.simbox[1][ii] != None:
	  if self.simbox[1][ii] > p2[ii]:
	    p2[ii] = self.simbox[1][ii]
    
    return (p1, p2)

  def set_simbox(self, simbox_):
    #TODO: no checkings on data done here ! Do it !
    # FIXME: How to do a deep copy ?
    p1 = [simbox_[0][0], simbox_[0][1], simbox_[0][2]]
    p2 = [simbox_[1][0], simbox_[1][1], simbox_[1][2]]
    self.simbox = [p1, p2]

  def set_simbox_xmin(self, xmin_):
    self.simbox[0][0] = xmin_

  def set_simbox_xmax(self, xmax_):
    self.simbox[1][0] = xmax_

  def set_simbox_ymin(self, ymin_):
    self.simbox[0][1] = ymin_

  def set_simbox_ymax(self, ymax_):
    self.simbox[1][1] = ymax_

  def set_simbox_zmin(self, zmin_):
    self.simbox[0][2] = zmin_

  def set_simbox_zmax(self, zmax_):
    self.simbox[1][2] = zmax_

###############################################
if __name__ == '__main__':
  from GroupGeometryObjects import *
  from GeometryObjectPatch import *

  print "Testing Mesh Module..."

  mesh = Mesh()

  mesh.get_bbox()
  mesh.add_xpoint(1)
  print mesh.get_bbox()
  mesh.add_xpoint(-1)
  print mesh.get_bbox()
  mesh.add_ypoint(2)
  print mesh.get_bbox()
  mesh.add_zpoint(2)
  print mesh.get_bbox()
  mesh.add_point([0,2,2])
  print mesh.get_bbox()
  mesh.add_point([-4,-4,-4])
  print mesh.get_bbox()

  mesh.add_points(([-11,-11,-11],[-12,-12,-12],[111,111,111]))
  print mesh.get_bbox()

  #######################
  print "---- Testing with GroupGeometryObjects ----"
  group = GroupGeometryObjects()
  patch1 = GeometryObjectPatch("Patch1", [0,0,0], [1,1,0])
  patch2 = GeometryObjectPatch("Patch2", [-1,-1,-1], [0.5,0.5,-1])
  group.add(patch1)
  group.add(patch2)
  dpoints = group.get_discretization_points()
  mesh2 = Mesh()
  mesh2.add_points(dpoints)
  print dpoints
  print mesh2.get_bbox()
  print mesh2.get_min_dl()

  #######################
  print "---- Testing Simbox ----"
  print mesh2.get_bbox()
  mesh2.set_simbox_zmax(11)
  print mesh2.get_bbox()
