#!/usr/bin/python
# Script for conversion of Gocad solid file to Flac3d 
# 
# COPYRIGHT: (c) Marcus Apel 2006
# All rights reserved.
# Contact: http://www.geo.tu-freiberg.de/~apelm
# 
# Redistribution and use in source and binary forms, with or without modification, 
# are permitted provided that the following conditions are met:
# Redistributions of source code must retain the above copyright notice and the following disclaimer. 
# Redistributions in binary form must reproduce the above copyright notice and the following
# disclaimer in the documentation and/or other materials provided with the distribution. 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# REMARKS:
# Requires Python 2.4 (www.python.org)
# Flac3d ZoneGroups are defined from the first property of the Solid Atoms
# (defined below by variable "groupproperty"), so this property should represent your zone code
# 


import sys, os, re, tkMessageBox
from tkFileDialog import *

if sys.argv.count == 2: # check if files are given in the command line
	sofilename = sys.argv[1]
elif sys.argv.count == 3:
	sofilename = sys.argv[1]
	flacfilename = sys.argv[2]
else: # open dialogs for filenames
	sofilename = askopenfilename(filetypes=[("Gocad Solid", "*.so")])
	flacfilename = asksaveasfilename()
solines = open(sofilename).readlines() # read input lines in list
flacfile = open(flacfilename,'w') # open output file
flaczonefile = open(flacfilename+'_tmpZones','w')# use temp files for building zones&groups
flacgroupfile = open(flacfilename+'_tmpGroups','w')

atomlist = [] # Gocad solid may contain shared atoms which are references to vertices
vertexlist = [] # these are the nodes storing the geometry
zgroup=[] # list of zgroups names
tetraid = 0
grouplinebreaker = 0 # count items in grouplines to insert linebreaks after ten items
groupproperty = 1

try:
	flacfile.write('*Flac3d file created from Gocad solid file by goflac.py\n')
	flacfile.write('*GRIDPOINTS\n')
	flaczonefile.write('*ZONES\n')    
	flacgroupfile.write('*GROUPS\n')

	
	for soline in solines:		
		soelem = soline.split()
		if len(soelem) > 3 and soelem[0]=='PATOM':
			atomlist.append(int(soelem[1])) # create lists to assign atoms to vertices
			vertexlist.append(int(soelem[2]))
		elif len(soelem) > 4:
			if soelem[0] == "PVRTX":
				flacfile.write('G '+soelem[1]+', '+soelem[2]+', '+soelem[3]+', '+soelem[4]+'\n')
				if soelem[5] not in zgroup:
					zgroup.append(soelem[groupproperty+4]) # the first node property is used to define groups
					if grouplinebreaker == 0: # to avoid double linefeeds
						flacgroupfile.write('ZGROUP '+soelem[groupproperty+4]+'\n')
					else:             
						flacgroupfile.write('\nZGROUP '+soelem[groupproperty+4]+'\n')
					grouplinebreaker = 0 
			elif soelem[0] == "TETRA":
				for it in range(1,5):
					vertex = int(soelem[it])
					if vertex in atomlist: # if atom, get id from vertexlist
						ind = atomlist.index(vertex)
						soelem[it] = str(vertexlist[ind]) 
				tetraid = tetraid + 1      
				#flaczonefile.write('Z T4 '+str(tetraid)+' '+soelem[1]+', '+soelem[2]+', '+soelem[3]+', '+soelem[4]+'\n')
				flaczonefile.write('Z T4 '+str(tetraid)+' '+soelem[1]+', '+soelem[2]+', '+soelem[3]+', '+soelem[4]+', '+soelem[3]+', '+soelem[4]+', '+soelem[4]+', '+soelem[4]+'\n') 
				if grouplinebreaker > 9: # lf after 10 zone id's
					flacgroupfile.write(str(tetraid)+'\n')
					grouplinebreaker = 0    
				else:
					flacgroupfile.write(str(tetraid)+' ')	
					grouplinebreaker = grouplinebreaker + 1 

	flaczonefile.close()
	flacgroupfile.close()
	zones=open(flacfilename+'_tmpZones').readlines()
	groups=open(flacfilename+'_tmpGroups').readlines()
	flacfile.writelines(zones)
	flacfile.writelines(groups)
	flacfile.close()
	os.remove(flacfilename+'_tmpZones')
	os.remove(flacfilename+'_tmpGroups')
	
	tkMessageBox.showinfo("OK", sofilename +" converted")
except:
	tkMessageBox.showinfo("Error", sys.exc_info()[1])
	
sys.exit()

