#!/usr/bin/env perl
#!/usr/bin/perl
#
# Albert Danial Oct 25 2004
#
use warnings;
use strict;
use File::Basename;
use POSIX;          # strftime()
use Getopt::Std;
use vars qw ( $opt_e $opt_n );

$opt_e = 0;    # default element ID offset
$opt_n = 0;    # default element ID offset
getopts('e:n:');
my $script = basename $0;
die "$script [options] <.gts file(s)>
                  Creates .csv file(s) from GNU Triangulated Surface
                  Library files (.gts) file(s).

             Options:

               -e <EID offset>   Offset to add to element ID's.  Without
                                 an offset element ID's are numbered 
                                 1..nElements.
                                
               -n <NID offset>   Offset to add to node ID's.  Without
                                 an offset node ID's are numbered 
                                 1..nNodes.
" unless scalar @ARGV >= 1;

my $timestamp = POSIX::strftime("%Y-%m-%d %H:%M:%S", localtime(time));
while (my $infile = shift @ARGV) {
    my $outfile = basename $infile;
    if      ($infile =~ /\.gts$/) {
        $outfile =~ s/\.gts$/.csv/;
    } elsif (-r "$infile.gts")    {
        $infile  .= ".gts";
        $outfile .= ".csv";
    } else {
        warn "Could not read '$infile' or '$infile.gts'\n";
        next;
    }

    open   IN,    $infile   or die "Cannot read $infile:  $!\n";

    open   OUT, ">$outfile" or die "Cannot write $outfile:  $!\n";

    printf OUT "# converted from %s with %s on %s\n", 
                $infile, $script, $timestamp;
    my @bogus_element = ();  # line number in .gts file w/bad elements
    my @edge          = ();  # pairs of node ID's
    my ($nNodes, $nEdges, $nTris) = split(' ', <IN>);
    chomp($nTris);
    my $in_coords = $nNodes;
    my $in_edges  = 0;
    my $in_tris   = 0;
    my $nid       = 1 + $opt_n;
    my $eid       = 1 + $opt_e;
    while (<IN>) {

        if ($in_coords) {
            if (/^\s*(\S+)\s+(\S+)\s+(\S+)\s*$/) {
                printf OUT "node,%5d, 1, %12.6f,%12.6f,%12.6f,\n", 
                           $nid, $1, $2, $3;
                ++$nid;
            } else {
                die "Parse error line $. of $infile.  Expected node\n" .
                    "coordinates but got this:\n$_\n";
            }
            --$in_coords;
            $in_edges = $nEdges if !$in_coords;

        } elsif ($in_edges) {
            --$in_edges;
            if (/^\s*(\d+)\s+(\d+)\s*$/) {
                push @edge, [$1, $2];
            } else {
                die "Parse error line $. of $infile.  Expected edge\n" .
                    "definition but got this:\n$_\n";
            }
            $in_tris = $nTris if !$in_edges;

        } elsif ($in_tris) {
            --$in_tris;
            if (/^\s*(\d+)\s+(\d+)\s+(\d+)\s*$/) {
                if (($1 > $nEdges) or
                    ($2 > $nEdges) or
                    ($3 > $nEdges)) {
                    # node ID is out of range; cannot use this element
                    push @bogus_element, $.;
                    --$nTris;
                } else {
                    # Triangles are defined in terms of three edges.
                    # Each edge has two endpoints, so there are six
                    # possible endpoints to work with.  Knock out the
                    # duplicates with a hash:
                    my %vertices = ();
                    $vertices{$edge[$1 - 1][0] + $opt_n} = 1;
                    $vertices{$edge[$1 - 1][1] + $opt_n} = 2;
                    $vertices{$edge[$2 - 1][0] + $opt_n} = 3;
                    $vertices{$edge[$2 - 1][1] + $opt_n} = 4;
                    $vertices{$edge[$3 - 1][0] + $opt_n} = 5;
                    $vertices{$edge[$3 - 1][1] + $opt_n} = 6;
                    my @vert = sort {$vertices{$a} <=> $vertices{$b}}
                                    keys %vertices;
                    printf OUT "tri3, %5d, 45_mil_alum, %5d, %5d, %5d\n",
                               $eid, @vert;
                }
                ++$eid;
            } else {
                die "Parse error line $. of $infile.  Expected triangle\n" .
                    "definition but got this:\n$_\n";
            }

        } else {
            die "huh?  $infile, line $.\n";
        }
    }

    print OUT
        "shell_prop, 45_mil_alum, al_6061, 4.5e-2\n"                           .
        "material,al_6061, 9.9E+06, 3.72180450E+06, 3.3E-01, 2.54e-4, 20000\n" .
        "coord, 1, , 1, , 0.0,0.0,0.0, , 0.0,0.0,1.0, ,1.0,0.0,1.0\n";

    close  OUT;
    close  IN;

    printf "Wrote $outfile:  %d nodes,  %d elements\n", $nNodes, $nTris;
    if (@bogus_element) {
        printf "Warning:  %d elements were ignored.  Node ID's out of range\n",
               scalar @bogus_element;
        print  "at these lines of $infile:\n";
        print  join(", ", @bogus_element), "\n";
    }

}
__END__

# element data
#
my $nElem = scalar keys %{$ref_model->{elem}{tri3}};
foreach my $ID (sort {$a <=> $b} keys %{$ref_model->{elem}{tri3}} ) {
    print OUT "tri3,$ID,45_mil_alum,",
              join(",", @{$ref_model->{elem}{tri3}{$ID}}), 
              "\n";
}

# node data
#
my $nNode = scalar keys %{$ref_model->{node}};
foreach my $ID (sort {$a <=> $b} keys %{$ref_model->{node}} ) {
    printf OUT "node,%d, 1, %12.6f,%12.6f,%12.6f,\n", 
               $ID, @{$ref_model->{node}{$ID}};
}


close(OUT);
print "Wrote $file ($nElem elements, $nNode nodes)\n";
} # 1}}}
