#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import getopt
import platform
import re
import math

def usage( ret = 0 ):
  optflag = "-"
  if platform.system() == "Windows":
    optflag = "/"
  print "usage: eq2xml.py [options] [function of \"x\" and \"z\"] > output.xml"
  print ""
  print "options: " + optflag + "x [value:float]  min X value (default=-10)"
  print "         " + optflag + "X [value:float]  max X value (default=10)"
  print "         " + optflag + "z [value:float]  min Z value (default=-10)"
  print "         " + optflag + "Z [value:float]  max Z value (default=10)"
  print "         " + optflag + "g [grid:float]   grid size (default=0.5)"
  print "         " + optflag + "c [color:string] object color (default=\"0x00FF00\")"
  print "         " + optflag + "a [alpha:float]  object alpha (default=1.0; opaqua)"
  sys.exit(ret)

def strPos( attrname, x, y, z ):
  return attrname + "=\"" + str(x) + " " + str(y) + " " + str(-z) + "\""

if __name__ == "__main__":
  if len( sys.argv ) <= 1:
    usage()

  try:
    opts, args = getopt.getopt( sys.argv[1:],
                                "x:X:y:Y:z:Z:g:c:a:",
                                [ "xmin=", "xmax=", "zmin=", "zmax=",
                                  "grid=", "color=", "alpha=" ] )
  except getopt.GetoptError:
    usage(1)

  if len( args ) == 0:
    print "eq2xml: you need to input equation."
    usage(2)

  # default values
  xmin = zmin = -10.0
  xmax = zmax = 10.0
  grid = 0.5
  color = "0x00FF00"
  alpha = 1.0

  optflag = "-"
  if platform.system() == "Windows":
    optflag = "/"
  regopt = re.compile( "^" + optflag + "+" )
  for o, a in opts:
    myo = regopt.sub( "", o )
    if myo in ( "x", "xmin" ):
      xmin = float( a )
    elif myo in ( "X", "xmax" ):
      xmax = float( a )
    elif myo in ( "z", "zmin" ):
      zmin = float( a )
    elif myo in ( "Z", "zmax" ):
      zmax = float( a )
    elif myo in ( "g", "grid" ):
      grid = float( a )
    elif myo in ( "a", "alpha" ):
      alpha = float( a )
    elif myo in ( "c", "color" ):
      color = a

  equation = args[0]
  # replace functions, such as log and exp, into python style
  equation = re.sub( "exp", "math.exp", equation )
  equation = re.sub( "log", "math.log", equation )
  equation = re.sub( "sin", "math.sin", equation )
  equation = re.sub( "cos", "math.cos", equation )
  equation = re.sub( "sqrt", "math.sqrt", equation )
  equation = re.sub( "abs", "math.fabs", equation )
  equation = re.sub( "pi", "math.pi", equation )
  equation = re.sub( "PI", "math.pi", equation )

  gridnumx = int( math.floor( ( xmax - xmin ) / grid ) ) + 1
  gridnumz = int( math.floor( ( zmax - zmin ) / grid ) ) + 1
  container = []
  for i in range( 0, gridnumx ):
    x = xmin + float(i) * grid
    row = []
    for j in range( 0, gridnumz ):
      z = zmin + float(j) * grid
      value = eval( equation )
      row.append( value )
    container.append( row )

  print "<WMXML>"
  print "  <SCENE>"
  print "    <SHAPE color=\"" + color + "\" alpha=\"" + str(alpha) + "\">"
  for i in range( 1, gridnumx ):
    x = xmin + float(i) * grid
    prex = xmin + float(i-1) * grid
    for j in range( 1, gridnumz ):
      z = zmin + float(j) * grid
      prez = zmin + float(j-1) * grid
      print "      <TRI",
      print strPos( "p0", prex, container[i-1][j-1], prez ),
      print strPos( "p1", x, container[i][j-1], prez ),
      print strPos( "p2", prex, container[i-1][j], z ) + "/>"
      print "      <TRI",
      print strPos( "p0", x, container[i][j-1], prez ),
      print strPos( "p1", x, container[i][j], z ),
      print strPos( "p2", prex, container[i-1][j], z ) + "/>"
  print "    </SHAPE>"
  print "  </SCENE>"
  print "</WMXML>"
