[cig-commits] r7614 - in cs/cigma/branches/cigma-0.9b1: . benchmarks benchmarks/short benchmarks/short/tests benchmarks/short/tools benchmarks/short/vtk doc doc/manual libcigma src tmc

luis at geodynamics.org luis at geodynamics.org
Mon Jul 9 09:53:40 PDT 2007


Author: luis
Date: 2007-07-09 09:53:39 -0700 (Mon, 09 Jul 2007)
New Revision: 7614

Added:
   cs/cigma/branches/cigma-0.9b1/COPYING
   cs/cigma/branches/cigma-0.9b1/Makefile
   cs/cigma/branches/cigma-0.9b1/benchmarks/
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/okada/
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp1.sh
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp2.sh
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp3.sh
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp4.sh
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp1.sh
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp2.sh
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp3.sh
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp4.sh
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/bmrsnog.py
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/bmssnog.py
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/download.sh
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/off2vtk.py
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/utils.py
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/vtkwriter.py
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/domain.vtk
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/reverse-slip-fault.vtk
   cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/strike-slip-fault.vtk
   cs/cigma/branches/cigma-0.9b1/bin/
   cs/cigma/branches/cigma-0.9b1/doc/
   cs/cigma/branches/cigma-0.9b1/doc/manual/
   cs/cigma/branches/cigma-0.9b1/doc/manual/cigma.lyx
   cs/cigma/branches/cigma-0.9b1/doc/manual/figures/
   cs/cigma/branches/cigma-0.9b1/lib/
   cs/cigma/branches/cigma-0.9b1/libcigma/
   cs/cigma/branches/cigma-0.9b1/libcigma/array.c
   cs/cigma/branches/cigma-0.9b1/libcigma/array.h
   cs/cigma/branches/cigma-0.9b1/libcigma/dataset.c
   cs/cigma/branches/cigma-0.9b1/libcigma/dataset.h
   cs/cigma/branches/cigma-0.9b1/libcigma/h5_attr.c
   cs/cigma/branches/cigma-0.9b1/libcigma/h5_attr.h
   cs/cigma/branches/cigma-0.9b1/libcigma/h5_io.c
   cs/cigma/branches/cigma-0.9b1/libcigma/h5_io.h
   cs/cigma/branches/cigma-0.9b1/libcigma/mesh.c
   cs/cigma/branches/cigma-0.9b1/libcigma/mesh.h
   cs/cigma/branches/cigma-0.9b1/libcigma/split.c
   cs/cigma/branches/cigma-0.9b1/libcigma/split.h
   cs/cigma/branches/cigma-0.9b1/src/
   cs/cigma/branches/cigma-0.9b1/src/cigma-compare.cpp
   cs/cigma/branches/cigma-0.9b1/src/cigma-eval.cpp
   cs/cigma/branches/cigma-0.9b1/src/cigma-extract.cpp
   cs/cigma/branches/cigma-0.9b1/src/cigma-import.cpp
   cs/cigma/branches/cigma-0.9b1/src/cigma-okada.cpp
   cs/cigma/branches/cigma-0.9b1/tests/
   cs/cigma/branches/cigma-0.9b1/tmc/
   cs/cigma/branches/cigma-0.9b1/tmc/Bounding_box_3d.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Bounding_box_3d.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Exterior_face.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Exterior_face.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/HDF5_Reader.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/HDF5_Reader.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set_off_reader.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set_off_reader.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Line_3f.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Line_3f.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Matrix_4d.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Matrix_4d.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Observer.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Observer.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Plane_3f.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Plane_3f.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Plane_RST_3d.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Plane_RST_3d.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Point_3d.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Point_3d.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Point_3f.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Point_3f.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Point_4f.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Point_4f.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/QuadratureRule.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/QuadratureRule.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Shape.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Shape.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/StringUtils.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/StringUtils.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Subject.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Subject.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Tetrahedron.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Tetrahedron.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Time_series.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Time_series.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Vector_3b.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Vector_3b.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Vector_3d.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Vector_3d.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Vector_3f.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Vector_3f.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Visitor.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Visitor.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/Writers.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/Writers.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/anyoption.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/anyoption.h
   cs/cigma/branches/cigma-0.9b1/tmc/assertions.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/c_decls.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/common.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/counter.h
   cs/cigma/branches/cigma-0.9b1/tmc/dprintf.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/epsilon.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/epsilon.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/errors.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/errors.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/gl_headers.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/graphics.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/gtb_config.h
   cs/cigma/branches/cigma-0.9b1/tmc/icc_patch.h
   cs/cigma/branches/cigma-0.9b1/tmc/io_util.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/io_util.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/kdtree_tetrahedra.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/math.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/math_util.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/math_util.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/namespace.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/null_template_args.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/patterns.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/program_name.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/program_name.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/ptrs.h
   cs/cigma/branches/cigma-0.9b1/tmc/stlext.h
   cs/cigma/branches/cigma-0.9b1/tmc/tet_sampling.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/tet_sampling.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/tmc.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/vect_stats.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/vect_stats.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/version.cpp
   cs/cigma/branches/cigma-0.9b1/tmc/version.hpp
   cs/cigma/branches/cigma-0.9b1/tmc/windows.hpp
Log:
Cleaned up version of cigma-tmc branch


Added: cs/cigma/branches/cigma-0.9b1/COPYING
===================================================================
--- cs/cigma/branches/cigma-0.9b1/COPYING	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/COPYING	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,482 @@
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+     Appendix: How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+    MA 02111-1307, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!

Added: cs/cigma/branches/cigma-0.9b1/Makefile
===================================================================
--- cs/cigma/branches/cigma-0.9b1/Makefile	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/Makefile	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,152 @@
+CIGMA = .
+#HDF5_HOME = /usr
+HDF5_HOME = /home/luis/opt/hdf5/1.6.5-serial
+
+###############################################################################
+
+FC  = gfortran
+CC  = gcc
+LD  = gcc
+CXX = g++
+
+###############################################################################
+
+WARNINGS = -Wall
+OPTIMIZE =
+DEBUG    = -g -UNDEBUG
+CFLAGS   = $(WARNINGS) $(OPTIMIZE) $(DEBUG)
+FFLAGS   = $(WARNINGS) $(OPTIMIZE) $(DEBUG)
+CXXFLAGS = $(WARNINGS) $(OPTIMIZE) $(DEBUG)
+
+###############################################################################
+
+LIBS        = -lhdf5 -lpthread -ldl -lm
+CIGMA_LIBS  = -lcigma $(LIBS)
+OKADA_LIBS  = -lgfortran
+
+STATIC_LIBS = $(CIGMA)/lib/libtmc.a $(CIGMA)/lib/libcigma.a
+
+###############################################################################
+
+INCLUDES  =
+INCLUDES += -I$(HDF5_HOME)/include
+INCLUDES += -I$(CIGMA)/libcigma
+INCLUDES += -I$(CIGMA)/tmc
+CFLAGS   += $(INCLUDES)
+CXXFLAGS += $(INCLUDES)
+
+###############################################################################
+
+LIBRARIES  =
+LIBRARIES += -L$(HDF5_HOME)/lib
+LIBRARIES += -L$(CIGMA)/lib
+CFLAGS    += $(LIBRARIES)
+CXXFLAGS  += $(LIBRARIES)
+
+###############################################################################
+
+LDFLAGS  =
+LDFLAGS += -Wl,--rpath -Wl,$(HDF5_HOME)/lib
+LDFLAGS += -Wl,--rpath -Wl,$(CIGMA)/lib
+LDFLAGS += -Wl,--rpath -Wl,../lib
+LDFLAGS += -Wl,--rpath -Wl,.
+
+###############################################################################
+
+COMMANDS = \
+	$(CIGMA)/bin/tmc \
+	$(CIGMA)/bin/cigma-compare \
+	$(CIGMA)/bin/cigma-extract \
+	$(CIGMA)/bin/cigma-eval \
+	$(CIGMA)/bin/cigma-import
+
+TARGETS = \
+	$(CIGMA)/lib/libcigma.so \
+	$(CIGMA)/lib/libcigma.a \
+	$(CIGMA)/lib/libtmc.a
+
+CIGMA_OBJS = \
+	$(CIGMA)/libcigma/split.o \
+	$(CIGMA)/libcigma/h5_io.o \
+	$(CIGMA)/libcigma/h5_attr.o \
+	$(CIGMA)/libcigma/dataset.o \
+	$(CIGMA)/libcigma/array.o \
+	$(CIGMA)/libcigma/mesh.o
+
+TMC_OBJS = \
+	$(CIGMA)/tmc/vect_stats.o \
+	$(CIGMA)/tmc/Line_3f.o \
+	$(CIGMA)/tmc/Vector_3f.o \
+	$(CIGMA)/tmc/epsilon.o \
+	$(CIGMA)/tmc/Point_3f.o \
+	$(CIGMA)/tmc/Plane_RST_3d.o \
+	$(CIGMA)/tmc/Plane_3f.o \
+	$(CIGMA)/tmc/version.o \
+	$(CIGMA)/tmc/Subject.o \
+	$(CIGMA)/tmc/Indexed_tetra_set.o \
+	$(CIGMA)/tmc/math_util.o \
+	$(CIGMA)/tmc/Vector_3d.o \
+	$(CIGMA)/tmc/Matrix_4d.o \
+	$(CIGMA)/tmc/Point_3d.o \
+	$(CIGMA)/tmc/Tetrahedron.o \
+	$(CIGMA)/tmc/io_util.o \
+	$(CIGMA)/tmc/errors.o \
+	$(CIGMA)/tmc/Time_series.o \
+	$(CIGMA)/tmc/program_name.o \
+	$(CIGMA)/tmc/Exterior_face.o \
+	$(CIGMA)/tmc/Shape.o \
+	$(CIGMA)/tmc/Vector_3b.o \
+	$(CIGMA)/tmc/Indexed_tetra_set_off_reader.o \
+	$(CIGMA)/tmc/Observer.o \
+	$(CIGMA)/tmc/Bounding_box_3d.o \
+	$(CIGMA)/tmc/Point_4f.o \
+	$(CIGMA)/tmc/tet_sampling.o \
+	$(CIGMA)/tmc/Visitor.o
+
+TMC_OBJS += \
+	$(CIGMA)/tmc/anyoption.o \
+	$(CIGMA)/tmc/StringUtils.o
+
+TMC_OBJS += \
+	$(CIGMA)/tmc/HDF5_Reader.o \
+	$(CIGMA)/tmc/Writers.o \
+	$(CIGMA)/tmc/QuadratureRule.o
+
+TESTS = 
+
+ALLOBJS = $(CIGMA_OBJS) $(TMC_OBJS)
+
+###############################################################################
+
+all: $(TARGETS) $(COMMANDS) $(TESTS)
+
+$(CIGMA)/lib/libtmc.a: $(TMC_OBJS)
+	ar rcs $@ $^
+
+$(CIGMA)/lib/libcigma.a: $(CIGMA_OBJS)
+	ar rcs $@ $^
+
+$(CIGMA)/lib/libcigma.so: $(CIGMA_OBJS)
+	$(LD) -shared -fPIC $(LDFLAGS) $^ -o $@
+
+$(CIGMA)/bin/tmc: $(CIGMA)/tmc/tmc.cpp $(CIGMA)/lib/libtmc.a
+	$(CXX) $(CXXFLAGS) $(LIBS) $^ -o $@
+
+$(CIGMA)/bin/cigma-%: $(CIGMA)/src/cigma-%.cpp $(STATIC_LIBS)
+	$(CXX) $(CXXFLAGS) $(LDFLAGS) $(LIBS) $^ -o $@
+
+.c.o:
+	$(CC) $(CFLAGS) -c $< -o $@
+
+.cpp.o:
+	$(CXX) $(CXXFLAGS) -c $< -o $@
+
+###############################################################################
+
+clean:
+	rm -f $(ALLOBJS)
+
+clean-all: clean
+	rm -f $(TARGETS)
+
+.PHONY: clean clean-all

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp1.sh
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp1.sh	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp1.sh	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,4 @@
+#!/bin/bash
+cigma-compare --first=$HOME/benchmarks/bmrsnog.h5:/pylith/bmrsnog_tet4_1000m/variables/displacement/step00010    \
+              --second=$HOME/benchmarks/bmrsnog.h5:/geofest/bmrsnog_tet4_1000m_A/variables/displacement/step00010  \
+              --output=bmrsnog_pylith1000m_geofest1000m_residuals.vtk

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp2.sh
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp2.sh	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp2.sh	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,4 @@
+#!/bin/bash
+cigma-compare --first=$HOME/benchmarks/bmrsnog.h5:/pylith/bmrsnog_tet4_1000m/variables/displacement/step00010    \
+              --second=$HOME/benchmarks/bmrsnog.h5:/geofest/bmrsnog_tet4_0500m_A/variables/displacement/step00010  \
+              --output=bmrsnog_pylith1000m_geofest0500m_residuals.vtk

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp3.sh
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp3.sh	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp3.sh	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,4 @@
+#!/bin/bash
+cigma-compare --first=$HOME/benchmarks/bmrsnog.h5:/pylith/bmrsnog_tet4_0500m/variables/displacement/step00010   \
+              --second=$HOME/benchmarks/bmrsnog.h5:/geofest/bmrsnog_tet4_0500m_B/variables/displacement/step00010  \
+              --output=bmrsnog_pylith0500m_geofest0500m_residuals.vtk

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp4.sh
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp4.sh	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmrsnog_cmp4.sh	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,4 @@
+#!/bin/bash
+cigma-compare --first=$HOME/benchmarks/bmrsnog.h5:/pylith/bmrsnog_tet4_0250m/variables/velocity/step00000             \
+              --second=$HOME/benchmarks/bmrsnog.h5:/geofest/bmrsnog_tet4_0500m_A/variables/del_displacement/step00000   \
+              --output=bmrsnog_pylith0250m_geofest0500m_residuals.vtk

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp1.sh
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp1.sh	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp1.sh	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,4 @@
+#!/bin/bash
+cigma-compare --first=$HOME/benchmarks/bmssnog.h5:/pylith/bmssnog_tet4_1000m/variables/displacement/step00010    \
+              --second=$HOME/benchmarks/bmssnog.h5:/geofest/bmssnog_tet4_1000m/variables/displacement/step00010  \
+              --output=bmssnog_pylith1000m_geofest1000m_residuals.vtk

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp2.sh
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp2.sh	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp2.sh	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,4 @@
+#!/bin/bash
+cigma-compare --first=$HOME/benchmarks/bmssnog.h5:/pylith/bmssnog_tet4_1000m/variables/displacement/step00010    \
+              --second=$HOME/benchmarks/bmssnog.h5:/geofest/bmssnog_tet4_0500m/variables/displacement/step00010  \
+              --output=bmssnog_pylith1000m_geofest0500m_residuals.vtk

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp3.sh
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp3.sh	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp3.sh	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,4 @@
+#!/bin/bash
+cigma-compare --first=$HOME/benchmarks/bmssnog.h5:/pylith/bmssnog_tet4_0500m_new_bc/variables/displacement/step00010   \
+              --second=$HOME/benchmarks/bmssnog.h5:/geofest/bmssnog_tet4_0500m/variables/displacement/step00010  \
+              --output=bmssnog_pylith0500m_geofest0500m_residuals.vtk

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp4.sh
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp4.sh	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tests/bmssnog_cmp4.sh	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,4 @@
+#!/bin/bash
+cigma-compare --first=$HOME/benchmarks/bmssnog.h5:/pylith/bmssnog_tet4_0250m/variables/velocity/step00000             \
+              --second=$HOME/benchmarks/bmssnog.h5:/geofest/bmssnog_tet4_0500m/variables/del_displacement/step00000   \
+              --output=bmssnog_pylith0250m_geofest0500m_residuals.vtk

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/bmrsnog.py
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/bmrsnog.py	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/bmrsnog.py	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,235 @@
+#!/usr/bin/env python
+#
+#       bmrsnog.h5
+#       |-- mesh
+#       |   |-- bmrsnog_hex8_1000m
+#       |   |-- bmrsnog_tet4_1000m
+#       |   |-- bmrsnog_tet4_0500m
+#       |   |-- bmrsnog_tet4_0250m
+#       |   |-- bmrsnog_tet4_var_res_01
+#       |   `-- bmrsnog_tet4_var_res_02
+#       |-- pylith
+#       |   |-- bmrsnog_hex8_1000m
+#       |   |-- bmrsnog_tet4_1000m
+#       |   |-- bmrsnog_tet4_0500m
+#       |   |-- bmrsnog_tet4_0250m
+#       |   `-- bmrsnog_tet4_var_res_01
+#       `-- geofest
+#           |-- bmrsnog_tet4_1000m
+#           |-- bmrsnog_tet4_1000m
+#           |-- bmrsnog_tet4_1000m
+#           |-- bmrsnog_tet4_1000m
+#           |-- bmrsnog_tet4_0500m
+#           |-- bmrsnog_tet4_0500m
+#           `-- bmrsnog_tet4_var_res_01
+#
+
+import os
+from os.path import join
+
+filename = 'bmrsnog.h5'
+homedir  = os.environ['HOME'] 
+topdir   = os.path.join(homedir, 'benchmarks', 'bmrsnog')
+
+#
+# Benchmark data is available for meshes with the following resolutions
+#
+resolutions = ['1000m', '0500m', '0250m', 'var_res_01']
+
+
+#
+# The mesh_db contains information about the size of the mesh.
+# The mapping is as follows
+#
+#   (space, resolution) -> (nno, nel, ndof)
+#
+mesh_db = {
+    ('hex8', '1000m'): (19000, 17040, 8),
+    ('tet4', '1000m'): (16071, 85368, 4),
+    ('tet4', '0500m'): (119451, 673396, 4),
+    ('tet4', '0250m'): (918980, 5341648, 4),
+    ('tet4', 'var_res_01'): (22973, 121918, 4),
+    ('tet4', 'var_res_02'): (52793, 287347, 4),
+}
+
+meshfileprefix_db = {
+    ('hex8', '1000m'): join(topdir,'input','bmrsnog_hex8_1000m','hex8_1000m'),
+    ('tet4', '1000m'): join(topdir,'input','bmrsnog_tet4_1000m','tet4_1000m'),
+    ('tet4', '0500m'): join(topdir,'input','bmrsnog_tet4_0500m','tet4_0500m'),
+    ('tet4', '0250m'): join(topdir,'input','bmrsnog_tet4_0250m','tet4_0250m'),
+    ('tet4', 'var_res_01'): join(topdir,'input','bmrsnog_tet4_var_res_01','tet_var_res_01'),
+    ('tet4', 'var_res_02'): join(topdir,'input','bmrsnog_tet4_var_res_02','tet_var_res_02'),
+}
+
+meshloc_db = {
+    ('hex8', '1000m'): '/mesh/bmrsnog_hex8_1000m',
+    ('tet4', '1000m'): '/mesh/bmrsnog_tet4_1000m',
+    ('tet4', '0500m'): '/mesh/bmrsnog_tet4_0500m',
+    ('tet4', '0250m'): '/mesh/bmrsnog_tet4_0250m',
+    ('tet4', 'var_res_01'): '/mesh/bmrsnog_tet4_var_res_01',
+    ('tet4', 'var_res_02'): '/mesh/bmrsnog_tet4_var_res_02'
+}
+
+def mesh_coord_file(mesh_key):
+    (fe_space, resolution) = mesh_key
+    return meshfileprefix_db[fe_space,resolution] + '.coord'
+
+def mesh_connect_file(mesh_key):
+    (fe_space, resolution) = mesh_key
+    return meshfileprefix_db[fe_space,resolution] + '.connect'
+
+# 
+# Not all data for every timestep is available on each mesh. The following
+# dictionary keeps track of what fields to read.
+#
+pylith_steps = {
+    ('hex8', '1000m'): [0, 10, 50, 100],
+    ('tet4', '1000m'): [0, 10, 50, 100],
+    ('tet4', '0500m'): [0, 10, 50, 100],
+    ('tet4', '0250m'): [0],
+    ('tet4', 'var_res_01'): [0, 10, 50, 100],
+}
+
+stepformat_db = {
+      0: '00000',
+     10: '00010',
+     50: '00050',
+    100: '00100',
+}
+
+
+pylith_datafiles = {
+    ('hex8','1000m',''): join(topdir,'pylith','bmrsnog_hex8_1000m','bmrsnog_1000m_1.0.mesh.time.%s.inp'),
+    ('tet4','1000m',''): join(topdir,'pylith','bmrsnog_tet4_1000m','bmrsnog_1000m_1.0.mesh.time.%s.inp'),
+    ('tet4','0500m',''): join(topdir,'pylith','bmrsnog_tet4_0500m','bmrsnog_500m_1.0.mesh.time.%s.inp'),
+    ('tet4','0250m',''): join(topdir,'pylith','bmrsnog_tet4_0250m','bmrsnog_250m_1.0.mesh.time.%s.inp'),
+    ('tet4','var_res_01',''): join(topdir,'pylith','bmrsnog_tet4_var_res_01','tet_var_res_01_1.0.mesh.time.%s.inp'),
+}
+
+geofest_datafiles = {
+    ('tet4','1000m','_A'): join(topdir,'geofest','bmrsnog_tet4_1000m','tet4_1kmA.out'),
+    ('tet4','1000m','_B'): join(topdir,'geofest','bmrsnog_tet4_1000m','tet4_1kmB.out'),
+    ('tet4','1000m','_C'): join(topdir,'geofest','bmrsnog_tet4_1000m','tet4_1kmC.out'),
+    ('tet4','1000m','_D'): join(topdir,'geofest','bmrsnog_tet4_1000m','tet4_1kmD.out'),
+    ('tet4','0500m','_A'): join(topdir,'geofest','bmrsnog_tet4_0500m','tet4_halfkmA.out'),
+    ('tet4','0500m','_B'): join(topdir,'geofest','bmrsnog_tet4_0500m','tet4_halfkmB.out'),
+    ('tet4','var_res_01',''): join(topdir,'geofest','bmrsnog_tet4_var_res_01','tet_var_res_01.out'),
+}
+
+geofest_steps = [0, 10, 50, 100]
+
+
+if __name__ == '__main__':
+
+    import numpy
+    import tables
+
+    from utils import skiplines, readfrom, readfromfile
+
+    h5 = tables.openFile(filename, 'w')
+
+
+    mesh_reader_kwarg_db = {
+        'tet4': {
+            'coord'  : dict(skip=1, factor=1000.0, dtype=float, range=slice(1,4)),
+            'connect': dict(skip=0, offset=1, dtype=int, range=slice(4,8)) 
+        },
+        'hex8': {
+            'coord'  : dict(skip=1, factor=1000.0, dtype=float, range=slice(1,4)),
+            'connect': dict(skip=0, offset=1, dtype=int, range=slice(4,12))
+        }
+    }
+
+    mesh_group = h5.createGroup('/', 'mesh')
+
+    for key in mesh_db:
+        
+        (space, res) = key
+        (nno, nel, ndof) = mesh_db[space,res]
+
+        coordinates = numpy.zeros((nno,3), numpy.float32)
+        connectivity = numpy.zeros((nel, ndof), numpy.int32)
+
+        coorfile = mesh_coord_file(key)
+        connfile = mesh_connect_file(key)
+
+        kw = mesh_reader_kwarg_db[space]
+        readfrom(coorfile, coordinates, **kw['coord'])
+        readfrom(connfile, connectivity, **kw['connect'])
+
+        group = h5.createGroup(mesh_group, 'bmrsnog_%s_%s' % key)
+        h5.createArray(group, 'coordinates', coordinates)
+        h5.createArray(group, 'connectivity', connectivity)
+    
+
+    pylith_group = h5.createGroup('/', 'pylith')
+    for key in pylith_datafiles:
+        
+        space, res, postfix = key
+        nno, nel, ndof = mesh_db[space,res]
+        steps = pylith_steps[space,res]
+
+        dispvelo = numpy.zeros((nno, 6), numpy.float32)
+
+        model_group = h5.createGroup(pylith_group, 'bmrsnog_%s_%s%s' % key)
+        vars_group  = h5.createGroup(model_group, 'variables')
+        disp_group  = h5.createGroup(vars_group, 'displacement')
+        velo_group  = h5.createGroup(vars_group, 'velocity')
+
+        for step in steps:
+            
+            stepfmt = stepformat_db[step]
+            datafile = pylith_datafiles[key] % stepfmt
+            readfrom(datafile, dispvelo, skip=7, factor=1.0, dtype=float, range=slice(1,7))
+            
+            d = h5.createArray(disp_group, 'step%s' % stepfmt, dispvelo[:,0:3])
+            d._v_attrs.MeshLocation = meshloc_db[space,res]
+            d._v_attrs.FunctionSpace = space
+            
+            v = h5.createArray(velo_group, 'step%s' % stepfmt, dispvelo[:,3:6])
+            v._v_attrs.MeshLocation = meshloc_db[space,res]
+            v._v_attrs.FunctionSpace = space
+
+
+    def geofest_readstep(fp, x):
+        skiplines(fp, 6)
+        readfromfile(fp, x, nodecol=1, offset=1, range=slice(5,11))
+        skiplines(fp, 7)
+
+
+    geofest_group = h5.createGroup('/', 'geofest')
+    for key in geofest_datafiles:
+        
+        space, res, postfix = key
+        nno, nel, ndof = mesh_db[space,res]
+
+        # prepare numpy array
+        dispdel = numpy.zeros((nno,6), numpy.float32)
+        
+        # prepare hdf5 group for data
+        model_group = h5.createGroup(geofest_group, 'bmrsnog_%s_%s%s' % key)
+        vars_group  = h5.createGroup(model_group, 'variables')
+        disp_group  = h5.createGroup(vars_group, 'displacement')
+        del_group   = h5.createGroup(vars_group, 'del_displacement')
+        
+        # read data file with all steps
+        datafile = geofest_datafiles[key]
+        print "Reading file", datafile
+        fp = open(datafile, 'r')
+        skiplines(fp, 3)
+
+        for step in geofest_steps:
+            
+            geofest_readstep(fp, dispdel)
+
+            stepfmt = stepformat_db[step]
+            
+            d = h5.createArray(disp_group, 'step%s' % stepfmt, dispdel[:,0:3])
+            d._v_attrs.MeshLocation = meshloc_db[space, res]
+            d._v_attrs.FunctionSpace = space
+
+            dd = h5.createArray(del_group, 'step%s' % stepfmt, dispdel[:,3:6])
+            dd._v_attrs.MeshLocation = meshloc_db[space, res]
+            dd._v_attrs.FunctionSpace = space
+
+    h5.close()

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/bmssnog.py
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/bmssnog.py	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/bmssnog.py	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,220 @@
+#!/usr/bin/env python
+#
+#       bmssnog.h5
+#       |-- mesh
+#       |   |-- bmssnog_hex8_1000m
+#       |   |-- bmssnog_tet4_1000m
+#       |   |-- bmssnog_tet4_0500m
+#       |   `-- bmssnog_tet4_0250m
+#       |-- pylith
+#       |   |-- bmssnog_hex8_1000m
+#       |   |-- bmssnog_tet4_1000m
+#       |   |-- bmssnog_tet4_0500m_old
+#       |   |-- bmssnog_tet4_0500m_new_bc
+#       |   |-- bmssnog_tet4_0500m_altered_bc
+#       |   `-- bmssnog_tet4_0250m
+#       `-- geofest
+#           |-- bmssnog_tet4_1000m
+#           |-- bmssnog_tet4_0500m
+#           `-- bmssnog_tet4_0250m
+#
+
+import os
+from os.path import join
+
+filename = 'bmssnog.h5'
+homedir  = os.environ['HOME'] 
+topdir   = os.path.join(homedir, 'benchmarks', 'bmssnog')
+
+#
+# Benchmark data is available for meshes with the following resolutions
+#
+resolutions = ['1000m', '0500m', '0250m']
+
+
+#
+# The mesh_db contains information about the size of the mesh.
+# The mapping is as follows
+#
+#   (space, resolution) -> (nno, nel, ndof)
+#
+mesh_db = {
+    ('hex8', '1000m'): (15625, 13824, 8),
+    ('tet4', '1000m'): (15625, 82944, 4),
+    ('tet4', '0500m'): (117649, 663552, 4),
+    ('tet4', '0250m'): (912673, 5308416, 4)
+}
+
+meshfileprefix_db = {
+    ('hex8', '1000m'): join(topdir,'pylith','bmssnog_hex8_1000m','bmssnog_1000m_1.0'),
+    ('tet4', '1000m'): join(topdir,'input','bmssnog_tet4_1000m','tet4_1000m'),
+    ('tet4', '0500m'): join(topdir,'input','bmssnog_tet4_0500m','tet4_0500m'),
+    ('tet4', '0250m'): join(topdir,'input','bmssnog_tet4_0250m','tet4_0250m')
+}
+
+meshloc_db = {
+    ('hex8', '1000m'): '/mesh/bmssnog_hex8_1000m',
+    ('tet4', '1000m'): '/mesh/bmssnog_tet4_1000m',
+    ('tet4', '0500m'): '/mesh/bmssnog_tet4_0500m',
+    ('tet4', '0250m'): '/mesh/bmssnog_tet4_0250m',
+}
+
+def mesh_coord_file(mesh_key):
+    (fe_space, resolution) = mesh_key
+    return meshfileprefix_db[fe_space,resolution] + '.coord'
+
+def mesh_connect_file(mesh_key):
+    (fe_space, resolution) = mesh_key
+    return meshfileprefix_db[fe_space,resolution] + '.connect'
+
+# 
+# Not all data for every timestep is available on each mesh. The following
+# dictionary keeps track of what fields to read.
+#
+pylith_steps = {
+    ('hex8', '1000m'): [0, 10, 50, 100],
+    ('tet4', '1000m'): [0, 10, 50, 100],
+    ('tet4', '0500m'): [0, 10, 50, 100],
+    ('tet4', '0250m'): [0],
+}
+
+stepformat_db = {
+      0: '00000',
+     10: '00010',
+     50: '00050',
+    100: '00100',
+}
+
+
+pylith_datafiles = {
+    ('hex8','1000m',''           ): join(topdir,'pylith','bmssnog_hex8_1000m/bmssnog_1000m_1.0.mesh.time.%s.inp'),
+    ('tet4','1000m',''           ): join(topdir,'pylith','bmssnog_tet4_1000m/bmssnog_1000m_1.0.mesh.time.%s.inp'),
+    ('tet4','0500m','_old'       ): join(topdir,'pylith','bmssnog_tet4_0500m_old/bmssnog_500m_1.0.mesh.time.%s.inp'),
+    ('tet4','0500m','_new_bc'    ): join(topdir,'pylith','bmssnog_tet4_0500m_new_bc/bmssnog_500m.0.mesh.time.%s.inp'),
+    ('tet4','0500m','_altered_bc'): join(topdir,'pylith','bmssnog_tet4_0500m_altered_bc/bmssnog_500m.0.mesh.time.%s.inp'),
+    ('tet4', '0250m', ''           ): join(topdir,'pylith','bmssnog_tet4_0250m/bmssnog_250m_1.0.mesh.time.%s.inp')
+}
+
+geofest_datafiles = {
+    '1000m': join(topdir,'geofest','bmssnog_tet4_1000m','bm4_uni1000.out'),
+    '0500m': join(topdir,'geofest','bmssnog_tet4_0500m','bm4_uni0500.out'),
+    '0250m': join(topdir,'geofest','bmssnog_tet4_0250m','bm4_uni0250.out'),
+}
+
+geofest_steps = [0, 10, 50, 100]
+
+
+if __name__ == '__main__':
+
+    import numpy
+    import tables
+
+    from utils import skiplines, readfrom, readfromfile
+
+    h5 = tables.openFile(filename, 'w')
+
+
+    mesh_reader_kwarg_db = {
+        'tet4': {
+            'coord'  : dict(skip=1, factor=1000.0, dtype=float, range=slice(1,4)),
+            'connect': dict(skip=0, offset=1, dtype=int, range=slice(4,8)) 
+        },
+        'hex8': {
+            'coord'  : dict(skip=6, factor=1000.0, dtype=float, range=slice(1,4)),
+            'connect': dict(skip=3, offset=1, dtype=int, range=slice(4,12))
+        }
+    }
+
+    mesh_group = h5.createGroup('/', 'mesh')
+
+    for key in mesh_db:
+        
+        (space, res) = key
+        (nno, nel, ndof) = mesh_db[space,res]
+
+        coordinates = numpy.zeros((nno,3), numpy.float32)
+        connectivity = numpy.zeros((nel, ndof), numpy.int32)
+
+        coorfile = mesh_coord_file(key)
+        connfile = mesh_connect_file(key)
+
+        kw = mesh_reader_kwarg_db[space]
+        readfrom(coorfile, coordinates, **kw['coord'])
+        readfrom(connfile, connectivity, **kw['connect'])
+
+        group = h5.createGroup(mesh_group, 'bmssnog_%s_%s' % key)
+        h5.createArray(group, 'coordinates', coordinates)
+        h5.createArray(group, 'connectivity', connectivity)
+    
+
+    pylith_group = h5.createGroup('/', 'pylith')
+    for key in pylith_datafiles:
+        
+        space, res, postfix = key
+        nno, nel, ndof = mesh_db[space,res]
+        steps = pylith_steps[space,res]
+
+        dispvelo = numpy.zeros((nno, 6), numpy.float32)
+
+        model_group = h5.createGroup(pylith_group, 'bmssnog_%s_%s%s' % key)
+        vars_group  = h5.createGroup(model_group, 'variables')
+        disp_group  = h5.createGroup(vars_group, 'displacement')
+        velo_group  = h5.createGroup(vars_group, 'velocity')
+
+        for step in steps:
+            
+            stepfmt = stepformat_db[step]
+            datafile = pylith_datafiles[key] % stepfmt
+            readfrom(datafile, dispvelo, skip=7, factor=1.0, dtype=float, range=slice(1,7))
+            
+            d = h5.createArray(disp_group, 'step%s' % stepfmt, dispvelo[:,0:3])
+            d._v_attrs.MeshLocation = meshloc_db[space,res]
+            d._v_attrs.FunctionSpace = space
+            
+            v = h5.createArray(velo_group, 'step%s' % stepfmt, dispvelo[:,3:6])
+            v._v_attrs.MeshLocation = meshloc_db[space,res]
+            v._v_attrs.FunctionSpace = space
+
+
+    def geofest_readstep(fp, x):
+        skiplines(fp, 6)
+        readfromfile(fp, x, nodecol=1, offset=1, range=slice(5,11))
+        skiplines(fp, 7)
+
+
+    geofest_group = h5.createGroup('/', 'geofest')
+    for key in geofest_datafiles:
+        
+        space, res = 'tet4', key
+        nno, nel, ndof = mesh_db[space,res]
+
+        # prepare numpy array
+        dispdel = numpy.zeros((nno,6), numpy.float32)
+        
+        # prepare hdf5 group for data
+        model_group = h5.createGroup(geofest_group, 'bmssnog_%s_%s' % (space,res))
+        vars_group  = h5.createGroup(model_group, 'variables')
+        disp_group  = h5.createGroup(vars_group, 'displacement')
+        del_group   = h5.createGroup(vars_group, 'del_displacement')
+        
+        # read data file with all steps
+        datafile = geofest_datafiles[key]
+        print "Reading file", datafile
+        fp = open(datafile, 'r')
+        skiplines(fp, 3)
+
+        for step in geofest_steps:
+            
+            geofest_readstep(fp, dispdel)
+
+            stepfmt = stepformat_db[step]
+            
+            d = h5.createArray(disp_group, 'step%s' % stepfmt, dispdel[:,0:3])
+            d._v_attrs.MeshLocation = meshloc_db[space, res]
+            d._v_attrs.FunctionSpace = space
+
+            dd = h5.createArray(del_group, 'step%s' % stepfmt, dispdel[:,3:6])
+            dd._v_attrs.MeshLocation = meshloc_db[space, res]
+            dd._v_attrs.FunctionSpace = space
+
+    h5.close()

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/download.sh
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/download.sh	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/download.sh	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,210 @@
+#!/bin/bash
+#
+# This script was used to download the benchmark files available on the website
+#
+#   http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/
+#
+# The resulting directory layout is as follows:
+#
+#       benchmarks
+#       |-- bmssnog
+#       |   |-- input
+#       |   |   |-- bmssnog_tet4_1000m
+#       |   |   |-- bmssnog_tet4_0500m
+#       |   |   `-- bmssnog_tet4_0250m
+#       |   |-- pylith
+#       |   |   |-- bmssnog_hex8_1000m
+#       |   |   |-- bmssnog_tet4_1000m
+#       |   |   |-- bmssnog_tet4_0500m_old
+#       |   |   |-- bmssnog_tet4_0500m_new_bc
+#       |   |   |-- bmssnog_tet4_0500m_altered_bc
+#       |   |   `-- bmssnog_tet4_0250m
+#       |   `-- geofest
+#       |       |-- bmssnog_tet4_1000m
+#       |       |-- bmssnog_tet4_0500m
+#       |       `-- bmssnog_tet4_0250m
+#       `-- bmrsnog
+#           |-- input
+#           |   |-- bmrsnog_tet4_1000m
+#           |   |-- bmrsnog_tet4_0500m
+#           |   |-- bmrsnog_tet4_0250m
+#           |   |-- bmrsnog_tet4_var_res_01
+#           |   `-- bmrsnog_tet4_var_res_02
+#           |-- pylith
+#           |   |-- bmrsnog_hex8_1000m
+#           |   |-- bmrsnog_tet4_1000m
+#           |   |-- bmrsnog_tet4_0500m
+#           |   |-- bmrsnog_tet4_0250m
+#           |   `-- bmrsnog_tet4_var_res_01
+#           `-- geofest
+#               |-- bmrsnog_tet4_1000m
+#               |-- bmrsnog_tet4_0500m
+#               `-- bmrsnog_tet4_var_res_01
+#
+
+bmdir="$HOME/benchmarks"
+bmssnog="$bmdir/bmssnog"
+bmrsnog="$bmdir/bmrsnog"
+
+mkdir -v $bmdir
+if [ "$?" != "0" ]; then
+    echo "Please remove or rename the specified directory."
+    exit 1
+fi
+
+
+mkdir -v -p $bmssnog
+mkdir -v -p $bmssnog/input
+mkdir -v -p $bmssnog/pylith
+mkdir -v -p $bmssnog/geofest
+
+mkdir -v -p $bmrsnog
+mkdir -v -p $bmrsnog/input
+mkdir -v -p $bmrsnog/pylith
+mkdir -v -p $bmrsnog/geofest
+
+################################################################################
+# Strike-slip benchmark                                                        #
+################################################################################
+
+# input meshes
+cd $bmssnog/input
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/pylith-0.8-input/bmssnog_tet4_1000m.tgz
+tar xvfz bmssnog_tet4_1000m.tgz -C $bmssnog/input 
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/pylith-0.8-input/bmssnog_tet4_0500m.tgz
+tar xvfz bmssnog_tet4_0500m.tgz -C $bmssnog/input 
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/pylith-0.8-input/bmssnog_tet4_0250m.tgz
+tar xvfz bmssnog_tet4_0250m.tgz -C $bmssnog/input 
+
+
+# pylith data (v0.8)
+cd $bmssnog/pylith
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/results/bmssnog_1000m-pylith-np1-linhex.tar.bz2    --output-document=bmssnog_hex8_1000m.tar.bz2
+tar xvfj bmssnog_hex8_1000m.tar.bz2
+mv -v bmssnog_1000m-pylith-np1-linhex/ bmssnog_hex8_1000m
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/results/bmssnog_1000m-pylith-np1-lintet.tar.bz2    --output-document=bmssnog_tet4_1000m.tar.bz2
+tar xvfj bmssnog_tet4_1000m.tar.bz2
+mv -v bmssnog_1000m-pylith-np1-lintet/ bmssnog_tet4_1000m
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/results/bmssnog_500m-pylith-np1-lintet.tar.bz2     --output-document=bmssnog_tet4_0500m.tar.bz2
+tar xvfj bmssnog_tet4_0500m.tar.bz2
+mv -v bmssnog_500m-pylith-np1-lintet/ bmssnog_tet4_0500m_old
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/results/bmssnog_250m.tar.bz2                       --output-document=bmssnog_tet4_0250m.tar.bz2
+tar xvfj bmssnog_tet4_0250m.tar.bz2
+mv -v bmssnog_250m/ bmssnog_tet4_0250m
+
+
+# revised pylith data (v0.8)
+
+cd $bmssnog/pylith
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/results/results1.tar.bz2       --output-document=bmssnog_tet4_0500m_new_bc.tar.bz2
+tar xvfj bmssnog_tet4_0500m_new_bc.tar.bz2
+mv -v bmssnog_500m-pylith-np1-lintet/ bmssnog_tet4_0500m_new_bc
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/results/bmssnog_500m-pylith-np1-tet4-new.tar.bz2   --output-document=bmssnog_tet4_0500m_altered_bc.tar.bz2
+tar xvfj bmssnog_tet4_0500m_altered_bc.tar.bz2
+mv -v bmssnog_500m-pylith-np1-tet4-new/ bmssnog_tet4_0500m_altered_bc
+
+
+# geofest data (v4.5)
+cd $bmssnog/geofest
+
+mkdir -v -p $bmssnog/geofest/bmssnog_tet4_1000m
+cd $bmssnog/geofest/bmssnog_tet4_1000m
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/results/bm4_uni1000.tar.gz
+tar xvfz bm4_uni1000.tar.gz
+
+mkdir -v -p $bmssnog/geofest/bmssnog_tet4_0500m
+cd $bmssnog/geofest/bmssnog_tet4_0500m
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/results/bm4_uni0500.out.gz
+gunzip bm4_uni0500.out.gz
+
+mkdir -v -p $bmssnog/geofest/bmssnog_tet4_0250m
+cd $bmssnog/geofest/bmssnog_tet4_0250m
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-strikeslip/results/bm4_uni0250.out.gz
+gunzip bm4_uni0250.out.gz
+
+
+
+################################################################################
+# Reverse-slip benchmark                                                       #
+################################################################################
+
+
+# input meshes
+cd $bmrsnog/input
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/pylith-0.8-input/bmrsnog_hex8_1000m.tgz
+tar xvfz bmrsnog_hex8_1000m.tgz
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/pylith-0.8-input/bmrsnog_tet4_1000m.tgz
+tar xvfz bmrsnog_tet4_1000m.tgz
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/pylith-0.8-input/bmrsnog_tet4_0500m.tgz
+tar xvfz bmrsnog_tet4_0500m.tgz
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/pylith-0.8-input/bmrsnog_tet4_0250m.tgz
+tar xvfz bmrsnog_tet4_0250m.tgz
+
+mkdir -v -p $bmrsnog/input/bmrsnog_tet4_var_res_01
+cd $bmrsnog/input/bmrsnog_tet4_var_res_01
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/pylith-0.8-input/tet_var_res_01_pylith_input.tgz
+tar xvfz tet_var_res_01_pylith_input.tgz
+
+mkdir -v -p $bmrsnog/input/bmrsnog_tet4_var_res_02
+cd $bmrsnog/input/bmrsnog_tet4_var_res_02
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/pylith-0.8-input/tet_var_res_02_pylith_input.tgz
+tar xvfz tet_var_res_02_pylith_input.tgz
+
+
+# pylith data (v0.8)
+cd $bmrsnog/pylith
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/results/bmrsnog_1000m-pylith-np1-linhex.tar.bz2
+tar xvfj bmrsnog_1000m-pylith-np1-linhex.tar.bz2
+mv -v bmrsnog_1000m-pylith-np1-linhex/ bmrsnog_hex8_1000m
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/results/bmrsnog_1000m-pylith-np1-lintet.tar.bz2
+tar xvfj bmrsnog_1000m-pylith-np1-lintet.tar.bz2
+mv -v bmrsnog_1000m-pylith-np1-lintet/ bmrsnog_tet4_1000m
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/results/bmrsnog_500m-pylith-np1-lintet.tar.bz2
+tar xvfj bmrsnog_500m-pylith-np1-lintet.tar.bz2
+mv -v bmrsnog_500m-pylith-np1-lintet/ bmrsnog_tet4_0500m
+
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/results/bmrsnog_250m_lintet.tar.bz2
+tar xvfj bmrsnog_250m_lintet.tar.bz2
+mv -v bmrsnog_250m_lintet/ bmrsnog_tet4_0250m
+
+mkdir -v -p $bmrsnog/pylith/bmrsnog_tet4_var_res_01
+cd $bmrsnog/pylith/bmrsnog_tet4_var_res_01
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/results/tet_var_res_01_pylith_soln.tgz
+tar xvfz tet_var_res_01_pylith_soln.tgz
+
+
+# geofest data (v4.5)
+cd $bmrsnog/geofest
+
+mkdir -v -p $bmrsnog/geofest/bmrsnog_tet4_1000m
+cd $bmrsnog/geofest/bmrsnog_tet4_1000m
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/results/tet4_1000m_geofest.tar
+tar xvf tet4_1000m_geofest.tar
+
+mkdir -v -p $bmrsnog/geofest/bmrsnog_tet4_0500m
+cd $bmrsnog/geofest/bmrsnog_tet4_0500m
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/results/tet4_500m_geofest.tar
+tar xvf tet4_500m_geofest.tar
+
+mkdir -v -p $bmrsnog/geofest/bmrsnog_tet4_var_res_01
+cd $bmrsnog/geofest/bmrsnog_tet4_var_res_01
+wget http://www.geodynamics.org/cig/workinggroups/short/workarea/benchmarks/benchmark-rs-nog/results/tet_var_res_01_geofest4.5_soln.tar.gz
+tar xvfz tet_var_res_01_geofest4.5_soln.tar.gz
+
+
+exit 0

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/off2vtk.py
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/off2vtk.py	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/off2vtk.py	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+
+import sys
+import numpy
+import tables
+
+from vtkwriter import write_tet4_vtk
+
+off_file = "residuals.off"
+vtk_file = "residuals.vtk"
+
+argc = len(sys.argv)
+if argc > 1:
+    off_file = sys.argv[1]
+if argc > 2:
+    vtk_file = sys.argv[2]
+
+fp = open(off_file, 'r')
+print "Reading", fp.name
+
+nno, nel = map(int, fp.readline().split())
+coordinates = numpy.zeros((nno,3), numpy.float32)
+connectivity = numpy.zeros((nel, 4), numpy.int32)
+residuals = numpy.zeros((nel,), numpy.float32)
+
+for n in xrange(nno):
+    line = fp.readline()
+    coordinates[n] = map(float, line.split())
+
+for e in xrange(nel):
+    line = fp.readline()
+    cols = line.split()
+    connectivity[e] = map(int, cols[0:4])
+    residuals[e] = float(cols[4])
+
+write_tet4_vtk(vtk_file, coordinates, connectivity, residuals)
+

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/utils.py
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/utils.py	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/utils.py	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,55 @@
+
+def skiplines(fp, n):
+    for i in xrange(n):
+        fp.readline()
+    return
+
+def readfromfile(fp, x, **kw):
+    """
+    Given a file object to an ascii file with data in a column-based
+    format. Note that x is assumed to be a numpy array with rank 2.
+    As many rows will be read from the file as can fit along the extent
+    of the first dimension of x.
+
+    The following keyword arguments may be specified
+
+      skip    - skip this many lines at beginning
+      factor  - conversion factor to apply to each value
+      range   - slice representing range of columns to copy into array row
+      dtype   - datatype factory for the column data (float or int)
+      offset  - whether to apply an index offset (0 or 1)
+      nodecol - column index corresponding to the element, or node, number
+
+    """
+    (n,d) = x.shape
+    skip = kw.get('skip', 0)
+    factor = kw.get('factor', 1.0)
+    range = kw.get('range', slice(1,4))
+    dtype = kw.get('dtype', float)
+    offset = kw.get('offset', 1)
+    nodecol = kw.get('nodecol', 0)
+    # skip the specified number of lines
+    for i in xrange(skip):
+        fp.readline()
+    # read n lines into array
+    for i in xrange(n):
+        line = fp.readline()
+        cols = line.split()
+        node = int(cols[nodecol]) - offset
+        x[node] = map(dtype, cols[range])
+    # finally, apply necessary corrections to x
+    if dtype is int:
+        x -= offset
+    elif dtype is float:
+        x *= factor
+    return
+
+
+def readfrom(filename, x, **kw):
+    print "Reading file", filename
+    fp = open(filename, 'r')
+    readfromfile(fp, x, **kw)
+    fp.close()
+    return
+
+readfrom.__doc__ = readfromfile.__doc__

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/vtkwriter.py
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/vtkwriter.py	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/tools/vtkwriter.py	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,38 @@
+import numpy
+
+def write_tet4_vtk(filename, coords, connect, errors):
+    """Write out cell-based local errors on given tetrahedral mesh"""
+
+    (nno, nsd) = coords.shape
+    (nel, ndof) = connect.shape
+    assert errors.shape[0] == nel
+
+    fp = open(filename, "w")
+    print "Creating", fp.name
+
+    fp.write("# vtk DataFile Version 3.0\n")
+    fp.write("This line is a comment\n")
+    fp.write("ASCII\n")
+
+    fp.write("DATASET UNSTRUCTURED_GRID\n")
+
+    fp.write("POINTS %d float\n" % nno)
+    for n in xrange(nno):
+        fp.write("%g %g %g\n" % tuple(coords[n]))
+
+    cellstr = str(ndof) + (" %d" * ndof) + "\n"
+    fp.write("CELLS %d %d\n" % (nel, nel + nel*ndof))
+    for e in xrange(nel):
+        fp.write(cellstr % tuple(connect[e]))
+
+    fp.write("CELL_TYPES %d\n" % nel)
+    for e in xrange(nel):
+        fp.write("10\n")
+    
+    fp.write("CELL_DATA %d\n" % nel)
+    fp.write("SCALARS LocalResiduals float\n")
+    fp.write("LOOKUP_TABLE default\n")
+    for e in xrange(nel):
+        fp.write("%g\n" % errors[e])
+
+    fp.close()

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/domain.vtk
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/domain.vtk	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/domain.vtk	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,20 @@
+# vtk DataFile Version 1.0
+This line is a comment
+ASCII
+DATASET POLYDATA
+POINTS 8 float
+    0.0      0.0       0.0
+24000.0      0.0       0.0
+    0.0  24000.0       0.0
+24000.0  24000.0       0.0
+    0.0      0.0  -24000.0
+24000.0      0.0  -24000.0
+    0.0  24000.0  -24000.0
+24000.0  24000.0  -24000.0
+POLYGONS 6 30
+4  0 2 6 4
+4  1 5 7 3
+4  0 4 5 1
+4  2 3 7 6
+4  0 1 3 2
+4  4 5 7 6

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/reverse-slip-fault.vtk
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/reverse-slip-fault.vtk	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/reverse-slip-fault.vtk	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,11 @@
+# vtk DataFile Version 1.0
+This line is a comment
+ASCII
+DATASET POLYDATA
+POINTS 4 float
+ 4000.0      0.0       0.0
+ 4000.0  16000.0       0.0
+16000.0  16000.0  -16000.0
+16000.0      0.0  -16000.0
+POLYGONS 1 5
+4  0 1 2 3

Added: cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/strike-slip-fault.vtk
===================================================================
--- cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/strike-slip-fault.vtk	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/benchmarks/short/vtk/strike-slip-fault.vtk	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,11 @@
+# vtk DataFile Version 1.0
+This line is a comment
+ASCII
+DATASET POLYDATA
+POINTS 4 float
+12000.0      0.0       0.0
+12000.0  16000.0       0.0
+12000.0  16000.0  -16000.0
+12000.0      0.0  -16000.0
+POLYGONS 1 5
+4  0 1 2 3

Added: cs/cigma/branches/cigma-0.9b1/doc/manual/cigma.lyx
===================================================================
--- cs/cigma/branches/cigma-0.9b1/doc/manual/cigma.lyx	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/doc/manual/cigma.lyx	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,2026 @@
+#LyX 1.4.4 created this file. For more info see http://www.lyx.org/
+\lyxformat 245
+\begin_document
+\begin_header
+\textclass book
+\begin_preamble
+\usepackage{hyperref}
+
+\let\myUrl\url
+\renewcommand{\url}[1]{(\myUrl{#1})}
+\end_preamble
+\language english
+\inputencoding auto
+\fontscheme default
+\graphics default
+\paperfontsize default
+\spacing single
+\papersize default
+\use_geometry true
+\use_amsmath 1
+\cite_engine basic
+\use_bibtopic false
+\paperorientation portrait
+\leftmargin 1in
+\topmargin 1in
+\rightmargin 1in
+\bottommargin 1in
+\secnumdepth 3
+\tocdepth 3
+\paragraph_separation indent
+\defskip medskip
+\quotes_language swedish
+\papercolumns 1
+\papersides 2
+\paperpagestyle headings
+\tracking_changes false
+\output_changes true
+\end_header
+
+\begin_body
+
+\begin_layout Standard
+\noindent
+\align center
+
+\color none
+\begin_inset ERT
+status collapsed
+
+\begin_layout Standard
+
+
+\backslash
+thispagestyle{empty}
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Title
+Cigma
+\end_layout
+
+\begin_layout Author
+© California Institute of Technology
+\newline
+Version 0.9
+\end_layout
+
+\begin_layout Date
+\begin_inset ERT
+status collapsed
+
+\begin_layout Standard
+
+
+\backslash
+today
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset LatexCommand \tableofcontents{}
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset FloatList figure
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset ERT
+status collapsed
+
+\begin_layout Standard
+
+
+\backslash
+raggedbottom
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\newpage
+
+\end_layout
+
+\begin_layout Chapter
+Introduction
+\end_layout
+
+\begin_layout Section
+About Cigma
+\end_layout
+
+\begin_layout Standard
+The CIG Model Analyzer (Cigma) consists of a suite of tools intended to
+ facilitate the comparison of numerical models.
+ CIG has developed Cigma in response to demand from the short-term tectonics
+ community, who desired for a simple tool that can perform rigorous error
+ analysis on their FEM codes.
+ 
+\end_layout
+
+\begin_layout Standard
+This release of Cigma performs three types of tasks:
+\end_layout
+
+\begin_layout Itemize
+Error analysis
+\end_layout
+
+\begin_layout Itemize
+Benchmarking
+\end_layout
+
+\begin_layout Itemize
+Code verification
+\end_layout
+
+\begin_layout Standard
+Cigma can do analysis in two ways.
+ It can take a random sampling of points inside a domain of interest and
+ analyze the pointwise differences between physical fields.
+ A second way it can operate is to perform an integration of the errors
+ over a discretized version of the domain.
+\end_layout
+
+\begin_layout Standard
+The code is being released under the GNU General Public License.
+\end_layout
+
+\begin_layout Section
+Citation
+\end_layout
+
+\begin_layout Standard
+Computational Infrastructure for Geodynamics (CIG) is making this source
+ code available to you in the hope that the software will enhance your research
+ in geophysics.
+ This is a brand-new code and at present no papers are published or at press
+ for use as citations other than this manual, which is cited as follows:
+\end_layout
+
+\begin_layout Quote
+Armendariz, Luis.
+ 
+\emph on
+Cigma User Manual.
+
+\emph default
+ Pasadena, CA: Computational Infrastructure of Geodynamics, 2007.
+ URL: geodynamics.org/cig/software/cs/cigma/cigma.pdf
+\end_layout
+
+\begin_layout Standard
+CIG requests that in your oral presentations and in your papers that you
+ indicate your use of this code and acknowledge the author of the code and
+ 
+\begin_inset LatexCommand \htmlurl[CIG]{www.geodynamics.org}
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Section
+Support
+\end_layout
+
+\begin_layout Standard
+Cigma development is supported by a grant from the National Science Foundation
+ to CIG, managed by the California Institute of Technology.
+\end_layout
+
+\begin_layout Chapter
+Installation and Getting Help
+\end_layout
+
+\begin_layout Section
+Introduction
+\end_layout
+
+\begin_layout Standard
+To use Cigma, download the source package (in the form of a compressed tar
+ file) from the 
+\begin_inset LatexCommand \htmlurl[CIG Cigma web page]{geodynamics.org/cig/software/packages/cs/cigma}
+
+\end_inset
+
+.
+ After unpacking the source, issue the following command
+\end_layout
+
+\begin_layout LyX-Code
+$ make
+\end_layout
+
+\begin_layout Standard
+This will create several binaries inside the (TODO: typewriter font) bin/
+ directory under the project root.
+\end_layout
+
+\begin_layout Section
+Software Dependencies
+\end_layout
+
+\begin_layout Subsection
+HDF5
+\end_layout
+
+\begin_layout Standard
+The primary dependency for Cigma is the Hierarchical Data Format (HDF5)
+ library, which can be obtained from.
+ HDF5 is available for download from http://hdf.ncsa.uiuc.edu/HDF5 (TODO)
+\end_layout
+
+\begin_layout Subsection
+PyTables (optional)
+\end_layout
+
+\begin_layout Standard
+PyTables is a python extension module that builds on top of the HDF5 library.
+ It is available from http://www.pytables.org (TODO: linkify)
+\end_layout
+
+\begin_layout Standard
+To compile and install this extension, download the latest stable version
+ and issue the following commands
+\end_layout
+
+\begin_layout Standard
+$ cd pytables-2.x.x
+\end_layout
+
+\begin_layout Standard
+$ python setup.py install --prefix=$HOME
+\end_layout
+
+\begin_layout Subsection
+HDFView (optional)
+\end_layout
+
+\begin_layout Standard
+NCSA HDFView is a graphical user interface tool for accessing data in your
+ HDF5 files.
+ You can use it for viewing the internal file hierarchy in a tree structure,
+ adding new datasets, and modifying or deleting existing datasets.
+ You can download it from the HDFView home page at http://hdf.ncsa.uiuc.edu/hdf-jav
+a-html/hdfview (TODO: linkify)
+\end_layout
+
+\begin_layout Standard
+(TODO: insert image of bmssnog.h5)
+\end_layout
+
+\begin_layout Section
+Getting Help
+\end_layout
+
+\begin_layout Standard
+For help, send an e-mail to the 
+\begin_inset LatexCommand \url[CIG Computational Science Mailing List]{cig-cs at geodynamics.org}
+
+\end_inset
+
+.
+ You can subscribe to the 
+\family typewriter
+cig-cs
+\family default
+ mailing list and view archived discussions at the 
+\begin_inset LatexCommand \htmlurl[CIG Mail Lists web page]{geodynamics.org/cig/lists}
+
+\end_inset
+
+.
+ If you encounter any bugs or have problems installing Cigma, please submit
+ a report to the 
+\begin_inset LatexCommand \htmlurl[CIG Bug Tracker]{geodynamics.org/bugs}
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Chapter
+Numerical Background
+\end_layout
+
+\begin_layout Standard
+A field assigns a physical quantity to every point in space.
+ Mathematically speaking, this quantity corresponds to a scalar, a vector,
+ or even a tensor.
+ Estimating errors between two arbitrarily represented fields is challenging
+ due to the variety of representations that are possible.
+ 
+\end_layout
+
+\begin_layout Section
+Mesh
+\end_layout
+
+\begin_layout Standard
+In Cigma, we define a finite element mesh simply by the coordinates of its
+ degrees of freedom, and the connectivity relations among them.
+\end_layout
+
+\begin_layout Section
+Fields
+\end_layout
+
+\begin_layout Standard
+In Cigma, a field is defined by a set of values on each of its coordinates,
+ with a dimension corresponding to the rank of the physical quantity.
+\end_layout
+
+\begin_layout Section
+Elements
+\end_layout
+
+\begin_layout Standard
+Cigma provides you with two builtin finite element spaces, along with a
+ framework for inserting new types of elements.
+\end_layout
+
+\begin_layout Subsection
+Reference coordinates
+\end_layout
+
+\begin_layout Standard
+(TODO: insert vtk image here)
+\end_layout
+
+\begin_layout Subsection
+Shape Functions
+\end_layout
+
+\begin_layout Standard
+Note that the shape functions have been defined on the reference-coordinate
+ space.
+\end_layout
+
+\begin_layout Subparagraph*
+tet4
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula $\begin{array}{c}
+a:\, TN_{0}\left(\vec{\xi}\right)=\frac{1}{2}\left(-1-\xi-\eta-\zeta\right)\\
+b:\, TN_{1}\left(\vec{\xi}\right)=\frac{1}{2}\left(1+\xi\right)\\
+c:\, TN_{2}\left(\vec{\xi}\right)=\frac{1}{2}\left(1+\eta\right)\\
+d:\, TN_{3}\left(\vec{\xi}\right)=\frac{1}{2}\left(1+\zeta\right)\end{array}$
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+For future reference, one can also evaluate the shape functions on a linear
+ hexahedral element.
+\end_layout
+
+\begin_layout Subparagraph*
+hex8
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula $\begin{array}{c}
+a:\, HN_{0}\left(\vec{\xi}\right)=\frac{1}{8}\left(1-\xi\right)\left(1-\eta\right)\left(1-\zeta\right)\\
+b:\, HN_{1}\left(\vec{\xi}\right)=\frac{1}{8}\left(1+\xi\right)\left(1-\eta\right)\left(1-\zeta\right)\\
+c:\, HN_{2}\left(\vec{\xi}\right)=\frac{1}{8}\left(1-\xi\right)\left(1+\eta\right)\left(1-\zeta\right)\\
+d:\, HN_{3}\left(\vec{\xi}\right)=\frac{1}{8}\left(1+\xi\right)\left(1+\eta\right)\left(1-\zeta\right)\\
+e:\, HN_{4}\left(\vec{\xi}\right)=\frac{1}{8}\left(1-\xi\right)\left(1-\eta\right)\left(1+\zeta\right)\\
+f:\, HN_{5}\left(\vec{\xi}\right)=\frac{1}{8}\left(1+\xi\right)\left(1-\eta\right)\left(1+\zeta\right)\\
+g:\, HN_{6}\left(\vec{\xi}\right)=\frac{1}{8}\left(1-\xi\right)\left(1+\eta\right)\left(1+\zeta\right)\\
+h:\, HN_{7}\left(\vec{\xi}\right)=\frac{1}{8}\left(1+\xi\right)\left(1+\eta\right)\left(1+\zeta\right)\end{array}$
+\end_inset
+
+
+\end_layout
+
+\begin_layout Chapter
+Software Components
+\end_layout
+
+\begin_layout Section
+Design Goals
+\end_layout
+
+\begin_layout Standard
+Cigma was designed with the following use cases in mind:
+\end_layout
+
+\begin_layout Itemize
+Error Analysis: To assist scientists in comparing two different codes, possibly
+ on the same mesh
+\end_layout
+
+\begin_layout Itemize
+Benchmarking: To help the geodynamics community agree on a standard solution
+ to a specific problem
+\end_layout
+
+\begin_layout Itemize
+Verification: For developers to test software changes so as to ensure that
+ those changes don't affect the consistency of the results
+\end_layout
+
+\begin_layout Section
+Data Format
+\end_layout
+
+\begin_layout Standard
+We use HDF5 for the following reasons
+\end_layout
+
+\begin_layout Enumerate
+A common format is necessary for comparisons in order to avoid having to
+ convert between formats
+\end_layout
+
+\begin_layout Enumerate
+In order to support large finite element meshes efficiently...
+\end_layout
+
+\begin_layout Enumerate
+Support for metadata
+\end_layout
+
+\begin_layout Standard
+(TODO: yank part of intro-to-hdf5 chapter from CitcomS manual)
+\end_layout
+
+\begin_layout Section
+Field Metadata
+\end_layout
+
+\begin_layout Standard
+Each field keeps a certain amount of metadata that allows Cigma to correctly
+ interpret the meaning of the field data
+\end_layout
+
+\begin_layout Itemize
+MeshID: a universally unique identifier (uuid) assigned to the mesh
+\end_layout
+
+\begin_layout Itemize
+MeshLocation: the HDF5 group which contains the appropriate coordinates
+ and connectivity datasets.
+\end_layout
+
+\begin_layout Itemize
+FunctionSpace: identifies which shape functions for interpolating values
+ inside the element.
+\end_layout
+
+\begin_layout Standard
+(TODO: insert tree with all metadata definitions)
+\end_layout
+
+\begin_layout Chapter
+Running Cigma
+\end_layout
+
+\begin_layout Standard
+The data flow in Cigma is decoupled to the extent.
+ 
+\end_layout
+
+\begin_layout Section
+Comparing two fields
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+cigma compare --first=field1.h5:/path/to/displ/0  
+\backslash
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+              --second=field2.h5:/path/to/displ/0 
+\backslash
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+              --output=residuals.vtk
+\end_layout
+
+\begin_layout Subsection
+Importing data
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+cigma import --coordinates=mesh.coord           
+\backslash
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+             --connectivity=mesh.connect        
+\backslash
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+             --variable=velocity                
+\backslash
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+             --variable-step=step00010          
+\backslash
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+             --variable-data=velo-field.10.time 
+\backslash
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+             --output=model.h5
+\end_layout
+
+\begin_layout Standard
+The effect of this command is to create a file with the following structure
+\end_layout
+
+\begin_layout LyX-Code
+model.h5
+\end_layout
+
+\begin_layout LyX-Code
+`-- model
+\end_layout
+
+\begin_layout LyX-Code
+    |-- mesh
+\end_layout
+
+\begin_layout LyX-Code
+    |   |-- coordinates  [nno x nsd]
+\end_layout
+
+\begin_layout LyX-Code
+    |   `-- connectivity [nel x ndof]
+\end_layout
+
+\begin_layout LyX-Code
+    `-- variables
+\end_layout
+
+\begin_layout LyX-Code
+        `-- velocity
+\end_layout
+
+\begin_layout LyX-Code
+            `-- step00010
+\end_layout
+
+\begin_layout Standard
+
+\end_layout
+
+\begin_layout Chapter
+Numerical Results
+\end_layout
+
+\begin_layout Section
+Benchmark cases
+\end_layout
+
+\begin_layout Subsection
+Strike-slip with no gravity
+\end_layout
+
+\begin_layout Standard
+(TODO: insert vtk images for the t=0, 10, 50, 100 years)
+\end_layout
+
+\begin_layout Subsection
+Reverse-slip with no gravity
+\end_layout
+
+\begin_layout Standard
+(TODO: insert high res vtk image)
+\end_layout
+
+\begin_layout LyX-Code
+
+\end_layout
+
+\begin_layout Chapter
+\start_of_appendix
+Text Input File Formats
+\end_layout
+
+\begin_layout Standard
+Cigma can easily import datasets from simple text files consisting of a
+ single header line followed by data.
+ The header consists of two numbers, the first of which consists of the
+ number of lines to read next, and the second number representing the number
+ of columns to read on each line.
+ Thus, after the header, each of the lines begin with the appropriate row
+ number, followed by the requisite number of columns.
+ For simplicity, the maximum line size is 1024, and lines beginning with
+ the '#' character are skipped.
+ 
+\end_layout
+
+\begin_layout Standard
+Mesh coordinates can be read from
+\end_layout
+
+\begin_layout LyX-Code
+nno nsd
+\end_layout
+
+\begin_layout LyX-Code
+1 x1 y1 z1
+\end_layout
+
+\begin_layout LyX-Code
+2 x2 y2 z2
+\end_layout
+
+\begin_layout LyX-Code
+3 x3 y3 z3
+\end_layout
+
+\begin_layout LyX-Code
+...
+\end_layout
+
+\begin_layout Standard
+Mesh connectivity 
+\end_layout
+
+\begin_layout LyX-Code
+nel ndof
+\end_layout
+
+\begin_layout LyX-Code
+1 node_1 node_2 node_3 node_4 ...
+\end_layout
+
+\begin_layout LyX-Code
+2 node_1 node_2 node_3 node_4 ...
+\end_layout
+
+\begin_layout LyX-Code
+3 node_1 node_2 node_3 node_4 ...
+\end_layout
+
+\begin_layout LyX-Code
+...
+\end_layout
+
+\begin_layout Standard
+A generic field with ndim components would be specified by
+\end_layout
+
+\begin_layout LyX-Code
+nno ndim
+\end_layout
+
+\begin_layout LyX-Code
+1 f1 f2 f3 ..
+\end_layout
+
+\begin_layout LyX-Code
+2 f1 f2 f3 ..
+\end_layout
+
+\begin_layout LyX-Code
+...
+\end_layout
+
+\begin_layout Chapter
+Shape Functions
+\end_layout
+
+\begin_layout Section
+Linear Tetrahedral Element (tet4)
+\end_layout
+
+\begin_layout LyX-Code
+\begin_inset Tabular
+<lyxtabular version="3" rows="1" columns="2">
+<features>
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Graphics
+	filename figures/cigma-abcd-triangle.jpg
+	lyxscale 50
+	scale 25
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $\begin{array}{ccccc}
+ &  &  & \phi\\
+(-1, & -1, & -1) & \mapsto & a\\
+(+1, & -1, & -1) & \mapsto & b\\
+(-1, & +1, & -1) & \mapsto & c\\
+(-1, & -1, & +1) & \mapsto & d\end{array}$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+\begin_inset Formula \[
+\begin{array}{c}
+x\left(\vec{\xi}\right)=\alpha_{0}+\alpha_{1}\xi+\alpha_{2}\eta+\alpha_{3}\zeta\\
+y\left(\vec{\xi}\right)=\beta_{0}+\beta_{1}\xi+\beta_{2}\eta+\beta_{3}\zeta\\
+z\left(\vec{\xi}\right)=\gamma_{0}+\gamma_{1}\xi+\gamma_{2}\eta+\gamma_{3}\zeta\end{array}\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+\begin_inset Formula \[
+\begin{array}{c}
+a\\
+b\\
+c\\
+d\end{array}\left[\begin{array}{cccc}
+1 & (-1) & (-1) & (-1)\\
+1 & (+1) & (-1) & (-1)\\
+1 & (-1) & (+1) & (-1)\\
+1 & (-1) & (-1) & (+1)\end{array}\right]\left[\begin{array}{c}
+\alpha_{0}\\
+\alpha_{1}\\
+\alpha_{2}\\
+\alpha_{3}\end{array}\right]=\left[\begin{array}{c}
+x_{0}\\
+x_{1}\\
+x_{2}\\
+x_{3}\end{array}\right]\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+\begin_inset Formula \[
+\left[\begin{array}{cccc}
+1 & -1 & -1 & -1\\
+1 & +1 & -1 & -1\\
+1 & -1 & +1 & -1\\
+1 & -1 & -1 & +1\end{array}\right]\left[\begin{array}{ccc}
+\alpha_{0} & \beta_{0} & \gamma_{0}\\
+\alpha_{1} & \beta_{1} & \gamma_{1}\\
+\alpha_{2} & \beta_{2} & \gamma_{2}\\
+\alpha_{3} & \beta_{3} & \gamma_{3}\end{array}\right]=\left[\begin{array}{ccc}
+x_{0} & y_{0} & z_{0}\\
+x_{1} & y_{1} & z_{1}\\
+x_{2} & y_{2} & z_{2}\\
+x_{3} & y_{3} & z_{3}\end{array}\right]\]
+
+\end_inset
+
+
+\begin_inset Formula \[
+\left[\begin{array}{ccc}
+\alpha_{0} & \beta_{0} & \gamma_{0}\\
+\alpha_{1} & \beta_{1} & \gamma_{1}\\
+\alpha_{2} & \beta_{2} & \gamma_{2}\\
+\alpha_{3} & \beta_{3} & \gamma_{3}\end{array}\right]=\frac{1}{2}\left[\begin{array}{cccc}
+-1 & 1 & 1 & 1\\
+-1 & 1 & 0 & 0\\
+-1 & 0 & 1 & 0\\
+-1 & 0 & 0 & 1\end{array}\right]\left[\begin{array}{ccc}
+x_{0} & y_{0} & z_{0}\\
+x_{1} & y_{1} & z_{1}\\
+x_{2} & y_{2} & z_{2}\\
+x_{3} & y_{3} & z_{3}\end{array}\right]\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+\begin_inset Formula \[
+\begin{array}{cc}
+x\left(\vec{\xi}\right) & =\alpha_{0}+\alpha_{1}\xi+\alpha_{2}\eta+\alpha_{3}\zeta\\
+ & =\left[\frac{1}{2}\left(-x_{0}+x_{1}+x_{2}+x_{3}\right)\right]\\
+ & +\left[\frac{1}{2}\left(-x_{0}+x_{1}\,\,\,\,\,\,\,\,\,\,\right)\right]\xi\\
+ & +\left[\frac{1}{2}\left(-x_{0}\,\,\,\,\,+x_{2}\,\,\,\,\,\right)\right]\eta\\
+ & +\left[\frac{1}{2}\left(-x_{0}\,\,\,\,\,\,\,\,\,\,+x_{3}\right)\right]\zeta\\
+\\ & =\left[\frac{1}{2}\left(-1-\xi-\eta-\zeta\right)\right]\times0\\
+ & +\left[\frac{1}{2}\left(1+\xi\,\,\,\,\,\,\,\,\,\,\right)\right]\times1\\
+ & +\left[\frac{1}{2}\left(1\,\,\,\,\,+\eta\,\,\,\,\,\right)\right]\times2\\
+ & +\left[\frac{1}{2}\left(1\,\,\,\,\,\,\,\,\,\,+\zeta\right)\right]\times3\\
+\\\end{array}\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula \[
+\begin{array}{c}
+x\left(\vec{\xi}\right)=N_{0}\left(\vec{\xi}\right)x_{0}+N_{1}\left(\vec{\xi}\right)x_{1}+N_{2}\left(\vec{\xi}\right)x_{2}+N_{3}\left(\vec{\xi}\right)x_{3}\\
+y\left(\vec{\xi}\right)=N_{0}\left(\vec{\xi}\right)y_{0}+N_{1}\left(\vec{\xi}\right)y_{1}+N_{2}\left(\vec{\xi}\right)y_{2}+N_{3}\left(\vec{\xi}\right)y_{3}\\
+z\left(\vec{\xi}\right)=N_{0}\left(\vec{\xi}\right)z_{0}+N_{1}\left(\vec{\xi}\right)z_{1}+N_{2}\left(\vec{\xi}\right)z_{2}+N_{3}\left(\vec{\xi}\right)z_{3}\\
+\\\end{array}\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula \[
+\begin{array}{cc}
+where & N_{0}\left(\vec{\xi}\right)=\frac{1}{2}\left(-1-\xi-\eta-\zeta\right)\\
+ & N_{1}\left(\vec{\xi}\right)=\frac{1}{2}\left(1+\xi\right)\\
+ & N_{2}\left(\vec{\xi}\right)=\frac{1}{2}\left(1+\eta\right)\\
+ & N_{3}\left(\vec{\xi}\right)=\frac{1}{2}\left(1+\zeta\right)\end{array}\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+\noindent
+\align center
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\end_layout
+
+\begin_layout LyX-Code
+\begin_inset Formula \[
+\left[\begin{array}{ccc}
+x\left(\vec{\xi}_{0}\right) & y\left(\vec{\xi}_{0}\right) & z\left(\vec{\xi}_{0}\right)\\
+x\left(\vec{\xi}_{1}\right) & y\left(\vec{\xi}_{1}\right) & z\left(\vec{\xi}_{1}\right)\\
+\vdots & \vdots & \vdots\\
+x\left(\vec{\xi}_{q-1}\right) & y\left(\vec{\xi}_{q-1}\right) & z\left(\vec{\xi}_{q-1}\right)\end{array}\right]=\left[\begin{array}{ccccc}
+N_{0}\left(\vec{\xi}_{0}\right) & N_{1}\left(\vec{\xi}_{0}\right) & N_{2}\left(\vec{\xi}_{0}\right) & N_{3}\left(\vec{\xi}_{0}\right)\\
+N_{0}\left(\vec{\xi}_{1}\right) & N_{1}\left(\vec{\xi}_{1}\right) & N_{2}\left(\vec{\xi}_{1}\right) & N_{3}\left(\vec{\xi}_{1}\right)\\
+\vdots & \vdots & \vdots & \vdots\\
+N_{0}\left(\vec{\xi}_{q-1}\right) & N_{1}\left(\vec{\xi}_{q-1}\right) & N_{2}\left(\vec{\xi}_{q-1}\right) & N_{3}\left(\vec{\xi}_{q-1}\right)\end{array}\right]\left[\begin{array}{ccc}
+x{}_{0} & y_{0} & z_{0}\\
+x_{1} & y_{1} & z_{1}\\
+x_{2} & y_{2} & z_{2}\\
+x_{3} & y_{3} & z_{3}\end{array}\right]\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+\begin_inset Formula \[
+\left[q\times3\right]\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,=\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\left[q\times8\right]\,\,\,\,\,\,\,\,\,\:\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\left[4\times3\right]\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Jacobian Matrix
+\end_layout
+
+\begin_layout LyX-Code
+
+\end_layout
+
+\begin_layout Standard
+\noindent
+\align center
+\begin_inset Tabular
+<lyxtabular version="3" rows="1" columns="2">
+<features>
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $\frac{\partial\vec{x}}{\partial\vec{\xi}}=\left[\begin{array}{ccc}
+\frac{\partial x}{\partial\xi} & \frac{\partial x}{\partial\eta} & \frac{\partial x}{\partial\zeta}\\
+\frac{\partial y}{\partial\xi} & \frac{\partial y}{\partial\eta} & \frac{\partial y}{\partial\zeta}\\
+\frac{\partial z}{\partial\xi} & \frac{\partial z}{\partial\eta} & \frac{\partial z}{\partial\zeta}\end{array}\right]$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $\begin{array}{c}
+x\left(\vec{\xi}\right)=\sum_{i}N_{i}\left(\vec{\xi}\right)x_{i}\\
+y\left(\vec{\xi}\right)=\sum_{i}N_{i}\left(\vec{\xi}\right)y_{i}\\
+z\left(\vec{\xi}\right)=\sum_{i}N_{i}\left(\vec{\xi}\right)z_{i}\end{array}$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula \[
+\frac{\partial x}{\partial\xi}=\sum_{i}\frac{\partial N_{i}}{\partial\xi}x_{i}\,\,\,\,\,\,,\,\,\,\frac{\partial x}{\partial\eta}=\sum_{i}\frac{\partial N_{i}}{\partial\eta}x_{i}\,\,\,\,\,\,,\,\,\,\frac{\partial x}{\partial\zeta}=\sum_{i}\frac{\partial N_{i}}{\partial\zeta}x_{i}\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula \[
+\frac{\partial y}{\partial\xi}=\sum_{i}\frac{\partial N_{i}}{\partial\xi}y_{i}\,\,\,\,\,\,,\,\,\,\frac{\partial y}{\partial\eta}=\sum_{i}\frac{\partial N_{i}}{\partial\eta}y_{i}\,\,\,\,\,\,,\,\,\,\frac{\partial y}{\partial\zeta}=\sum_{i}\frac{\partial N_{i}}{\partial\zeta}y_{i}\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula \[
+\frac{\partial z}{\partial\xi}=\sum_{i}\frac{\partial N_{i}}{\partial\xi}z_{i}\,\,\,\,\,\,,\,\,\,\frac{\partial z}{\partial\eta}=\sum_{i}\frac{\partial N_{i}}{\partial\eta}z_{i}\,\,\,\,\,\,,\,\,\,\frac{\partial z}{\partial\zeta}=\sum_{i}\frac{\partial N_{i}}{\partial\zeta}z_{i}\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Paragraph*
+Tet4
+\end_layout
+
+\begin_layout Standard
+\begin_inset Tabular
+<lyxtabular version="3" rows="5" columns="5">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $i$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $TN_{i}$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $\partial TN_{i}/\partial\xi$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $\partial TN_{i}/\partial\eta$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $\partial TN_{i}/\partial\zeta$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+0
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $\frac{1}{2}\left(-1-\xi-\eta-\zeta\right)$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $-\frac{1}{2}$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $-\frac{1}{2}$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $-\frac{1}{2}$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+1
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $\frac{1}{2}\left(1+\xi\right)$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $+\frac{1}{2}$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+0
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+0
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+2
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $\frac{1}{2}\left(1+\eta\right)$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+0
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $+\frac{1}{2}$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+0
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+3
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $\frac{1}{2}\left(1+\zeta\right)$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+0
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+0
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Standard
+\begin_inset Formula $+\frac{1}{2}$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula \[
+\frac{\partial x}{\partial\xi}=\left(-\frac{1}{2}\right)x_{0}+\left(\frac{1}{2}\right)x_{1}\,\,\,,\,\,\,\frac{\partial x}{\partial\eta}=\left(-\frac{1}{2}\right)x_{0}+\left(\frac{1}{2}\right)x_{2}\,\,\,,\,\,\,\frac{\partial x}{\partial\zeta}=\left(-\frac{1}{2}\right)x_{0}+\left(\frac{1}{2}\right)x_{3}\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula \[
+\frac{\partial y}{\partial\xi}=\left(-\frac{1}{2}\right)y_{0}+\left(\frac{1}{2}\right)y_{1}\,\,\,,\,\,\,\frac{\partial y}{\partial\eta}=\left(-\frac{1}{2}\right)y_{0}+\left(\frac{1}{2}\right)y_{2}\,\,\,,\,\,\,\frac{\partial y}{\partial\zeta}=\left(-\frac{1}{2}\right)y_{0}+\left(\frac{1}{2}\right)y_{3}\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula \[
+\frac{\partial z}{\partial\xi}=\left(-\frac{1}{2}\right)z_{0}+\left(\frac{1}{2}\right)z_{1}\,\,\,,\,\,\,\frac{\partial z}{\partial\eta}=\left(-\frac{1}{2}\right)z_{0}+\left(\frac{1}{2}\right)z_{2}\,\,\,,\,\,\,\frac{\partial z}{\partial\zeta}=\left(-\frac{1}{2}\right)z_{0}+\left(\frac{1}{2}\right)z_{3}\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula \[
+\mathrm{J}=\left|\frac{\partial\vec{x}}{\partial\vec{\xi}}\right|=\left|\begin{array}{c}
+\frac{1}{2}\left(x_{1}-x_{0}\right)\,\,\frac{1}{2}\left(x_{2}-x_{0}\right)\,\,\frac{1}{2}\left(x_{3}-x_{0}\right)\\
+\frac{1}{2}\left(y_{1}-y_{0}\right)\,\,\frac{1}{2}\left(y_{2}-y_{0}\right)\,\,\frac{1}{2}\left(y_{3}-y_{0}\right)\\
+\frac{1}{2}\left(z_{1}-z_{0}\right)\,\,\frac{1}{2}\left(z_{2}-z_{0}\right)\,\,\frac{1}{2}\left(z_{3}-z_{0}\right)\end{array}\right|\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula \[
+=\frac{1}{8}\left|\begin{array}{cccc}
+1 & x_{0} & y_{0} & z_{0}\\
+1 & x_{1} & y_{1} & z_{1}\\
+1 & x_{2} & y_{2} & z_{2}\\
+1 & x_{3} & y_{3} & z_{3}\end{array}\right|\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Chapter
+License 
+\end_layout
+
+\begin_layout Standard
+
+\series bold
+GNU GENERAL PUBLIC LICENSE Version 2, June 1991.
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+\series default
+ 
+\newline
+
+\series medium
+Everyone is permitted to copy and distribute verbatim copies of this license
+ document, but changing it is not allowed.
+\end_layout
+
+\begin_layout Section*
+Preamble
+\end_layout
+
+\begin_layout Standard
+The licenses for most software are designed to take away your freedom to
+ share and change it.
+ By contrast, the GNU General Public License is intended to guarantee your
+ freedom to share and change free software -- to make sure the software
+ is free for all its users.
+ This General Public License applies to most of the Free Software Foundation's
+ software and to any other program whose authors commit to using it.
+ (Some other Free Software Foundation software is covered by the GNU Library
+ General Public License instead.) You can apply it to your programs, too.
+\end_layout
+
+\begin_layout Standard
+When we speak of free software, we are referring to freedom, not price.
+ Our General Public Licenses are designed to make sure that you have the
+ freedom to distribute copies of free software (and charge for this service
+ if you wish), that you receive source code or can get it if you want it,
+ that you can change the software or use pieces of it in new free programs;
+ and that you know you can do these things.
+\end_layout
+
+\begin_layout Standard
+To protect your rights, we need to make restrictions that forbid anyone
+ to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.
+\end_layout
+
+\begin_layout Standard
+For example, if you distribute copies of such a program, whether gratis
+ or for a fee, you must give the recipients all the rights that you have.
+ You must make sure that they, too, receive or can get the source code.
+ And you must show them these terms so they know their rights.
+\end_layout
+
+\begin_layout Standard
+We protect your rights with two steps:
+\end_layout
+
+\begin_layout Enumerate
+Copyright the software, and 
+\end_layout
+
+\begin_layout Enumerate
+Offer you this license which gives you legal permission to copy, distribute
+ and/or modify the software.
+\end_layout
+
+\begin_layout Standard
+Also, for each author's protection and ours, we want to make certain that
+ everyone understands that there is no warranty for this free software.
+ If the software is modified by someone else and passed on, we want its
+ recipients to know that what they have is not the original, so that any
+ problems introduced by others will not reflect on the original authors'
+ reputations.
+\end_layout
+
+\begin_layout Standard
+Finally, any free program is threatened constantly by software patents.
+ We wish to avoid the danger that redistributors of a free program will
+ individually obtain patent licenses, in effect making the program proprietary.
+ To prevent this, we have made it clear that any patent must be licensed
+ for everyone's free use or not licensed at all.
+ 
+\end_layout
+
+\begin_layout Standard
+The precise terms and conditions for copying, distribution and modification
+ follow.
+\end_layout
+
+\begin_layout Section*
+GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION
+ AND MODIFICATION 
+\end_layout
+
+\begin_layout Standard
+\begin_inset ERT
+status collapsed
+
+\begin_layout Standard
+
+
+\backslash
+begin{itemize}
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset ERT
+status collapsed
+
+\begin_layout Standard
+
+
+\backslash
+item[0.]
+\end_layout
+
+\end_inset
+
+This License applies to any program or other work which contains a notice
+ placed by the copyright holder saying it may be distributed under the terms
+ of this General Public License.
+ The "Program" below refers to any such program or work, and a "work based
+ on the Program" means either the Program or any derivative work under copyright
+ law: that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another language.
+ (Hereinafter, translation is included without limitation in the term "modificat
+ion.") Each licensee is addressed as "you."
+\newline
+
+\newline
+Activities other than copying,
+ distribution and modification are not covered by this License; they are
+ outside its scope.
+ The act of running the Program is not restricted, and the output from the
+ Program is covered only if its contents constitute a work based on the
+ Program (independent of having been made by running the Program).
+ Whether that is true depends on what the Program does.
+ 
+\end_layout
+
+\begin_layout Standard
+\begin_inset ERT
+status collapsed
+
+\begin_layout Standard
+
+
+\backslash
+end{itemize}
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Enumerate
+You may copy and distribute verbatim copies of the Program's source code
+ as you receive it, in any medium, provided that you conspicuously and appropria
+tely publish on each copy an appropriate copyright notice and disclaimer
+ of warranty; keep intact all the notices that refer to this License and
+ to the absence of any warranty; and give any other recipients of the Program
+ a copy of this License along with the Program.
+ 
+\end_layout
+
+\begin_deeper
+\begin_layout Standard
+You may charge a fee for the physical act of transferring a copy, and you
+ may at your option offer warranty protection in exchange for a fee.
+ 
+\end_layout
+
+\end_deeper
+\begin_layout Enumerate
+You may modify your copy or copies of the Program or any portion of it,
+ thus forming a work based on the Program, and copy and distribute such
+ modifications or work under the terms of Section 1 above, provided that
+ you also meet all of these conditions: 
+\end_layout
+
+\begin_deeper
+\begin_layout Enumerate
+You must cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change.
+ 
+\end_layout
+
+\begin_layout Enumerate
+You must cause any work that you distribute or publish, that in whole or
+ in part contains or is derived from the Program or any part thereof, to
+ be licensed as a whole at no charge to all third parties under the terms
+ of this License.
+ 
+\end_layout
+
+\begin_layout Enumerate
+If the modified program normally reads commands interactively when run,
+ you must cause it, when started running for such interactive use in the
+ most ordinary way, to print or display an announcement including an appropriate
+ copyright notice and a notice that there is no warranty (or else, saying
+ that you provide a warranty) and that users may redistribute the program
+ under these conditions, and telling the user how to view a copy of this
+ License.
+ (Exception: if the Program itself is interactive but does not normally
+ print such an announcement, your work based on the Program is not required
+ to print an announcement.) 
+\end_layout
+
+\begin_layout Standard
+These requirements apply to the modified work as a whole.
+ If identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in themselves,
+ then this License, and its terms, do not apply to those sections when you
+ distribute them as separate works.
+ But when you distribute the same sections as part of a whole which is a
+ work based on the Program, the distribution of the whole must be on the
+ terms of this License, whose permissions for other licensees extend to
+ the entire whole, and thus to each and every part regardless of who wrote
+ it.
+ 
+\end_layout
+
+\begin_layout Standard
+Thus, it is not the intent of this section to claim rights or contest your
+ rights to work written entirely by you; rather, the intent is to exercise
+ the right to control the distribution of derivative or collective works
+ based on the Program.
+ 
+\end_layout
+
+\begin_layout Standard
+In addition, mere aggregation of another work not based on the Program with
+ the Program (or with a work based on the Program) on a volume of a storage
+ or distribution medium does not bring the other work under the scope of
+ this License.
+ 
+\end_layout
+
+\end_deeper
+\begin_layout Enumerate
+You may copy and distribute the Program (or a work based on it, under Section
+ 2) in object code or executable form under the terms of Sections 1 and
+ 2 above provided that you also do one of the following: 
+\end_layout
+
+\begin_deeper
+\begin_layout Enumerate
+Accompany it with the complete corresponding machine-readable source code,
+ which must be distributed under the terms of Sections 1 and 2 above on
+ a medium customarily used for software interchange; or, 
+\end_layout
+
+\begin_layout Enumerate
+Accompany it with a written offer, valid for at least three years, to give
+ any third party, for a charge no more than your cost of physically performing
+ source distribution, a complete machine-readable copy of the corresponding
+ source code, to be distributed under the terms of Sections 1 and 2 above
+ on a medium customarily used for software interchange; or, 
+\end_layout
+
+\begin_layout Enumerate
+Accompany it with the information you received as to the offer to distribute
+ corresponding source code.
+ (This alternative is allowed only for noncommercial distribution and only
+ if you received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.) 
+\end_layout
+
+\begin_layout Standard
+The source code for a work means the preferred form of the work for making
+ modifications to it.
+ For an executable work, complete source code means all the source code
+ for all modules it contains, plus any associated interface definition files,
+ plus the scripts used to control compilation and installation of the executable.
+ However, as a special exception, the source code distributed need not include
+ anything that is normally distributed (in either source or binary form)
+ with the major components (compiler, kernel, and so on) of the operating
+ system on which the executable runs, unless that component itself accompanies
+ the executable.
+\end_layout
+
+\begin_layout Standard
+If distribution of executable or object code is made by offering access
+ to copy from a designated place, then offering equivalent access to copy
+ the source code from the same place counts as distribution of the source
+ code, even though third parties are not compelled to copy the source along
+ with the object code.
+ 
+\end_layout
+
+\end_deeper
+\begin_layout Enumerate
+You may not copy, modify, sublicense, or distribute the Program except as
+ expressly provided under this License.
+ Any attempt otherwise to copy, modify, sublicense or distribute the Program
+ is void, and will automatically terminate your rights under this License.
+ However, parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such parties
+ remain in full compliance.
+ 
+\end_layout
+
+\begin_layout Enumerate
+You are not required to accept this License, since you have not signed it.
+ However, nothing else grants you permission to modify or distribute the
+ Program or its derivative works.
+ These actions are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Program (or any work based
+ on the Program), you indicate your acceptance of this License to do so,
+ and all its terms and conditions for copying, distributing or modifying
+ the Program or works based on it.
+ 
+\end_layout
+
+\begin_layout Enumerate
+Each time you redistribute the Program (or any work based on the Program),
+ the recipient automatically receives a license from the original licensor
+ to copy, distribute or modify the Program subject to these terms and conditions.
+ You may not impose any further restrictions on the recipients' exercise
+ of the rights granted herein.
+ You are not responsible for enforcing compliance by third parties to this
+ License.
+ 
+\end_layout
+
+\begin_layout Enumerate
+If, as a consequence of a court judgment or allegation of patent infringement
+ or for any other reason (not limited to patent issues), conditions are
+ imposed on you (whether by court order, agreement or otherwise) that contradict
+ the conditions of this License, they do not excuse you from the conditions
+ of this License.
+ If you cannot distribute so as to satisfy simultaneously your obligations
+ under this License and any other pertinent obligations, then as a consequence
+ you may not distribute the Program at all.
+ For example, if a patent license would not permit royalty-free redistribution
+ of the Program by all those who receive copies directly or indirectly through
+ you, then the only way you could satisfy both it and this License would
+ be to refrain entirely from distribution of the Program.
+\end_layout
+
+\begin_deeper
+\begin_layout Standard
+If any portion of this section is held invalid or unenforceable under any
+ particular circumstance, the balance of the section is intended to apply
+ and the section as a whole is intended to apply in other circumstances.
+\end_layout
+
+\begin_layout Standard
+It is not the purpose of this section to induce you to infringe any patents
+ or other property right claims or to contest validity of any such claims;
+ this section has the sole purpose of protecting the integrity of the free
+ software distribution system, which is implemented by public license practices.
+ Many people have made generous contributions to the wide range of software
+ distributed through that system in reliance on consistent application of
+ that system; it is up to the author/donor to decide if he or she is willing
+ to distribute software through any other system and a licensee cannot impose
+ that choice.
+ 
+\end_layout
+
+\begin_layout Standard
+This section is intended to make thoroughly clear what is believed to be
+ a consequence of the rest of this License.
+ 
+\end_layout
+
+\end_deeper
+\begin_layout Enumerate
+If the distribution and/or use of the Program is restricted in certain countries
+ either by patents or by copyrighted interfaces, the original copyright
+ holder who places the Program under this License may add an explicit geographic
+al distribution limitation excluding those countries, so that distribution
+ is permitted only in or among countries not thus excluded.
+ In such case, this License incorporates the limitation as if written in
+ the body of this License.
+ 
+\end_layout
+
+\begin_layout Enumerate
+The Free Software Foundation may publish revised and/or new versions of
+ the General Public License from time to time.
+ Such new versions will be similar in spirit to the present version, but
+ may differ in detail to address new problems or concerns.
+ 
+\end_layout
+
+\begin_deeper
+\begin_layout Standard
+Each version is given a distinguishing version number.
+ If the Program specifies a version number of this License which applies
+ to it and "any later version," you have the option of following the terms
+ and conditions either of that version or of any later version published
+ by the Free Software Foundation.
+ If the Program does not specify a version number of this License, you may
+ choose any version ever published by the Free Software Foundation.
+\end_layout
+
+\end_deeper
+\begin_layout Enumerate
+If you wish to incorporate parts of the Program into other free programs
+ whose distribution conditions are different, write to the author to ask
+ for permission.
+ For software which is copyrighted by the Free Software Foundation, write
+ to the Free Software Foundation; we sometimes make exceptions for this.
+ Our decision will be guided by the two goals of preserving the free status
+ of all derivatives of our free software and of promoting the sharing and
+ reuse of software generally.
+ 
+\end_layout
+
+\begin_layout Subsection*
+NO WARRANTY 
+\end_layout
+
+\begin_layout Standard
+\begin_inset ERT
+status collapsed
+
+\begin_layout Standard
+
+
+\backslash
+begin{itemize}
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset ERT
+status collapsed
+
+\begin_layout Standard
+
+
+\backslash
+item[11.]
+\end_layout
+
+\end_inset
+
+BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+ THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+ EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
+ PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU.
+ SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
+ SERVICING, REPAIR OR CORRECTION.
+ 
+\end_layout
+
+\begin_layout Standard
+\begin_inset ERT
+status collapsed
+
+\begin_layout Standard
+
+
+\backslash
+item[12.]
+\end_layout
+
+\end_inset
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
+ ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
+ THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS
+ OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+ THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY
+ OF SUCH DAMAGES.
+\end_layout
+
+\begin_layout Standard
+\begin_inset ERT
+status collapsed
+
+\begin_layout Standard
+
+
+\backslash
+end{itemize}
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section*
+END OF TERMS AND CONDITIONS 
+\end_layout
+
+\begin_layout Subsection*
+How to Apply These Terms to Your New Programs
+\end_layout
+
+\begin_layout Standard
+If you develop a new program, and you want it to be of the greatest possible
+ use to the public, the best way to achieve this is to make it free software
+ which everyone can redistribute and change under these terms.
+ 
+\end_layout
+
+\begin_layout Standard
+To do so, attach the following notices to the program.
+ It is safest to attach them to the start of each source file to most effectivel
+y convey the exclusion of warranty; and each file should have at least the
+ "copyright" line and a pointer to where the full notice is found.
+ For example:
+\end_layout
+
+\begin_layout Quote
+One line to give the program's name and a brief idea of what it does.
+ Copyright 
+\size footnotesize
+© (
+\size default
+year) (name of author) 
+\end_layout
+
+\begin_layout Quote
+This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your option)
+ any later version.
+ 
+\end_layout
+
+\begin_layout Quote
+This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+ 
+\end_layout
+
+\begin_layout Quote
+You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+\end_layout
+
+\begin_layout Standard
+Also add information on how to contact you by electronic and paper mail.
+ 
+\end_layout
+
+\begin_layout Standard
+If the program is interactive, make it output a short notice like this when
+ it starts in an interactive mode: 
+\end_layout
+
+\begin_layout Quote
+Gnomovision version 69, Copyright © year name of author Gnomovision comes
+ with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it under certain
+ conditions; type `show c' for details.
+ 
+\end_layout
+
+\begin_layout Standard
+The hypothetical commands `show w' and `show c' should show the appropriate
+ parts of the General Public License.
+ Of course, the commands you use may be called something other than `show
+ w' and `show c'; they could even be mouse-clicks or menu items -- whatever
+ suits your program.
+ 
+\end_layout
+
+\begin_layout Standard
+You should also get your employer (if you work as a programmer) or your
+ school, if any, to sign a "copyright disclaimer" for the program, if necessary.
+ Here is a sample; alter the names: 
+\end_layout
+
+\begin_layout Quote
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovisi
+on' (which makes passes at compilers) written by James Hacker.
+ 
+\end_layout
+
+\begin_layout Quote
+(signature of Ty Coon)
+\newline
+1 April 1989 
+\newline
+Ty Coon, President of Vice 
+\end_layout
+
+\begin_layout Standard
+This General Public License does not permit incorporating your program into
+ proprietary programs.
+ If your program is a subroutine library, you may consider it more useful
+ to permit linking proprietary applications with the library.
+ If this is what you want to do, use the GNU Library General Public License
+ instead of this License.
+\end_layout
+
+\begin_layout Bibliography
+
+\bibitem {key-10}
+ TODO
+\end_layout
+
+\end_body
+\end_document

Added: cs/cigma/branches/cigma-0.9b1/libcigma/array.c
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/array.c	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/array.c	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,428 @@
+#include <stdlib.h>
+#include <hdf5.h>
+#include "array.h"
+#include "h5_attr.h"
+
+
+
+int array_init(array_t *array, hid_t type_id, int rank, int *shape, void *data)
+{
+    int i;
+
+    // initialize dataspace
+    array->rank = rank;
+    array->shape = (hsize_t *)malloc(rank * sizeof(hsize_t));
+    if (shape != NULL)
+    {
+        for (i = 0; i < rank; i++)
+            array->shape[i] = shape[i];
+    }
+    else
+    {
+        for (i = 0; i < rank; i++)
+            array->shape[i] = 0;
+    }
+
+    // initialize datatype
+    array->type_id = type_id;
+
+    // initialize data
+    array->data = data;
+
+    return 0;
+}
+
+int array_free_dims(array_t *array)
+{
+    free(array->shape);
+    return 0;
+}
+
+int array_free_data(array_t *array)
+{
+    if (array->data != NULL)
+    {
+        free(array->data);
+    }
+    return 0;
+}
+
+int array_free(array_t *array)
+{
+    array_free_dims(array);
+    array_free_data(array);
+    return 0;
+}
+
+
+
+int array_npoints(array_t *array)
+{
+    int i;
+    int npoints = 1;
+    for (i = 0; i < array->rank; i++)
+    {
+        npoints *= (int) array->shape[i];
+    }
+    return npoints;
+}
+
+int array_dim(array_t *array, int i)
+{
+
+    if ((0 <= i) && (i < array->rank))
+    {
+        return (int)(array->shape[i]);
+    }
+    return 0;
+}
+
+void array_dims(array_t *array, int *rank, int **shape)
+{
+    int i;
+
+    *rank  = array->rank;
+    *shape = (int *)malloc((array->rank) * sizeof(int));
+    for (i = 0; i < array->rank; i++)
+    {
+        (*shape)[i] = (int) array->shape[i];
+    }
+}
+
+void array_dims1(array_t *array, int *n)
+{
+    *n = array->shape[0];
+}
+
+void array_dims2(array_t *array, int *m, int *n)
+{
+    *m = array->shape[0];
+    *n = array->shape[1];
+}
+
+void array_dims3(array_t *array, int *l, int *m, int *n)
+{
+    *l = array->shape[0];
+    *m = array->shape[1];
+    *n = array->shape[2];
+}
+
+
+
+hid_t array_open(array_t *array, hid_t loc_id, const char *name)
+{
+    hid_t dataset_id;
+    hid_t dataspace_id;
+    herr_t status;
+
+    dataset_id = H5Dopen(loc_id, name);
+    if (dataset_id < 0)
+    {
+        return -1;
+    }
+
+    dataspace_id = H5Dget_space(dataset_id);
+    if (dataspace_id < 0)
+    {
+        H5Dclose(dataset_id);
+        return -2;
+    }
+    
+    array->rank = H5Sget_simple_extent_ndims(dataspace_id);
+
+    status = H5Sget_simple_extent_dims(dataspace_id, array->shape, NULL);
+    
+    status = H5Sclose(dataspace_id);
+
+    return dataset_id;
+}
+
+hid_t array_create(array_t *array, hid_t loc_id, const char *name, const char *title)
+{
+    hid_t dataspace_id;
+    hid_t dataset_id;
+    herr_t status;
+
+    dataspace_id = H5Screate_simple(array->rank, array->shape, NULL);
+    if (dataspace_id < 0)
+    {
+        return -1;
+    }
+
+    dataset_id = H5Dcreate(loc_id, name, array->type_id, dataspace_id,
+                           H5P_DEFAULT);
+    if (dataset_id < 0)
+    {
+        H5Sclose(dataspace_id);
+        return -2;
+    }
+    
+    status = set_str_attr(dataset_id, "TITLE", title);
+    status = set_str_attr(dataset_id, "CLASS", "ARRAY");
+    status = set_str_attr(dataset_id, "FLAVOR", "numpy");
+    status = set_str_attr(dataset_id, "VERSION", "2.3");
+
+    status = H5Sclose(dataspace_id);
+
+    return dataset_id;
+}
+
+
+
+int array_read(array_t *array, hid_t loc_id, const char *name)
+{
+    int npoints;
+    hid_t dataset_id;
+    herr_t status;
+
+    dataset_id = array_open(array, loc_id, name);
+    if (dataset_id < 0)
+    {
+        return -1;
+    }
+
+    npoints = array_npoints(array);
+
+    array->data = malloc(npoints * H5Tget_size(array->type_id));
+    if (array->data == NULL)
+    {
+        H5Dclose(dataset_id);
+        return -2;
+    }
+
+    status = H5Dread(dataset_id, array->type_id, H5S_ALL, H5S_ALL,
+                     H5P_DEFAULT, array->data);
+    if (status < 0)
+    {
+        H5Dclose(dataset_id);
+        return -3;
+    }
+
+    status = H5Dclose(dataset_id);
+
+    return 0;
+}
+
+int array_write(array_t *array, hid_t loc_id, const char *name)
+{
+    hid_t dataspace_id;
+    hid_t dataset_id;
+    herr_t status;
+
+    dataspace_id = H5Screate_simple(array->rank, array->shape, NULL);
+    if (dataspace_id < 0)
+    {
+        return -1;
+    }
+
+    dataset_id = H5Dcreate(loc_id, name, array->type_id, dataspace_id,
+                           H5P_DEFAULT);
+    if (dataset_id < 0)
+    {
+        H5Sclose(dataspace_id);
+        return -2;
+    }
+
+    status = H5Dwrite(dataset_id, array->type_id, H5S_ALL, H5S_ALL,
+                      H5P_DEFAULT, array->data);
+    if (status < 0)
+    {
+        H5Sclose(dataspace_id);
+        H5Dclose(dataset_id);
+        return -3;
+    }
+
+    status = H5Sclose(dataspace_id);
+    status = H5Dclose(dataset_id);
+
+    return 0;
+}
+
+
+
+static herr_t array_hyperslab_init(array_t *array,
+                                   hsize_t **offset, hsize_t **stride,
+                                   hsize_t **count,  hsize_t **block,
+                                   int start, int end)
+{
+    int i;
+
+    *offset = NULL;
+    *stride = NULL;
+    *count  = NULL;
+    *block  = NULL;
+
+    if ((start < 0) || (start > end))
+    {
+        return -1;
+    }
+
+    if (start >= array->rank)
+    {
+        return -2;
+    }
+
+    if (array->rank == 0)
+    {
+        return -3;
+    }
+
+    *offset = (hsize_t *)malloc((array->rank) * sizeof(hsize_t));
+    *stride = (hsize_t *)malloc((array->rank) * sizeof(hsize_t));
+    *count  = (hsize_t *)malloc((array->rank) * sizeof(hsize_t));
+    *block  = (hsize_t *)malloc((array->rank) * sizeof(hsize_t));
+
+    // first select everything
+    for (i = 0; i < array->rank; i++)
+    {
+        (*offset)[i] = 0;
+        (*block )[i] = array->shape[i];
+        (*stride)[i] = 1;
+        (*count )[i] = 1;
+    }
+
+    // now, do the selection on the first dimension only
+    (*offset)[0] = start;
+    (*block )[0] = end - start;
+
+    return 0;
+}
+
+static void array_hyperslab_free(hsize_t *offset, hsize_t *stride,
+                                 hsize_t *count,  hsize_t *block)
+{
+    if (offset != NULL) free(offset);
+    if (stride != NULL) free(stride);
+    if (count != NULL)  free(count);
+    if (block != NULL)  free(block);
+}
+
+int array_read_slice(array_t *array, hid_t dataset_id, int start, int end)
+{
+    hsize_t *offset, *stride, *count, *block;
+    hid_t memspace_id;
+    hid_t filespace_id;
+    herr_t status;
+
+    status = array_hyperslab_init(array,
+                                  &offset, &stride,
+                                  &count, &block,
+                                  start, end);
+    if (status < 0)
+    {
+        return -1;
+    }
+
+    memspace_id = H5Screate_simple(array->rank, block, NULL);
+    if (memspace_id < 0)
+    {
+        return -2;
+    }
+
+    filespace_id = H5Dget_space(dataset_id);
+    if (filespace_id < 0)
+    {
+        H5Sclose(memspace_id);
+        return -3;
+    }
+
+    if (array->data == NULL)
+    {
+        int i;
+        int npoints = 1;
+
+        for (i = 0; i < array->rank; i++)
+        {
+            npoints *= block[i];
+        }
+        
+        array->data = malloc(npoints * H5Tget_size(array->type_id));
+        if (array->data == NULL)
+        {
+            H5Sclose(memspace_id);
+            H5Sclose(filespace_id);
+            return -4;
+        }
+    }
+
+    status = H5Sselect_hyperslab(filespace_id, H5S_SELECT_SET,
+                                 offset, stride, count, block);
+    if (status < 0)
+    {
+        H5Sclose(memspace_id);
+        H5Sclose(filespace_id);
+        return -5;
+    }
+
+    status = H5Dread(dataset_id, array->type_id, memspace_id, filespace_id,
+                     H5P_DEFAULT, array->data);
+    if (status < 0)
+    {
+        H5Sclose(memspace_id);
+        H5Sclose(filespace_id);
+        return -5;
+    }
+
+    status = H5Sclose(memspace_id);
+    status = H5Sclose(filespace_id);
+
+    array_hyperslab_free(offset, stride, count, block);
+
+    return 0;
+}
+
+int array_write_slice(array_t *array, hid_t dataset_id, int start, int end)
+{
+    hsize_t *offset, *stride, *count, *block;
+    hid_t memspace_id;
+    hid_t filespace_id;
+    herr_t status;
+
+    status = array_hyperslab_init(array,
+                                  &offset, &stride,
+                                  &count, &block,
+                                  start, end);
+    if (status < 0)
+    {
+        return -1;
+    }
+
+    memspace_id = H5Screate_simple(array->rank, block, NULL);
+    if (memspace_id < 0)
+    {
+        return -2;
+    }
+
+    filespace_id = H5Dget_space(dataset_id);
+    if (filespace_id < 0)
+    {
+        H5Sclose(memspace_id);
+        return -3;
+    }
+
+    status = H5Sselect_hyperslab(filespace_id, H5S_SELECT_SET,
+                                 offset, stride, count, block);
+    if (status < 0)
+    {
+        H5Sclose(memspace_id);
+        H5Sclose(filespace_id);
+        return -4;
+    }
+
+    status = H5Dwrite(dataset_id, array->type_id, memspace_id, filespace_id,
+                      H5P_DEFAULT, array->data);
+    if (status < 0)
+    {
+        H5Sclose(memspace_id);
+        H5Sclose(filespace_id);
+        return -5;
+    }
+
+    status = H5Sclose(memspace_id);
+    status = H5Sclose(filespace_id);
+
+    array_hyperslab_free(offset, stride, count, block);
+
+    return 0;
+}
+

Added: cs/cigma/branches/cigma-0.9b1/libcigma/array.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/array.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/array.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,48 @@
+#ifndef __CIGMA_ARRAY_H__
+#define __CIGMA_ARRAY_H__
+#include <hdf5.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct {
+    int rank;
+    hsize_t *shape;
+    hid_t type_id;
+    void *data;
+} array_t;
+
+
+
+int array_init(array_t *array, hid_t type_id, int rank, int *shape, void *data);
+int array_free_dims(array_t *array);
+int array_free_data(array_t *array);
+int array_free(array_t *array);
+
+
+int array_npoints(array_t *array);
+int array_dim(array_t *array, int i);
+void array_dims(array_t *array, int *rank, int **shape);
+void array_dims1(array_t *array, int *n);
+void array_dims2(array_t *array, int *m, int *n);
+void array_dims3(array_t *array, int *l, int *m, int *n);
+
+
+hid_t array_open(array_t *array, hid_t loc_id, const char *name);
+hid_t array_create(array_t *array, hid_t loc_id, const char *name, const char *title);
+
+
+int array_read(array_t *array, hid_t loc_id, const char *name);
+int array_write(array_t *array, hid_t loc_id, const char *name);
+
+
+int array_read_slice(array_t *array, hid_t dataset_id, int start, int end);
+int array_write_slice(array_t *array, hid_t dataset_id, int start, int end);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __CIGMA_H5_ARRAY_H__ */

Added: cs/cigma/branches/cigma-0.9b1/libcigma/dataset.c
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/dataset.c	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/dataset.c	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,254 @@
+#include <stdlib.h>
+#include <hdf5.h>
+#include "h5_attr.h"
+#include "dataset.h"
+
+
+
+hid_t dataset_create(hid_t loc_id, const char *name, const char *title,
+                     hid_t type_id, int rank, int *shape)
+{
+    hid_t dataset_id;
+    hid_t dataspace_id;
+    herr_t status;
+
+    if (rank > 0)
+    {
+        hsize_t *dims;
+        int i;
+
+        dims = (hsize_t *)malloc(rank * sizeof(hsize_t));
+        for (i = 0; i < rank; i++)
+        {
+            dims[i] = shape[i];
+        }
+
+        dataspace_id = H5Screate_simple(rank, dims, NULL);
+        if (dataspace_id < 0)
+        {
+            free(dims);
+            return -1;
+        }
+        free(dims);
+    }
+    else
+    {
+        return -3;
+    }
+
+
+    dataset_id = H5Dcreate(loc_id, name, type_id, dataspace_id, H5P_DEFAULT);
+    if (dataset_id < 0)
+    {
+        H5Sclose(dataspace_id);
+        return -2;
+    }
+
+
+    status = set_str_attr(dataset_id, "TITLE", title);
+    status = set_str_attr(dataset_id, "CLASS", "ARRAY");
+    status = set_str_attr(dataset_id, "FLAVOR", "numpy");
+    status = set_str_attr(dataset_id, "VERSION", "2.3");
+
+    status = H5Sclose(dataspace_id);
+
+    return dataset_id;
+}
+
+
+
+hid_t dataset_open(hid_t loc_id, const char *name,
+                   hid_t *type_id, int *rank, int *shape,
+                   int *npoints)
+{
+    hid_t dataset_id;
+    hid_t dataspace_id;
+    herr_t status;
+
+    dataset_id = H5Dopen(loc_id, name);
+    if (dataset_id < 0)
+    {
+        return -1;
+    }
+    
+    if (type_id != NULL)
+    {
+        *type_id = H5Dget_type(dataset_id);
+    }
+
+    if ((rank != NULL) || (shape != NULL) || (npoints != NULL))
+    {
+        dataspace_id = H5Dget_space(dataset_id);
+
+        if (rank != NULL)
+        {
+            *rank = H5Sget_simple_extent_ndims(dataspace_id);
+        }
+
+        if (shape != NULL)
+        {
+            int i;
+            hsize_t *dims;
+
+            dims = (hsize_t *)malloc((*rank) * sizeof(hsize_t));
+            status = H5Sget_simple_extent_dims(dataspace_id, dims, NULL);
+            for (i = 0; i < *rank; i++)
+            {
+                shape[i] = (int)dims[i];
+            }
+            free(dims);
+        }
+
+        if (npoints != NULL)
+        {
+            *npoints = H5Sget_simple_extent_npoints(dataspace_id);
+        }
+
+        status = H5Sclose(dataspace_id);
+    }
+
+    return dataset_id;
+}
+
+
+
+int dataset_read(hid_t loc_id, const char *name,
+                 hid_t type_id, int rank, int *shape,
+                 void **data)
+{
+    int dset_rank;
+    int dset_npts;
+    hid_t dataset_id;
+    herr_t status;
+
+    dataset_id = dataset_open(loc_id, name, NULL, &dset_rank, shape, &dset_npts);
+    if (dataset_id < 0)
+    {
+        return -1;
+    }
+    if (rank != dset_rank)
+    {
+        H5Dclose(dataset_id);
+        return -2;
+    }
+
+    *data = malloc(dset_npts * H5Tget_size(type_id));
+    if (*data == NULL)
+    {
+        H5Dclose(dataset_id);
+        return -3;
+    }
+
+    status = H5Dread(dataset_id, type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, *data);
+    if (status < 0)
+    {
+        H5Dclose(dataset_id);
+        return -4;
+    }
+
+    status = H5Dclose(dataset_id);
+
+    return 0;
+}
+
+
+
+int dataset_write(hid_t loc_id, const char *name, const char *title,
+                  hid_t type_id, int rank, int *shape,
+                  void *data)
+{
+    hid_t dataset_id;
+    herr_t status;
+
+    dataset_id = dataset_create(loc_id, name, title, type_id, rank, shape);
+    if (dataset_id < 0)
+    {
+        return -1;
+    }
+
+    status = H5Dwrite(dataset_id, type_id, H5S_ALL, H5S_ALL,
+                      H5P_DEFAULT, data);
+    if (status < 0)
+    {
+        H5Dclose(dataset_id);
+        return -2;
+    }
+
+    H5Dclose(dataset_id);
+    return 0;
+}
+
+
+
+int dataset_read1(hid_t loc_id,
+                  const char *name,
+                  hid_t type_id,
+                  void **data, int *n)
+{
+    return dataset_read(loc_id, name, type_id, 1, n, data);
+}
+
+int dataset_read2(hid_t loc_id,
+                  const char *name,
+                  hid_t type_id,
+                  void **data, int *m, int *n)
+{
+    int shape[2];
+    int ret;
+    
+    ret = dataset_read(loc_id, name, type_id, 2, shape, data);
+
+    *m = shape[0];
+    *n = shape[1];
+
+    return ret;
+}
+
+int dataset_read3(hid_t loc_id,
+                  const char *name,
+                  hid_t type_id,
+                  void **data, int *l, int *m, int *n)
+{
+    int shape[3];
+    int ret;
+
+    ret = dataset_read(loc_id, name, type_id, 3, shape, data);
+
+    *l = shape[0];
+    *m = shape[1];
+    *n = shape[2];
+
+    return ret;
+}
+
+
+
+int dataset_write1(hid_t loc_id,
+                   const char *name,
+                   const char *title,
+                   hid_t type_id,
+                   void *data, int n)
+{
+    return dataset_write(loc_id, name, title, type_id, 1, &n, data);
+}
+
+int dataset_write2(hid_t loc_id,
+                   const char *name,
+                   const char *title,
+                   hid_t type_id,
+                   void *data, int m, int n)
+{
+    int dims[2] = {m,n};
+    return dataset_write(loc_id, name, title, type_id, 2, dims, data);
+}
+
+int dataset_write3(hid_t loc_id,
+                   const char *name,
+                   const char *title,
+                   hid_t type_id,
+                   void *data, int l, int m, int n)
+{
+    int dims[3] = {l,m,n};
+    return dataset_write(loc_id, name, title, type_id, 3, dims, data);
+}
+

Added: cs/cigma/branches/cigma-0.9b1/libcigma/dataset.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/dataset.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/dataset.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,86 @@
+#ifndef __CIGMA_DATASET_H__
+#define __CIGMA_DATASET_H__
+
+#include <hdf5.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+hid_t dataset_create(hid_t loc_id,
+                     const char *name,
+                     const char *title,
+                     hid_t type_id, int rank, int *shape);
+
+hid_t dataset_open(hid_t loc_id,
+                   const char *name,
+                   hid_t *type_id, int *rank, int *shape,
+                   int *npoints);
+
+
+int dataset_read(hid_t loc_id,
+                 const char *name,
+                 hid_t type_id, int rank, int *shape,
+                 void **data);
+
+
+int dataset_write(hid_t loc_id,
+                  const char *name,
+                  const char *title,
+                  hid_t type_id, int rank, int *shape,
+                  void *data);
+
+
+int dataset_read1(hid_t loc_id,
+                  const char *name,
+                  hid_t type_id,
+                  void **data, int *n);
+
+int dataset_read2(hid_t loc_id,
+                  const char *name,
+                  hid_t type_id,
+                  void **data, int *m, int *n);
+
+int dataset_read3(hid_t loc_id,
+                  const char *name,
+                  hid_t type_id,
+                  void **data, int *l, int *m, int *n);
+
+
+int dataset_write1(hid_t loc_id,
+                   const char *name,
+                   const char *title,
+                   hid_t type_id,
+                   void *data, int n);
+
+int dataset_write2(hid_t loc_id,
+                   const char *name,
+                   const char *title,
+                   hid_t type_id,
+                   void *data, int m, int n);
+
+int dataset_write3(hid_t loc_id,
+                   const char *name,
+                   const char *title,
+                   hid_t type_id,
+                   void *data, int l, int m, int n);
+
+
+int dataset_read3_slice(hid_t loc_id,
+                        const char *name,
+                        hid_t type_id,
+                        int rank, hsize_t *dims, void *data,
+                        int start, int end);
+
+int dataset_write3_slice(hid_t loc_id,
+                         const char *name,
+                         const char *title,
+                         hid_t type_id,
+                         int start, int end);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CIGMA_DATASET_H__ */

Added: cs/cigma/branches/cigma-0.9b1/libcigma/h5_attr.c
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/h5_attr.c	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/h5_attr.c	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,574 @@
+#include <stdlib.h>
+#include <string.h>
+#include <hdf5.h>
+#include "h5_attr.h"
+
+/****************************************************************************
+ * Some of the following functions were based from the H5ATTR.c             *
+ * source file in PyTables, which is a BSD-licensed python extension        *
+ * for accessing HDF5 files.                                                *
+ *                                                                          *
+ * The copyright notice is hereby retained.                                 *
+ *                                                                          *
+ * NCSA HDF                                                                 *
+ * Scientific Data Technologies                                             *
+ * National Center for Supercomputing Applications                          *
+ * University of Illinois at Urbana-Champaign                               *
+ * 605 E. Springfield, Champaign IL 61820                                   *
+ *                                                                          *
+ * For conditions of distribution and use, see the accompanying             *
+ * hdf/COPYING file.                                                        *
+ *                                                                          *
+ * Modified versions of H5LT for getting and setting attributes for open    *
+ * groups and leaves.                                                       *
+ * F. Altet 2005/09/29                                                      *
+ *                                                                          *
+ ****************************************************************************/
+
+
+
+/* Function  : find_attr_op
+ * Purpose   : operator function used by find_attribute
+ * Programmer: Pedro Vicente, pvn at ncsa.uiuc.edu
+ * Date      : June 21, 2001
+ */
+static herr_t find_attr_op(hid_t loc_id, const char *name, void *op_data)
+{
+    /* 
+     * Define a default zero value for return. This will cause the
+     * iterator to continue if the palette attribute is not found yet.
+     */
+    int ret = 0;
+
+    char *attr_name = (char *)op_data;
+
+    /* Shut the compiler up */
+    loc_id = loc_id;
+
+    /*
+     * Define a positive value for return value if the attribute was
+     * found. This will cause the iterator to immediately return that
+     * positive value, indicating short-circuit sucesss
+     */
+
+    if (strcmp(name, attr_name) == 0)
+    {
+        ret = 1;
+    }
+
+    return ret;
+}
+
+
+
+/* Function  : find_attr
+ * Purpose   : Inquires if an attribute named attr_name exists attached
+ *             to the object loc_id.
+ * Programmer: Pedro Vicente, pvn at ncsa.uiuc.edu
+ * Date      : June 21, 2001
+ *
+ * Comments:
+ *
+ *  The function uses H5Aiterate with the operator function find_attr
+ *
+ * Return:
+ *
+ *  Success: The return value of the first operator that returns
+ *           non-zero, or zero if all members were processed with no
+ *           operator returning non-zero.
+ *
+ *  Failure: Negative if something goes wrong within the library,
+ *           or the negative value returned by one of the operators.
+ */
+herr_t find_attr(hid_t loc_id, const char *attr_name)
+{
+    unsigned int attr_num;
+    herr_t ret;
+
+    attr_num = 0;
+    ret = H5Aiterate(loc_id, &attr_num, find_attr_op, (void *)attr_name);
+
+    return ret;
+}
+
+
+
+/* Function  : set_attr
+ * Purpose   : Private function used by
+ *             set_int_attr and set_float_attr
+ * Return    : Success 0, Failure -1
+ * Programmer: Pedro Vicente, pvn at ncsa.uiuc.edu
+ * Date      : July 25, 2001
+ */
+herr_t set_attr(hid_t obj_id, const char *attr_name, hid_t type_id, const void *data)
+{
+    hid_t space_id, attr_id;
+    herr_t status;
+
+    int has_attr;
+
+    /* Create the data space for the attribute. */
+    space_id = H5Screate(H5S_SCALAR);
+    if (space_id < 0)
+    {
+        goto out;
+    }
+
+    /* Verify if the attribute already exists. */
+    has_attr = find_attr(obj_id, attr_name);
+    if (has_attr == 1)
+    {
+        /* The attribute already exists. Delete it. */
+        status = H5Adelete(obj_id, attr_name);
+        if (status < 0)
+        {
+            goto out;
+        }
+    }
+
+    /* Create the attribute. */
+    attr_id = H5Acreate(obj_id, attr_name, type_id, space_id, H5P_DEFAULT);
+    if (attr_id < 0)
+    {
+        goto out;
+    }
+
+    /* Write the attribute data. */
+    status = H5Awrite(attr_id, type_id, data);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    /* Close the attribute. */
+    status = H5Aclose(attr_id);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    /* Close the data space. */
+    status = H5Sclose(space_id);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    return 0;
+
+out:
+    return -1;
+}
+
+
+
+/* Function  : get_attr
+ * Purpose   : Reads an attribute named attr_name with the memory type type_id
+ * Return    : Success 0, Failure -1
+ * Programmer: Pedro Vicente, pvn at ncsa.uiuc.edu
+ * Date      : September 19, 2002
+ */
+herr_t get_attr(hid_t obj_id, const char *attr_name, hid_t type_id, void *data)
+{
+    hid_t attr_id;
+    herr_t status;
+
+    attr_id = H5Aopen_name(obj_id, attr_name);
+    if (attr_id < 0)
+    {
+        return -1;
+    }
+
+    status = H5Aread(attr_id, type_id, data);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    status = H5Aclose(attr_id);
+    if (status < 0)
+    {
+        return -1;
+    }
+
+    return 0;
+
+out:
+    H5Aclose(attr_id);
+    return -1;
+}
+
+
+
+/* Function  : get_attr_dims
+ * Purpose   : Gets the dimensionality of an attribute
+ * Return    : Success 0, Failure -1
+ * Programmer: Pedro Vicente, pvn at ncsa.uiuc.edu
+ * Date      : September 4, 2001
+ */
+herr_t get_attr_dims(hid_t obj_id,
+                     const char *attr_name,
+                     int *rank,
+                     hsize_t *dims)
+{
+    hid_t attr_id;
+    hid_t space_id;
+    herr_t status;
+
+    /* Open the attribute */
+    attr_id = H5Aopen_name(obj_id, attr_name);
+    if (attr_id < 0)
+    {
+        return -1;
+    }
+
+    /* Get the dataspace handle */
+    space_id = H5Aget_space(attr_id);
+    if (space_id < 0)
+    {
+        goto out;
+    }
+
+    /* Get number of dimensions */
+    *rank = H5Sget_simple_extent_ndims(space_id);
+    if (*rank < 0)
+    {
+        goto out;
+    }
+
+    /* Get dimensions */
+    status = H5Sget_simple_extent_dims(space_id, dims, NULL);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    /* Terminate access to the dataspace */
+    status = H5Sclose(space_id);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    /* End access to the attribute */
+    status = H5Aclose(attr_id);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    return 0;
+
+out:
+    H5Aclose(attr_id);
+    return -1;
+}
+
+
+
+/* Function  : set_str_attr
+ *
+ * Purpose   : Creates and writes a string attribute named attr_name
+ *             and attaches it to the object specified by obj_id
+ *
+ * Return    : Success 0, Failure -1
+ * Programmer: Pedro Vicente, pvn at ncsa.uiuc.edu
+ * Date      : July 23, 2001
+ * Comments  : If the attribute already exists, it is overwritten.
+ */
+herr_t set_str_attr(hid_t obj_id,
+                    const char *attr_name,
+                    const char *attr_data)
+{
+    hid_t attr_type;
+    hid_t attr_size;
+    hid_t attr_space_id;
+    hid_t attr_id;
+    int has_attr;
+    herr_t status;
+
+    /* Create the attribute */
+    attr_type = H5Tcopy(H5T_C_S1);
+    if (attr_type < 0)
+    {
+        goto out;
+    }
+
+    attr_size = strlen(attr_data) + 1; /* extra null term */
+
+    status = H5Tset_size(attr_type, (size_t)attr_size);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    status = H5Tset_strpad(attr_type, H5T_STR_NULLTERM);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    attr_space_id = H5Screate(H5S_SCALAR);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    /* Verify if the attribute already exists */
+    has_attr = find_attr(obj_id, attr_name);
+
+    /* The attribute already exists, delete it */
+    if (has_attr == 1)
+    {
+        status = H5Adelete(obj_id, attr_name);
+        if (status < 0)
+        {
+            goto out;
+        }
+    }
+
+    /* Create the attribute. */
+    attr_id = H5Acreate(obj_id, attr_name, attr_type, attr_space_id,
+                        H5P_DEFAULT);
+    if (attr_id < 0)
+    {
+        goto out;
+    }
+
+    /* Write the attribute data. */
+    status = H5Awrite(attr_id, attr_type, attr_data);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    status = H5Aclose(attr_id);
+    if (status < 0)
+    {
+        goto out;
+    }
+    status = H5Sclose(attr_space_id);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    status = H5Tclose(attr_type);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    return 0;
+
+out:
+    return -1;
+}
+
+
+
+/* Function  : get_str_attr
+ * Purpose   : Reads a string attribute named attr_name
+ * Return    : Success 0, Failure -1
+ * Programmer: Francesc Altet, faltet at carabos.com
+ * Date      : February 23, 2005
+ */
+herr_t get_str_attr(hid_t obj_id, const char *attr_name, char **data)
+{
+    hid_t attr_id;
+    hid_t attr_type;
+    size_t type_size;
+    herr_t status;
+
+    *data = NULL;
+
+    attr_id = H5Aopen_name(obj_id, attr_name);
+    if (attr_id < 0)
+    {
+        return -1;
+    }
+
+    attr_type = H5Aget_type(attr_id);
+    if (attr_type < 0)
+    {
+        goto out;
+    }
+
+    /* Get the size */
+    type_size = H5Tget_size(attr_type);
+    if (type_size < 0)
+    {
+        goto out;
+    }
+
+    /* Malloc enough space for the string, plus 1 for the trailing '\0' */
+    *data = (char *)malloc((type_size + 1) * sizeof(char));
+
+    status = H5Aread(attr_id, attr_type, *data);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    /* Set the last character to \0 in case we are dealing with
+     * space padded strings
+     */
+    (*data)[type_size] = '\0';
+
+    /* TODO: WHY DOES THIS PART FAIL?!?
+    status = H5Tclose(attr_type);
+    if (status < 0);
+    {
+        goto out;
+    } // */
+
+    status = H5Aclose(attr_id);
+    if (status < 0)
+    {
+        return -1;
+    }
+
+    return 0;
+
+out:
+    if (attr_type != 0)
+        H5Tclose(attr_type);
+    H5Aclose(attr_id);
+    if (*data)
+        free(*data);
+    return -1;
+}
+
+
+
+/* Function: set_array_attr
+ * Purpose : write an array attribute
+ * Return  : Success 0, Failure -1
+ * Date    : July 25, 2001
+ */
+herr_t set_array_attr(hid_t obj_id,
+                      const char *attr_name,
+                      size_t rank,
+                      hsize_t *dims,
+                      hid_t type_id,
+                      const void *data)
+{
+    hid_t space_id, attr_id;
+    herr_t status;
+
+    int has_attr;
+
+    /* Create the data space for the attribute. */
+    space_id = H5Screate_simple(rank, dims, NULL);
+    if (space_id < 0)
+    {
+        goto out;
+    }
+
+    /* Verify if the attribute already exists. */
+    has_attr = find_attr(obj_id, attr_name);
+    if (has_attr == 1)
+    {
+        /* The attribute already exists. Delete it. */
+        status = H5Adelete(obj_id, attr_name);
+        if (status < 0)
+        {
+            goto out;
+        }
+    }
+
+    /* Create the attribute. */
+    attr_id = H5Acreate(obj_id, attr_name, type_id, space_id, H5P_DEFAULT);
+    if (attr_id < 0)
+    {
+        goto out;
+    }
+
+    /* Write the attribute data. */
+    status = H5Awrite(attr_id, type_id, data);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    /* Close the attribute. */
+    status = H5Aclose(attr_id);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    /* Close the dataspace. */
+    status = H5Sclose(space_id);
+    if (status < 0)
+    {
+        goto out;
+    }
+
+    return 0;
+
+out:
+    return -1;
+}
+
+
+
+herr_t set_float_attr(hid_t obj_id, const char *attr_name, float x)
+{
+    return set_attr(obj_id, attr_name, H5T_NATIVE_FLOAT, &x);
+}
+
+herr_t set_double_attr(hid_t obj_id, const char *attr_name, double x)
+{
+    return set_attr(obj_id, attr_name, H5T_NATIVE_DOUBLE, &x);
+}
+
+herr_t set_int_attr(hid_t obj_id, const char *attr_name, int n)
+{
+    return set_attr(obj_id, attr_name, H5T_NATIVE_INT, &n);
+}
+
+herr_t set_long_attr(hid_t obj_id, const char *attr_name, long n)
+{
+    return set_attr(obj_id, attr_name, H5T_NATIVE_LONG, &n);
+}
+
+herr_t set_llong_attr(hid_t obj_id, const char *attr_name, long long n)
+{
+    return set_attr(obj_id, attr_name, H5T_NATIVE_LLONG, &n);
+}
+
+
+herr_t set_array1_attr(hid_t obj_id,
+                       const char *attr_name,
+                       hsize_t dim,
+                       hid_t type_id,
+                       const void *data)
+{
+    return set_array_attr(obj_id, attr_name, 1, &dim, type_id, data);
+}
+
+herr_t set_int_array_attr(hid_t obj_id,
+                          const char *attr_name,
+                          hsize_t dim,
+                          const int *data)
+{
+    return set_array_attr(obj_id, attr_name, 1, &dim, H5T_NATIVE_INT, data);
+}
+
+herr_t set_float_array_attr(hid_t obj_id,
+                            const char *attr_name,
+                            hsize_t dim,
+                            const float *data)
+{
+    return set_array_attr(obj_id, attr_name, 1, &dim, H5T_NATIVE_FLOAT, data);
+}
+
+herr_t set_double_array_attr(hid_t obj_id,
+                             const char *attr_name,
+                             hsize_t dim,
+                             const double *data)
+{
+    return set_array_attr(obj_id, attr_name, 1, &dim, H5T_NATIVE_DOUBLE, data);
+}
+

Added: cs/cigma/branches/cigma-0.9b1/libcigma/h5_attr.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/h5_attr.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/h5_attr.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,45 @@
+#ifndef __CIGMA_ATTR_H__
+#define __CIGMA_ATTR_H__
+#include <hdf5.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+herr_t find_attr(hid_t loc_id, const char *attr_name);
+herr_t set_attr(hid_t obj_id, const char *attr_name, hid_t type_id, const void *data);
+herr_t get_attr(hid_t obj_id, const char *attr_name, hid_t type_id, void *data);
+herr_t get_attr_dims(hid_t obj_id, const char *attr_name, int *rank, hsize_t *dims);
+
+
+herr_t set_str_attr(hid_t obj_id, const char *attr_name, const char *attr_data);
+herr_t get_str_attr(hid_t obj_id, const char *attr_name, char **data);
+
+
+herr_t set_float_attr(hid_t obj_id, const char *attr_name, float x);
+herr_t set_double_attr(hid_t obj_id, const char *attr_name, double x);
+herr_t set_int_attr(hid_t obj_id, const char *attr_name, int n);
+herr_t set_long_attr(hid_t obj_id, const char *attr_name, long n);
+herr_t set_llong_attr(hid_t obj_id, const char *attr_name, long long n);
+
+
+herr_t set_array_attr(hid_t obj_id, const char *attr_name,
+                      size_t rank, hsize_t *dims, hid_t type_id, const void *data);
+
+herr_t set_array1_attr(hid_t obj_id, const char *attr_name,
+                       hsize_t dim, hid_t type_id, const void *data);
+
+herr_t set_int_array_attr(hid_t obj_id, const char *attr_name,
+                          hsize_t dim, const int *data);
+
+herr_t set_float_array_attr(hid_t obj_id, const char *attr,
+                            hsize_t dim, const float *data);
+
+herr_t set_double_array_attr(hid_t obj_id, const char *attr,
+                             hsize_t dim, const double *data);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

Added: cs/cigma/branches/cigma-0.9b1/libcigma/h5_io.c
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/h5_io.c	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/h5_io.c	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,275 @@
+#include <string.h>
+#include <hdf5.h>
+#include "h5_io.h"
+#include "h5_attr.h"
+#include "split.h"
+
+
+
+hid_t h5_file_create(const char *filename, const char *mode)
+{
+    hid_t file_id;
+    hid_t root;
+    herr_t status;
+    
+    if (strcmp(mode, "w") == 0)
+    {
+        /* Create file by truncating (i.e. overwriting previous file) */
+        file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+    }
+    else if (strcmp(mode, "x") == 0)
+    {
+        /* Create file exclusively (i.e. fail if it already exists) */
+        file_id = H5Fcreate(filename, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT);
+    }
+    else
+    {
+        return -1;
+    }
+    
+    if (file_id < 0)
+    {
+        return -2;
+    }
+
+    root = H5Gopen(file_id, "/");
+    status = set_str_attr(root, "TITLE", "CIGMA file");
+    status = set_str_attr(root, "CLASS", "GROUP");
+    status = set_str_attr(root, "VERSION", "1.0");
+    status = set_str_attr(root, "PYTABLES_FORMAT_VERSION", "1.5");
+    status = H5Gclose(root);
+
+    return file_id;
+}
+
+
+
+hid_t h5_file_open(const char *filename, const char *mode)
+{
+    /*
+     * Open file for reading. Fail if file doesn't exist.
+     */
+    if (strcmp(mode, "r") == 0)
+    {
+        hid_t file_id;
+
+        /* Open file in read-only mode */
+        file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
+
+        /* Check for failure */
+        if (file_id < 0)
+        {
+            return -1;
+        }
+
+        return file_id;
+    }
+
+    /*
+     * Open file for writing. If file exists, it is truncated.
+     */
+    if (strcmp(mode, "w") == 0)
+    {
+        hid_t file_id;
+
+        file_id = h5_file_create(filename, "w");
+
+        if (file_id < 0)
+        {
+            return -2;
+        }
+
+        return file_id;
+    }
+
+    /*
+     * Open file for reading and writing. Fail if file doesn't exist.
+     */
+    if (strcmp(mode, "rw") == 0)
+    {
+        hid_t file_id;
+
+        /* Open file in read-write mode */
+        file_id = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT);
+
+        /* Check for failure */
+        if (file_id < 0)
+        {
+            return -3;
+        }
+
+        return file_id;
+    }
+
+    /*
+     * Open file for reading and writing. Create the file if necessary.
+     */
+    if (strcmp(mode, "rw+") == 0)
+    {
+        hid_t file_id;
+
+        /* See http://hdf.ncsa.uiuc.edu/HDF5/doc/Errors.html */
+        herr_t (*old_func)(void *);
+        void *old_client_data;
+        
+        /* Save old error handler */
+        H5Eget_auto(&old_func, &old_client_data);
+
+        /* Turn off error handling */
+        H5Eset_auto(NULL, NULL);
+
+        /* Open file in read-write mode -- errors suppressed */
+        file_id = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT);
+        
+        /* Restore error handler */
+        H5Eset_auto(old_func, old_client_data);
+
+        /* If opening the file failed, try to create it */
+        if (file_id < 0)
+        {
+            file_id = h5_file_create(filename, "w");
+
+            if (file_id < 0)
+            {
+                return -4;
+            }
+        }
+
+        return file_id;
+    }
+
+    /* 
+     * Exclusively open file for writing. Fail if file already exists.
+     */
+    if (strcmp(mode, "x") == 0)
+    {
+        hid_t file_id;
+
+        file_id = h5_file_create(filename, "x");
+
+        if (file_id < 0)
+        {
+            return -5;
+        }
+    }
+
+
+    /*
+     * Invalid mode
+     */
+    return -6;
+}
+
+
+
+hid_t h5_group_create(hid_t loc_id, const char *name)
+{
+    hid_t group_id;
+    herr_t status;
+
+    group_id = H5Gcreate(loc_id, name, 0);
+    if (group_id < 0)
+    {
+        return -1;
+    }
+
+    status = set_str_attr(group_id, "TITLE", "");
+    status = set_str_attr(group_id, "CLASS", "GROUP");
+    status = set_str_attr(group_id, "VERSION", "1.0");
+    status = set_str_attr(group_id, "PYTABLES_FORMAT_VERSION", "1.5");
+    
+    return group_id;
+}
+
+
+
+hid_t h5_group_open(hid_t loc_id, const char *name)
+{
+    return H5Gopen(loc_id, name);
+}
+
+
+
+hid_t h5_touch_group(hid_t loc_id, const char *name)
+{
+    hid_t group_id;
+
+    group_id = H5Gopen(loc_id, name);
+
+    if (group_id < 0)
+    {
+        group_id = h5_group_create(loc_id, name);
+        if (group_id < 0)
+        {
+            return -1;
+        }
+    }
+
+    return group_id;
+}
+
+
+
+hid_t h5_touch_path(hid_t loc_id, const char *path)
+{
+    hid_t group_id;
+
+    /* Temporarily disabling error messages:
+     * http://hdf.ncsa.uiuc.edu/HDF5/doc/Errors.html
+     */
+    herr_t (*old_func)(void *);
+    void *old_client_data;
+
+    /* Save old error handler */
+    H5Eget_auto(&old_func, &old_client_data);
+
+    /* Turn off error handling */
+    H5Eset_auto(NULL, NULL);
+
+    /* Attempt to open the group */
+    group_id = H5Gopen(loc_id, path);
+
+    if (group_id < 0)
+    {
+        herr_t status;
+        hid_t parent_id;
+        hid_t child_id;
+        char **names;
+        int i,n;
+
+        split(path, strlen(path), &names, &n, '/');
+
+        // first parent
+        parent_id = h5_touch_group(loc_id, names[0]);
+        if (parent_id < 0)
+        {
+            H5Eset_auto(old_func, old_client_data);
+            split_free(names, n);
+            return -1;
+        }
+
+        for (i = 1; i < n; i++)
+        {
+            // get child id
+            child_id = h5_touch_group(parent_id, names[i]);
+            if (child_id < 0)
+            {
+                H5Eset_auto(old_func, old_client_data);
+                split_free(names, n);
+                return -2;
+            }
+            // move to next parent
+            status = H5Gclose(parent_id);
+            parent_id = child_id;
+        }
+
+        // return last group
+        group_id = parent_id;
+    }
+    
+    /* Restore previous error handler */
+    H5Eset_auto(old_func, old_client_data);
+
+    return group_id;
+}
+

Added: cs/cigma/branches/cigma-0.9b1/libcigma/h5_io.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/h5_io.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/h5_io.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,23 @@
+#ifndef __CIGMA_H5IO_H__
+#define __CIGMA_H5IO_H__
+
+#include <hdf5.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+hid_t h5_file_create(const char *filename, const char *mode);
+hid_t h5_file_open(const char *filename, const char *mode);
+
+hid_t h5_group_create(hid_t loc_id, const char *name);
+hid_t h5_group_open(hid_t loc_id, const char *name);
+
+hid_t h5_touch_group(hid_t loc_id, const char *name);
+hid_t h5_touch_path(hid_t loc_id, const char *path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CIGMA_H5IO_H__ */

Added: cs/cigma/branches/cigma-0.9b1/libcigma/mesh.c
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/mesh.c	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/mesh.c	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,162 @@
+#include <stdlib.h>
+#include <assert.h>
+#include <hdf5.h>
+#include "h5_io.h"
+#include "mesh.h"
+#include "dataset.h"
+
+
+
+/*
+ * Input :  mesh object, element number e
+ * Output:  dof coordinates -- [ndof x nsd] matrix
+ */
+void mesh_coords(mesh_t *mesh, int e, double *dof_coords)
+{
+    
+    double *coord = mesh->coords;
+    int *conn = mesh->connect;
+    int ndof = mesh->ndof;
+
+    int i,j;
+    for (i = 0; i < ndof; i++)
+    {
+        j = conn[ndof*e + i];
+        dof_coords[3*i + 0] = coord[3*j + 0];
+        dof_coords[3*i + 1] = coord[3*j + 1];
+        dof_coords[3*i + 2] = coord[3*j + 2];
+    }
+}
+
+
+
+int mesh_init_coords(mesh_t *mesh, int nno, int nsd)
+{
+    mesh->nno = nno;
+    mesh->nsd = nsd;
+    mesh->coords = (double *)malloc(nno * nsd * sizeof(double));
+    return 0;
+}
+
+int mesh_init_connect(mesh_t *mesh, int nel, int ndof)
+{
+    mesh->nel  = nel;
+    mesh->ndof = ndof;
+    mesh->connect = (int *)malloc(nel * ndof * sizeof(int));
+    return 0;
+}
+
+int mesh_free(mesh_t *mesh)
+{
+    if (mesh->connect != NULL)
+        free(mesh->connect);
+
+    if (mesh->coords != NULL)
+        free(mesh->coords);
+
+    return 0;
+}
+
+
+
+int mesh_open(mesh_t *mesh,
+              const char *filename,
+              const char *path)
+{
+    hid_t file_id;
+    hid_t model_id;
+    int ierr;
+
+    /* open the file in read-write mode */
+    file_id = h5_file_open(filename, "rw");
+    if (file_id < 0)
+    {
+        return -1;
+    }
+    
+    model_id = H5Gopen(file_id, path);
+    if (model_id < 0)
+    {
+        H5Fclose(file_id);
+        return -2;
+    }
+
+    //
+    // TODO: read attributes in model_id to determine the following paths
+    //
+
+    /* read all coords */
+    ierr = mesh_read_coords(mesh, model_id, "coordinates");
+    if (ierr < 0)
+    {
+        H5Gclose(model_id);
+        H5Fclose(file_id);
+        return -3;
+    }
+    assert(mesh->nsd == 3);
+
+    /* read all elements */
+    ierr = mesh_read_connect(mesh, model_id, "connectivity");
+    if (ierr < 0)
+    {
+        H5Gclose(model_id);
+        H5Fclose(file_id);
+        return -4;
+    }
+
+    H5Gclose(model_id);
+    H5Fclose(file_id);
+    return 0;
+}
+
+int mesh_open2(mesh_t *mesh,
+              const char *filename,
+              const char *coords_path,
+              const char *connect_path)
+{
+    hid_t file_id;
+    int ierr;
+
+    /* open the file in read-write mode */
+    file_id = h5_file_open(filename, "rw");
+    if (file_id < 0)
+    {
+        return -1;
+    }
+    
+    /* read all coords */
+    ierr = mesh_read_coords(mesh, file_id, coords_path);
+    if (ierr < 0)
+    {
+        H5Fclose(file_id);
+        return -2;
+    }
+    assert(mesh->nsd == 3);
+
+    /* read all elements */
+    ierr = mesh_read_connect(mesh, file_id, connect_path);
+    if (ierr < 0)
+    {
+        H5Fclose(file_id);
+        return -3;
+    }
+
+    H5Fclose(file_id);
+    return 0;
+}
+
+
+
+int mesh_read_coords(mesh_t *mesh, hid_t loc_id, const char *coords_path)
+{
+    return dataset_read2(loc_id, coords_path, H5T_NATIVE_DOUBLE,
+                         (void **)&(mesh->coords), &(mesh->nno), &(mesh->nsd));
+}
+
+int mesh_read_connect(mesh_t *mesh, hid_t loc_id, const char *connect_path)
+{
+
+    return dataset_read2(loc_id, connect_path, H5T_NATIVE_INT,
+                         (void **)&(mesh->connect), &(mesh->nel), &(mesh->ndof));
+}
+

Added: cs/cigma/branches/cigma-0.9b1/libcigma/mesh.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/mesh.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/mesh.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,41 @@
+#ifndef __CIGMA_MESH_H__
+#define __CIGMA_MESH_H__
+#include <hdf5.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct {
+    int nno;            // number of nodes
+    int nsd;            // number of spatial dimensions
+    int nel;            // number of elements
+    int ndof;           // number of degrees of freedom per element
+    double *coords;     // node coordinates
+    int *connect;       // element connectivity
+} mesh_t;
+
+
+
+int mesh_init_coords(mesh_t *m, int nno, int nsd);
+int mesh_init_connect(mesh_t *m, int nel, int ndof);
+int mesh_free(mesh_t *m);
+
+
+int mesh_open(mesh_t *m, const char *filename, const char *path);
+int mesh_open2(mesh_t *m, const char *filename, const char *coords_path, const char *connect_path);
+
+
+int mesh_read_coords(mesh_t *m, hid_t loc_id, const char *coords_path);
+int mesh_read_connect(mesh_t *m, hid_t loc_id, const char *connect_path);
+
+
+void mesh_coords(mesh_t *m, int e, double *dof_coords);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __CIGMA_MESH_H__ */

Added: cs/cigma/branches/cigma-0.9b1/libcigma/split.c
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/split.c	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/split.c	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,184 @@
+#include <stdlib.h>
+#include <string.h>
+#include "split.h"
+
+
+/*
+ * Data structure for our basic string tokenizer. Basically, the strategy
+ * is to copy the desired string into our buffer, where we can zero out
+ * the separator characters in-place. Using a struct allows us to avoid
+ * defining global variables like in the version of split.c from the project
+ * http://www.nongnu.org/uri/ on which this code is inspired.
+ *
+ */
+
+typedef struct
+{
+    char **tokens;          // tokens array
+    int token_count;        // real size of tokens array
+    int max_token_count;    // size of tokens array
+
+    char *buffer;           // buffer string
+    int buffer_length;      // length of buffer string
+
+} strtok_t;
+
+
+
+/*
+ * In this section, we define the methods for our string tokenizer
+ * object. Namely, a constructor, a destructor, and then the actual
+ * routine to split the string.
+ * 
+ */
+
+static void strtok_init(strtok_t *st)
+{
+    /* starting up with 0 tokens */
+    st->token_count = 0;
+
+    /* setup the initial array sizes */
+    st->max_token_count = 16;               // 16 tokens in array
+    st->buffer_length = 512;                // 512 chars in buffer
+
+    /* allocate enough tokens and initialize buffer */
+    st->buffer = (char *)malloc(st->buffer_length * sizeof(char));
+    st->tokens = (char **)malloc(st->max_token_count * sizeof(char *));
+}
+
+static void strtok_free(strtok_t *st)
+{
+    if (st != NULL)
+    {
+        free(st->buffer);
+        free(st->tokens);
+    }
+}
+
+static void strtok_split(strtok_t *st, const char *s, int len, char separator)
+{
+    /* 
+     * First, check whether our buffer is large enough to manipulate
+     * the string s, and if not, reallocate enough memory.
+     */
+    if (st->buffer_length < len)
+    {
+        st->buffer_length = (len < 512) ? 512 : len+1;
+        st->buffer = (char *)realloc(st->buffer, st->buffer_length * sizeof(char));
+    }
+
+    /*
+     * Next, copy the string s into our buffer and tokenize it in-place.
+     * Essentially, zero out the locations where we find the separator
+     * character, while remembering the beginning of each string.
+     */
+    memcpy(st->buffer, s, len);
+    st->buffer[len] = '\0';
+    {
+
+        char *first, *p;
+        int index, last;
+
+        first = st->buffer;
+        last  = st->buffer_length - 1;
+
+        /* remove trailing separators */
+        while (last >= 0 && st->buffer[last] == separator)
+        {
+            st->buffer[last] = '\0';
+            last--;
+        }
+
+        /* remove leading separators */
+        while (*first == separator)
+        {
+            first++;
+        }
+        
+        /* store first token */
+        index = 0;
+        st->tokens[index++] = first;
+        
+        /* keep tokenizing the buffer */
+        for (p = strchr(first, separator);
+             p != NULL;
+             p = strchr(p, separator))
+        {
+            /* separator found -- zero it out */
+            *p = '\0';
+
+            /* make p point to next char */
+            p++;
+
+            /* store the next token */
+            if ((*p != separator) && (*p != '\0'))
+            {
+                st->tokens[index++] = p;
+
+                /* check whether we need to expand our tokens array,
+                 * to make room for the next batch of tokens
+                 */
+                if (index >= (st->max_token_count))
+                {
+                    st->max_token_count += 16;
+                    st->tokens = (char **)realloc(st->tokens,
+                                                  st->max_token_count
+                                                  * sizeof(char *));
+                }
+            }
+        }
+
+        /* store the final count */
+        st->token_count = index;
+    }
+
+    return;
+}
+
+
+
+/*
+ * Finally, we provide a procedural interface to our string tokenizer.
+ * The caller subsumes the responsibility of freeing the newly allocated
+ * list, as well as each individual string in that list.
+ */
+void split(const char *str, int len,
+           char ***split_list, int *split_count,
+           char sep)
+{
+    int i;
+    strtok_t tok;
+
+    if (sep == '\0')
+    {
+        *split_list = NULL;
+        *split_count = 0;
+        return;
+    }
+
+    strtok_init(&tok);
+    strtok_split(&tok, str, len, sep);
+
+    *split_list  = (char **)malloc(tok.token_count * sizeof(char *));
+    *split_count = tok.token_count;
+
+    for (i = 0; i < tok.token_count; i++)
+    {
+        (*split_list)[i] = strdup(tok.tokens[i]);
+    }
+
+    strtok_free(&tok);
+}
+
+void split_free(char **split_list, int split_count)
+{
+    int i;
+    if (split_list != NULL)
+    {
+        for (i = 0; i < split_count; i++)
+        {
+            free(split_list[i]);
+        }
+        free(split_list);
+    }
+}

Added: cs/cigma/branches/cigma-0.9b1/libcigma/split.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/libcigma/split.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/libcigma/split.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,16 @@
+#ifndef __UTIL_SPLIT_H__
+#define __UTIL_SPLIT_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void split(const char *str, int len,
+           char ***split_list, int *split_count,
+           char sep);
+
+void split_free(char **split_list, int split_count);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

Added: cs/cigma/branches/cigma-0.9b1/src/cigma-compare.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/src/cigma-compare.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/src/cigma-compare.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,308 @@
+#include <stdio.h>
+#include <iostream>
+#include <vector>
+#include "anyoption.h"
+#include "../libcigma/dataset.h"
+#include "HDF5_Reader.hpp"
+#include "Indexed_tetra_set.hpp"
+#include "Time_series.hpp"
+#include "StringUtils.hpp"
+#include "kdtree_tetrahedra.hpp"
+#include "vect_stats.hpp"
+#include "tet_sampling.hpp"
+#include "Writers.hpp"
+
+using namespace gtb;
+using namespace std;
+
+int compare_main(char *first, char *second, char *output);
+
+void compare_scalar_fields(Indexed_tetra_set *its1,
+                           Indexed_tetra_set *its2,
+                           Scalar_time_series *sts1,
+                           Scalar_time_series *sts2,
+                           std::vector<float> &residuals);
+
+void compare_vector_fields(Indexed_tetra_set *its1,
+                           Indexed_tetra_set *its2,
+                           Vector_time_series *vts1,
+                           Vector_time_series *vts2,
+                           std::vector<float> &residuals);
+
+
+
+void print_usage(void)
+{
+    cerr << "Usage: cigma-compare --first=field.h5:/model/variables/displacement/step0" << endl
+         << "                     --second=field2.h5:/model/variables/displacement/step0" << endl
+         << "                     --output=residuals.vtk" << endl;
+}
+
+void print_mesh_info(Indexed_tetra_set *its)
+{
+    printf("num tetrahedra: %d\n", its->get_num_tetrahedra());
+}
+
+
+
+int main(int argc, char **argv)
+{
+    AnyOption *opt = new AnyOption();
+
+    opt->setFlag("help", 'h');
+    opt->setOption("first");
+    opt->setOption("second");
+    opt->setOption("output", 'o');
+
+    opt->processCommandArgs(argc, argv);
+
+    if (!opt->hasOptions())
+    {
+        print_usage();
+        delete opt;
+        return 0;
+    }
+
+    if (opt->getFlag("help") || opt->getFlag('h'))
+    {
+        print_usage();
+        delete opt;
+        return 0;
+    }
+
+    if (opt->getValue("first") != NULL)
+    {
+        cout << "first  = \"" << opt->getValue("first") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify the first field with --first" << endl;
+        delete opt;
+        return -1;
+    }
+
+
+    if (opt->getValue("second") != NULL)
+    {
+        cout << "second = \"" << opt->getValue("second") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify the second field with --second" << endl;
+        delete opt;
+        return -2;
+    }
+
+    if (opt->getValue("output") != NULL)
+    {
+        cout << "output = \"" << opt->getValue("output") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify an output vtk file with --output" << endl;
+        delete opt;
+        return -3;
+    }
+
+    char *first  = opt->getValue("first");
+    char *second = opt->getValue("second");
+    char *output = opt->getValue("output");
+    int exitcode;
+
+    exitcode = compare_main(first, second, output);
+
+    delete opt;
+    return exitcode;
+}
+
+
+
+int compare_main(char *first, char *second, char *output)
+{
+    HDF5_Reader reader;
+    Indexed_tetra_set *its1, *its2;
+    Scalar_time_series *sts1, *sts2;
+    Vector_time_series *vts1, *vts2;
+
+    std::vector<string> path1, path2;
+
+    SplitString(first, ":", path1, false);
+    if (path1.size() != 2)
+    {
+        cerr << "Error: Please specify an argument of the form "
+             << "--first 'file1.h5:/path/to/field'" << endl;
+        return -1;
+    }
+
+    SplitString(second, ":", path2, false);
+    if (path2.size() != 2)
+    {
+        cerr << "Error: Please specify an argument of the form "
+             << "--second 'file2.h5:/path/to/field'" << endl;
+        return -2;
+    }
+
+    const char *firstfile = path1[0].c_str();
+    const char *first_loc = path1[1].c_str();
+
+    const char *secondfile = path2[0].c_str();
+    const char *second_loc = path2[1].c_str();
+
+    reader.get_time_series(firstfile, first_loc, &sts1, &vts1, &its1);
+    print_mesh_info(its1);
+
+    reader.get_time_series(secondfile, second_loc, &sts2, &vts2, &its2);
+    print_mesh_info(its2);
+    
+    if (((sts1 != NULL) && (vts2 != NULL)) ||
+        ((sts2 != NULL) && (vts1 != NULL)))
+    {
+        cerr << "Error: Incompatible fields: "
+             << "Cannot compare scalar and vector fields "
+             << endl;
+        return -3;
+    }
+
+    std::vector<float> residuals;
+    int nel = its1->get_num_tetrahedra();
+
+    residuals.resize(nel);
+
+    if ((sts1 != NULL) && (sts2 != NULL))
+    {
+        compare_scalar_fields(its1, its2, sts1, sts2, residuals);
+    }
+    else if ((vts1 != NULL) && (vts2 != NULL))
+    {
+        compare_vector_fields(its1, its2, vts1, vts2, residuals);
+    }
+    else 
+    {
+        return -4;
+    }
+
+    residuals_write_vtk(output,
+                        its1->get_vertices(),
+                        its1->get_tetrahedra(),
+                        residuals);
+    
+    return 0;
+}
+
+
+void compare_scalar_fields(Indexed_tetra_set *its1,
+                           Indexed_tetra_set *its2,
+                           Scalar_time_series *sts1,
+                           Scalar_time_series *sts2,
+                           std::vector<float> &residuals)
+{
+    printf("Not supported yet!");
+}
+
+void compare_vector_fields(Indexed_tetra_set *its1,
+                           Indexed_tetra_set *its2,
+                           Vector_time_series *vts1,
+                           Vector_time_series *vts2,
+                           std::vector<float> &residuals)
+{
+    float max_tet_per_leaf = 1000;
+    unsigned num_samples_per_tet = 1;
+
+    printf("\n%s\n", "Building kdtree...");
+
+    KDTet<unsigned> tree(max_tet_per_leaf, its2, vts2);
+    tree.MakeTree();
+
+    printf("%s\r", "Sampling inside the elements...");
+
+    const std::vector<Point_3f> &vertices = its1->get_vertices();
+    const std::vector<Tetrahedron> &tets = its1->get_tetrahedra();
+
+    unsigned num_eval_misses = 0;
+    std::vector<float> err(num_samples_per_tet);
+
+    std::vector<float> errors;
+
+    err.resize(num_samples_per_tet);
+
+    for (unsigned ti = 0; ti < tets.size(); ti++)
+    {
+        const Tetrahedron &t = tets[ti];
+        Vector_3f v0(vertices[t.get_vertex(0)]);
+        Vector_3f v1(vertices[t.get_vertex(1)]);
+        Vector_3f v2(vertices[t.get_vertex(2)]);
+        Vector_3f v3(vertices[t.get_vertex(3)]);
+
+        for (unsigned i = 0; i < num_samples_per_tet; i++)
+        {
+            Vector_3f pick = Pick(v0, v1, v2, v3);
+            Point_3f sf(pick[0], pick[1], pick[2]);
+            Point_3d sd(sf[0], sf[1], sf[2]);
+
+            KDTet<unsigned>::TreeNode *parent;
+            KDTet<unsigned>::LeafNode *node = tree.Find(sd, parent);
+
+            Vector_3f val2;
+            if (!tree.FindAndEvalTet(node, sf, &val2))
+            {
+                num_eval_misses++;
+                continue;
+            }
+
+            Vector_3f val1;
+            if (!its1->interpol_tetra(vts1, t, sf, &val1))
+            {
+                num_eval_misses++;
+                continue;
+            }
+
+            Vector_3f point_residual = val1 - val2;
+            err[i] = point_residual.squared_length();
+            errors.push_back(err[i]);
+        }
+        residuals[ti] = vect_mean(err);
+
+        if (ti % 1000 == 0)
+        {
+            printf("\r%s %.0f%%",
+                   "Sampling inside the elements...",
+                   (float)ti/tets.size() * 100);
+            fflush(stdout);
+        }
+    }
+
+    printf("\r%s             \n",
+           "Sampling inside the elements...");
+
+
+    //printf("tets.size() = %d\n", tets.size());
+    //printf("residuals.size() = %d\n", residuals.size());
+
+    printf("\nSampling:\n");
+    printf("num samples per tet: \t%d\n", num_samples_per_tet);
+    printf("total num samples  : \t%d\n", (int)errors.size());
+    printf("ignored samples    : \t%d (%f%%)\n", num_eval_misses,
+                                                 (float)num_eval_misses*100/vertices.size());
+
+    float max_err = vect_max(errors);
+    float mean_err = vect_mean(errors);
+    float std_dev = vect_std_dev(errors, mean_err);
+    float rms_err = sqrt(vect_mean_squared(errors));
+
+    printf("\nField Errors:\n");
+    printf("max:             \t%e\n", max_err);
+    printf("mean:            \t%e\n", mean_err);
+    printf("std dev:         \t%e\n", std_dev);
+    printf("rms:             \t%e\n", rms_err);
+
+    float max_res = vect_max(residuals);
+    float mean_res = vect_mean(residuals);
+    float std_res = vect_std_dev(residuals, mean_res);
+    float rms_res = sqrt(vect_mean_squared(residuals));
+    printf("\nResiduals:\n");
+    printf("max:             \t%e\n", max_res);
+    printf("mean:            \t%e\n", mean_res);
+    printf("std dev:         \t%e\n", std_res);
+    printf("rms:             \t%e\n", rms_res);
+
+}

Added: cs/cigma/branches/cigma-0.9b1/src/cigma-eval.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/src/cigma-eval.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/src/cigma-eval.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,74 @@
+#include <iostream>
+#include "anyoption.h"
+
+using namespace std;
+
+void print_usage(void)
+{
+    cerr << "Usage: cigma-compare --field=field.h5:/model/variables/displacement/step0" << endl
+         << "                     --points=points.h5" << endl
+         << "                     --output=values.h5" << endl;
+}
+
+int main(int argc, char **argv)
+{
+    AnyOption *opt = new AnyOption();
+
+    opt->setFlag("help", 'h');
+    opt->setOption("field",'f');
+    opt->setOption("points",'p');
+    opt->setOption("output", 'o');
+
+    opt->processCommandArgs(argc, argv);
+
+    if (!opt->hasOptions())
+    {
+        print_usage();
+        delete opt;
+        return 0;
+    }
+
+    if (opt->getFlag("help") || opt->getFlag('h'))
+    {
+        print_usage();
+        delete opt;
+        return 0;
+    }
+
+    if (opt->getValue("field") != NULL)
+    {
+        cout << "field = \"" << opt->getValue("first") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify a field with --field" << endl;
+        delete opt;
+        return -1;
+    }
+
+
+    if (opt->getValue("points") != NULL)
+    {
+        cout << "points = \"" << opt->getValue("points") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify points with --points" << endl;
+        delete opt;
+        return -2;
+    }
+
+    if (opt->getValue("output") != NULL)
+    {
+        cout << "output = \"" << opt->getValue("output") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify output file with --output" << endl;
+        delete opt;
+        return -3;
+    }
+
+    delete opt;
+    return 0;
+}

Added: cs/cigma/branches/cigma-0.9b1/src/cigma-extract.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/src/cigma-extract.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/src/cigma-extract.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,80 @@
+#include <iostream>
+#include "anyoption.h"
+
+using namespace std;
+
+
+void print_usage(void)
+{
+    cerr << "Usage: cigma-extract --rule=qr.h5:/FIAT/cools/tet_4" << endl
+         << "                     --mesh=meshes.h5:/model/mesh" << endl
+         << "                     --output=points.h5" << endl;
+}
+
+
+
+int main(int argc, char **argv)
+{
+    AnyOption *opt = new AnyOption();
+
+    opt->setFlag("help", 'h');
+    opt->setOption("rule", 'r');
+    opt->setOption("mesh", 'm');
+    opt->setOption("output", 'o');
+
+    opt->processCommandArgs(argc, argv);
+
+    if (!opt->hasOptions())
+    {
+        print_usage();
+        delete opt;
+        return 0;
+    }
+
+    if (opt->getFlag("help") || opt->getFlag('h'))
+    {
+        print_usage();
+        delete opt;
+        return 0;
+    }
+
+    if (opt->getValue("rule") != NULL)
+    {
+        cout << "rule = \"" << opt->getValue("rule") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify a quadrature rule with --rule" << endl;
+        delete opt;
+        return -1;
+    }
+
+
+    if (opt->getValue("mesh") != NULL)
+    {
+        cout << "mesh = \"" << opt->getValue("mesh") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify an input mesh with --mesh" << endl;
+        delete opt;
+        return -2;
+    }
+
+    if (opt->getValue("output") != NULL)
+    {
+        cout << "output = \"" << opt->getValue("output") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify an output file with --output" << endl;
+        delete opt;
+        return -3;
+    }
+
+
+    delete opt;
+    return 0;
+}
+
+

Added: cs/cigma/branches/cigma-0.9b1/src/cigma-import.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/src/cigma-import.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/src/cigma-import.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,80 @@
+#include <iostream>
+#include "anyoption.h"
+
+using namespace std;
+
+
+void print_usage(void)
+{
+    cerr << "Usage: cigma-extract --rule=qr.h5:/FIAT/cools/tet_4" << endl
+         << "                     --mesh=meshes.h5:/model/mesh" << endl
+         << "                     --output=points.h5" << endl;
+}
+
+
+
+int main(int argc, char **argv)
+{
+    AnyOption *opt = new AnyOption();
+
+    opt->setFlag("help", 'h');
+    opt->setOption("rule", 'r');
+    opt->setOption("mesh", 'm');
+    opt->setOption("output", 'o');
+
+    opt->processCommandArgs(argc, argv);
+
+    if (!opt->hasOptions())
+    {
+        print_usage();
+        delete opt;
+        return 0;
+    }
+
+    if (opt->getFlag("help") || opt->getFlag('h'))
+    {
+        print_usage();
+        delete opt;
+        return 0;
+    }
+
+    if (opt->getValue("rule") != NULL)
+    {
+        cout << "rule = \"" << opt->getValue("rule") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify a quadrature rule with --rule" << endl;
+        delete opt;
+        return -1;
+    }
+
+
+    if (opt->getValue("mesh") != NULL)
+    {
+        cout << "mesh = \"" << opt->getValue("mesh") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify an input mesh with --mesh" << endl;
+        delete opt;
+        return -2;
+    }
+
+    if (opt->getValue("output") != NULL)
+    {
+        cout << "output = \"" << opt->getValue("output") << "\"" << endl;
+    }
+    else
+    {
+        cout << "Error: Please specify an output file with --output" << endl;
+        delete opt;
+        return -3;
+    }
+
+
+    delete opt;
+    return 0;
+}
+
+

Added: cs/cigma/branches/cigma-0.9b1/src/cigma-okada.cpp
===================================================================

Added: cs/cigma/branches/cigma-0.9b1/tmc/Bounding_box_3d.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Bounding_box_3d.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Bounding_box_3d.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,297 @@
+#ifndef GTB_BOUNDING_BOX_3D_INCLUDED
+#include "Bounding_box_3d.hpp"
+#endif
+
+#ifndef GTB_MATH_UTIL_INCLUDED
+#include "math_util.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+Bounding_box_3d::Relative_position Bounding_box_3d::
+relative_position_of(const Bounding_box_3d &b) const
+{
+	if ((m_max_point[0] < b.m_min_point[0]) ||
+	    (m_min_point[0] > b.m_max_point[0]) ||
+	    (m_max_point[1] < b.m_min_point[1]) ||
+	    (m_min_point[1] > b.m_max_point[1]) ||
+	    (m_max_point[2] < b.m_min_point[2]) ||
+	    (m_min_point[2] > b.m_max_point[2])) {
+		return OUTSIDE;
+	}
+
+	if ((m_min_point[0] <= b.m_min_point[0]) &&
+	    (m_max_point[0] >= b.m_max_point[0]) &&
+	    (m_min_point[1] <= b.m_min_point[1]) &&
+	    (m_max_point[1] >= b.m_max_point[1]) &&
+	    (m_min_point[2] <= b.m_min_point[2]) &&
+	    (m_max_point[2] >= b.m_max_point[2])) {
+		return INSIDE;
+        }
+
+	return INTERSECTING;
+}
+
+
+// void Bounding_box_3d::render_solid() const
+// {
+// 	glBegin(GL_QUADS);
+
+// 	// back
+// 	glNormal3d(0.0, 0.0, -1.0);
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_min_point[2]);
+
+// 	// front
+// 	glNormal3d(0.0, 0.0, 1.0);
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_max_point[2]);
+
+// 	// left
+// 	glNormal3d(-1.0, 0.0, 0.0);
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_min_point[2]);
+
+// 	// right
+// 	glNormal3d(1.0, 0.0, 0.0);
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_max_point[2]);
+
+// 	// top
+// 	glNormal3d(0.0, 1.0, 0.0);
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_min_point[2]);
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_min_point[2]);
+
+// 	// bottom
+// 	glNormal3d(0.0, -1.0, 0.0);
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_max_point[2]);
+
+// 	glEnd();
+// }
+
+
+// void Bounding_box_3d::render_solid_no_normals() const
+// {
+// 	glBegin(GL_QUADS);
+
+// 	// back
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_min_point[2]);
+
+// 	// front
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_max_point[2]);
+
+// 	// left
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_min_point[2]);
+
+// 	// right
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_max_point[2]);
+
+// 	// top
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_min_point[2]);
+// 	glVertex3d(m_min_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3d(m_max_point[0], m_max_point[1], m_min_point[2]);
+
+// 	// bottom
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3d(m_max_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3d(m_min_point[0], m_min_point[1], m_max_point[2]);
+
+// 	glEnd();
+// }
+
+
+// void Bounding_box_3d::outline() const
+// {
+// 	glPushAttrib(GL_ENABLE_BIT);
+// 	glDisable(GL_LIGHTING);
+
+// 	glBegin(GL_LINE_LOOP);
+// 	glVertex3f(m_min_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3f(m_max_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3f(m_max_point[0], m_max_point[1], m_min_point[2]);
+// 	glVertex3f(m_min_point[0], m_max_point[1], m_min_point[2]);
+// 	glEnd();
+
+// 	glBegin(GL_LINE_LOOP);
+// 	glVertex3f(m_min_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3f(m_max_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3f(m_max_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3f(m_min_point[0], m_max_point[1], m_max_point[2]);
+// 	glEnd();
+
+// 	glBegin(GL_LINES);
+// 	glVertex3f(m_min_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3f(m_min_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3f(m_max_point[0], m_min_point[1], m_min_point[2]);
+// 	glVertex3f(m_max_point[0], m_min_point[1], m_max_point[2]);
+// 	glVertex3f(m_max_point[0], m_max_point[1], m_min_point[2]);
+// 	glVertex3f(m_max_point[0], m_max_point[1], m_max_point[2]);
+// 	glVertex3f(m_min_point[0], m_max_point[1], m_min_point[2]);
+// 	glVertex3f(m_min_point[0], m_max_point[1], m_max_point[2]);
+// 	glEnd();
+
+// 	glPopAttrib();
+// }
+
+
+void Bounding_box_3d::print(FILE *fp) const
+{
+	const Point_3d &p1 = m_min_point;
+	const Point_3d &p2 = m_max_point;
+	fprintf(fp, "(%f, %f, %f) (%f %f %f)\n",
+		p1[0], p1[1], p1[2], p2[0], p2[1], p2[2]);
+}
+
+
+Point_3d Bounding_box_3d::random_point() const
+{
+	Vector_3d v((drand() - 0.5) * x_length(),
+		    (drand() - 0.5) * y_length(),
+		    (drand() - 0.5) * z_length());
+	return centroid() + v;
+}
+
+
+double Bounding_box_3d::distance(const Point_3d &p) const
+{
+	Vector_3d dl = m_min_point - p;
+	Vector_3d dr = p - m_max_point;
+	for (unsigned i = 0; i < 3; ++i) {
+		if (dl[i] < 0) {
+			dl[i] = 0;
+		}
+		if (dr[i] < 0) {
+			dr[i] = 0;
+		}
+	}
+	Vector_3d diff = dl + dr;
+	double d = diff.length();
+	return d;
+}
+
+
+Bounding_box_3d Bounding_box_3d::smallest_cube_containing(
+	const Bounding_box_3d &b)
+{
+	Point_3d c = b.centroid();
+	double len = 0.5 * b.longest_axis_length();
+	Vector_3d v(1.0, 1.0, 1.0);
+	Point_3d p_min = c - len * v;
+	Point_3d p_max = c + len * v;
+	return Bounding_box_3d(p_min, p_max);
+}
+
+
+// bool Bounding_box_3d::is_visible() const
+// {
+
+// /* Copyright (c) Hewlett Packard Company, 1997. */
+
+// /* This program is freely distributable without licensing fees and is
+//    provided without guarantee or warrantee expressed or implied. This
+//    program is -not- in the public domain. */
+
+// #define GL_OCCLUSION_TEST_HP			0x8165
+// #define GL_OCCLUSION_RESULT_HP			0x8166
+// #define GL_OCCLUSION_TEST_HP_OLD		0x816E
+// #define GL_OCCLUSION_RESULT_HP_OLD		0x816F
+
+// 	GLfloat x1 = m_min_point[0];
+// 	GLfloat y1 = m_min_point[1];
+// 	GLfloat z1 = m_min_point[2];
+
+// 	GLfloat x2 = m_max_point[0];
+// 	GLfloat y2 = m_max_point[1];
+// 	GLfloat z2 = m_max_point[2];
+
+// 	GLboolean result = false;
+
+// 	// enable HP test
+// //	glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
+// //	glDisable(GL_LIGHTING);
+// 	glDisable(GL_STENCIL_TEST);
+// 	glEnable(GL_OCCLUSION_TEST_HP);
+// 	glDepthMask(GL_FALSE);
+// 	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+// 	// perform HP tests
+
+
+// 	glBegin(GL_QUADS);
+
+// 	/* Front */
+// 	glVertex3f(x1, y1, z1);
+// 	glVertex3f(x1, y2, z1);
+// 	glVertex3f(x2, y2, z1);
+// 	glVertex3f(x2, y1, z1);
+
+// 	/* Right */
+// 	glVertex3f(x2, y2, z1);
+// 	glVertex3f(x2, y1, z1);
+// 	glVertex3f(x2, y1, z2);
+// 	glVertex3f(x2, y2, z2);
+
+// 	/* Back */
+// 	glVertex3f(x2, y2, z2);
+// 	glVertex3f(x2, y1, z2);
+// 	glVertex3f(x1, y1, z2);
+// 	glVertex3f(x1, y2, z2);
+
+// 	/* Left */
+// 	glVertex3f(x1, y2, z2);
+// 	glVertex3f(x1, y1, z2);
+// 	glVertex3f(x1, y1, z1);
+// 	glVertex3f(x1, y2, z1);
+
+// 	/* Top */
+// 	glVertex3f(x2, y2, z1);
+// 	glVertex3f(x2, y2, z2);
+// 	glVertex3f(x1, y2, z2);
+// 	glVertex3f(x1, y2, z1);
+
+// 	/* Bottom */
+// 	glVertex3f(x2, y1, z1);
+// 	glVertex3f(x2, y1, z2);
+// 	glVertex3f(x1, y1, z2);
+// 	glVertex3f(x1, y1, z1);
+// 	glEnd();
+
+
+// 	// disable HP test
+// 	glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP, &result);
+// 	glDisable(GL_OCCLUSION_TEST_HP);
+// 	glDepthMask(GL_TRUE);
+// 	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+// //	glPopAttrib();
+// 	return (result == GL_TRUE);
+// }
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Bounding_box_3d.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Bounding_box_3d.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Bounding_box_3d.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,645 @@
+#ifndef GTB_BOUNDING_BOX_3D_INCLUDED
+#define GTB_BOUNDING_BOX_3D_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_POINT_3F_INCLUDED
+#include "Point_3f.hpp"
+#endif
+
+#ifndef GTB_POINT_3D_INCLUDED
+#include "Point_3d.hpp"
+#endif
+
+#ifndef GTB_C_STDIO_INCLUDED
+#include <stdio.h>
+#define GTB_C_STDIO_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+class Bounding_box_3d {
+public:
+	// initialize to empty box
+	Bounding_box_3d();
+
+	// initialize explicitly
+	Bounding_box_3d(double min_x, double min_y, double min_z,
+			double max_x, double max_y, double max_z);
+
+	// create given 2 points
+	Bounding_box_3d(const Point_3d &a, const Point_3d &b);
+	Bounding_box_3d(const Point_3f &a, const Point_3f &b);
+
+	// create given 3 points
+	Bounding_box_3d(const Point_3d &a,
+			const Point_3d &b,
+			const Point_3d &c);
+
+	Bounding_box_3d(const Point_3f &a,
+			const Point_3f &b,
+			const Point_3f &c);
+
+	// create given 4 points
+	Bounding_box_3d(const Point_3d &a,
+			const Point_3d &b,
+			const Point_3d &c,
+			const Point_3d &d);
+
+	Bounding_box_3d(const Point_3f &a,
+			const Point_3f &b,
+			const Point_3f &c,
+			const Point_3f &d);
+
+	// create given C array of points
+	Bounding_box_3d(const Point_3d v[], unsigned point_count);
+	Bounding_box_3d(const Point_3f v[], unsigned point_count);
+
+	// create given std::vector of points
+	Bounding_box_3d(const std::vector<Point_3d> &v);
+	Bounding_box_3d(const std::vector<Point_3f> &v);
+
+	// create given centroid and axes lengths
+	Bounding_box_3d(const Point_3d &centroid,
+			double x_length,
+			double y_length, 
+			double z_length);
+
+	// make union
+	Bounding_box_3d(const Bounding_box_3d &b1, const Bounding_box_3d &b2);
+
+	// copy
+	Bounding_box_3d(const Bounding_box_3d &b);
+	Bounding_box_3d &operator=(const Bounding_box_3d &b);
+
+	// query
+	bool eps_is_equal(const Bounding_box_3d &b, double eps) const;
+	bool eps_is_empty(double eps) const;
+
+	// get
+	const Point_3d &get_min_point() const;
+	const Point_3d &get_max_point() const;
+	double get_min_x() const;
+	double get_min_y() const;
+	double get_min_z() const;
+	double get_max_x() const;
+	double get_max_y() const;
+	double get_max_z() const;
+
+	// set
+	Bounding_box_3d &set_min_point(const Point_3d &min_point);
+	Bounding_box_3d &set_max_point(const Point_3d &max_point);
+	Bounding_box_3d &reset(const Point_3d &min_point,
+			       const Point_3d &max_point);
+	Bounding_box_3d &reset(double min_x, double min_y, double min_z,
+			       double max_x, double max_y, double max_z);
+	Bounding_box_3d &set_min_x(double min_x);
+	Bounding_box_3d &set_min_y(double min_y);
+	Bounding_box_3d &set_min_z(double min_z);
+	Bounding_box_3d &set_max_x(double max_x);
+	Bounding_box_3d &set_max_y(double max_y);
+	Bounding_box_3d &set_max_z(double max_z);
+
+	void set_min(int axis, double value);
+	void set_max(int axis, double value);
+	void scale(double s);
+
+	// compute
+	Point_3d centroid() const;
+	double x_length() const;
+	double y_length() const;
+	double z_length() const;
+	double diagonal_squared_length() const;
+	double diagonal_length() const;
+	double shortest_axis_length() const;
+	double longest_axis_length() const;
+	double volume() const;
+	bool contains(const Point_3d &p) const;
+	bool contains(const Point_3f &p) const;
+	Point_3d random_point() const;
+	double distance(const Point_3d &p) const;
+	Bounding_box_3d smallest_cube_containing(const Bounding_box_3d &b);
+	bool is_visible() const;
+
+	enum Relative_position { INSIDE, INTERSECTING, OUTSIDE };
+	Relative_position relative_position_of(const Bounding_box_3d &b) const;
+
+	// render
+	void render_solid() const;
+	void render_solid_no_normals() const;
+	void outline() const;
+
+	void print(FILE *fp) const;
+
+protected:
+	bool is_order_correct(double eps) const;
+
+	Point_3d m_min_point;
+	Point_3d m_max_point;
+};
+
+
+inline bool Bounding_box_3d::is_order_correct(double eps) const
+{
+	return (gtb::eps_is_less_or_equal(m_min_point[0],
+					  m_max_point[0],
+					  eps)
+		&& gtb::eps_is_less_or_equal(m_min_point[1],
+					     m_max_point[1],
+					     eps)
+		&& gtb::eps_is_less_or_equal(m_min_point[2],
+					     m_max_point[2],
+					     eps));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d()
+	: m_min_point(FLT_MAX, FLT_MAX, FLT_MAX),
+	  m_max_point(-FLT_MAX, -FLT_MAX, -FLT_MAX)
+{
+	GTB_CHECK(eps_is_empty(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(
+	double min_x, double min_y, double min_z,
+	double max_x, double max_y, double max_z)
+	: m_min_point(min_x, min_y, min_z),
+	  m_max_point(max_x, max_y, max_z)
+{
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const Point_3d &a, const Point_3d &b)
+	: m_min_point(MIN(a[0], b[0]),
+		      MIN(a[1], b[1]),
+		      MIN(a[2], b[2])),
+
+	  m_max_point(MAX(a[0], b[0]),
+		      MAX(a[1], b[1]),
+		      MAX(a[2], b[2]))
+{
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const Point_3f &a, const Point_3f &b)
+	: m_min_point(MIN(a[0], b[0]),
+		      MIN(a[1], b[1]),
+		      MIN(a[2], b[2])),
+
+	  m_max_point(MAX(a[0], b[0]),
+		      MAX(a[1], b[1]),
+		      MAX(a[2], b[2]))
+{
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const Point_3d &a,
+					const Point_3d &b,
+					const Point_3d &c)
+	: m_min_point(MIN(MIN(a[0], b[0]), c[0]),
+		      MIN(MIN(a[1], b[1]), c[1]),
+		      MIN(MIN(a[2], b[2]), c[2])),
+
+	  m_max_point(MAX(MAX(a[0], b[0]), c[0]),
+		      MAX(MAX(a[1], b[1]), c[1]),
+		      MAX(MAX(a[2], b[2]), c[2]))
+{
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const Point_3f &a,
+					const Point_3f &b,
+					const Point_3f &c)
+	: m_min_point(MIN(MIN(a[0], b[0]), c[0]),
+		      MIN(MIN(a[1], b[1]), c[1]),
+		      MIN(MIN(a[2], b[2]), c[2])),
+
+	  m_max_point(MAX(MAX(a[0], b[0]), c[0]),
+		      MAX(MAX(a[1], b[1]), c[1]),
+		      MAX(MAX(a[2], b[2]), c[2]))
+{
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const Point_3d &a,
+					const Point_3d &b,
+					const Point_3d &c,
+					const Point_3d &d)
+	: m_min_point(MIN(MIN(MIN(a[0], b[0]), c[0]), d[0]),
+		      MIN(MIN(MIN(a[1], b[1]), c[1]), d[1]),
+		      MIN(MIN(MIN(a[2], b[2]), c[2]), d[2])),
+
+	  m_max_point(MAX(MAX(MAX(a[0], b[0]), c[0]), d[0]),
+		      MAX(MAX(MAX(a[1], b[1]), c[1]), d[1]),
+		      MAX(MAX(MAX(a[2], b[2]), c[2]), d[2]))
+{
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const Point_3f &a,
+					const Point_3f &b,
+					const Point_3f &c,
+					const Point_3f &d)
+	: m_min_point(MIN(MIN(MIN(a[0], b[0]), c[0]), d[0]),
+		      MIN(MIN(MIN(a[1], b[1]), c[1]), d[1]),
+		      MIN(MIN(MIN(a[2], b[2]), c[2]), d[2])),
+
+	  m_max_point(MAX(MAX(MAX(a[0], b[0]), c[0]), d[0]),
+		      MAX(MAX(MAX(a[1], b[1]), c[1]), d[1]),
+		      MAX(MAX(MAX(a[2], b[2]), c[2]), d[2]))
+{
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const Point_3d v[],
+					unsigned point_count)
+{
+	GTB_REQUIRE(point_count > 0);
+	m_min_point = v[0];
+	m_max_point = v[0];
+	for (unsigned i = 1; i < point_count; i++) {
+		const Point_3d &p = v[i];
+
+		m_min_point.set_x(MIN(m_min_point[0], p[0]));
+		m_min_point.set_y(MIN(m_min_point[1], p[1]));
+		m_min_point.set_z(MIN(m_min_point[2], p[2]));
+
+		m_max_point.set_x(MAX(m_max_point[0], p[0]));
+		m_max_point.set_y(MAX(m_max_point[1], p[1]));
+		m_max_point.set_z(MAX(m_max_point[2], p[2]));
+	}
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const Point_3f v[],
+					unsigned point_count)
+{
+	GTB_REQUIRE(point_count > 0);
+	m_min_point.reset(v[0][0], v[0][1], v[0][2]);
+	m_max_point.reset(v[0][0], v[0][1], v[0][2]);
+	for (unsigned i = 1; i < point_count; i++) {
+		const Point_3f &p = v[i];
+
+		m_min_point.set_x(MIN(m_min_point[0], (double) p[0]));
+		m_min_point.set_y(MIN(m_min_point[1], (double) p[1]));
+		m_min_point.set_z(MIN(m_min_point[2], (double) p[2]));
+
+		m_max_point.set_x(MAX(m_max_point[0], (double) p[0]));
+		m_max_point.set_y(MAX(m_max_point[1], (double) p[1]));
+		m_max_point.set_z(MAX(m_max_point[2], (double) p[2]));
+	}
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const std::vector<Point_3d> &v)
+{
+	GTB_REQUIRE(v.size() > 0);
+	m_min_point = v[0];
+	m_max_point = v[0];
+	for (unsigned i = 1; i < v.size(); i++) {
+		const Point_3d &p = v[i];
+
+		m_min_point.set_x(MIN(m_min_point[0], p[0]));
+		m_min_point.set_y(MIN(m_min_point[1], p[1]));
+		m_min_point.set_z(MIN(m_min_point[2], p[2]));
+
+		m_max_point.set_x(MAX(m_max_point[0], p[0]));
+		m_max_point.set_y(MAX(m_max_point[1], p[1]));
+		m_max_point.set_z(MAX(m_max_point[2], p[2]));
+	}
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const std::vector<Point_3f> &v)
+{
+	GTB_REQUIRE(v.size() > 0);
+	m_min_point.reset(v[0][0], v[0][1], v[0][2]);
+	m_max_point.reset(v[0][0], v[0][1], v[0][2]);
+	for (unsigned i = 1; i < v.size(); i++) {
+		const Point_3f &p = v[i];
+
+		m_min_point.set_x(MIN(m_min_point[0], (double) p[0]));
+		m_min_point.set_y(MIN(m_min_point[1], (double) p[1]));
+		m_min_point.set_z(MIN(m_min_point[2], (double) p[2]));
+
+		m_max_point.set_x(MAX(m_max_point[0], (double) p[0]));
+		m_max_point.set_y(MAX(m_max_point[1], (double) p[1]));
+		m_max_point.set_z(MAX(m_max_point[2], (double) p[2]));
+	}
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const Point_3d &c,
+					double lx,
+					double ly, 
+					double lz)
+	: m_min_point(c[0] - lx / 2.0,
+		      c[1] - ly / 2.0,
+		      c[2] - lz / 2.0),
+
+	  m_max_point(c[0] + lx / 2.0,
+		      c[1] + ly / 2.0,
+		      c[2] + lz / 2.0)
+{
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const Bounding_box_3d &b1,
+					const Bounding_box_3d &b2)
+	: m_min_point(MIN(b1.get_min_x(), b2.get_min_x()),
+		      MIN(b1.get_min_y(), b2.get_min_y()),
+		      MIN(b1.get_min_z(), b2.get_min_z())),
+
+	  m_max_point(MAX(b1.get_max_x(), b2.get_max_x()),
+		      MAX(b1.get_max_y(), b2.get_max_y()),
+		      MAX(b1.get_max_z(), b2.get_max_z()))
+{
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d::Bounding_box_3d(const Bounding_box_3d &b)
+	: m_min_point(b.m_min_point),
+	  m_max_point(b.m_max_point)
+{
+	// OK to be incorrect
+	// GTB_CHECK(is_order_correct(FLT_EPSILON));
+}
+
+
+inline Bounding_box_3d &Bounding_box_3d::operator=(const Bounding_box_3d &b)
+{
+	m_min_point = b.m_min_point;
+	m_max_point = b.m_max_point;
+	return *this;
+}
+
+
+inline bool Bounding_box_3d::eps_is_equal(const Bounding_box_3d &b,
+					  double eps) const
+{
+	return (m_min_point.eps_is_equal(b.m_min_point, eps) &&
+		m_max_point.eps_is_equal(b.m_max_point, eps));
+}
+
+
+inline bool Bounding_box_3d::eps_is_empty(double eps) const
+{
+	return !is_order_correct(eps);
+}
+
+
+inline const Point_3d &Bounding_box_3d::get_min_point() const
+{
+	return m_min_point;
+}
+
+
+inline const Point_3d &Bounding_box_3d::get_max_point() const
+{
+	return m_max_point;
+}
+
+
+inline double Bounding_box_3d::get_min_x() const
+{
+	return m_min_point[0];
+}
+
+
+inline double Bounding_box_3d::get_min_y() const
+{
+	return m_min_point[1];
+}
+
+
+inline double Bounding_box_3d::get_min_z() const
+{
+	return m_min_point[2];
+}
+
+
+inline double Bounding_box_3d::get_max_x() const
+{
+	return m_max_point[0];
+}
+
+
+inline double Bounding_box_3d::get_max_y() const
+{
+	return m_max_point[1];
+}
+
+
+inline double Bounding_box_3d::get_max_z() const
+{
+	return m_max_point[2];
+}
+
+
+inline Bounding_box_3d &Bounding_box_3d::set_min_point(
+	const Point_3d &min_point)
+{
+	m_min_point = min_point;
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+	return *this;
+}
+
+
+inline Bounding_box_3d &Bounding_box_3d::set_max_point(
+	const Point_3d &max_point)
+{
+	m_max_point = max_point;
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+	return *this;
+}
+
+
+inline Bounding_box_3d &Bounding_box_3d::reset(const Point_3d &min_point,
+					       const Point_3d &max_point)
+{
+	m_min_point = min_point;
+	m_max_point = max_point;
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+	return *this;
+}
+
+
+inline Bounding_box_3d &Bounding_box_3d::reset(
+	double min_x, double min_y, double min_z,
+	double max_x, double max_y, double max_z)
+{
+	m_min_point.reset(min_x, min_y, min_z);
+	m_max_point.reset(max_x, max_y, max_z);
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+	return *this;
+}
+
+
+inline Bounding_box_3d &Bounding_box_3d::set_min_x(double min_x)
+{
+	m_min_point.set_x(min_x);
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+	return *this;
+}
+
+
+inline Bounding_box_3d &Bounding_box_3d::set_min_y(double min_y)
+{
+	m_min_point.set_y(min_y);
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+	return *this;
+}
+
+
+inline Bounding_box_3d &Bounding_box_3d::set_min_z(double min_z)
+{
+	m_min_point.set_z(min_z);
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+	return *this;
+}
+
+
+inline Bounding_box_3d &Bounding_box_3d::set_max_x(double max_x)
+{
+	m_max_point.set_x(max_x);
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+	return *this;
+}
+
+
+inline Bounding_box_3d &Bounding_box_3d::set_max_y(double max_y)
+{
+	m_max_point.set_y(max_y);
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+	return *this;
+}
+
+
+inline Bounding_box_3d &Bounding_box_3d::set_max_z(double max_z)
+{
+	m_max_point.set_z(max_z);
+	GTB_CHECK(is_order_correct(FLT_EPSILON));
+	return *this;
+}
+
+
+inline Point_3d Bounding_box_3d::centroid() const
+{
+	return Point_3d((m_min_point[0] + m_max_point[0]) / 2.0,
+			(m_min_point[1] + m_max_point[1]) / 2.0,
+			(m_min_point[2] + m_max_point[2]) / 2.0);
+}
+
+
+inline double Bounding_box_3d::x_length() const
+{
+	return m_max_point[0] - m_min_point[0];
+}
+
+
+inline double Bounding_box_3d::y_length() const
+{
+	return m_max_point[1] - m_min_point[1];
+}
+
+
+inline double Bounding_box_3d::z_length() const
+{
+	return m_max_point[2] - m_min_point[2];
+}
+
+
+inline double Bounding_box_3d::diagonal_squared_length() const
+{
+	return (m_max_point - m_min_point).squared_length();
+}
+
+
+inline double Bounding_box_3d::diagonal_length() const
+{
+	return sqrt(diagonal_squared_length());
+}
+
+
+inline double Bounding_box_3d::shortest_axis_length() const
+{
+	double dx = x_length();
+	double dy = y_length();
+	double dz = z_length();
+	return MIN(MIN(dx, dy), dz);
+}
+
+
+inline double Bounding_box_3d::longest_axis_length() const
+{
+	double dx = x_length();
+	double dy = y_length();
+	double dz = z_length();
+	return MAX(MAX(dx, dy), dz);
+}
+
+
+inline double Bounding_box_3d::volume() const
+{
+	return x_length() * y_length() * z_length();
+}
+
+
+inline bool Bounding_box_3d::contains(const Point_3d &p) const
+{
+	return ((p[0] >= m_min_point[0]) && (p[0] <= m_max_point[0]) &&
+		(p[1] >= m_min_point[1]) && (p[1] <= m_max_point[1]) &&
+		(p[2] >= m_min_point[2]) && (p[2] <= m_max_point[2]));
+}
+
+
+inline bool Bounding_box_3d::contains(const Point_3f &p) const
+{
+	return ((p[0] >= m_min_point[0]) && (p[0] <= m_max_point[0]) &&
+		(p[1] >= m_min_point[1]) && (p[1] <= m_max_point[1]) &&
+		(p[2] >= m_min_point[2]) && (p[2] <= m_max_point[2]));
+}
+
+
+inline void Bounding_box_3d::set_min(int axis, double value)
+{
+	GTB_REQUIRE((axis >= 0) && (axis < 3));
+	m_min_point[axis] = value;
+}
+
+
+inline void Bounding_box_3d::set_max(int axis, double value)
+{
+	GTB_REQUIRE((axis >= 0) && (axis < 3));
+	m_max_point[axis] = value;
+}
+
+
+inline void Bounding_box_3d::scale(double s)
+{
+	Point_3d origin = centroid();
+	m_min_point.scale(origin, s);
+	m_max_point.scale(origin, s);
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_BOUNDING_BOX_3D_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Exterior_face.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Exterior_face.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Exterior_face.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,65 @@
+#ifndef GTB_EXTERIOR_FACE_INCLUDED
+#include "Exterior_face.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+int Exterior_face::cmp(const Exterior_face &f1, const Exterior_face &f2) 
+{
+	if (f1.m_global_vertices[0] < f2.m_global_vertices[0]) {
+		return -1;
+	} else if (f1.m_global_vertices[0] > f2.m_global_vertices[0]) {
+		return 1;
+	} else if (f1.m_global_vertices[1] < f2.m_global_vertices[1]) {
+		return -1;
+	} else if (f1.m_global_vertices[1] > f2.m_global_vertices[1]) {
+		return 1;
+	} else if (f1.m_global_vertices[2] < f2.m_global_vertices[2]) {
+		return -1;
+	} else if (f1.m_global_vertices[2] > f2.m_global_vertices[2]) {
+		return 1;
+	}
+	return 0;
+}
+
+
+Exterior_face::Exterior_face(const unsigned global_vertices[3],
+			     unsigned global_octree_node,
+			     unsigned local_tetra,
+			     char local_index_on_tetra,
+			     unsigned local_face)
+	: m_global_octree_node(global_octree_node),
+	  m_local_tetra(local_tetra),
+	  m_local_index_on_tetra(local_index_on_tetra),
+	  m_local_face(local_face)
+{
+	m_global_vertices[0] = global_vertices[0];
+	m_global_vertices[1] = global_vertices[1];
+	m_global_vertices[2] = global_vertices[2];
+}
+
+
+Exterior_face::Exterior_face(FILE *fp)
+{
+	read(fp);
+}
+
+
+void Exterior_face::read(FILE *fp) 
+{
+	if (fread(this, sizeof(*this), 1, fp) != 1) {
+		GTB_ERROR("failed to read face");
+	}
+}
+
+
+void Exterior_face::write(FILE *fp) const
+{
+ 	if (fwrite(this, sizeof(*this), 1, fp) != 1) {
+ 		GTB_ERROR("failed to write face");
+ 	}
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Exterior_face.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Exterior_face.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Exterior_face.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,99 @@
+#ifndef GTB_EXTERIOR_FACE_INCLUDED
+#define GTB_EXTERIOR_FACE_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_ASSERTIONS_INCLUDED
+#include "assertions.hpp"
+#endif
+
+#ifndef GTB_C_STDIO_INCLUDED
+#include <stdio.h>
+#define GTB_C_STDIO_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+class Exterior_face  {
+public:
+	Exterior_face(const unsigned global_vertices[3],
+		      unsigned global_octree_node,
+		      unsigned local_tetra,
+		      char local_index_on_tetra,
+		      unsigned local_face);
+
+	Exterior_face(FILE *fp);
+
+	bool operator==(const Exterior_face &f) const;
+	static int cmp(const Exterior_face &f1, 
+		       const Exterior_face &f2);
+	void write(FILE *fp) const;
+	void read(FILE *fp);
+
+	void get_global_vertices(unsigned v[3]) const;
+	unsigned get_global_vertex(unsigned v) const;
+	const unsigned &get_global_octree_node() const;
+	const unsigned &get_local_tetra() const;
+	const char &get_local_index_on_tetra() const;
+	const unsigned &get_local_face() const;
+
+protected:
+	unsigned m_global_vertices[3];
+	unsigned m_global_octree_node;
+	unsigned m_local_tetra;
+	char m_local_index_on_tetra;
+	unsigned m_local_face;
+};
+
+
+inline bool Exterior_face::operator==(const Exterior_face &f) const 
+{
+	return cmp(*this, f) == 0;
+}
+
+
+inline void Exterior_face::get_global_vertices(	unsigned v[3]) const
+{
+	v[0] = m_global_vertices[0];
+	v[1] = m_global_vertices[1];
+	v[2] = m_global_vertices[2];
+}
+
+
+inline unsigned Exterior_face::get_global_vertex(unsigned v) const
+{
+	GTB_REQUIRE(v < 3);
+	return m_global_vertices[v];
+}
+
+
+inline const unsigned &Exterior_face::get_global_octree_node() const
+{
+	return m_global_octree_node;
+}
+
+
+inline const unsigned &Exterior_face::get_local_tetra() const
+{
+	return m_local_tetra;
+}
+
+
+inline const char &Exterior_face::get_local_index_on_tetra() const
+{
+	return m_local_index_on_tetra;
+}
+
+
+inline const unsigned &Exterior_face::get_local_face() const
+{
+	return m_local_face;
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_EXTERIOR_FACE_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/HDF5_Reader.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/HDF5_Reader.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/HDF5_Reader.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,128 @@
+#ifndef GTB_HDF5_READER_INCLUDED
+#include "HDF5_Reader.hpp"
+#endif
+
+#ifndef GTB_INDEXED_TETRA_SET_INCLUDED
+#include "Indexed_tetra_set.hpp"
+#endif
+
+#ifndef GTB_TIME_SERIES_INCLUDED
+#include "Time_series.hpp"
+#endif
+
+#include <hdf5.h>
+#include "../libcigma/h5_io.h"
+#include "../libcigma/h5_attr.h"
+#include "../libcigma/dataset.h"
+#include "../libcigma/mesh.h"
+
+GTB_BEGIN_NAMESPACE
+
+HDF5_Reader::HDF5_Reader()
+{
+
+}
+
+void HDF5_Reader::get_time_series(const char *filename,
+                                  const char *field_location,
+                                  Scalar_time_series **out_sts,
+                                  Vector_time_series **out_vts,
+                                  Indexed_tetra_set **out_its)
+{
+    *out_sts = NULL;
+    *out_vts = NULL;
+
+    herr_t status;
+    hid_t field_file_id;
+
+    field_file_id = h5_file_open(filename, "rw");
+
+    m_vertices.clear();
+    m_tetrahedra.clear();
+
+    hid_t dataset_id;
+    dataset_id = H5Dopen(field_file_id, field_location);
+    if (dataset_id < 0)
+    {
+        H5Fclose(field_file_id);
+        return;
+    }
+
+    char *mesh_location;
+    status = get_str_attr(dataset_id, "MeshLocation", &mesh_location);
+    if (status < 0)
+    {
+        H5Fclose(field_file_id);
+        return;
+    }
+    status = H5Dclose(dataset_id);
+
+    int nno, ndim;
+    double *dofs;
+    int ierr;
+    ierr = dataset_read2(field_file_id, field_location, H5T_NATIVE_DOUBLE,
+                         (void **)&dofs, &nno, &ndim);
+
+    if (ierr < 0)
+    {
+        status = H5Fclose(field_file_id);
+        return;
+    }
+
+    std::vector<float> scalars;
+    std::vector<Vector_3f> vectors;
+
+    if (ndim == 1)
+    {
+        scalars.resize(nno);
+        for (int i = 0; i < nno; i++)
+        {
+            scalars[i] = dofs[i];
+        }
+        *out_sts = new Scalar_time_series(scalars);
+    }
+    else if (ndim == 3)
+    {
+        vectors.resize(nno);
+        for (int i = 0; i < nno; i++)
+        {
+            vectors[i] = Vector_3f(dofs[3*i], dofs[3*i+1], dofs[3*i+2]);
+        }
+        *out_vts = new Vector_time_series(vectors);
+    }
+
+    hid_t mesh_group_id;
+    mesh_group_id = h5_group_open(field_file_id, mesh_location);
+
+    mesh_t mesh;
+    ierr = mesh_read_coords(&mesh, mesh_group_id, "coordinates");
+    ierr = mesh_read_connect(&mesh, mesh_group_id, "connectivity");
+
+    free(mesh_location);
+
+    status = H5Gclose(mesh_group_id);
+    status = H5Fclose(field_file_id);
+
+    m_vertices.resize(mesh.nno);
+    for (int i = 0; i < mesh.nno; i++)
+    {
+        m_vertices[i] = Point_3f(mesh.coords[3*i],
+                                 mesh.coords[3*i+1],
+                                 mesh.coords[3*i+2]);
+    }
+    
+    m_tetrahedra.resize(mesh.nel);
+    for (int e = 0; e < mesh.nel; e++)
+    {
+        m_tetrahedra[e] = Tetrahedron(mesh.connect[4*e],
+                                      mesh.connect[4*e+1],
+                                      mesh.connect[4*e+2],
+                                      mesh.connect[4*e+3]);
+    }
+
+    mesh_free(&mesh);
+
+    *out_its = new Indexed_tetra_set(m_vertices, m_tetrahedra);
+}
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/HDF5_Reader.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/HDF5_Reader.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/HDF5_Reader.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,47 @@
+#ifndef GTB_HDF5_READER_INCLUDED
+#define GTB_HDF5_READER_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_C_STDIO_INCLUDED
+#include <stdio.h>
+#define GTB_C_STDIO_INCLUDED
+#endif
+
+#ifndef GTB_POINT_3F_INCLUDED
+#include "Point_3f.hpp"
+#endif
+
+#ifndef GTB_TIME_SERIES_INCLUDED
+#include "Time_series.hpp"
+#endif
+
+#include <hdf5.h>
+
+GTB_BEGIN_NAMESPACE
+
+class Indexed_tetra_set;
+class Tetrahedron;
+
+
+class HDF5_Reader {
+public:
+    HDF5_Reader();
+
+    void get_time_series(const char *filename,
+                         const char *field_location,
+                         Scalar_time_series **out_sts,
+                         Vector_time_series **out_vts,
+                         Indexed_tetra_set **out_its);
+
+protected:
+    std::vector<Point_3f> m_vertices;
+    std::vector<Tetrahedron> m_tetrahedra;
+};
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_HDF5_READER_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,1172 @@
+// Based on code by Peter Shirley, Peter L. Williams, Nelson Max, and
+// Claudio Silva
+
+#ifndef GTB_INDEXED_TETRA_SET_INCLUDED
+#include "Indexed_tetra_set.hpp"
+#endif
+
+#ifndef GTB_CXX_SET_INCLUDED
+#include <set>
+#define GTB_CXX_SET_INCLUDED
+#endif
+
+//#ifndef GTB_IO_INCLUDED
+//#include "io.hpp"
+//#endif
+
+// #ifndef GTB_TETRA_SORTER_INCLUDED
+// #include "Tetra_sorter.hpp"
+// #endif
+
+#ifndef GTB_EXTERIOR_FACE_INCLUDED
+#include "Exterior_face.hpp"
+#endif
+
+// #ifndef GTB_RENDERING_CONTEXT_INCLUDED
+// #include "Rendering_context.hpp"
+// #endif
+
+#ifndef GTB_VISITOR_INCLUDED
+#include "Visitor.hpp"
+#endif
+
+// #ifndef GTB_SHAPE_FILE_INCLUDED
+// #include "Shape_file.hpp"
+// #endif
+
+#include "math.hpp"
+
+#define DBL_EPS 1.e-10
+
+GTB_BEGIN_NAMESPACE
+
+const char *Indexed_tetra_set::m_class_name = "Indexed_tetra_set";
+// static int s_nifty_counter = 0;
+
+
+Indexed_tetra_set_init::Indexed_tetra_set_init()
+{
+// 	if (0 == s_nifty_counter++) {
+// 		GTB_SHAPE_FILE_REGISTER_READER(Indexed_tetra_set);
+// 	}
+}
+
+
+Indexed_tetra_set_init::~Indexed_tetra_set_init()
+{
+// 	if (0 == --s_nifty_counter) {
+// 		// nothing
+// 	}
+}
+
+
+#define FREAD(x, fp) fread(&x, sizeof(x), 1, fp)
+#define FWRITE(x, fp) fwrite(&x, sizeof(x), 1, fp)
+
+
+struct Tetra_set_file_header {
+	unsigned id;
+	bool complete;
+	bool out_of_core;
+	unsigned num_vertices;
+	unsigned num_global_indices;
+	unsigned num_faces;
+	unsigned num_tetrahedra;
+	unsigned num_centroids;
+	Bounding_box_3d bounding_box;
+
+	Tetra_set_file_header(const Indexed_tetra_set &its)
+		: id(its.get_id()), 
+		  complete(its.is_complete()),
+		  out_of_core(its.is_out_of_core()),
+		  num_vertices(its.get_num_vertices()),
+		  num_global_indices(its.get_num_vertices()),
+		  num_faces(its.get_num_faces()),
+		  num_tetrahedra(its.get_num_tetrahedra() + 1),
+		  num_centroids(its.get_num_centroids()),
+		  bounding_box(its.get_bounding_box()) {
+	}
+
+	Tetra_set_file_header(FILE *fp) {
+		if ((FREAD(id, fp) +
+		     FREAD(complete, fp) +
+		     FREAD(out_of_core, fp) +
+		     FREAD(num_vertices, fp) +
+		     FREAD(num_global_indices, fp) +
+		     FREAD(num_faces, fp) +
+		     FREAD(num_tetrahedra, fp) +
+		     FREAD(num_centroids, fp) +
+		     FREAD(bounding_box, fp))
+		    != 9) {
+			GTB_ERROR("failed to read header");
+		}
+	}
+
+	void write(FILE *fp) const {
+		if ((FWRITE(id, fp) +
+		     FWRITE(complete, fp) +
+		     FWRITE(out_of_core, fp) +
+		     FWRITE(num_vertices, fp) +
+		     FWRITE(num_global_indices, fp) +
+		     FWRITE(num_faces, fp) +
+		     FWRITE(num_tetrahedra, fp) +
+		     FWRITE(num_centroids, fp) +
+		     FWRITE(bounding_box, fp))
+		    != 9) {
+			GTB_ERROR("failed to write header");
+		}
+	}
+};
+
+
+Indexed_tetra_set::Indexed_tetra_set()
+	: m_id(0), 
+	  m_complete(false),
+	  m_out_of_core(false)
+{
+}
+
+
+Indexed_tetra_set::Indexed_tetra_set(
+	const std::vector<Point_3f> &vertices, 
+	const std::vector<Tetrahedron> &tetrahedra)
+	: m_vertices(vertices),
+	  m_tetrahedra(tetrahedra),
+	  m_id(0), 
+	  m_complete(true),
+	  m_out_of_core(false)
+{
+	// create the global indices
+	m_global_indices.resize(get_num_vertices());
+	for (unsigned i = 0; i < get_num_vertices(); i++) {
+		m_global_indices[i] = i;
+	}
+ 
+	// complete the creation of the indexed tetra set
+	m_bounding_box = Bounding_box_3d(m_vertices);
+#if 0
+	build_tetrahedra();
+	build_centroids();
+	build_faces();
+#endif
+	set_id(0);
+}
+
+
+Indexed_tetra_set::Indexed_tetra_set(
+	const std::vector<Point_3f> &vertices, 
+	const std::vector<unsigned> &global_indices,
+	const std::vector<Tetrahedron> &tetrahedra)
+	: m_vertices(vertices),
+	  m_tetrahedra(tetrahedra),
+	  m_global_indices(global_indices),
+	  m_id(0),
+	  m_complete(false),
+	  m_out_of_core(true)
+{
+	m_bounding_box = Bounding_box_3d(m_vertices);
+}
+
+
+Indexed_tetra_set::Indexed_tetra_set(
+	const std::vector<Point_3f> &vertices, 
+	const std::vector<Tetrahedron> &tetrahedra,
+	bool replicate)
+	: m_vertices(vertices),
+	  m_tetrahedra(tetrahedra),
+	  m_id(0), 
+	  m_complete(false),
+	  m_out_of_core(false)
+{
+	(void) replicate;
+	// create the global indices
+	m_global_indices.resize(get_num_vertices());
+	for (unsigned i = 0; i < get_num_vertices(); i++) {
+		m_global_indices[i] = i;
+	}
+ 
+	// complete the creation of the indexed tetra set
+	m_bounding_box = Bounding_box_3d(m_vertices);
+}
+
+
+struct Vertex_tuple {
+	Vertex_tuple (unsigned gi, unsigned li) {
+		global_index = gi;
+		local_index = li;
+	}
+	
+	friend bool operator==(const Vertex_tuple &a, const Vertex_tuple &b) {
+		return (a.global_index == b.global_index);
+	}
+	friend bool operator<(const Vertex_tuple &a, const Vertex_tuple &b) {
+		return (a.global_index < b.global_index);
+	}
+	
+	unsigned global_index;
+	unsigned local_index;
+};
+
+
+Indexed_tetra_set::Indexed_tetra_set(
+	const Indexed_tetra_set &src, 
+	const std::vector<Tetrahedron> &src_tetra)
+	: m_id(0),
+	  m_complete(false),
+	  m_out_of_core(true)
+{
+	GTB_CHECK(are_tetrahedra_vertices_valid());
+ 	std::set<Vertex_tuple> vertex_tuple_set;
+	std::set<Vertex_tuple>::const_iterator vti;
+	const std::vector<Point_3f> &src_vertices = src.get_vertices();
+	const std::vector<unsigned> &src_vertex_global_indices = 
+		src.get_vertex_global_indices();
+
+	m_vertices.reserve(src_tetra.size() * 4);
+	m_tetrahedra.reserve(src_tetra.size() + 1); // +1 because of dummy
+	m_global_indices.reserve(src_tetra.size() * 4);	
+
+	// the dummy
+	m_tetrahedra.push_back(Tetrahedron(0, 0, 0, 0));
+
+	for (unsigned i = 0; i < src_tetra.size(); i++) {
+ 		const Tetrahedron &T1 = src_tetra[i];
+		unsigned vi[4];
+			
+		for (char j = 0; j < 4; j++) {
+			unsigned vertex = T1.get_vertex(j);
+			if (vertex >= src_vertex_global_indices.size()) {
+				GTB_ERROR3("vertex=%d  svgi.size=%d\n",
+					   vertex,
+					   src_vertex_global_indices.size());
+			}
+			unsigned vgi = src_vertex_global_indices[vertex];
+			Vertex_tuple tuple(vgi,0);
+			vti = vertex_tuple_set.find(tuple);
+
+			if (vti == vertex_tuple_set.end()) {
+				Point_3f p = src_vertices[vertex];
+				m_vertices.push_back(p);
+				m_global_indices.push_back(vgi);
+				
+				vi[j] = m_vertices.size() - 1;
+				tuple.local_index = vi[j];
+				vertex_tuple_set.insert(tuple);
+			} else {
+				vi[j] = (*vti).local_index;
+			}
+		}
+			
+		Tetrahedron T2(vi[0], vi[1], vi[2], vi[3]);
+		m_tetrahedra.push_back(T2);	
+	}
+
+ 	m_bounding_box = Bounding_box_3d(m_vertices);
+	GTB_CHECK(are_tetrahedra_vertices_valid());
+}
+
+
+void Indexed_tetra_set::add(const Indexed_tetra_set &src)
+{
+	GTB_CHECK(are_tetrahedra_vertices_valid());
+	GTB_CHECK(src.are_tetrahedra_vertices_valid());
+ 	std::set<Vertex_tuple> vertex_tuple_set;
+	std::set<Vertex_tuple>::const_iterator vti;
+	const std::vector<Point_3f> &src_vertices = src.get_vertices();
+	const std::vector<unsigned> &src_vertex_global_indices = 
+		src.get_vertex_global_indices();
+	const std::vector<Tetrahedron> &src_tetra = src.get_tetrahedra();
+
+	m_complete = false;
+	m_out_of_core = true;
+
+	m_vertices.reserve(get_num_vertices() + src.get_num_vertices());
+	m_tetrahedra.reserve(get_num_tetrahedra() + src.get_num_tetrahedra());
+	m_global_indices.reserve(get_num_vertices() + 
+					src.get_num_vertices());	
+
+	for (unsigned i = 0; i < get_num_vertices(); i++) {
+		unsigned vgi = m_global_indices[i];
+		Vertex_tuple tuple(vgi,i);
+		vertex_tuple_set.insert(tuple);
+	}
+
+	// skip dummy
+	for (unsigned i = 1; i < src.get_num_tetrahedra(); i++) {
+ 		const Tetrahedron &T1 = src_tetra[i];
+		GTB_CHECK(T1.are_vertices_valid());
+		unsigned vi[4];
+			
+		for (char j = 0; j < 4; j++) {
+			unsigned vertex = T1.get_vertex(j);
+			unsigned vgi = src_vertex_global_indices[vertex];
+			Vertex_tuple tuple(vgi,0);
+			vti = vertex_tuple_set.find(tuple);
+
+			if (vti == vertex_tuple_set.end()) {
+				Point_3f p = src_vertices[vertex];
+				m_vertices.push_back(p);
+				m_global_indices.push_back(vgi);
+				
+				vi[j] = m_vertices.size() - 1;
+				tuple.local_index = vi[j];
+				vertex_tuple_set.insert(tuple);
+ 			} else {
+				vi[j] = (*vti).local_index;
+			}
+		}
+			
+		Tetrahedron T2(vi[0], vi[1], vi[2], vi[3]);
+		m_tetrahedra.push_back(T2);	
+	}
+
+ 	m_bounding_box = Bounding_box_3d(m_vertices);
+	GTB_CHECK(are_tetrahedra_vertices_valid());
+}
+
+
+void Indexed_tetra_set::build(unsigned octree_node_id)
+{
+#if 0
+	if (is_complete()) {
+		return;
+	}
+#endif
+	m_complete = true;
+
+	build_tetrahedra();
+	build_centroids();
+	build_faces();
+	set_id(octree_node_id);
+}
+
+
+void Indexed_tetra_set::shift(float z_shift)
+{
+	printf("\n replicate vertices and global indices\n");
+
+	unsigned i;
+	for (i = 0; i < get_num_vertices(); i++) {
+		m_vertices[i].set_z(m_vertices[i].get_z() + z_shift);
+		m_global_indices[i] = m_global_indices[i] + 
+			get_num_vertices();
+	}
+
+ 	m_bounding_box = Bounding_box_3d(m_vertices);
+}
+
+
+void Indexed_tetra_set::write(FILE * fp) const
+{
+	GTB_REQUIRE(fp != NULL);
+
+	// write header
+	Tetra_set_file_header header(*this);
+	header.write(fp);
+
+        // write vertices
+	if (header.num_vertices > 0) {
+		if (fwrite(&m_vertices[0],
+			   header.num_vertices * sizeof(m_vertices[0]),
+			   1, fp) != 1) {
+			GTB_ERROR("failed to write vertices");
+		}
+	}
+
+	// write faces
+	if (header.num_faces > 0) {
+		if (fwrite(&m_faces[0],
+			   header.num_faces * sizeof(m_faces[0]),
+			   1, fp) != 1) {
+			GTB_ERROR("failed to write faces");
+		}
+	}
+
+	// write tetrahedra
+	if (header.num_tetrahedra > 0) {
+		if (fwrite(&m_tetrahedra[0],
+			   header.num_tetrahedra * sizeof(m_tetrahedra[0]),
+			   1, fp) != 1) {
+			GTB_ERROR("failed to write tetrahedra");
+		}
+	}
+
+	// write centroids
+	if (header.num_centroids > 0) {
+		if (fwrite(&m_centroids[0],
+			   header.num_centroids * sizeof(m_centroids[0]),
+			   1, fp) != 1) {
+			GTB_ERROR("failed to write centroids");
+		}
+	}
+
+        // write vertex global indices
+	if (header.num_global_indices > 0) {
+		if (fwrite(&m_global_indices[0],
+			   header.num_global_indices * 
+			   sizeof(m_global_indices[0]),
+			   1, fp) != 1) {
+			GTB_ERROR("failed to write vertex global indices");
+		}
+	}
+
+}
+
+
+Indexed_tetra_set::Indexed_tetra_set(FILE *fp)
+{
+	GTB_REQUIRE(fp != NULL);
+
+	// read header
+	Tetra_set_file_header header(fp);
+
+	m_id = header.id;
+	m_complete = header.complete;
+	m_out_of_core = header.out_of_core;
+	m_bounding_box = header.bounding_box;
+
+        // read vertices
+	if (header.num_vertices > 0) {
+		m_vertices.resize(header.num_vertices);
+		if (fread(&m_vertices[0],
+			  header.num_vertices * sizeof(m_vertices[0]),
+			  1, fp) != 1) {
+			GTB_ERROR("failed to read vertices");
+		}
+	}
+
+	// read faces
+	if (header.num_faces > 0) {
+		m_faces.resize(header.num_faces);
+		if (fread(&m_faces[0],
+			  header.num_faces * sizeof(m_faces[0]),
+			  1, fp) != 1) {
+			GTB_ERROR("failed to read faces");
+		}
+	}
+
+	// read tetrahedra
+	if (header.num_tetrahedra > 0) {
+		m_tetrahedra.resize(header.num_tetrahedra);
+		if (fread(&m_tetrahedra[0],
+			  header.num_tetrahedra * sizeof(m_tetrahedra[0]),
+			  1, fp) != 1) {
+			GTB_ERROR("failed to read tetrahedra");
+		}
+	}
+
+	// read centroids
+	if (header.num_centroids > 0) {
+		m_centroids.resize(header.num_centroids);
+		if (fread(&m_centroids[0],
+			  header.num_centroids * sizeof(m_centroids[0]),
+			  1, fp) != 1) {
+			GTB_ERROR("failed to read centroids");
+		}
+	}
+
+        // read global indices
+	if (header.num_global_indices > 0) {
+		m_global_indices.resize(header.num_global_indices);
+		if (fread(&m_global_indices[0],
+			  header.num_global_indices * 
+			  sizeof(m_global_indices[0]),
+			  1, fp) != 1) {
+			GTB_ERROR("failed to read vertex global indices");
+		}
+	}
+
+	//print_status();
+}
+
+
+Indexed_tetra_set::~Indexed_tetra_set()
+{
+}
+
+
+void Indexed_tetra_set::print_status()
+{
+ 	printf (" complete state : %d\n", is_complete());
+ 	printf (" num vertices   : %d\n", get_num_vertices());
+	printf (" num tetra      : %d\n", get_num_tetrahedra());
+	printf (" num faces      : %d\n", get_num_faces());
+	printf (" num centroids  : %d\n", get_num_centroids());
+	printf (" num ext faces  : %d\n", get_num_exterior_faces());
+	printf (" num ext tetra  : %d\n", get_num_exterior_tetrahedra());
+
+	for(unsigned i = 0; i < get_num_vertices(); i++) {
+		Point_3f &p = m_vertices[i];
+		printf("  v[%d] = %f, %f, %f\n",i, p[0], p[1], p[2]);
+	}
+
+	printf("\n");
+	for(unsigned i = 0; i <= get_num_tetrahedra(); i++) {
+		Tetrahedron &t = m_tetrahedra[i];
+		printf("  t[%d] = %d   f[0] = %2d  -> t = %2d   ext = %d\n"
+		       "         %d   f[1] = %2d  ->  t = %2d   ext = %d\n"
+		       "         %d   f[2] = %2d  ->  t = %2d   ext = %d\n"
+		       "         %d   f[3] = %2d  ->  t = %2d   ext = %d\n\n", 
+		       i,
+		       t.get_vertex(0),t.get_face(0),t.get_neighbor(0),
+		       t.is_face_exterior(0), 
+		       t.get_vertex(1),t.get_face(1),t.get_neighbor(1),
+		       t.is_face_exterior(1), 
+		       t.get_vertex(2),t.get_face(2),t.get_neighbor(2),
+		       t.is_face_exterior(2), 
+		       t.get_vertex(3),t.get_face(3),t.get_neighbor(3),
+		       t.is_face_exterior(3)); 
+	}
+	
+	printf("\n");
+	for(unsigned i=0; i < get_num_faces(); i++) {
+		Indexed_tetra_set::Face &f = m_faces[i];
+		printf("  f[%2d] = %d, %d, %d     ext = %d      t[%d][%d]  <=>  t[%d][%d]\n", 
+		       i, 
+		       f.get_vertex(0), f.get_vertex(1), f.get_vertex(2),
+		       f.is_exterior(),
+		       f.get_left_tetra(), f.get_index_on_left_tetra(),
+		       f.get_right_tetra(), f.get_index_on_right_tetra());
+	}
+
+	printf("\n");
+	for(unsigned i=0; i < get_num_centroids(); i++) {
+		printf("  c[%d] = %f %f %f\n",
+		       i, 
+		       m_centroids[i][0], 
+		       m_centroids[i][1], 
+		       m_centroids[i][2]);
+	}
+}
+
+
+void Indexed_tetra_set::set_id(unsigned id)
+{
+	m_id = id;
+
+// 	printf("octree node id = %d\n", id);
+
+	// set the tetrahedron neighbors octree nodes
+
+	// FIXME: why does get_num_tetrahedra() return
+	// m_tetrahedra.size() - 1, instead of m_tetrahedra.size().
+	for (unsigned i = 0; i < get_num_tetrahedra(); i++) {
+		GTB_CHECK(i < m_tetrahedra.size());
+		m_tetrahedra[i].set_octree_node(id);
+		for (int f = 0; f < 4; f++) {
+			m_tetrahedra[i].set_neighbor_octree_node(f, id);
+		}
+	}
+
+	// set the faces left and right octree nodes
+
+	// FIXME: Here was the bug:
+	// for (unsigned i = 0; i <= get_num_faces(); i++) {
+	for (unsigned i = 0; i < get_num_faces(); i++) {
+		GTB_CHECK(i < m_faces.size());
+		m_faces[i].set_left_octree_node(id);
+		m_faces[i].set_right_octree_node(id);
+	}
+}
+
+
+Indexed_tetra_set::Face::Face()
+	: m_left_tetra(0),
+	  m_right_tetra(0),
+	  m_index_on_left_tetra(-1),
+	  m_index_on_right_tetra(-1),
+	  m_left_octree_node(0),
+	  m_right_octree_node(0),
+	  m_is_exterior(false)
+{
+	m_vertices[0] = 0;
+	m_vertices[1] = 0;
+	m_vertices[2] = 0;
+}
+
+
+Indexed_tetra_set::Face::Face(unsigned i, unsigned j, unsigned k)
+	: m_left_tetra(0),
+	  m_right_tetra(0),
+	  m_index_on_left_tetra(-1),
+	  m_index_on_right_tetra(-1),
+	  m_left_octree_node(0),
+	  m_right_octree_node(0),
+	  m_is_exterior(false)
+{
+	GTB_CHECK((i != j) && (i != k) && (j != k));
+	m_vertices[0] = i;
+	m_vertices[1] = j;
+	m_vertices[2] = k;
+	std::sort(&m_vertices[0], &m_vertices[3]);
+}
+
+
+void Indexed_tetra_set::Face::set_tetra(int t)
+{
+	GTB_CHECK(t > 0);
+	if (m_left_tetra == 0) {
+		m_left_tetra = t;
+	} else if (m_right_tetra == 0) {
+		m_right_tetra = t;
+	} else {
+		fprintf(stderr, "m_left_tetra=%d ", m_left_tetra);
+		fprintf(stderr, "m_right_tetra=%d ", m_right_tetra);
+		fprintf(stderr, "m_vertices=(%d %d %d)\n",
+			m_vertices[0], m_vertices[1], m_vertices[2]);
+		GTB_ERROR("more than 2 tetra share face");
+	}
+}
+
+
+bool Indexed_tetra_set::are_tetrahedra_vertices_valid() const
+{
+	bool result = true;
+
+	// skip 0, because it's the dummy tetrahedron
+	for (unsigned i = 1; i < m_tetrahedra.size(); ++i) {
+		const Tetrahedron &t = m_tetrahedra[i];
+		if (!t.are_vertices_valid()) {
+			fprintf(stderr, "tetra set: %d  ", m_id);
+			fprintf(stderr, "bad tetrahedron: %d  ", i);
+			fprintf(stderr, "vertices: %d %d %d %d\n",
+				t.get_vertex(0),
+				t.get_vertex(1),
+				t.get_vertex(2),
+				t.get_vertex(3));
+			result = false;
+			break;
+		}
+	}
+	return result;
+}
+
+
+void Indexed_tetra_set::compute_connectivity()
+{
+	GTB_CHECK(are_tetrahedra_vertices_valid());
+	std::set<Face> face_set;
+
+	// create faces
+	unsigned num_tetrahedra = get_num_tetrahedra();
+	for (unsigned i = 1; i <= num_tetrahedra; i++) {
+		for (int f = 0; f < 4; f++) {
+			Face ft;
+			switch (f) {
+			case 0:
+				ft = Face(m_tetrahedra[i].get_vertex(0),
+					  m_tetrahedra[i].get_vertex(1),
+					  m_tetrahedra[i].get_vertex(2));
+				break;
+			case 1:
+				ft = Face(m_tetrahedra[i].get_vertex(1),
+					  m_tetrahedra[i].get_vertex(2),
+					  m_tetrahedra[i].get_vertex(3));
+				break;
+			case 2:
+				ft = Face(m_tetrahedra[i].get_vertex(0),
+					  m_tetrahedra[i].get_vertex(1),
+					  m_tetrahedra[i].get_vertex(3));
+				break;
+			case 3:
+				ft = Face(m_tetrahedra[i].get_vertex(0),
+					  m_tetrahedra[i].get_vertex(2),
+					  m_tetrahedra[i].get_vertex(3));
+				break;
+			}
+
+			std::set<Face>::iterator fi = face_set.find(ft);
+			if (fi == face_set.end()) {
+				ft.set_tetra(i);
+				face_set.insert(ft);
+			} else {
+				Face aux = *fi;
+				aux.set_tetra(i);
+				face_set.erase(fi);
+				face_set.insert(aux);
+			}
+		}
+	}
+
+	// compute neighbors
+	for (unsigned i = 1; i <= num_tetrahedra; i++) {
+		for (int f = 0; f < 4; f++) {
+			Face ft;
+			switch (f) {
+			case 3:
+				ft = Face(m_tetrahedra[i].get_vertex(0),
+					  m_tetrahedra[i].get_vertex(1),
+					  m_tetrahedra[i].get_vertex(2));
+				break;
+			case 0:
+				ft = Face(m_tetrahedra[i].get_vertex(1),
+					  m_tetrahedra[i].get_vertex(2),
+					  m_tetrahedra[i].get_vertex(3));
+				break;
+			case 2:
+				ft = Face(m_tetrahedra[i].get_vertex(0),
+					  m_tetrahedra[i].get_vertex(1),
+					  m_tetrahedra[i].get_vertex(3));
+				break;
+			case 1:
+				ft = Face(m_tetrahedra[i].get_vertex(0),
+					  m_tetrahedra[i].get_vertex(2),
+					  m_tetrahedra[i].get_vertex(3));
+				break;
+			}
+
+			std::set <Face>::const_iterator fi = face_set.find(ft);
+			if (fi == face_set.end()) {
+				GTB_ERROR("could not find face");
+			}
+
+			if ((*fi).get_left_tetra() != i) {
+				m_tetrahedra[i].set_neighbor(
+					f, (*fi).get_left_tetra());
+				GTB_CHECK((*fi).get_right_tetra() == i);
+			} else if ((*fi).get_right_tetra() != i) {
+				m_tetrahedra[i].set_neighbor(
+					f, (*fi).get_right_tetra());
+				GTB_CHECK((*fi).get_left_tetra() == i);
+			}
+		}
+	}
+// 	printf("face_set.size() = %d\n", face_set.size());
+}
+
+
+void Indexed_tetra_set::build_tetrahedra()
+{
+	compute_connectivity();
+ 
+	m_num_exterior_faces = 0;
+	m_num_exterior_tetrahedra = 0;
+	unsigned face_count = 0;
+
+	for (unsigned t = 1; t <= get_num_tetrahedra(); t++) {
+		bool first_exterior_face = true;
+		for (int f = 0; f < 4; f++) {
+			if (m_tetrahedra[t].is_face_exterior(f)) {
+				/* use the neighbor field to point to
+				 * the centroid (oh boy...) */
+				m_num_exterior_faces++;
+				m_tetrahedra[t].set_face(f, face_count++);
+				if (first_exterior_face) {
+					first_exterior_face = false;
+					m_num_exterior_tetrahedra++;
+					m_tetrahedra[t].set_neighbor(
+						f, -m_num_exterior_tetrahedra);
+				} else {
+					m_tetrahedra[t].set_neighbor(
+						f, -m_num_exterior_tetrahedra);
+				}
+			} else {
+				GTB_CHECK(m_tetrahedra[t].get_neighbor(f) > 0);
+				unsigned st = m_tetrahedra[t].get_neighbor(f);
+				if (st > t) {
+					/* the tetrahedron with lower
+					 * index is responsible for
+					 * setting the face number on
+					 * both tetrahedra of the face */
+
+					int fn = face_count++;
+					m_tetrahedra[t].set_face(f, fn);
+					unsigned i;
+					for (i = 0; i < 4; i++) {
+						if (m_tetrahedra[st].
+						    get_neighbor(i)
+						    == (int) t) {
+							break;
+						}
+					}
+					m_tetrahedra[st].set_face(i, fn);
+				}
+			}
+		}
+	}
+
+	m_faces.resize(face_count);
+
+// 	fprintf(stderr, "m_num_exterior_faces=%d\n", m_num_exterior_faces);
+// 	fprintf(stderr, "m_num_exterior_tetrahedra=%d\n", m_num_exterior_tetrahedra);
+// 	fprintf(stderr, "face_count=%d\n", face_count);
+}
+
+
+void Indexed_tetra_set::build_centroids()
+{
+	m_centroids.resize(m_num_exterior_tetrahedra + 1);
+	for (unsigned tet = 1; tet <= get_num_tetrahedra(); tet++) {
+		for (int f = 0; f <= 3; f++) {
+			if (m_tetrahedra[tet].is_face_exterior(f)) {
+				int i = -m_tetrahedra[tet].get_neighbor(f);
+				m_centroids[i] = Point_3f::centroid(
+					m_vertices[m_tetrahedra[tet].
+						   get_vertex(0)],
+					m_vertices[m_tetrahedra[tet].
+						   get_vertex(1)],
+					m_vertices[m_tetrahedra[tet].
+						   get_vertex(2)],
+					m_vertices[m_tetrahedra[tet].
+						   get_vertex(3)]);
+			}
+		}
+	}
+}
+
+
+void Indexed_tetra_set::Face::orient_normal(const Point_3f &p)
+{
+	if (m_plane.signed_distance(p) > 0.0) {
+		m_plane.flip();
+		unsigned aux = m_vertices[1];
+		m_vertices[1] = m_vertices[2];
+		m_vertices[2] = aux;
+	}
+}
+
+
+// Why do we need this separate function?  Why don't we keep the map
+// in compute_connectivity() instead?  We are losing the vertex
+// indices inside the faces.  Do we ever need them?
+void Indexed_tetra_set::build_faces()
+{
+	for (unsigned ti = 1; ti <= get_num_tetrahedra(); ti++) {
+		Tetrahedron &t = m_tetrahedra[ti];
+		for (unsigned fi = 0; fi <= 3; fi++) {
+			int st = t.get_neighbor(fi);
+			if (!t.is_face_exterior(fi) && ((int) ti >= st)) {
+				continue;
+			}
+			Face &f = m_faces[t.get_face(fi)];
+			f.set_left_tetra(ti);
+			f.set_index_on_left_tetra(fi);
+			if (t.is_face_exterior(fi)) {
+				f.set_exterior(true);
+				f.set_right_tetra(st);
+			} else {
+				f.set_exterior(false);
+				f.set_right_tetra(st);
+				Tetrahedron &tst = m_tetrahedra[st];
+				for (int i = 0; i < 4; i++) {
+					if (tst.get_neighbor(i) == (int) ti) {
+						f.set_index_on_right_tetra(i);
+						break;
+					}
+				}
+			}
+			unsigned v[4];
+			t.get_face_indices(fi, v);
+			f.set_vertices(v[0], v[1], v[2]);
+			f.set_plane(Plane_3f(m_vertices[v[0]],
+					     m_vertices[v[1]],
+					     m_vertices[v[2]]));
+			f.orient_normal(m_vertices[v[3]]);
+		}
+	}
+}
+
+
+void Indexed_tetra_set::export_exterior_faces(FILE *fp)
+{
+	for(unsigned i = 0; i < get_num_faces(); i++) {
+		Face &F = m_faces[i];
+		if (!F.is_exterior()) {
+			continue;
+		}
+		unsigned v[3];
+		if (is_out_of_core()) {
+			v[0] = m_global_indices[F.get_vertex(0)];
+			v[1] = m_global_indices[F.get_vertex(1)];
+			v[2] = m_global_indices[F.get_vertex(2)];
+		} else {
+			v[0] = F.get_vertex(0);
+			v[1] = F.get_vertex(1);
+			v[2] = F.get_vertex(2);
+		}
+		std::sort(&v[0], &v[3]);
+
+		unsigned left_tetra = F.get_left_tetra();
+		unsigned left_octree_node = F.get_left_octree_node();
+		char index_on_left_tetra = F.get_index_on_left_tetra();
+		const Tetrahedron &T = m_tetrahedra[left_tetra]; 
+		unsigned face = T.get_face(index_on_left_tetra);
+
+		Exterior_face ef(v, 
+				 left_octree_node,
+				 left_tetra,
+				 index_on_left_tetra,
+				 face);
+		ef.write(fp);
+	}
+}
+
+
+void Indexed_tetra_set::set_as_interior_face(
+	unsigned face,
+	unsigned index_on_left_tetra,
+	unsigned right_octree_node,
+	unsigned right_tetra,
+	unsigned index_on_right_tetra)
+{
+	GTB_CHECK(face < m_faces.size());
+	GTB_CHECK(index_on_left_tetra < 4);
+	GTB_CHECK(index_on_right_tetra < 4);
+
+	// update face
+	Face &F = m_faces[face];
+	F.set_right_octree_node(right_octree_node);
+	F.set_right_tetra(right_tetra);
+	F.set_index_on_right_tetra(index_on_right_tetra);
+	F.set_exterior(false);
+ 
+	// update tetrahedron
+	unsigned left_tetra = F.get_left_tetra();
+	Tetrahedron &LT = m_tetrahedra[left_tetra]; 
+	LT.set_neighbor_octree_node(index_on_left_tetra, right_octree_node);
+	LT.set_neighbor(index_on_left_tetra, right_tetra);
+}
+
+
+Shape *Indexed_tetra_set::read(FILE *fp)
+{
+	return new Indexed_tetra_set(fp);
+}
+
+
+// void Indexed_tetra_set::render(Rendering_context &rc)
+// {
+// 	glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_LIGHTING_BIT);
+// 	glEnable(GL_BLEND);
+// 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+// 	glDisable(GL_TEXTURE_2D);
+// 	glDisable(GL_CULL_FACE);
+// 	glDisable(GL_DEPTH_TEST);
+// 	glDepthMask(GL_FALSE);
+// 	glDisable(GL_LIGHTING);
+// 	glShadeModel(GL_SMOOTH);
+
+// 	GTB_CHECK(is_complete());
+
+// 	if (rc.is_enabled(rc.DRAW_BOUNDING_BOX)) {
+// 		rc.get_bounding_box_color().gl_load();
+// 		get_bounding_box().outline();
+// 	}
+
+// 	if (rc.is_enabled(rc.DRAW_CONTENTS)) {
+// 		Vector_3d t = rc.get_view().get_camera().get_towards();
+// 		Vector_3f pd(t[0], t[1], t[2]);
+
+// 		Tetra_sorter *sorter = rc.get_tetra_sorter();
+// 		Tetra_splatter *splatter = rc.get_tetra_splatter();
+// 		Scalar_colors *C = rc.get_scalar_colors();
+// 		Scalar_densities *D = rc.get_scalar_densities();
+// 		Color_map *color_map = rc.get_color_map();
+
+// 		GTB_CHECK(sorter != NULL);
+// 		GTB_CHECK(splatter != NULL);
+// 		GTB_CHECK(C != NULL);
+// 		GTB_CHECK(D != NULL);
+// 		GTB_CHECK(color_map != NULL);
+
+// 		sorter->compute_visibility_graph(*this, pd);
+// 		sorter->sort_visibility_graph(*this,
+// 					      *C, *D, *color_map,
+// 					      *splatter, pd);
+// 	}
+
+// 	glPopAttrib();
+// }
+
+
+// void Indexed_tetra_set::render_geometry(Rendering_context &rc)
+// { 
+// 	(void) rc;
+// 	for (unsigned ti = 1; ti < m_tetrahedra.size(); ti++) {
+// 		const Tetrahedron &t = m_tetrahedra[ti];
+// 		for (unsigned fi = 0; fi < 4; fi++) {
+// 			const Indexed_tetra_set::Face &f =
+// 				m_faces[t.get_face(fi)];
+// 			Color_3f c;
+// 			c = get_color_3f(GTB_WHITE);
+// 			glBegin(GL_LINE_LOOP);
+// 			c.gl_load();
+// 			m_vertices[f.get_vertex(0)].gl_vertex();
+// 			m_vertices[f.get_vertex(1)].gl_vertex();
+// 			m_vertices[f.get_vertex(2)].gl_vertex();
+// 			glEnd();  
+// 		}
+// 	}
+// }
+
+
+bool Indexed_tetra_set::approx_inside_tetra(const Tetrahedron &t, const Point_3f &p)
+{
+	for (unsigned fi = 0; fi < 4; fi++) {
+
+		unsigned v[4];
+		t.get_face_indices(fi, v);
+
+#if 1
+		Face f;
+		f.set_vertices(v[0], v[1], v[2]);
+		f.set_plane(Plane_3f(m_vertices[v[0]],
+				     m_vertices[v[1]],
+				     m_vertices[v[2]]));
+#else
+		Face &f = m_faces[t.get_face(fi)];
+#endif
+		// orient the normal to the outside
+		f.orient_normal(m_vertices[v[3]]);
+
+		float dist = f.get_plane().signed_distance(p);
+ 		if (eps_is_positive(dist, 1e-5)) {
+			// the point is on the outside of the face
+			return false;
+		}
+	}
+	return true;
+}
+
+
+bool Indexed_tetra_set::interpol_tetra(Scalar_time_series *ts, const Tetrahedron &t, const Point_3f &V, float *result)
+{ 
+	bool inside = true;
+
+    // compute barycentric coordinates
+    // M = (A-D|B-D|C-D)
+    Point_3f &D = m_vertices[t.get_vertex(3)];
+    Vector_3f C0 = m_vertices[t.get_vertex(0)] - D;
+    Vector_3f C1 = m_vertices[t.get_vertex(1)] - D;
+    Vector_3f C2 = m_vertices[t.get_vertex(2)] - D;
+    float m[][4] = { { C0[0], C1[0], C2[0], 0 },
+                     { C0[1], C1[1], C2[1], 0 },
+                     { C0[2], C1[2], C2[2], 0 },
+                     { 0, 0, 0, 1 }
+    };
+	Matrix_4d M(m);
+
+#if 1
+	Matrix_4d a(M);
+	Matrix_4d b(MATRIX_4D_IDENTITY);
+	int p[4];
+	if (!a.LU_decomposition(p)) {
+        //fprintf(stderr, "Degenerated tet\n");
+		return false;
+	}
+	a.LU_back_substitution(p, b, M);
+#else
+	M = M.inverse();
+#endif
+
+	// coords = M^-1 * (V-D)
+	Vector_3f coords3 = M * (V - D);
+
+	float coords4[4];
+	memcpy(&coords4[0], &coords3[0], 3*sizeof(float));
+	coords4[3] = 1 - coords3[0] - coords3[1] - coords3[2];
+
+	if (!eps_is_positive_or_zero(coords4[0], DBL_EPS) ||
+	    !eps_is_positive_or_zero(coords4[1], DBL_EPS) ||
+	    !eps_is_positive_or_zero(coords4[2], DBL_EPS) ||
+	    !eps_is_positive_or_zero(coords4[3], DBL_EPS)) {
+//		fprintf(stderr, "wrong barycenter: %e %e %e %e\n",
+//			coords4[0],coords4[1],coords4[2],coords4[3]);
+		inside = false;
+	}
+
+	float total_val = 0;
+	for (unsigned i=0; i<4; i++) {
+		unsigned gi = get_global_vertex(t.get_vertex(i));
+		float Si = ts->get_value(gi);
+		total_val += coords4[i] * Si;
+	}
+
+	*result = total_val;
+	return inside;
+}
+
+bool Indexed_tetra_set::interpol_tetra(Vector_time_series *ts, const Tetrahedron &t, const Point_3f &V, Vector_3f *result)
+{ 
+	bool inside = true;
+
+    // compute barycentric coordinates
+    // M = (A-D|B-D|C-D)
+    Point_3f &D = m_vertices[t.get_vertex(3)];
+    Vector_3f C0 = m_vertices[t.get_vertex(0)] - D;
+    Vector_3f C1 = m_vertices[t.get_vertex(1)] - D;
+    Vector_3f C2 = m_vertices[t.get_vertex(2)] - D;
+    float m[][4] = { { C0[0], C1[0], C2[0], 0 },
+                     { C0[1], C1[1], C2[1], 0 },
+                     { C0[2], C1[2], C2[2], 0 },
+                     { 0, 0, 0, 1 }
+    };
+	Matrix_4d M(m);
+
+#if 1
+	Matrix_4d a(M);
+	Matrix_4d b(MATRIX_4D_IDENTITY);
+	int p[4];
+	if (!a.LU_decomposition(p)) {
+        //fprintf(stderr, "Degenerated tet\n");
+		return false;
+	}
+	a.LU_back_substitution(p, b, M);
+#else
+	M = M.inverse();
+#endif
+
+	// coords = M^-1 * (V-D)
+	Vector_3f coords3 = M * (V - D);
+
+	float coords4[4];
+	memcpy(&coords4[0], &coords3[0], 3*sizeof(float));
+	coords4[3] = 1 - coords3[0] - coords3[1] - coords3[2];
+
+	if (!eps_is_positive_or_zero(coords4[0], DBL_EPS) ||
+	    !eps_is_positive_or_zero(coords4[1], DBL_EPS) ||
+	    !eps_is_positive_or_zero(coords4[2], DBL_EPS) ||
+	    !eps_is_positive_or_zero(coords4[3], DBL_EPS)) {
+//		fprintf(stderr, "wrong barycenter: %e %e %e %e\n",
+//			coords4[0],coords4[1],coords4[2],coords4[3]);
+		inside = false;
+	}
+
+	Vector_3f total_val(0,0,0);
+	for (unsigned i=0; i<4; i++) {
+		unsigned gi = get_global_vertex(t.get_vertex(i));
+		Vector_3f Si = ts->get_value(gi);
+		total_val += coords4[i] * Si;
+	}
+
+	*result = total_val;
+	return inside;
+}
+
+bool Indexed_tetra_set::eval(Scalar_time_series *ts, const Point_3f &p, float *result)
+{
+	for (unsigned ti = 1; ti < m_tetrahedra.size(); ti++) {
+		const Tetrahedron &t = m_tetrahedra[ti];
+		if (!approx_inside_tetra(t, p)) continue;
+		float value;
+		if (interpol_tetra(ts, t, p, &value)) {
+			*result = value;
+			return true;
+		}
+	}
+	return false;
+}
+
+void Indexed_tetra_set::accept(Visitor &visitor)
+{
+	visitor.visit(*this);
+}
+
+
+void Indexed_tetra_set::transform(const Matrix_4d &)
+{
+	GTB_ERROR("not implemented yet");
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,526 @@
+#ifndef GTB_INDEXED_TETRA_SET_INCLUDED
+#define GTB_INDEXED_TETRA_SET_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_PLANE_3F_INCLUDED
+#include "Plane_3f.hpp"
+#endif
+
+// #ifndef GTB_COLOR_3F_INCLUDED
+// #include "Color_3f.hpp"
+// #endif
+
+// #ifndef GTB_COLOR_4F_INCLUDED
+// #include "Color_4f.hpp"
+// #endif
+
+#ifndef GTB_TETRAHEDRON_INCLUDED
+#include "Tetrahedron.hpp"
+#endif
+
+#ifndef GTB_BOUNDING_BOX_3D_INCLUDED
+#include "Bounding_box_3d.hpp"
+#endif
+
+#ifndef GTB_SHAPE_INCLUDED
+#include "Shape.hpp"
+#endif
+
+#ifndef GTB_TIME_SERIES_INCLUDED
+#include "Time_series.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+class Indexed_tetra_set : public Shape {
+public:
+	Indexed_tetra_set();
+
+	Indexed_tetra_set(const std::vector<Point_3f> &vertices, 
+			  const std::vector<Tetrahedron> &tetrahedra);
+
+	Indexed_tetra_set(const std::vector<Point_3f> &vertices, 
+			  const std::vector<Tetrahedron> &tetrahedra,
+			  bool replicate);
+
+	Indexed_tetra_set(const std::vector<Point_3f> &vertices, 
+			  const std::vector<unsigned> &vertex_global_indices,
+			  const std::vector<Tetrahedron> &tetrahedra); 
+
+	Indexed_tetra_set(const Indexed_tetra_set &src, 
+			  const std::vector<Tetrahedron> &src_tetra); 
+
+	~Indexed_tetra_set();
+
+	void add(const Indexed_tetra_set &src); 
+
+	class Face {
+	public:
+		Face();
+		Face(unsigned i, unsigned j, unsigned k);
+		void set_tetra(int t); // tetra 0 is reserved
+
+		void set_vertices(unsigned v0, unsigned v1, unsigned v2);
+		unsigned get_vertex(unsigned i) const;
+
+		unsigned get_left_tetra() const;
+		void set_left_tetra(unsigned t);
+
+		unsigned get_right_tetra() const;
+		void set_right_tetra(unsigned t);
+
+		char get_index_on_left_tetra() const;
+		void set_index_on_left_tetra(char i);
+
+		char get_index_on_right_tetra() const;
+		void set_index_on_right_tetra(char i);
+
+		unsigned get_left_octree_node() const;
+		void set_left_octree_node(unsigned on);
+
+		unsigned get_right_octree_node() const;
+		void set_right_octree_node(unsigned on);
+
+		bool is_exterior() const;
+		void set_exterior(bool value);
+
+		const Plane_3f &get_plane() const;
+		void set_plane(const Plane_3f &p);
+		void orient_normal(const Point_3f &p);
+
+		bool operator==(const Face &b) const;
+		bool operator<(const Face &b) const;
+
+	protected:
+		unsigned m_vertices[3];
+		Plane_3f m_plane;
+		unsigned m_left_tetra;
+		unsigned m_right_tetra;
+		char m_index_on_left_tetra;
+		char m_index_on_right_tetra;
+		unsigned m_left_octree_node;
+		unsigned m_right_octree_node;
+		bool m_is_exterior;
+	};
+
+	// Shape interface
+	const char *get_class_name() const;
+	static const char *static_get_class_name();
+	const Bounding_box_3d &get_bounding_box() const;
+	unsigned get_size_in_bytes() const;
+	void write(FILE *fp) const;
+	static Shape *read(FILE *fp);
+// 	void render(Rendering_context &rc);
+// 	void render_geometry(Rendering_context &rc);
+	void accept(Visitor &visitor);
+	void transform(const Matrix_4d &m);
+
+	void export_exterior_faces(FILE *fp);
+	void build(unsigned octree_node_id);
+	void set_as_interior_face(unsigned face, 
+				  unsigned index_on_left_tetra,
+				  unsigned right_octree_node,
+				  unsigned right_tetra,
+				  unsigned index_on_right_tetra);
+
+	const std::vector<Point_3f> &get_vertices() const;
+	std::vector<Point_3f> &get_vertices();
+
+	const std::vector<unsigned> &get_vertex_global_indices() const;
+	std::vector<unsigned> &get_vertex_global_indices();
+
+	const Tetrahedron &get_tetrahedron(unsigned i) const;
+
+	const std::vector<Tetrahedron> &get_tetrahedra() const;
+	std::vector<Tetrahedron> &get_tetrahedra();
+
+	const std::vector<Face> &get_faces() const;
+	std::vector<Face> &get_faces();
+
+	const std::vector<Point_3f> &get_centroids() const;
+	std::vector<Point_3f> &get_centroids();
+
+	unsigned get_global_vertex(unsigned local_vertex);
+
+	unsigned get_num_vertices() const;
+	unsigned get_num_primitives() const;
+	unsigned get_num_tetrahedra() const;
+	unsigned get_num_faces() const;
+	unsigned get_num_centroids() const;
+	unsigned get_num_exterior_faces() const;
+	unsigned get_num_exterior_tetrahedra() const;
+	bool is_complete() const;
+	bool is_out_of_core() const;
+
+	unsigned get_id() const;
+	void set_id(unsigned id);
+
+	void shift(float z_shif);
+
+	bool approx_inside_tetra(const Tetrahedron &t, const Point_3f &p);
+	bool interpol_tetra(Scalar_time_series *ts, const Tetrahedron &t, const Point_3f &p, float *value);
+	bool interpol_tetra(Vector_time_series *ts, const Tetrahedron &t, const Point_3f &p, Vector_3f *value); //
+	bool eval(Scalar_time_series *ts, const Point_3f &p, float *result);
+
+	void print_status();
+
+protected:
+
+	explicit Indexed_tetra_set(FILE *fp);
+
+	void build_centroids();
+	void build_faces();
+	void build_tetrahedra();
+	void compute_connectivity();
+	bool are_tetrahedra_vertices_valid() const;
+
+	std::vector<Point_3f> m_vertices;
+	std::vector<Tetrahedron> m_tetrahedra;
+	std::vector<Face> m_faces;
+	std::vector<Point_3f> m_centroids;
+	std::vector<unsigned> m_global_indices;
+	Bounding_box_3d m_bounding_box;
+	static const char *m_class_name;
+	
+	unsigned m_id;
+	bool m_complete;
+	bool m_out_of_core;
+	unsigned m_num_exterior_faces;
+	unsigned m_num_exterior_tetrahedra;
+};
+
+
+struct Indexed_tetra_set_init {
+	Indexed_tetra_set_init();
+	~Indexed_tetra_set_init();
+};
+
+
+static Indexed_tetra_set_init indexed_tetra_set_init;
+
+
+inline unsigned Indexed_tetra_set::get_id() const
+{
+	return m_id;
+}
+
+
+inline const char *Indexed_tetra_set::get_class_name() const
+{
+	return m_class_name;
+}
+
+
+inline const char *Indexed_tetra_set::static_get_class_name()
+{
+	return m_class_name;
+}
+
+
+inline const Bounding_box_3d &Indexed_tetra_set::get_bounding_box() const
+{
+	return m_bounding_box;
+}
+
+
+inline unsigned Indexed_tetra_set::get_size_in_bytes() const
+{
+        return sizeof(m_num_exterior_faces)
+		+ sizeof(m_num_exterior_tetrahedra)
+		+ sizeof(m_complete)
+		+ sizeof(m_out_of_core)
+		+ get_num_vertices() * sizeof(m_vertices[0])
+		+ get_num_vertices() * sizeof(m_global_indices[0])
+		+ (get_num_tetrahedra() + 1) * sizeof(m_tetrahedra[0])
+		+ get_num_faces() * sizeof(m_faces[0])
+		+ get_num_centroids() * sizeof(m_centroids[0])
+		+ sizeof(m_bounding_box)
+		;
+}
+
+
+inline const std::vector<Point_3f> &
+Indexed_tetra_set::get_vertices() const
+{
+	return m_vertices;
+}
+
+
+inline std::vector<Point_3f> &
+Indexed_tetra_set::get_vertices()
+{
+	return m_vertices;
+}
+
+
+inline const std::vector<unsigned> &
+Indexed_tetra_set::get_vertex_global_indices() const
+{
+	return m_global_indices;
+}
+
+
+inline std::vector<unsigned> &
+Indexed_tetra_set::get_vertex_global_indices()
+{
+	return m_global_indices;
+}
+
+
+inline const Tetrahedron &Indexed_tetra_set::get_tetrahedron(unsigned i) const
+{
+	// 0 is dummy
+	GTB_REQUIRE((i > 0) && (i < m_tetrahedra.size()));
+	return m_tetrahedra[i];
+}
+
+
+inline const std::vector<Tetrahedron> &
+Indexed_tetra_set::get_tetrahedra() const
+{
+	return m_tetrahedra;
+}
+
+
+inline std::vector<Tetrahedron> &
+Indexed_tetra_set::get_tetrahedra()
+{
+	return m_tetrahedra;
+}
+
+
+inline const std::vector<Indexed_tetra_set::Face> &
+Indexed_tetra_set::get_faces() const
+{
+	return m_faces;
+}
+
+
+inline std::vector<Indexed_tetra_set::Face> &
+Indexed_tetra_set::get_faces()
+{
+	return m_faces;
+}
+
+
+inline const std::vector<Point_3f> &
+Indexed_tetra_set::get_centroids() const
+{
+	return m_centroids;
+}
+
+
+inline std::vector<Point_3f> &
+Indexed_tetra_set::get_centroids()
+{
+	return m_centroids;
+}
+
+
+inline bool Indexed_tetra_set::Face::
+operator==(const Indexed_tetra_set::Face &b) const
+{
+        const Indexed_tetra_set::Face &a = *this;
+	return (a.m_vertices[0] == b.m_vertices[0] &&
+		a.m_vertices[1] == b.m_vertices[1] &&
+		a.m_vertices[2] == b.m_vertices[2]);
+}
+
+
+inline bool Indexed_tetra_set::Face::
+operator<(const Indexed_tetra_set::Face &b) const
+{
+        const Indexed_tetra_set::Face &a = *this;
+	if (a.m_vertices[0] == b.m_vertices[0]) {
+		if (a.m_vertices[1] == b.m_vertices[1]) {
+			return (a.m_vertices[2] < b.m_vertices[2]);
+		} else {
+			return (a.m_vertices[1] < b.m_vertices[1]);
+		}
+	} else {
+		return (a.m_vertices[0] < b.m_vertices[0]);
+	}
+}
+
+
+inline void Indexed_tetra_set::Face::set_vertices(unsigned v0,
+						  unsigned v1,
+						  unsigned v2)
+{
+	m_vertices[0] = v0;
+	m_vertices[1] = v1;
+	m_vertices[2] = v2;
+}
+
+
+inline unsigned Indexed_tetra_set::Face::get_vertex(unsigned i) const
+{
+	assert(i < 3);
+	return m_vertices[i];
+}
+
+
+inline unsigned Indexed_tetra_set::Face::get_left_tetra() const
+{
+	return m_left_tetra;
+}
+
+
+inline void Indexed_tetra_set::Face::set_left_tetra(unsigned t)
+{
+	m_left_tetra = t;
+}
+
+
+inline unsigned Indexed_tetra_set::Face::get_right_tetra() const
+{
+	return m_right_tetra;
+}
+
+
+inline void Indexed_tetra_set::Face::set_right_tetra(unsigned t)
+{
+	m_right_tetra = t;
+}
+
+
+inline char Indexed_tetra_set::Face::get_index_on_left_tetra() const
+{
+	return m_index_on_left_tetra;
+}
+
+
+inline void Indexed_tetra_set::Face::set_index_on_left_tetra(char i)
+{
+	m_index_on_left_tetra = i;
+}
+
+
+inline char Indexed_tetra_set::Face::get_index_on_right_tetra() const
+{
+	return m_index_on_right_tetra;
+}
+
+
+inline void Indexed_tetra_set::Face::set_index_on_right_tetra(char i)
+{
+	m_index_on_right_tetra = i;
+}
+
+
+inline unsigned Indexed_tetra_set::Face::get_left_octree_node() const
+{
+	return m_left_octree_node;
+}
+
+
+inline void Indexed_tetra_set::Face::set_left_octree_node(unsigned on)
+{
+	m_left_octree_node = on;
+}
+
+
+inline unsigned Indexed_tetra_set::Face::get_right_octree_node() const
+{
+	return m_right_octree_node;
+}
+
+
+inline void Indexed_tetra_set::Face::set_right_octree_node(unsigned on)
+{
+	m_right_octree_node = on;
+}
+
+
+inline bool Indexed_tetra_set::Face::is_exterior() const
+{
+	return m_is_exterior;
+}
+
+
+inline void Indexed_tetra_set::Face::set_exterior(bool value)
+{
+	m_is_exterior = value;
+}
+
+
+inline const Plane_3f &Indexed_tetra_set::Face::get_plane() const
+{
+	return m_plane;
+}
+
+
+inline void Indexed_tetra_set::Face::set_plane(const Plane_3f &p)
+{
+	m_plane = p;
+}
+
+
+inline unsigned Indexed_tetra_set::get_num_vertices() const
+{
+	return m_vertices.size();
+}
+
+
+inline unsigned Indexed_tetra_set::get_num_tetrahedra() const
+{
+    return m_tetrahedra.size();
+	//return m_tetrahedra.size() - 1; // TODO: off by one error? check all code that refers to this function
+}
+
+
+inline unsigned Indexed_tetra_set::get_num_primitives() const
+{
+	return get_num_tetrahedra();
+}
+
+
+inline unsigned Indexed_tetra_set::get_num_faces() const
+{
+	return m_faces.size();
+}
+
+
+inline unsigned Indexed_tetra_set::get_num_centroids() const
+{
+	return m_centroids.size();
+}
+
+
+inline unsigned Indexed_tetra_set::get_num_exterior_faces() const
+{
+	return m_num_exterior_faces;
+}
+
+
+inline unsigned Indexed_tetra_set::get_num_exterior_tetrahedra() const
+{
+	return m_num_exterior_tetrahedra;
+}
+
+
+inline bool Indexed_tetra_set::is_complete() const
+{
+	return m_complete;
+}
+
+inline bool Indexed_tetra_set::is_out_of_core() const
+{
+	return m_out_of_core;
+}
+
+
+inline unsigned Indexed_tetra_set::get_global_vertex(unsigned local_vertex)
+{
+	GTB_REQUIRE(local_vertex < m_global_indices.size());
+	return m_global_indices[local_vertex];
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_INDEXED_TETRA_SET_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set_off_reader.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set_off_reader.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set_off_reader.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,104 @@
+#ifndef GTB_INDEXED_TETRA_SET_OFF_READER_INCLUDED
+#include "Indexed_tetra_set_off_reader.hpp"
+#endif
+
+#ifndef GTB_INDEXED_TETRA_SET_INCLUDED
+#include "Indexed_tetra_set.hpp"
+#endif
+
+#ifndef GTB_TIME_SERIES_INCLUDED
+#include "Time_series.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+Indexed_tetra_set_off_reader::Indexed_tetra_set_off_reader()
+{
+}
+
+
+void Indexed_tetra_set_off_reader::read(FILE *in_off_fp,
+					Indexed_tetra_set **out_its,
+					Scalar_time_series **out_sts)
+{
+	GTB_REQUIRE(in_off_fp);
+
+        // start fresh (same reader can be used multiple times)
+	m_vertices.clear();
+	m_tetrahedra.clear();
+
+	unsigned num_vertices;
+	unsigned num_tetrahedra;
+	if (fscanf(in_off_fp, "%u %u", &num_vertices, &num_tetrahedra) != 2) {
+		GTB_ERROR("failed to read the header");
+	}
+
+	// write scalars header
+// 	unsigned num_times = 1;
+// 	unsigned num_scalars_per_time = num_vertices;
+// 	Scalar_time_series::File_header header(num_times,
+// 					       num_scalars_per_time,
+// 					       FLT_MAX,
+// 					       FLT_MIN);
+// 	header.write(out_scalars_fp);
+	std::vector<float> scalars(num_vertices);
+
+	// for each vertex
+	float min_scalar = FLT_MAX;
+	float max_scalar = FLT_MIN;
+	m_vertices.resize(num_vertices);
+	for (unsigned i = 0; i < num_vertices; i++) {
+		// read vertex and scalar
+		Point_3f p;
+		float s;
+		if (fscanf(in_off_fp, "%f %f %f %f",
+			   &p[0], &p[1], &p[2], &s) != 4) {
+			GTB_ERROR("failed to read the vertices");
+		}
+		m_vertices[i] = p;
+
+		// update min and max
+		if (s < min_scalar) {
+			min_scalar = s;
+		}
+		if (s > max_scalar) {
+			max_scalar = s;
+		}
+
+		// write scalar
+// 		if (fwrite(&s, sizeof(s), 1, out_scalars_fp) != 1) {
+// 			GTB_ERROR("failed to write scalar");
+// 		}
+		scalars[i] = s;
+	}
+
+	// update min and max
+// 	header.set_min_value(min_scalar);
+// 	header.set_max_value(max_scalar);
+// 	fseek(out_scalars_fp, 0, SEEK_SET);
+// 	header.write(out_scalars_fp);
+	Scalar_time_series *sts = new Scalar_time_series(scalars);
+	sts->set_min_value(min_scalar);
+	sts->set_max_value(max_scalar);
+
+	// read tetrahedra 
+	m_tetrahedra.reserve(num_tetrahedra + 1);
+	Tetrahedron dummy;
+	m_tetrahedra.push_back(dummy);
+	for (unsigned i = 0; i < num_tetrahedra; i++) {
+		unsigned a, b, c, d;
+		if (fscanf(in_off_fp, "%u %u %u %u", &a, &b, &c, &d) != 4) {
+			GTB_ERROR("failed to read the tetrahedra");
+		}
+		Tetrahedron t(a, b, c, d);
+		m_tetrahedra.push_back(t);	
+	}
+
+        // create indexed tetra set
+	*out_its = new Indexed_tetra_set(m_vertices, m_tetrahedra);
+	*out_sts = sts;
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set_off_reader.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set_off_reader.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Indexed_tetra_set_off_reader.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,45 @@
+#ifndef GTB_INDEXED_TETRA_SET_OFF_READER_INCLUDED
+#define GTB_INDEXED_TETRA_SET_OFF_READER_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_C_STDIO_INCLUDED
+#include <stdio.h>
+#define GTB_C_STDIO_INCLUDED
+#endif
+
+#ifndef GTB_POINT_3F_INCLUDED
+#include "Point_3f.hpp"
+#endif
+
+#ifndef GTB_TIME_SERIES_INCLUDED
+#include "Time_series.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+class Indexed_tetra_set;
+class Tetrahedron;
+
+
+class Indexed_tetra_set_off_reader {
+public:
+	Indexed_tetra_set_off_reader();
+
+        //Indexed_tetra_set *read(FILE *in_off_fp, FILE *out_scalars_fp);
+     
+        void read(FILE *in_off_fp,
+	     Indexed_tetra_set **out_its,
+	     Scalar_time_series **out_sts);
+
+protected:
+ 	std::vector<Point_3f> m_vertices;
+	std::vector<Tetrahedron> m_tetrahedra;
+};
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_INDEXED_TETRA_SET_OFF_READER_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Line_3f.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Line_3f.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Line_3f.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,8 @@
+#ifndef GTB_LINE_3F_INCLUDED
+#include "Line_3f.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Line_3f.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Line_3f.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Line_3f.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,118 @@
+#ifndef GTB_LINE_3F_INCLUDED
+#define GTB_LINE_3F_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_POINT_3F_INCLUDED
+#include "Point_3f.hpp"
+#endif
+
+#ifndef GTB_VECTOR_3F_INCLUDED
+#include "Vector_3f.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+class Line_3f {
+public:
+	Line_3f();
+	Line_3f(const Line_3f &l);
+	Line_3f(const Point_3f &p, const Point_3f &q);
+	Line_3f(const Point_3f &p, const Vector_3f &d, bool is_normalized);
+	Line_3f &operator=(const Line_3f &r);
+
+	bool eps_is_equal(const Line_3f &l, float eps) const;
+	bool eps_contains(const Point_3f &p, float eps) const;
+
+	// Returns an arbitrary point on the line.
+	// point(i) == point(j), iff i == j.
+	Point_3f point(int i) const;
+
+	const Vector_3f &direction() const;
+
+	Point_3f projection(const Point_3f &p) const;
+
+protected:
+	Point_3f m_p;
+        Vector_3f m_d;
+};
+
+
+inline Line_3f::Line_3f()
+{
+}
+
+
+inline Line_3f::Line_3f(const Line_3f &l)
+	: m_p(l.m_p),
+	  m_d(l.m_d)
+{
+}
+
+
+inline Line_3f::Line_3f(const Point_3f &p, const Point_3f &q)
+	: m_p(p),
+	  m_d(q - p)
+{
+	m_d.normalize();
+}
+
+
+inline Line_3f::Line_3f(const Point_3f &p,
+			const Vector_3f &d,
+			bool is_normalized)
+	: m_p(p),
+	  m_d(d)
+{
+	if (!is_normalized) {
+		m_d.normalize();
+	}
+}
+
+
+inline Line_3f &Line_3f::operator=(const Line_3f &l)
+{
+	m_p = l.m_p;
+	m_d = l.m_d;
+	return *this;
+}
+
+
+inline bool Line_3f::eps_contains(const Point_3f &p, float eps) const
+{
+	return (p - m_p).cross(m_d).eps_is_zero(eps);
+}
+
+
+inline bool Line_3f::eps_is_equal(const Line_3f &l, float eps) const
+{
+	return ((m_d.eps_is_equal(l.m_d, eps) 
+		 || m_d.eps_is_equal(-l.m_d, eps))
+		&& eps_contains(l.m_p, eps));
+}
+
+
+inline const Vector_3f &Line_3f::direction() const
+{
+	return m_d;
+}
+
+
+inline Point_3f Line_3f::point(int i) const
+{
+	return m_p + (i * m_d);
+}
+
+
+inline Point_3f Line_3f::projection(const Point_3f &p) const
+{
+	return m_p + ((p - m_p).dot(m_d)) * m_d;
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_LINE_3F_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Matrix_4d.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Matrix_4d.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Matrix_4d.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,475 @@
+#ifndef GTB_MATRIX_4D_INCLUDED
+#include "Matrix_4d.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+const Matrix_4d MATRIX_4D_ZERO(0.0, 0.0, 0.0, 0.0,
+			       0.0, 0.0, 0.0, 0.0,
+			       0.0, 0.0, 0.0, 0.0,
+			       0.0, 0.0, 0.0, 0.0);
+
+
+const Matrix_4d MATRIX_4D_IDENTITY(1.0, 0.0, 0.0, 0.0,
+				   0.0, 1.0, 0.0, 0.0,
+				   0.0, 0.0, 1.0, 0.0,
+				   0.0, 0.0, 0.0, 1.0);
+
+
+Matrix_4d::Matrix_4d(float m[4][4])
+{
+	m_m[0][0] = m[0][0];
+	m_m[0][1] = m[0][1];
+	m_m[0][2] = m[0][2];
+	m_m[0][3] = m[0][3];
+
+	m_m[1][0] = m[1][0];
+	m_m[1][1] = m[1][1];
+	m_m[1][2] = m[1][2];
+	m_m[1][3] = m[1][3];
+
+	m_m[2][0] = m[2][0];
+	m_m[2][1] = m[2][1];
+	m_m[2][2] = m[2][2];
+	m_m[2][3] = m[2][3];
+
+	m_m[3][0] = m[3][0];
+	m_m[3][1] = m[3][1];
+	m_m[3][2] = m[3][2];
+	m_m[3][3] = m[3][3];
+}
+
+
+Matrix_4d::Matrix_4d(float m[3][3])
+{
+        m_m[0][0] = m[0][0];
+        m_m[0][1] = m[0][1];
+        m_m[0][2] = m[0][2];
+        m_m[0][3] = 0.0;
+                                                                                                                   
+        m_m[1][0] = m[1][0];
+        m_m[1][1] = m[1][1];
+        m_m[1][2] = m[1][2];
+        m_m[1][3] = 0.0;
+                                                                                                                   
+        m_m[2][0] = m[2][0];
+        m_m[2][1] = m[2][1];
+        m_m[2][2] = m[2][2];
+        m_m[2][3] = 0.0;
+                                                                                                                   
+        m_m[3][0] = 0.0;
+        m_m[3][1] = 0.0;
+        m_m[3][2] = 0.0;
+        m_m[3][3] = 1.0;
+}
+
+
+Matrix_4d::Matrix_4d(float m[16])
+{
+	m_m[0][0] = m[0];
+	m_m[0][1] = m[1];
+	m_m[0][2] = m[2];
+	m_m[0][3] = m[3];
+
+	m_m[1][0] = m[4];
+	m_m[1][1] = m[5];
+	m_m[1][2] = m[6];
+	m_m[1][3] = m[7];
+
+	m_m[2][0] = m[8];
+	m_m[2][1] = m[9];
+	m_m[2][2] = m[10];
+	m_m[2][3] = m[11];
+
+	m_m[3][0] = m[12];
+	m_m[3][1] = m[13];
+	m_m[3][2] = m[14];
+	m_m[3][3] = m[15];
+}
+
+
+Matrix_4d::Matrix_4d(double m[4][4])
+{
+	m_m[0][0] = m[0][0];
+	m_m[0][1] = m[0][1];
+	m_m[0][2] = m[0][2];
+	m_m[0][3] = m[0][3];
+
+	m_m[1][0] = m[1][0];
+	m_m[1][1] = m[1][1];
+	m_m[1][2] = m[1][2];
+	m_m[1][3] = m[1][3];
+
+	m_m[2][0] = m[2][0];
+	m_m[2][1] = m[2][1];
+	m_m[2][2] = m[2][2];
+	m_m[2][3] = m[2][3];
+
+	m_m[3][0] = m[3][0];
+	m_m[3][1] = m[3][1];
+	m_m[3][2] = m[3][2];
+	m_m[3][3] = m[3][3];
+}
+
+
+Matrix_4d::Matrix_4d(double m[16])
+{
+	m_m[0][0] = m[0];
+	m_m[0][1] = m[1];
+	m_m[0][2] = m[2];
+	m_m[0][3] = m[3];
+
+	m_m[1][0] = m[4];
+	m_m[1][1] = m[5];
+	m_m[1][2] = m[6];
+	m_m[1][3] = m[7];
+
+	m_m[2][0] = m[8];
+	m_m[2][1] = m[9];
+	m_m[2][2] = m[10];
+	m_m[2][3] = m[11];
+
+	m_m[3][0] = m[12];
+	m_m[3][1] = m[13];
+	m_m[3][2] = m[14];
+	m_m[3][3] = m[15];
+}
+
+
+Matrix_4d::Matrix_4d(double m00, double m01, double m02, double m03,
+		     double m10, double m11, double m12, double m13,
+		     double m20, double m21, double m22, double m23,
+		     double m30, double m31, double m32, double m33)
+{
+	m_m[0][0] = m00;
+	m_m[0][1] = m01;
+	m_m[0][2] = m02;
+	m_m[0][3] = m03;
+
+	m_m[1][0] = m10;
+	m_m[1][1] = m11;
+	m_m[1][2] = m12;
+	m_m[1][3] = m13;
+
+	m_m[2][0] = m20;
+	m_m[2][1] = m21;
+	m_m[2][2] = m22;
+	m_m[2][3] = m23;
+
+	m_m[3][0] = m30;
+	m_m[3][1] = m31;
+	m_m[3][2] = m32;
+	m_m[3][3] = m33;
+}
+
+
+Matrix_4d::Matrix_4d(const Matrix_4d &m)
+{
+	m_m[0][0] = m.m_m[0][0];
+	m_m[0][1] = m.m_m[0][1];
+	m_m[0][2] = m.m_m[0][2];
+	m_m[0][3] = m.m_m[0][3];
+
+	m_m[1][0] = m.m_m[1][0];
+	m_m[1][1] = m.m_m[1][1];
+	m_m[1][2] = m.m_m[1][2];
+	m_m[1][3] = m.m_m[1][3];
+
+	m_m[2][0] = m.m_m[2][0];
+	m_m[2][1] = m.m_m[2][1];
+	m_m[2][2] = m.m_m[2][2];
+	m_m[2][3] = m.m_m[2][3];
+
+	m_m[3][0] = m.m_m[3][0];
+	m_m[3][1] = m.m_m[3][1];
+	m_m[3][2] = m.m_m[3][2];
+	m_m[3][3] = m.m_m[3][3];
+}
+
+
+Matrix_4d &Matrix_4d::operator=(const Matrix_4d &m)
+{
+	if (&m != this) {
+		m_m[0][0] = m.m_m[0][0];
+		m_m[0][1] = m.m_m[0][1];
+		m_m[0][2] = m.m_m[0][2];
+		m_m[0][3] = m.m_m[0][3];
+
+		m_m[1][0] = m.m_m[1][0];
+		m_m[1][1] = m.m_m[1][1];
+		m_m[1][2] = m.m_m[1][2];
+		m_m[1][3] = m.m_m[1][3];
+
+		m_m[2][0] = m.m_m[2][0];
+		m_m[2][1] = m.m_m[2][1];
+		m_m[2][2] = m.m_m[2][2];
+		m_m[2][3] = m.m_m[2][3];
+
+		m_m[3][0] = m.m_m[3][0];
+		m_m[3][1] = m.m_m[3][1];
+		m_m[3][2] = m.m_m[3][2];
+		m_m[3][3] = m.m_m[3][3];
+	}
+	return *this;
+}
+
+
+Matrix_4d &Matrix_4d::make_identity()
+{
+	m_m[0][0] = 1.0;
+	m_m[0][1] = 0.0;
+	m_m[0][2] = 0.0;
+	m_m[0][3] = 0.0;
+
+	m_m[1][0] = 0.0;
+	m_m[1][1] = 1.0;
+	m_m[1][2] = 0.0;
+	m_m[1][3] = 0.0;
+
+	m_m[2][0] = 0.0;
+	m_m[2][1] = 0.0;
+	m_m[2][2] = 1.0;
+	m_m[2][3] = 0.0;
+
+	m_m[3][0] = 0.0;
+	m_m[3][1] = 0.0;
+	m_m[3][2] = 0.0;
+	m_m[3][3] = 1.0;
+
+	return *this;
+}
+
+
+Matrix_4d &Matrix_4d::negate()
+{
+	m_m[0][0] = -m_m[0][0];
+	m_m[0][1] = -m_m[0][1];
+	m_m[0][2] = -m_m[0][2];
+	m_m[0][3] = -m_m[0][3];
+
+	m_m[1][0] = -m_m[1][0];
+	m_m[1][1] = -m_m[1][1];
+	m_m[1][2] = -m_m[1][2];
+	m_m[1][3] = -m_m[1][3];
+
+	m_m[2][0] = -m_m[2][0];
+	m_m[2][1] = -m_m[2][1];
+	m_m[2][2] = -m_m[2][2];
+	m_m[2][3] = -m_m[2][3];
+
+	m_m[3][0] = -m_m[3][0];
+	m_m[3][1] = -m_m[3][1];
+	m_m[3][2] = -m_m[3][2];
+	m_m[3][3] = -m_m[3][3];
+
+	return *this;
+}
+
+
+bool Matrix_4d::LU_decomposition(int p[4])
+{
+	int i, j, k;
+
+	for (j = 0; j < 3; j++) {
+
+		// Find line of pivot
+		p[j] = j;
+		for (i = j + 1; i < 4; i++) {
+			if (fabs(m_m[i][j]) > fabs(m_m[p[j]][j])) {
+				p[j] = i;
+			}
+		}
+
+		// Swap lines if necessary
+		if (p[j] != j) {
+			i = p[j];
+			for (k = 0; k < 4; k++) {
+				double t = m_m[i][k];
+				m_m[i][k] = m_m[j][k];
+				m_m[j][k] = t;
+			}
+		}
+
+		// Check if matrix is singular
+		if (gtb::eps_is_zero(m_m[j][j], DBL_EPSILON)) {
+//			GTB_WARNING("singular matrix");
+			return false;
+		}
+
+		// Eliminate elements below diagonal
+		for (i = j + 1; i < 4; i++) {
+			m_m[i][j] = -m_m[i][j] / m_m[j][j];
+			for (k = j + 1; k < 4; k++) {
+				m_m[i][k] += m_m[i][j] * m_m[j][k];
+			}
+		}
+	}
+	return true;
+}
+
+
+void Matrix_4d::LU_back_substitution(const int p[4],
+				     Matrix_4d &b,
+				     Matrix_4d &x)
+{
+	int i, j, k;
+
+	// Swap lines of b when necessary
+	for (i = 0; i < 3; i++) {
+		if (p[i] != i) {
+			for (j = 0, k = p[i]; j < 4; j++) {
+				double t = b.m_m[i][j];
+				b.m_m[i][j] = b.m_m[k][j];
+				b.m_m[k][j] = t;
+			}
+		}
+	}
+
+	// Apply multipliers to b
+	for (j = 0; j < 3 ; j++) {
+		for (i = j + 1; i < 4; i++) {
+			for (k = 0; k < 4; k++) {
+				b.m_m[i][k] += m_m[i][j] * b.m_m[j][k];
+			}
+		}
+	}
+
+	// Back substitution
+	for (k = 0; k < 4; k++) {
+		for (i = 3; i >= 0; i--) {
+			x.m_m[i][k] = b.m_m[i][k];
+			for (j = i + 1; j < 4; j++) {
+				x.m_m[i][k] -= m_m[i][j] * x.m_m[j][k];
+			}
+			GTB_CHECK(!gtb::eps_is_zero(m_m[i][i], DBL_EPSILON));
+			x.m_m[i][k] /= m_m[i][i];
+		}
+	}
+}
+
+
+Matrix_4d Matrix_4d::inverse() const
+{
+	Matrix_4d a(*this);
+	Matrix_4d b(MATRIX_4D_IDENTITY);
+	Matrix_4d x;
+	int p[4];
+
+	a.LU_decomposition(p);
+	a.LU_back_substitution(p, b, x);
+	return x;
+}
+
+
+double Matrix_4d::det() const
+{
+	double d;
+	Matrix_4d t(*this);
+	int p[4];
+
+	t.LU_decomposition(p);
+	d = 1.0;
+	for (int i = 0; i < 3; i++) {
+		d *= t.m_m[i][i];
+		if (p[i] != i) {
+			d = -d;
+		}
+	}
+	d *= t.m_m[3][3];
+	return d;
+}
+
+inline
+void Matrix_4d::rot(const double s, const double tau, const int i,
+		    const int j, const int k, const int l)
+{
+	double g,h;
+
+	g = m_m[i][j];
+	h = m_m[k][l];
+	m_m[i][j] = g-s*(h+g*tau);
+	m_m[k][l] = h+s*(g-h*tau);
+}
+
+bool Matrix_4d::jacobi(float *d, double **v, int &nrot)
+{
+	int i,j,ip,iq;
+	double tresh,theta,tau,t,sm,s,h,g,c;
+
+	int n=4;
+	double b[4];
+	double z[4];
+	for (ip=0; ip<n; ip++) {
+		for (iq=0; iq<n; iq++) v[ip][iq] = 0.0;
+		v[ip][ip] = 1.0;
+	}
+	for (ip=0; ip<n; ip++) {
+		b[ip] = d[ip] = m_m[ip][ip];
+		z[ip] = 0.0;
+	}
+	nrot = 0;
+	for (i=1; i<= 50; i++) {
+		sm = 0.0;
+		// sum magnitude of off-diagonal elements
+		for (ip=0; ip<n-1; ip++) {
+			for (iq=ip+1; iq<n; iq++)
+				sm += fabs(m_m[ip][iq]);
+		}
+		if (sm == 0.0) {
+			// relies on quadric convergence to machine underflow
+			return true;
+		}
+		if (i < 4)
+			tresh = 0.2*sm/(n*n);
+		else
+			tresh = 0.0;
+		for (ip=0; ip<n-1; ip++) {
+			for (iq=ip+1; iq<n; iq++) {
+				g=100.0 * fabs(m_m[i][iq]);
+				// after 4 sweeps, skip the rotation if the off-diagonal element is small.
+				if (i > 4 && (fabs(d[ip])+g) == fabs(d[ip])
+				    && (fabs(d[iq])+g) == fabs(d[iq]))
+					m_m[ip][iq] = 0.0;
+				else if (fabs(m_m[ip][iq]) > tresh) {
+					h = d[iq]-d[ip];
+					if ((fabs(h)+g) == fabs(h)) {
+						t = (m_m[ip][iq])/h;
+					} else {
+						theta = 0.5*h/(m_m[ip][iq]);
+						t = 1.0/(fabs(theta)+sqrt(1.0+theta*theta));
+						if (theta < 0.0) t = -t;
+					}
+					c = 1.0/sqrt(1+t*t);
+					s = t*c;
+					tau = s/(1.0+c);
+					h=t*m_m[ip][iq];
+					z[ip] -= h;
+					z[iq] += h;
+					d[ip] -= h;
+					d[iq] += h;
+					m_m[ip][iq] = 0.0;
+					for (j=0; j<ip; j++)
+						rot(s, tau, j, ip, j, iq);
+					for (j=ip+1; j<iq; j++)
+						rot(s, tau, ip, j, j, iq);
+					for (j=iq+1; i<n; j++)
+						rot(s, tau, ip, j, iq, j);
+					for (j=0; j<n; j++)
+						rot(s, tau, j, ip, j, iq);
+					++nrot;
+				}
+			}
+		}
+		for (ip=0; ip<n; ip++) {
+			b[ip] += z[ip];
+			d[ip] = b[ip];
+			z[ip] = 0.0;
+		}
+	}
+	// Too many iterations in routine jacobi
+	return false;
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Matrix_4d.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Matrix_4d.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Matrix_4d.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,371 @@
+#ifndef GTB_MATRIX_4D_INCLUDED
+#define GTB_MATRIX_4D_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_ASSERTIONS_INCLUDED
+#include "assertions.hpp"
+#endif
+
+#ifndef GTB_EPSILON_INCLUDED
+#include "epsilon.hpp"
+#endif
+
+#ifndef GTB_C_MATH_INCLUDED
+#include <math.h>
+#define GTB_C_MATH_INCLUDED
+#endif
+
+#ifndef GTB_C_FLOAT_INCLUDED
+#include <float.h>
+#define GTB_C_FLOAT_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+class Matrix_4d {
+public:
+	Matrix_4d();
+
+	explicit Matrix_4d(float m[4][4]);
+	explicit Matrix_4d(float m[3][3]);
+	explicit Matrix_4d(float m[16]);
+
+	explicit Matrix_4d(double m[4][4]);
+	explicit Matrix_4d(double m[16]);
+
+	Matrix_4d(double m00, double m01, double m02, double m03,
+		  double m10, double m11, double m12, double m13,
+		  double m20, double m21, double m22, double m23,
+		  double m30, double m31, double m32, double m33);
+
+	Matrix_4d(const Matrix_4d &m);
+	Matrix_4d &operator=(const Matrix_4d &m);
+
+	bool eps_is_equal(const Matrix_4d &m, double eps) const;
+
+	Matrix_4d &reset(double m00, double m01, double m02, double m03,
+			 double m10, double m11, double m12, double m13,
+			 double m20, double m21, double m22, double m23,
+			 double m30, double m31, double m32, double m33);
+
+	Matrix_4d &make_identity();
+	Matrix_4d &negate();
+
+	Matrix_4d transpose() const;
+	Matrix_4d inverse() const;
+	double det() const;
+
+	const double &operator()(unsigned i, unsigned j) const;
+	double &operator()(unsigned i, unsigned j);
+
+	Matrix_4d operator-() const;
+	Matrix_4d &operator+=(const Matrix_4d &m);
+	Matrix_4d &operator-=(const Matrix_4d &m);
+	Matrix_4d &operator*=(const Matrix_4d &m);
+	Matrix_4d &operator*=(double a);
+
+	friend Matrix_4d operator+(const Matrix_4d &m1, const Matrix_4d &m2);
+	friend Matrix_4d operator-(const Matrix_4d &m1, const Matrix_4d &m2);
+	friend Matrix_4d operator*(const Matrix_4d &m1, const Matrix_4d &m2);
+	friend Matrix_4d operator*(const double a, const Matrix_4d &m);
+	friend Matrix_4d operator*(const Matrix_4d &m, double a);
+
+	bool jacobi(float *d, double **v, int &nrot);
+
+	bool LU_decomposition(int p[4]);
+
+	void LU_back_substitution(const int p[4],
+				  Matrix_4d &b,
+				  Matrix_4d &x);
+protected:
+	void rot(const double s, const double tau, const int i,
+			    const int j, const int k, const int l);
+
+	double m_m[4][4];
+};
+
+
+extern const Matrix_4d MATRIX_4D_ZERO;
+extern const Matrix_4d MATRIX_4D_IDENTITY;
+
+
+inline Matrix_4d::Matrix_4d()
+{
+}
+
+
+inline bool Matrix_4d::eps_is_equal(const Matrix_4d &m, double eps) const
+{
+	return (gtb::eps_is_equal(m_m[0][0], m.m_m[0][0], eps) &&
+		gtb::eps_is_equal(m_m[0][1], m.m_m[0][1], eps) &&
+		gtb::eps_is_equal(m_m[0][2], m.m_m[0][2], eps) &&
+		gtb::eps_is_equal(m_m[0][3], m.m_m[0][3], eps) &&
+		
+		gtb::eps_is_equal(m_m[1][0], m.m_m[1][0], eps) &&
+		gtb::eps_is_equal(m_m[1][1], m.m_m[1][1], eps) &&
+		gtb::eps_is_equal(m_m[1][2], m.m_m[1][2], eps) &&
+		gtb::eps_is_equal(m_m[1][3], m.m_m[1][3], eps) &&
+		
+		gtb::eps_is_equal(m_m[2][0], m.m_m[2][0], eps) &&
+		gtb::eps_is_equal(m_m[2][1], m.m_m[2][1], eps) &&
+		gtb::eps_is_equal(m_m[2][2], m.m_m[2][2], eps) &&
+		gtb::eps_is_equal(m_m[2][3], m.m_m[2][3], eps) &&
+		
+		gtb::eps_is_equal(m_m[3][0], m.m_m[3][0], eps) &&
+		gtb::eps_is_equal(m_m[3][1], m.m_m[3][1], eps) &&
+		gtb::eps_is_equal(m_m[3][2], m.m_m[3][2], eps) &&
+		gtb::eps_is_equal(m_m[3][3], m.m_m[3][3], eps));
+}
+
+
+inline Matrix_4d &Matrix_4d::reset(
+	double m00, double m01, double m02, double m03,
+	double m10, double m11, double m12, double m13,
+	double m20, double m21, double m22, double m23,
+	double m30, double m31, double m32, double m33)
+{
+	m_m[0][0] = m00;
+	m_m[0][1] = m01;
+	m_m[0][2] = m02;
+	m_m[0][3] = m03;
+
+	m_m[1][0] = m10;
+	m_m[1][1] = m11;
+	m_m[1][2] = m12;
+	m_m[1][3] = m13;
+
+	m_m[2][0] = m20;
+	m_m[2][1] = m21;
+	m_m[2][2] = m22;
+	m_m[2][3] = m23;
+
+	m_m[3][0] = m30;
+	m_m[3][1] = m31;
+	m_m[3][2] = m32;
+	m_m[3][3] = m33;
+
+	return *this;
+}
+
+
+inline Matrix_4d Matrix_4d::transpose() const
+{
+	return Matrix_4d(m_m[0][0], m_m[1][0], m_m[2][0], m_m[3][0],
+			 m_m[0][1], m_m[1][1], m_m[2][1], m_m[3][1],
+			 m_m[0][2], m_m[1][2], m_m[2][2], m_m[3][2],
+			 m_m[0][3], m_m[1][3], m_m[2][3], m_m[3][3]);
+}
+
+
+inline const double &Matrix_4d::operator()(unsigned i, unsigned j) const
+{
+	GTB_REQUIRE(i < 4);
+	GTB_REQUIRE(j < 4);
+	return m_m[i][j];
+}
+
+
+inline double &Matrix_4d::operator()(unsigned i, unsigned j)
+{
+	GTB_REQUIRE(i < 4);
+	GTB_REQUIRE(j < 4);
+	return m_m[i][j];
+}
+
+
+inline Matrix_4d Matrix_4d::operator-() const
+{
+	return Matrix_4d(-m_m[0][0], -m_m[0][1], -m_m[0][2], -m_m[0][3],
+			 -m_m[1][0], -m_m[1][1], -m_m[1][2], -m_m[1][3],
+			 -m_m[2][0], -m_m[2][1], -m_m[2][2], -m_m[2][3],
+			 -m_m[3][0], -m_m[3][1], -m_m[3][2], -m_m[3][3]);
+}
+
+
+inline Matrix_4d &Matrix_4d::operator+=(const Matrix_4d &m)
+{
+	m_m[0][0] += m.m_m[0][0];
+	m_m[0][1] += m.m_m[0][1];
+	m_m[0][2] += m.m_m[0][2];
+	m_m[0][3] += m.m_m[0][3];
+
+	m_m[1][0] += m.m_m[1][0];
+	m_m[1][1] += m.m_m[1][1];
+	m_m[1][2] += m.m_m[1][2];
+	m_m[1][3] += m.m_m[1][3];
+
+	m_m[2][0] += m.m_m[2][0];
+	m_m[2][1] += m.m_m[2][1];
+	m_m[2][2] += m.m_m[2][2];
+	m_m[2][3] += m.m_m[2][3];
+
+	m_m[3][0] += m.m_m[3][0];
+	m_m[3][1] += m.m_m[3][1];
+	m_m[3][2] += m.m_m[3][2];
+	m_m[3][3] += m.m_m[3][3];
+
+	return *this;
+}
+
+
+inline Matrix_4d &Matrix_4d::operator-=(const Matrix_4d &m)
+{
+	m_m[0][0] -= m.m_m[0][0];
+	m_m[0][1] -= m.m_m[0][1];
+	m_m[0][2] -= m.m_m[0][2];
+	m_m[0][3] -= m.m_m[0][3];
+
+	m_m[1][0] -= m.m_m[1][0];
+	m_m[1][1] -= m.m_m[1][1];
+	m_m[1][2] -= m.m_m[1][2];
+	m_m[1][3] -= m.m_m[1][3];
+
+	m_m[2][0] -= m.m_m[2][0];
+	m_m[2][1] -= m.m_m[2][1];
+	m_m[2][2] -= m.m_m[2][2];
+	m_m[2][3] -= m.m_m[2][3];
+
+	m_m[3][0] -= m.m_m[3][0];
+	m_m[3][1] -= m.m_m[3][1];
+	m_m[3][2] -= m.m_m[3][2];
+	m_m[3][3] -= m.m_m[3][3];
+
+	return *this;
+}
+
+
+inline Matrix_4d operator*(const Matrix_4d &m1, const Matrix_4d &m2)
+{
+	Matrix_4d t;
+
+	for (unsigned i = 0; i < 4; i++) {
+		for (unsigned j = 0; j < 4; j++) {
+			t.m_m[i][j] = 0.0;
+			for (unsigned k = 0; k < 4; k++) {
+				t.m_m[i][j] += m1.m_m[i][k] * m2.m_m[k][j];
+			}
+		}
+	}
+	return t;
+}
+
+
+inline Matrix_4d &Matrix_4d::operator*=(const Matrix_4d &m)
+{
+	*this = *this * m;
+	return *this;
+}
+
+
+inline Matrix_4d &Matrix_4d::operator*=(double a)
+{
+	m_m[0][0] *= a;
+	m_m[0][1] *= a;
+	m_m[0][2] *= a;
+	m_m[0][3] *= a;
+
+	m_m[1][0] *= a;
+	m_m[1][1] *= a;
+	m_m[1][2] *= a;
+	m_m[1][3] *= a;
+
+	m_m[2][0] *= a;
+	m_m[2][1] *= a;
+	m_m[2][2] *= a;
+	m_m[2][3] *= a;
+
+	m_m[3][0] *= a;
+	m_m[3][1] *= a;
+	m_m[3][2] *= a;
+	m_m[3][3] *= a;
+
+	return *this;
+}
+
+
+inline Matrix_4d operator+(const Matrix_4d &m1, const Matrix_4d &m2)
+{
+	return Matrix_4d(m1.m_m[0][0] + m2.m_m[0][0],
+			 m1.m_m[0][1] + m2.m_m[0][1],
+			 m1.m_m[0][2] + m2.m_m[0][2],
+			 m1.m_m[0][3] + m2.m_m[0][3],
+
+			 m1.m_m[1][0] + m2.m_m[1][0],
+			 m1.m_m[1][1] + m2.m_m[1][1],
+			 m1.m_m[1][2] + m2.m_m[1][2],
+			 m1.m_m[1][3] + m2.m_m[1][3],
+
+			 m1.m_m[2][0] + m2.m_m[2][0],
+			 m1.m_m[2][1] + m2.m_m[2][1],
+			 m1.m_m[2][2] + m2.m_m[2][2],
+			 m1.m_m[2][3] + m2.m_m[2][3],
+
+			 m1.m_m[3][0] + m2.m_m[3][0],
+			 m1.m_m[3][1] + m2.m_m[3][1],
+			 m1.m_m[3][2] + m2.m_m[3][2],
+			 m1.m_m[3][3] + m2.m_m[3][3]);
+}
+
+
+inline Matrix_4d operator-(const Matrix_4d &m1, const Matrix_4d &m2)
+{
+	return Matrix_4d(m1.m_m[0][0] - m2.m_m[0][0],
+			 m1.m_m[0][1] - m2.m_m[0][1],
+			 m1.m_m[0][2] - m2.m_m[0][2],
+			 m1.m_m[0][3] - m2.m_m[0][3],
+
+			 m1.m_m[1][0] - m2.m_m[1][0],
+			 m1.m_m[1][1] - m2.m_m[1][1],
+			 m1.m_m[1][2] - m2.m_m[1][2],
+			 m1.m_m[1][3] - m2.m_m[1][3],
+
+			 m1.m_m[2][0] - m2.m_m[2][0],
+			 m1.m_m[2][1] - m2.m_m[2][1],
+			 m1.m_m[2][2] - m2.m_m[2][2],
+			 m1.m_m[2][3] - m2.m_m[2][3],
+
+			 m1.m_m[3][0] - m2.m_m[3][0],
+			 m1.m_m[3][1] - m2.m_m[3][1],
+			 m1.m_m[3][2] - m2.m_m[3][2],
+			 m1.m_m[3][3] - m2.m_m[3][3]);
+}
+
+
+inline Matrix_4d operator*(const double a, const Matrix_4d &m)
+{
+	return Matrix_4d(
+		a * m.m_m[0][0],
+		a * m.m_m[0][1],
+		a * m.m_m[0][2],
+		a * m.m_m[0][3],
+
+		a * m.m_m[1][0],
+		a * m.m_m[1][1],
+		a * m.m_m[1][2],
+		a * m.m_m[1][3],
+
+		a * m.m_m[2][0],
+		a * m.m_m[2][1],
+		a * m.m_m[2][2],
+		a * m.m_m[2][3],
+
+		a * m.m_m[3][0],
+		a * m.m_m[3][1],
+		a * m.m_m[3][2],
+		a * m.m_m[3][3]);
+}
+
+
+inline Matrix_4d operator*(const Matrix_4d &m, double a)
+{
+	return a * m;
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_MATRIX_4D_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Observer.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Observer.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Observer.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,13 @@
+#ifndef GTB_OBSERVER_INCLUDED
+#include "Observer.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+Observer::~Observer()
+{
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Observer.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Observer.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Observer.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,21 @@
+#ifndef GTB_OBSERVER_INCLUDED
+#define GTB_OBSERVER_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+class Observer {
+public:
+	virtual ~Observer();
+
+	virtual void update() = 0;
+};
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_OBSERVER_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Plane_3f.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Plane_3f.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Plane_3f.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,8 @@
+#ifndef GTB_PLANE_3F_INCLUDED
+#include "Plane_3f.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Plane_3f.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Plane_3f.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Plane_3f.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,169 @@
+#ifndef GTB_PLANE_3F_INCLUDED
+#define GTB_PLANE_3F_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_VECTOR_3F_INCLUDED
+#include "Vector_3f.hpp"
+#endif
+
+#ifndef GTB_PLANE_RST_3D_INCLUDED
+#include "Plane_RST_3d.hpp"
+#endif
+
+#ifndef GTB_MATH_INCLUDED
+#include "math.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+class Plane_3f {
+public:
+	Plane_3f();
+	Plane_3f(const Plane_3f &p);
+	Plane_3f(const Vector_3f &normal, float D);
+	Plane_3f(const Point_3f &A, const Point_3f &B, const Point_3f &C);
+	Plane_3f(const Plane_RST_3d &rhs);
+	Plane_3f &operator=(const Plane_3f &p);
+
+	const Vector_3f &get_normal() const;
+	const float &get_D() const;
+
+	void set_normal(const Vector_3f &n);
+	void set_D(float D);
+
+	float distance(const Point_3f &p) const;
+	float signed_distance(const Point_3f &p) const;
+
+	void smallest_normal_axes(unsigned &axis1, unsigned &axis2) const;
+	void flip();
+
+	bool eps_contains(const Point_3f &p, float eps) const;
+
+protected:
+	// n.p + D = 0
+	Vector_3f m_n;
+	float m_D;
+};
+
+
+inline Plane_3f::Plane_3f()
+{
+}
+
+
+inline Plane_3f::Plane_3f(const Plane_3f &p)
+	: m_n(p.m_n),
+	  m_D(p.m_D)
+{
+}
+
+
+inline Plane_3f::Plane_3f(const Vector_3f &n, float D)
+	: m_n(n),
+	  m_D(D)
+{
+}
+
+
+inline Plane_3f::Plane_3f(const Point_3f &A,
+			  const Point_3f &B,
+			  const Point_3f &C)
+	: m_n(Point_3f::normal(A, B, C)),
+	  m_D(-(m_n * A))
+{
+}
+
+
+// D = sin(rhs.t) because that's the way the optimization function
+// computes things, the idea is to find a minimum of d, we do not want
+// d=infinity because of numerical problems.
+inline Plane_3f::Plane_3f(const Plane_RST_3d &p) :
+	m_n(cos(p.get_r()) * cos(p.get_s()),
+	    sin(p.get_r()) * cos(p.get_s()),
+	    sin(p.get_s())),
+	m_D(p.get_t())		// WAS sin(p.get_t())
+{
+}
+
+
+inline Plane_3f &Plane_3f::operator=(const Plane_3f &p)
+{
+	m_n = p.m_n;
+	m_D = p.m_D;
+	return *this;
+}
+
+
+inline const Vector_3f &Plane_3f::get_normal() const
+{
+	return m_n;
+}
+
+
+inline const float &Plane_3f::get_D() const
+{
+	return m_D;
+}
+
+
+inline void Plane_3f::set_normal(const Vector_3f &n)
+{
+	m_n = n;
+}
+
+
+inline void Plane_3f::set_D(float D)
+{
+	m_D = D;
+}
+
+
+inline float Plane_3f::signed_distance(const Point_3f &p) const
+{
+	return (m_n * p + m_D);
+}
+
+
+inline float Plane_3f::distance(const Point_3f &p) const
+{
+	return abs(signed_distance(p));
+}
+
+
+inline void Plane_3f::flip()
+{
+	m_n.flip();
+	m_D = -m_D;
+}
+
+
+inline void Plane_3f::smallest_normal_axes(unsigned &axis1,
+					   unsigned &axis2) const
+{
+	if ((fabs(m_n[0]) > fabs(m_n[1])) &&
+	    (fabs(m_n[0]) > fabs(m_n[2]))) {
+		axis1 = 1;
+		axis2 = 2;
+	} else if (fabs(m_n[1]) > fabs(m_n[2])) {
+		axis1 = 0;
+		axis2 = 2;
+	} else {
+		axis1 = 0;
+		axis2 = 1;
+	}
+}
+
+
+inline bool Plane_3f::eps_contains(const Point_3f &p, float eps) const
+{
+	return gtb::eps_is_zero(signed_distance(p), eps);
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_PLANE_3F_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Plane_RST_3d.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Plane_RST_3d.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Plane_RST_3d.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,8 @@
+#ifndef GTB_PLANE_RST_3D_INCLUDED
+#include "Plane_RST_3d.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Plane_RST_3d.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Plane_RST_3d.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Plane_RST_3d.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,61 @@
+#ifndef GTB_PLANE_RST_3D_INCLUDED
+#define GTB_PLANE_RST_3D_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+// This class represents a plane in 3D using two angles and a distance
+// from the origin
+class Plane_RST_3d {
+public:
+	Plane_RST_3d();
+	Plane_RST_3d(double r, double s, double t);
+
+	const double &get_r() const;
+	const double &get_s() const;
+	const double &get_t() const;
+
+protected:
+	double m_r, m_s;	// Angles
+	double m_t;		// Distance from the origin
+};
+
+
+inline Plane_RST_3d::Plane_RST_3d()
+{
+}
+
+
+inline Plane_RST_3d::Plane_RST_3d(double r, double s, double t)
+	: m_r(r),
+	  m_s(s),
+	  m_t(t)
+{
+}
+
+
+inline const double &Plane_RST_3d::get_r() const
+{
+	return m_r;
+}
+
+
+inline const double &Plane_RST_3d::get_s() const
+{
+	return m_s;
+}
+
+
+inline const double &Plane_RST_3d::get_t() const
+{
+	return m_t;
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_PLANE_RST_3D_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Point_3d.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Point_3d.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Point_3d.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,63 @@
+#ifndef GTB_POINT_3D_INCLUDED
+#include "Point_3d.hpp"
+#endif
+
+// #ifndef GTB_RAY_3D_INCLUDED
+// #include "Ray_3d.hpp"
+// #endif
+
+GTB_BEGIN_NAMESPACE
+
+
+const Point_3d POINT_3D_ZERO(0.0, 0.0, 0.0);
+
+
+Point_3d &Point_3d::scale(const Point_3d &origin, double s)
+{
+	Vector_3d t(origin.m_p);
+	*this -= t;
+	m_p[0] *= s;
+	m_p[1] *= s;
+	m_p[2] *= s;
+	*this += t;
+	return *this;
+}
+
+
+Point_3d &Point_3d::rotate(const Vector_3d &axis, double theta)
+{
+	Vector_3d v(m_p);
+	v.rotate(axis, theta);
+	this->reset(v.m_v[0], v.m_v[1], v.m_v[2]);
+	return *this;
+}
+
+
+// Point_3d &Point_3d::rotate(const Ray_3d &r, double theta)
+// {
+// 	const Point_3d &q = r.get_origin();
+// 	Vector_3d v = *this - q;
+// 	v.rotate(r.get_direction(), theta);
+// 	*this = q + v;
+// 	return *this;
+// }
+
+
+Point_3d Point_3d::centroid(const std::vector<Point_3d> &v)
+{
+	double cx = 0.0;
+	double cy = 0.0;
+	double cz = 0.0;
+	unsigned n = v.size();
+	double n_inv = 1.0 / n;
+
+	for (unsigned i = 0; i < n; ++i) {
+		cx += v[i].m_p[0] * n_inv;
+		cy += v[i].m_p[1] * n_inv;
+		cz += v[i].m_p[2] * n_inv;
+	}
+	return Point_3d(cx, cy, cz);
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Point_3d.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Point_3d.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Point_3d.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,460 @@
+#ifndef GTB_POINT_3D_INCLUDED
+#define GTB_POINT_3D_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_EPSILON_INCLUDED
+#include "epsilon.hpp"
+#endif
+
+#ifndef GTB_MATRIX_4d_INCLUDED
+#include "Matrix_4d.hpp"
+#endif
+
+#ifndef GTB_CXX_VECTOR_INCLUDED
+#include <vector>
+#define GTB_CXX_VECTOR_INCLUDED
+#endif
+
+#ifndef GTB_GL_HEADERS_INCLUDED
+#include "gl_headers.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+class Vector_3d;
+class Ray_3d;
+
+
+class Point_3d {
+public:
+	Point_3d();
+	Point_3d(const Point_3d &p);
+	Point_3d(double px, double py, double pz);
+	Point_3d(const double p[3]);
+	Point_3d &operator=(const Point_3d &p);
+
+	const double &get_x() const;
+	const double &get_y() const;
+	const double &get_z() const;
+
+	const double &operator[](unsigned i) const;
+	double &operator[](unsigned i);
+
+	Point_3d &set_x(double px);
+	Point_3d &set_y(double py);
+	Point_3d &set_z(double pz);
+	Point_3d &reset(double px, double py, double pz);
+
+	bool eps_is_equal(const Point_3d &p, double eps) const;
+	bool eps_is_zero(double eps) const;
+
+	Point_3d &operator*=(const Matrix_4d &m);
+	Point_3d &operator+=(const Vector_3d &v);
+	Point_3d &operator-=(const Vector_3d &v);
+
+	friend Point_3d operator*(const Matrix_4d &m, const Point_3d &p);
+	friend Point_3d operator+(const Point_3d &p, const Vector_3d &v);
+	friend Vector_3d operator-(const Point_3d &p, const Point_3d &q);
+	friend Point_3d operator-(const Point_3d &p, const Vector_3d &v);
+
+	Point_3d &scale(const Point_3d &origin, double s);
+	Point_3d &translate(const Vector_3d &v);
+	Point_3d &translate(double dx, double dy, double dz);
+	Point_3d &translate_x(double d);
+	Point_3d &translate_y(double d);
+	Point_3d &translate_z(double d);
+	Point_3d &rotate(const Vector_3d &axis, double theta);
+	Point_3d &rotate(const Ray_3d &r, double theta);
+	Point_3d &transform(const Matrix_4d &m);
+	Point_3d &affine_transform(const Matrix_4d &m);
+
+	void gl_vertex() const;
+
+	static double distance(const Point_3d &p, const Point_3d &q);
+
+	static double squared_distance(const Point_3d &p, const Point_3d &q);
+
+	static bool eps_are_collinear(const Point_3d &A,
+				      const Point_3d &B,
+				      const Point_3d &C,
+				      double eps);
+
+	static Vector_3d normal(const Point_3d &A,
+				const Point_3d &B,
+				const Point_3d &C);
+
+	static Point_3d midpoint(const Point_3d &A, const Point_3d &B);
+
+	static Point_3d centroid(const Point_3d &A,
+				 const Point_3d &B,
+				 const Point_3d &C);
+
+	static Point_3d centroid(const Point_3d &A,
+				 const Point_3d &B,
+				 const Point_3d &C,
+				 const Point_3d &D);
+
+	static Point_3d centroid(const std::vector<Point_3d> &v);
+
+	friend class Vector_3d;
+
+protected:
+	double m_p[3];
+};
+
+
+extern const Point_3d POINT_3D_ZERO;
+
+
+GTB_END_NAMESPACE
+
+
+#ifndef GTB_VECTOR_3D_INCLUDED
+#include "Vector_3d.hpp"
+#endif
+
+
+GTB_BEGIN_NAMESPACE
+
+
+inline Point_3d::Point_3d()
+{
+}
+
+
+inline Point_3d::Point_3d(const Point_3d &p)
+{
+	m_p[0] = p.m_p[0];
+	m_p[1] = p.m_p[1];
+	m_p[2] = p.m_p[2];
+}
+
+
+inline Point_3d::Point_3d(double px, double py, double pz)
+{
+	m_p[0] = px;
+	m_p[1] = py;
+	m_p[2] = pz;
+}
+
+
+inline Point_3d::Point_3d(const double p[3])
+{
+	m_p[0] = p[0];
+	m_p[1] = p[1];
+	m_p[2] = p[2];
+}
+
+
+inline Point_3d &Point_3d::operator=(const Point_3d &p)
+{
+	m_p[0] = p.m_p[0];
+	m_p[1] = p.m_p[1];
+	m_p[2] = p.m_p[2];
+	return *this;
+}
+
+
+inline bool Point_3d::eps_is_equal(const Point_3d &p, double eps) const
+{
+	return (gtb::eps_is_equal(m_p[0], p.m_p[0], eps) &&
+		gtb::eps_is_equal(m_p[1], p.m_p[1], eps) &&
+		gtb::eps_is_equal(m_p[2], p.m_p[2], eps));
+}
+
+
+inline bool Point_3d::eps_is_zero(double eps) const
+{
+	return (gtb::eps_is_zero(m_p[0], eps) &&
+		gtb::eps_is_zero(m_p[1], eps) &&
+		gtb::eps_is_zero(m_p[2], eps));
+}
+
+
+inline const double &Point_3d::get_x() const
+{
+	return m_p[0];
+}
+
+
+inline const double &Point_3d::get_y() const
+{
+	return m_p[1];
+}
+
+
+inline const double &Point_3d::get_z() const
+{
+	return m_p[2];
+}
+
+
+inline const double &Point_3d::operator[](unsigned i) const
+{
+	GTB_REQUIRE(i < 3);
+	return m_p[i];
+}
+
+
+inline double &Point_3d::operator[](unsigned i)
+{
+	GTB_REQUIRE(i < 3);
+	return m_p[i];
+}
+
+
+inline Point_3d &Point_3d::set_x(double px)
+{
+	m_p[0] = px;
+	return *this;
+}
+
+
+inline Point_3d &Point_3d::set_y(double py)
+{
+	m_p[1] = py;
+	return *this;
+}
+
+
+inline Point_3d &Point_3d::set_z(double pz)
+{
+	m_p[2] = pz;
+	return *this;
+}
+
+
+inline Point_3d &Point_3d::reset(double px, double py, double pz)
+{
+	m_p[0] = px;
+	m_p[1] = py;
+	m_p[2] = pz;
+	return *this;
+}
+
+
+inline Point_3d &Point_3d::operator*=(const Matrix_4d &m)
+{
+	double w = m_p[0] * m(3, 0) 
+		+ m_p[1] * m(3, 1) 
+		+ m_p[2] * m(3, 2) 
+		+ m(3, 3);
+
+	double wi = 1.0 / w;
+
+	return reset((m_p[0] * m(0, 0) 
+		      + m_p[1] * m(0, 1) 
+		      + m_p[2] * m(0, 2) 
+		      + m(0, 3)) * wi,
+
+		     (m_p[0] * m(1, 0) 
+		      + m_p[1] * m(1, 1)
+		      + m_p[2] * m(1, 2) 
+		      + m(1, 3)) * wi,
+
+		     (m_p[0] * m(2, 0)
+		      + m_p[1] * m(2, 1)
+		      + m_p[2] * m(2, 2)
+		      + m(2, 3)) * wi);
+}
+
+
+inline Point_3d &Point_3d::operator+=(const Vector_3d &v)
+{
+	m_p[0] += v.m_v[0];
+	m_p[1] += v.m_v[1];
+	m_p[2] += v.m_v[2];
+	return *this;
+}
+
+
+inline Point_3d &Point_3d::operator-=(const Vector_3d &v)
+{
+	m_p[0] -= v.m_v[0];
+	m_p[1] -= v.m_v[1];
+	m_p[2] -= v.m_v[2];
+	return *this;
+}
+
+
+inline Point_3d operator*(const Matrix_4d &m, const Point_3d &p)
+{
+	double w = p.m_p[0] * m(3, 0)
+		+ p.m_p[1] * m(3, 1)
+		+ p.m_p[2] * m(3, 2)
+		+ m(3, 3);
+
+	double wi = 1.0 / w;
+
+	return Point_3d((p.m_p[0] * m(0, 0)
+			 + p.m_p[1] * m(0, 1)
+			 + p.m_p[2] * m(0, 2)
+			 + m(0, 3)) * wi,
+
+			(p.m_p[0] * m(1, 0)
+			 + p.m_p[1] * m(1, 1)
+			 + p.m_p[2] * m(1, 2)
+			 + m(1, 3)) * wi,
+
+			(p.m_p[0] * m(2, 0)
+			 + p.m_p[1] * m(2, 1)
+			 + p.m_p[2] * m(2, 2)
+			 + m(2, 3)) * wi);
+}
+
+
+inline Point_3d operator+(const Point_3d &p, const Vector_3d &v)
+{
+	return Point_3d(p.m_p[0] + v.m_v[0],
+			p.m_p[1] + v.m_v[1],
+			p.m_p[2] + v.m_v[2]);
+}
+
+
+inline Vector_3d operator-(const Point_3d &p, const Point_3d &q)
+{
+	return Vector_3d(p.m_p[0] - q.m_p[0],
+			 p.m_p[1] - q.m_p[1],
+			 p.m_p[2] - q.m_p[2]);
+}
+
+
+inline Point_3d operator-(const Point_3d &p, const Vector_3d &v)
+{
+	return Point_3d(p.m_p[0] - v.m_v[0],
+			p.m_p[1] - v.m_v[1],
+			p.m_p[2] - v.m_v[2]);
+}
+
+
+inline Point_3d &Point_3d::translate(const Vector_3d &t)
+{
+	return *this += t;
+}
+
+
+inline Point_3d &Point_3d::translate(double dx, double dy, double dz)
+{
+	m_p[0] += dx;
+	m_p[1] += dy;
+	m_p[2] += dz;
+	return *this;
+}
+
+
+inline Point_3d &Point_3d::translate_x(double d)
+{
+	m_p[0] += d;
+	return *this;
+}
+
+
+inline Point_3d &Point_3d::translate_y(double d)
+{
+	m_p[1] += d;
+	return *this;
+}
+
+
+inline Point_3d &Point_3d::translate_z(double d)
+{
+	m_p[2] += d;
+	return *this;
+}
+
+
+inline void Point_3d::gl_vertex() const
+{
+	glVertex3dv(m_p);
+}
+
+
+inline double Point_3d::distance(const Point_3d &p, const Point_3d &q)
+{
+	return (p - q).length();
+}
+
+
+inline double Point_3d::squared_distance(const Point_3d &p, const Point_3d &q)
+{
+	return (p - q).squared_length();
+}
+
+
+inline bool Point_3d::eps_are_collinear(const Point_3d &A,
+					const Point_3d &B,
+					const Point_3d &C,
+					double eps)
+{
+	return (B - A).cross(C - A).eps_is_zero(eps);
+}
+
+
+inline Vector_3d Point_3d::normal(const Point_3d &A,
+				  const Point_3d &B,
+				  const Point_3d &C)
+{
+	return (B - A).cross(C - A).normalize();
+}
+
+
+inline Point_3d Point_3d::midpoint(const Point_3d &A, const Point_3d &B)
+{
+	return Point_3d(0.5 * (A.m_p[0] + B.m_p[0]),
+			0.5 * (A.m_p[1] + B.m_p[1]),
+			0.5 * (A.m_p[2] + B.m_p[2]));
+}
+
+
+inline Point_3d Point_3d::centroid(const Point_3d &A,
+				   const Point_3d &B,
+				   const Point_3d &C)
+{
+	return Point_3d((A.m_p[0] + B.m_p[0] + C.m_p[0]) / 3.0,
+			(A.m_p[1] + B.m_p[1] + C.m_p[1]) / 3.0,
+			(A.m_p[2] + B.m_p[2] + C.m_p[2]) / 3.0);
+}
+
+
+inline Point_3d Point_3d::centroid(const Point_3d &A,
+				   const Point_3d &B,
+				   const Point_3d &C,
+				   const Point_3d &D)
+{
+	return Point_3d((A.m_p[0] + B.m_p[0] + C.m_p[0] + D.m_p[0]) / 4.0,
+			(A.m_p[1] + B.m_p[1] + C.m_p[1] + D.m_p[1]) / 4.0,
+			(A.m_p[2] + B.m_p[2] + C.m_p[2] + D.m_p[2]) / 4.0);
+}
+
+
+inline Point_3d &Point_3d::transform(const Matrix_4d &m)
+{
+	return *this *= m;
+}
+
+
+inline Point_3d &Point_3d::affine_transform(const Matrix_4d &m)
+{
+	return reset(m_p[0] * m(0, 0)
+		     + m_p[1] * m(0, 1)
+		     + m_p[2] * m(0, 2)
+		     + m(0, 3),
+
+		     m_p[0] * m(1, 0)
+		     + m_p[1] * m(1, 1)
+		     + m_p[2] * m(1, 2)
+		     + m(1, 3),
+
+		     m_p[0] * m(2, 0)
+		     + m_p[1] * m(2, 1)
+		     + m_p[2] * m(2, 2)
+		     + m(2, 3));
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_POINT_3D_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Point_3f.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Point_3f.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Point_3f.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,63 @@
+#ifndef GTB_POINT_3F_INCLUDED
+#include "Point_3f.hpp"
+#endif
+
+// #ifndef GTB_RAY_3F_INCLUDED
+// #include "Ray_3f.hpp"
+// #endif
+
+GTB_BEGIN_NAMESPACE
+
+
+const Point_3f POINT_3F_ZERO(0.0, 0.0, 0.0);
+
+
+Point_3f &Point_3f::scale(const Point_3f &origin, float s)
+{
+	Vector_3f t(origin.m_p);
+	*this -= t;
+	m_p[0] *= s;
+	m_p[1] *= s;
+	m_p[2] *= s;
+	*this += t;
+	return *this;
+}
+
+
+Point_3f &Point_3f::rotate(const Vector_3f &axis, float theta)
+{
+	Vector_3f v(m_p);
+	v.rotate(axis, theta);
+	this->reset(v.m_v[0], v.m_v[1], v.m_v[2]);
+	return *this;
+}
+
+
+// Point_3f &Point_3f::rotate(const Ray_3f &r, float theta)
+// {
+// 	const Point_3f &q = r.get_origin();
+// 	Vector_3f v = *this - q;
+// 	v.rotate(r.get_direction(), theta);
+// 	*this = q + v;
+// 	return *this;
+// }
+
+
+Point_3f Point_3f::centroid(const std::vector<Point_3f> &v)
+{
+	float cx = 0.0;
+	float cy = 0.0;
+	float cz = 0.0;
+	unsigned n = v.size();
+	float n_inv = 1.0 / n;
+
+	for (unsigned i = 0; i < n; ++i) {
+		cx += v[i].m_p[0] * n_inv;
+		cy += v[i].m_p[1] * n_inv;
+		cz += v[i].m_p[2] * n_inv;
+	}
+	return Point_3f(cx, cy, cz);
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Point_3f.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Point_3f.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Point_3f.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,463 @@
+#ifndef GTB_POINT_3F_INCLUDED
+#define GTB_POINT_3F_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_EPSILON_INCLUDED
+#include "epsilon.hpp"
+#endif
+
+#ifndef GTB_MATRIX_4d_INCLUDED
+#include "Matrix_4d.hpp"
+#endif
+
+#ifndef GTB_CXX_VECTOR_INCLUDED
+#include <vector>
+#define GTB_CXX_VECTOR_INCLUDED
+#endif
+
+#ifndef GTB_GL_HEADERS_INCLUDED
+#include "gl_headers.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+class Vector_3f;
+class Ray_3f;
+
+
+class Point_3f {
+public:
+	Point_3f();
+// 	Point_3f(const Point_3f &p);
+	Point_3f(float px, float py, float pz);
+	Point_3f(const float p[3]);
+// 	Point_3f &operator=(const Point_3f &p);
+
+	const float &get_x() const;
+	const float &get_y() const;
+	const float &get_z() const;
+
+	const float &operator[](unsigned i) const;
+	float &operator[](unsigned i);
+
+	Point_3f &set_x(float px);
+	Point_3f &set_y(float py);
+	Point_3f &set_z(float pz);
+	Point_3f &reset(float px, float py, float pz);
+
+	bool eps_is_equal(const Point_3f &p, float eps) const;
+	bool eps_is_zero(float eps) const;
+
+	Point_3f &operator*=(const Matrix_4d &m);
+	Point_3f &operator+=(const Vector_3f &v);
+	Point_3f &operator-=(const Vector_3f &v);
+
+	friend Point_3f operator*(const Matrix_4d &m, const Point_3f &p);
+	friend Point_3f operator+(const Point_3f &p, const Vector_3f &v);
+	friend Vector_3f operator-(const Point_3f &p, const Point_3f &q);
+	friend Point_3f operator-(const Point_3f &p, const Vector_3f &v);
+
+	Point_3f &scale(const Point_3f &origin, float s);
+	Point_3f &translate(const Vector_3f &v);
+	Point_3f &translate(float dx, float dy, float dz);
+	Point_3f &translate_x(float d);
+	Point_3f &translate_y(float d);
+	Point_3f &translate_z(float d);
+	Point_3f &rotate(const Vector_3f &axis, float theta);
+	Point_3f &rotate(const Ray_3f &r, float theta);
+	Point_3f &transform(const Matrix_4d &m);
+	Point_3f &affine_transform(const Matrix_4d &m);
+
+	void gl_vertex() const;
+
+	static float distance(const Point_3f &p, const Point_3f &q);
+
+	static float squared_distance(const Point_3f &p, const Point_3f &q);
+
+	static bool eps_are_collinear(const Point_3f &A,
+				      const Point_3f &B,
+				      const Point_3f &C,
+				      float eps);
+
+	static Vector_3f normal(const Point_3f &A,
+				const Point_3f &B,
+				const Point_3f &C);
+
+	static Point_3f midpoint(const Point_3f &A, const Point_3f &B);
+
+	static Point_3f centroid(const Point_3f &A,
+				 const Point_3f &B,
+				 const Point_3f &C);
+
+	static Point_3f centroid(const Point_3f &A,
+				 const Point_3f &B,
+				 const Point_3f &C,
+				 const Point_3f &D);
+
+	static Point_3f centroid(const std::vector<Point_3f> &v);
+
+	friend class Vector_3f;
+
+protected:
+	float m_p[3];
+};
+
+
+extern const Point_3f POINT_3F_ZERO;
+
+
+GTB_END_NAMESPACE
+
+
+#ifndef GTB_VECTOR_3F_INCLUDED
+#include "Vector_3f.hpp"
+#endif
+
+
+GTB_BEGIN_NAMESPACE
+
+
+inline Point_3f::Point_3f()
+{
+}
+
+
+// inline Point_3f::Point_3f(const Point_3f &p)
+// {
+// 	m_p[0] = p.m_p[0];
+// 	m_p[1] = p.m_p[1];
+// 	m_p[2] = p.m_p[2];
+// }
+
+
+inline Point_3f::Point_3f(float px, float py, float pz)
+{
+	m_p[0] = px;
+	m_p[1] = py;
+	m_p[2] = pz;
+}
+
+
+inline Point_3f::Point_3f(const float p[3])
+{
+	m_p[0] = p[0];
+	m_p[1] = p[1];
+	m_p[2] = p[2];
+}
+
+
+// inline Point_3f &Point_3f::operator=(const Point_3f &p)
+// {
+// 	m_p[0] = p.m_p[0];
+// 	m_p[1] = p.m_p[1];
+// 	m_p[2] = p.m_p[2];
+// 	return *this;
+// }
+
+
+inline bool Point_3f::eps_is_equal(const Point_3f &p, float eps) const
+{
+	return (gtb::eps_is_equal(m_p[0], p.m_p[0], eps) &&
+		gtb::eps_is_equal(m_p[1], p.m_p[1], eps) &&
+		gtb::eps_is_equal(m_p[2], p.m_p[2], eps));
+}
+
+
+inline bool Point_3f::eps_is_zero(float eps) const
+{
+	return (gtb::eps_is_zero(m_p[0], eps) &&
+		gtb::eps_is_zero(m_p[1], eps) &&
+		gtb::eps_is_zero(m_p[2], eps));
+}
+
+
+inline const float &Point_3f::get_x() const
+{
+	return m_p[0];
+}
+
+
+inline const float &Point_3f::get_y() const
+{
+	return m_p[1];
+}
+
+
+inline const float &Point_3f::get_z() const
+{
+	return m_p[2];
+}
+
+
+inline const float &Point_3f::operator[](unsigned i) const
+{
+	GTB_REQUIRE(i < 3);
+	return m_p[i];
+}
+
+
+inline float &Point_3f::operator[](unsigned i)
+{
+	GTB_REQUIRE(i < 3);
+	return m_p[i];
+}
+
+
+inline Point_3f &Point_3f::set_x(float px)
+{
+	m_p[0] = px;
+	return *this;
+}
+
+
+inline Point_3f &Point_3f::set_y(float py)
+{
+	m_p[1] = py;
+	return *this;
+}
+
+
+inline Point_3f &Point_3f::set_z(float pz)
+{
+	m_p[2] = pz;
+	return *this;
+}
+
+
+inline Point_3f &Point_3f::reset(float px, float py, float pz)
+{
+	m_p[0] = px;
+	m_p[1] = py;
+	m_p[2] = pz;
+	return *this;
+}
+
+
+inline Point_3f &Point_3f::operator*=(const Matrix_4d &m)
+{
+	float w = m_p[0] * m(3, 0) 
+		+ m_p[1] * m(3, 1) 
+		+ m_p[2] * m(3, 2) 
+		+ m(3, 3);
+
+	float wi = 1.0 / w;
+
+	return reset((m_p[0] * m(0, 0) 
+		      + m_p[1] * m(0, 1) 
+		      + m_p[2] * m(0, 2) 
+		      + m(0, 3)) * wi,
+
+		     (m_p[0] * m(1, 0) 
+		      + m_p[1] * m(1, 1)
+		      + m_p[2] * m(1, 2) 
+		      + m(1, 3)) * wi,
+
+		     (m_p[0] * m(2, 0)
+		      + m_p[1] * m(2, 1)
+		      + m_p[2] * m(2, 2)
+		      + m(2, 3)) * wi);
+}
+
+
+inline Point_3f &Point_3f::operator+=(const Vector_3f &v)
+{
+	m_p[0] += v.m_v[0];
+	m_p[1] += v.m_v[1];
+	m_p[2] += v.m_v[2];
+	return *this;
+}
+
+
+inline Point_3f &Point_3f::operator-=(const Vector_3f &v)
+{
+	m_p[0] -= v.m_v[0];
+	m_p[1] -= v.m_v[1];
+	m_p[2] -= v.m_v[2];
+	return *this;
+}
+
+
+inline Point_3f operator*(const Matrix_4d &m, const Point_3f &p)
+{
+#if 0
+	float w = p.m_p[0] * m(3, 0)
+		+ p.m_p[1] * m(3, 1)
+		+ p.m_p[2] * m(3, 2)
+		+ m(3, 3);
+
+	float wi = 1.0 / w;
+#endif
+	float wi = 1;
+
+	return Point_3f((p.m_p[0] * m(0, 0)
+			 + p.m_p[1] * m(0, 1)
+			 + p.m_p[2] * m(0, 2)
+			 + m(0, 3)) * wi,
+
+			(p.m_p[0] * m(1, 0)
+			 + p.m_p[1] * m(1, 1)
+			 + p.m_p[2] * m(1, 2)
+			 + m(1, 3)) * wi,
+
+			(p.m_p[0] * m(2, 0)
+			 + p.m_p[1] * m(2, 1)
+			 + p.m_p[2] * m(2, 2)
+			 + m(2, 3)) * wi);
+}
+
+
+inline Point_3f operator+(const Point_3f &p, const Vector_3f &v)
+{
+	return Point_3f(p.m_p[0] + v.m_v[0],
+			p.m_p[1] + v.m_v[1],
+			p.m_p[2] + v.m_v[2]);
+}
+
+
+inline Vector_3f operator-(const Point_3f &p, const Point_3f &q)
+{
+	return Vector_3f(p.m_p[0] - q.m_p[0],
+			 p.m_p[1] - q.m_p[1],
+			 p.m_p[2] - q.m_p[2]);
+}
+
+
+inline Point_3f operator-(const Point_3f &p, const Vector_3f &v)
+{
+	return Point_3f(p.m_p[0] - v.m_v[0],
+			p.m_p[1] - v.m_v[1],
+			p.m_p[2] - v.m_v[2]);
+}
+
+
+inline Point_3f &Point_3f::translate(const Vector_3f &t)
+{
+	return *this += t;
+}
+
+
+inline Point_3f &Point_3f::translate(float dx, float dy, float dz)
+{
+	m_p[0] += dx;
+	m_p[1] += dy;
+	m_p[2] += dz;
+	return *this;
+}
+
+
+inline Point_3f &Point_3f::translate_x(float d)
+{
+	m_p[0] += d;
+	return *this;
+}
+
+
+inline Point_3f &Point_3f::translate_y(float d)
+{
+	m_p[1] += d;
+	return *this;
+}
+
+
+inline Point_3f &Point_3f::translate_z(float d)
+{
+	m_p[2] += d;
+	return *this;
+}
+
+
+inline void Point_3f::gl_vertex() const
+{
+	glVertex3fv(m_p);
+}
+
+
+inline float Point_3f::distance(const Point_3f &p, const Point_3f &q)
+{
+	return (p - q).length();
+}
+
+
+inline float Point_3f::squared_distance(const Point_3f &p, const Point_3f &q)
+{
+	return (p - q).squared_length();
+}
+
+
+inline bool Point_3f::eps_are_collinear(const Point_3f &A,
+					const Point_3f &B,
+					const Point_3f &C,
+					float eps)
+{
+	return (B - A).cross(C - A).eps_is_zero(eps);
+}
+
+
+inline Vector_3f Point_3f::normal(const Point_3f &A,
+				  const Point_3f &B,
+				  const Point_3f &C)
+{
+	return (B - A).cross(C - A).normalize();
+}
+
+
+inline Point_3f Point_3f::midpoint(const Point_3f &A, const Point_3f &B)
+{
+	return Point_3f(0.5 * (A.m_p[0] + B.m_p[0]),
+			0.5 * (A.m_p[1] + B.m_p[1]),
+			0.5 * (A.m_p[2] + B.m_p[2]));
+}
+
+
+inline Point_3f Point_3f::centroid(const Point_3f &A,
+				   const Point_3f &B,
+				   const Point_3f &C)
+{
+	return Point_3f((A.m_p[0] + B.m_p[0] + C.m_p[0]) / 3.0,
+			(A.m_p[1] + B.m_p[1] + C.m_p[1]) / 3.0,
+			(A.m_p[2] + B.m_p[2] + C.m_p[2]) / 3.0);
+}
+
+
+inline Point_3f Point_3f::centroid(const Point_3f &A,
+				   const Point_3f &B,
+				   const Point_3f &C,
+				   const Point_3f &D)
+{
+	return Point_3f((A.m_p[0] + B.m_p[0] + C.m_p[0] + D.m_p[0]) / 4.0,
+			(A.m_p[1] + B.m_p[1] + C.m_p[1] + D.m_p[1]) / 4.0,
+			(A.m_p[2] + B.m_p[2] + C.m_p[2] + D.m_p[2]) / 4.0);
+}
+
+
+inline Point_3f &Point_3f::transform(const Matrix_4d &m)
+{
+	return *this *= m;
+}
+
+
+inline Point_3f &Point_3f::affine_transform(const Matrix_4d &m)
+{
+	return reset(m_p[0] * m(0, 0)
+		     + m_p[1] * m(0, 1)
+		     + m_p[2] * m(0, 2)
+		     + m(0, 3),
+
+		     m_p[0] * m(1, 0)
+		     + m_p[1] * m(1, 1)
+		     + m_p[2] * m(1, 2)
+		     + m(1, 3),
+
+		     m_p[0] * m(2, 0)
+		     + m_p[1] * m(2, 1)
+		     + m_p[2] * m(2, 2)
+		     + m(2, 3));
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_POINT_3F_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Point_4f.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Point_4f.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Point_4f.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,11 @@
+#ifndef GTB_POINT_4F_INCLUDED
+#include "Point_4f.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+const Point_4f POINT_4F_ZERO(0.0, 0.0, 0.0, 0.0);
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Point_4f.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Point_4f.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Point_4f.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,225 @@
+#ifndef GTB_POINT_4F_INCLUDED
+#define GTB_POINT_4F_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_EPSILON_INCLUDED
+#include "epsilon.hpp"
+#endif
+
+#ifndef GTB_MATRIX_4d_INCLUDED
+#include "Matrix_4d.hpp"
+#endif
+
+#ifndef GTB_GL_HEADERS_INCLUDED
+#include "gl_headers.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+class Point_4f {
+public:
+	Point_4f();
+	Point_4f(const Point_4f &p);
+	Point_4f(float px, float py, float pz, float pw);
+	Point_4f(const float p[4]);
+	Point_4f &operator=(const Point_4f &p);
+
+	const float &get_x() const;
+	const float &get_y() const;
+	const float &get_z() const;
+	const float &get_w() const;
+	void get(float p[4]) const;
+	void get(float &px, float &py, float &pz, float &pw);
+
+	const float &operator[](unsigned i) const;
+	float &operator[](unsigned i);
+
+	Point_4f &set_x(float px);
+	Point_4f &set_y(float py);
+	Point_4f &set_z(float pz);
+	Point_4f &set_w(float pw);
+	Point_4f &set(float px, float py, float pz, float pw);
+	Point_4f &set(const float p[4]);
+
+	bool eps_is_equal(const Point_4f &p, float eps) const;
+	bool eps_is_zero(float eps) const;
+
+protected:
+	float m_p[4];
+};
+
+
+extern const Point_4f POINT_4F_ZERO;
+
+
+inline Point_4f::Point_4f()
+{
+}
+
+
+inline Point_4f::Point_4f(const Point_4f &p)
+{
+	m_p[0] = p.m_p[0];
+	m_p[1] = p.m_p[1];
+	m_p[2] = p.m_p[2];
+	m_p[3] = p.m_p[3];
+}
+
+
+inline Point_4f::Point_4f(float px, float py, float pz, float pw)
+{
+	m_p[0] = px;
+	m_p[1] = py;
+	m_p[2] = pz;
+	m_p[3] = pw;
+}
+
+
+inline Point_4f::Point_4f(const float p[4])
+{
+	m_p[0] = p[0];
+	m_p[1] = p[1];
+	m_p[2] = p[2];
+	m_p[3] = p[3];
+}
+
+
+inline Point_4f &Point_4f::operator=(const Point_4f &p)
+{
+	m_p[0] = p.m_p[0];
+	m_p[1] = p.m_p[1];
+	m_p[2] = p.m_p[2];
+	m_p[3] = p.m_p[3];
+	return *this;
+}
+
+
+inline bool Point_4f::eps_is_equal(const Point_4f &p, float eps) const
+{
+	return (gtb::eps_is_equal(m_p[0], p.m_p[0], eps) &&
+		gtb::eps_is_equal(m_p[1], p.m_p[1], eps) &&
+		gtb::eps_is_equal(m_p[2], p.m_p[2], eps) &&
+		gtb::eps_is_equal(m_p[3], p.m_p[3], eps));
+}
+
+
+inline bool Point_4f::eps_is_zero(float eps) const
+{
+	return (gtb::eps_is_zero(m_p[0], eps) &&
+		gtb::eps_is_zero(m_p[1], eps) &&
+		gtb::eps_is_zero(m_p[2], eps) &&
+		gtb::eps_is_zero(m_p[3], eps));
+}
+
+
+inline const float &Point_4f::get_x() const
+{
+	return m_p[0];
+}
+
+
+inline const float &Point_4f::get_y() const
+{
+	return m_p[1];
+}
+
+
+inline const float &Point_4f::get_z() const
+{
+	return m_p[2];
+}
+
+
+inline const float &Point_4f::get_w() const
+{
+	return m_p[3];
+}
+
+
+inline void Point_4f::get(float &px, float &py, float &pz, float &pw)
+{
+	px = m_p[0];
+	py = m_p[1];
+	pz = m_p[2];
+	pw = m_p[3];
+}
+
+
+inline void Point_4f::get(float p[4]) const
+{
+	p[0] = m_p[0];
+	p[1] = m_p[1];
+	p[2] = m_p[2];
+	p[3] = m_p[3];
+}
+
+
+inline const float &Point_4f::operator[](unsigned i) const
+{
+	GTB_REQUIRE(i < 4);
+	return m_p[i];
+}
+
+
+inline float &Point_4f::operator[](unsigned i)
+{
+	GTB_REQUIRE(i < 4);
+	return m_p[i];
+}
+
+
+inline Point_4f &Point_4f::set_x(float px)
+{
+	m_p[0] = px;
+	return *this;
+}
+
+
+inline Point_4f &Point_4f::set_y(float py)
+{
+	m_p[1] = py;
+	return *this;
+}
+
+
+inline Point_4f &Point_4f::set_z(float pz)
+{
+	m_p[2] = pz;
+	return *this;
+}
+
+
+inline Point_4f &Point_4f::set_w(float pw)
+{
+	m_p[3] = pw;
+	return *this;
+}
+
+
+inline Point_4f &Point_4f::set(float px, float py, float pz, float pw)
+{
+	m_p[0] = px;
+	m_p[1] = py;
+	m_p[2] = pz;
+	m_p[3] = pw;
+	return *this;
+}
+
+
+inline Point_4f &Point_4f::set(const float p[4])
+{
+	m_p[0] = p[0];
+	m_p[1] = p[1];
+	m_p[2] = p[2];
+	m_p[3] = p[3];
+	return *this;
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_POINT_4F_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/QuadratureRule.cpp
===================================================================

Added: cs/cigma/branches/cigma-0.9b1/tmc/QuadratureRule.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/QuadratureRule.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/QuadratureRule.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,18 @@
+#ifndef __CIGMA_QRULE_H__
+#define __CIGMA_QRULE_H__
+#include "../libcigma/rule.h"
+
+class QuadratureRule
+{
+public:
+    QuadratureRule();
+    ~QuadratureRule();
+
+    void set();
+    void read(FILE *fp);
+
+public:
+    rule_t *qr;
+};
+
+#endif

Added: cs/cigma/branches/cigma-0.9b1/tmc/Shape.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Shape.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Shape.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,25 @@
+#ifndef GTB_SHAPE_INCLUDED
+#include "Shape.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+Shape::~Shape()
+{
+}
+
+
+void Shape::set_lod_hint(float hint)
+{
+	(void) hint;
+}
+
+
+float Shape::get_lod_hint() const
+{
+	return 0.0;
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Shape.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Shape.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Shape.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,43 @@
+#ifndef GTB_SHAPE_INCLUDED
+#define GTB_SHAPE_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_BOUNDING_BOX_3D_INCLUDED
+#include "Bounding_box_3d.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+//class Rendering_context;
+class Visitor;
+class Matrix_4d;
+
+
+class Shape {
+public:
+	virtual ~Shape();
+
+	virtual const char *get_class_name() const = 0;
+	// static const char *static_get_class_name();
+	virtual const Bounding_box_3d &get_bounding_box() const = 0;
+	virtual unsigned get_num_vertices() const = 0;
+	virtual unsigned get_num_primitives() const = 0;
+	virtual unsigned get_size_in_bytes() const = 0;
+	// static Shape *read(FILE *fp);
+	virtual void write(FILE *fp) const = 0;
+	//virtual void render(Rendering_context &rc) = 0;
+	//virtual void render_geometry(Rendering_context &rc) = 0;
+	virtual void accept(Visitor &visitor) = 0;
+	virtual void transform(const Matrix_4d &m) = 0;
+
+	virtual void set_lod_hint(float hint);
+	virtual float get_lod_hint() const;
+};
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_SHAPE_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/StringUtils.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/StringUtils.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/StringUtils.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,71 @@
+// http://www.codeproject.com/string/stringsplit.asp
+#include "StringUtils.hpp"
+
+int SplitString(const string& input,
+                const string& delimiter,
+                vector<string>& results,
+                bool includeEmpties)
+{
+    int iPos = 0;
+    int newPos = -1;
+    int sizeS2 = (int)delimiter.size();
+    int isize = (int)input.size();
+
+    if ((isize == 0) || (sizeS2 == 0))
+    {
+        return 0;
+    }
+
+    vector<int> positions;
+
+    newPos = input.find(delimiter, 0);
+
+    if (newPos < 0)
+    {
+        return 0;
+    }
+
+    int numFound = 0;
+
+    while (newPos >= iPos)
+    {
+        numFound++;
+        positions.push_back(newPos);
+        iPos = newPos;
+        newPos = input.find(delimiter, iPos + sizeS2);
+    }
+
+    if (numFound == 0)
+    {
+        return 0;
+    }
+
+    for (int i = 0; i <= (int)positions.size(); i++)
+    {
+        string s("");
+        if (i == 0)
+        {
+            s = input.substr(i, positions[i]);
+        }
+        int offset = positions[i-1] + sizeS2;
+        if (offset < isize)
+        {
+            if (i == (int)positions.size())
+            {
+                s = input.substr(offset);
+            }
+            else if (i > 0)
+            {
+                s = input.substr(positions[i-1] + sizeS2,
+                                 positions[i] - positions[i-1] - sizeS2);
+            }
+        }
+        if (includeEmpties || (s.size() > 0))
+        {
+            results.push_back(s);
+        }
+    }
+
+    return numFound;
+}
+

Added: cs/cigma/branches/cigma-0.9b1/tmc/StringUtils.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/StringUtils.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/StringUtils.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,15 @@
+// http://www.codeproject.com/string/stringsplit.asp
+#ifndef __STRINGUTILS_H__
+#define __STRINGUTILS_H__
+
+#include <string>
+#include <vector>
+
+using namespace std;
+
+int SplitString(const string& input,
+                const string& delimiter,
+                vector<string>& results,
+                bool includeEmpties = true);
+
+#endif // __STRINGUTILS_H__

Added: cs/cigma/branches/cigma-0.9b1/tmc/Subject.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Subject.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Subject.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,61 @@
+#ifndef GTB_SUBJECT_INCLUDED
+#include "Subject.hpp"
+#endif
+
+#ifndef GTB_OBSERVER_INCLUDED
+#include "Observer.hpp"
+#endif
+
+#ifndef GTB_CXX_ALGORITHM_INCLUDED
+#include <algorithm>
+#define GTB_CXX_ALGORITHM_INCLUDED
+#endif
+
+#ifndef GTB_ASSERTIONS_INCLUDED
+#include "assertions.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+Subject::~Subject()
+{
+}
+
+
+void Subject::attach(Observer &observer)
+{
+	std::list<Observer *>::const_iterator i = std::find(m_observers.begin(),
+						            m_observers.end(),
+						            &observer);
+	if (i == m_observers.end()) {
+		m_observers.push_back(&observer);
+	}
+}
+
+
+void Subject::detach(Observer &observer)
+{
+	std::list<Observer *>::iterator i = std::find(m_observers.begin(),
+                                                      m_observers.end(),
+						      &observer);
+	if (i == m_observers.end()) {
+		GTB_ERROR("observer not found");
+	}
+	m_observers.erase(i);
+}
+
+
+void Subject::notify()
+{
+	for (std::list<Observer *>::const_iterator i = m_observers.begin();
+	     i != m_observers.end();
+	     ++i) {
+		Observer *observer = *i;
+		GTB_CHECK(observer != NULL);
+		observer->update();
+	}
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Subject.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Subject.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Subject.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,33 @@
+#ifndef GTB_SUBJECT_INCLUDED
+#define GTB_SUBJECT_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_CXX_LIST_INCLUDED
+#include <list>
+#define GTB_CXX_LIST_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+class Observer;
+
+
+class Subject {
+public:
+	virtual ~Subject();
+
+	void attach(Observer &observer);
+	void detach(Observer &observer);
+	void notify();
+
+protected:
+	std::list<Observer *> m_observers;
+};
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_SUBJECT_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Tetrahedron.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Tetrahedron.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Tetrahedron.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,94 @@
+#ifndef GTB_TETRAHEDRON_INCLUDED
+#include "Tetrahedron.hpp"
+#endif
+
+#ifndef GTB_CXX_VECTOR_INCLUDED
+#include <vector>
+#define GTB_CXX_VECTOR_INCLUDED
+#endif
+
+#ifndef GTB_CXX_ALGORITHM_INCLUDED
+#include <algorithm>
+#define GTB_CXX_ALGORITHM_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+Tetrahedron::Tetrahedron()
+	: m_type(TT_NORMAL),
+	  m_inbound_count(0),
+	  m_visited(false)
+{
+	m_vertices[0] = 0;
+	m_vertices[1] = 0;
+	m_vertices[2] = 0;
+	m_vertices[3] = 0;
+
+	m_faces[0] = 0;
+	m_faces[1] = 0;
+	m_faces[2] = 0;
+	m_faces[3] = 0;
+
+	m_neighbors[0] = 0;
+	m_neighbors[1] = 0;
+	m_neighbors[2] = 0;
+	m_neighbors[3] = 0;
+
+	m_face_types[0] = FT_UNDEFINED;
+	m_face_types[1] = FT_UNDEFINED;
+	m_face_types[2] = FT_UNDEFINED;
+	m_face_types[3] = FT_UNDEFINED;
+}
+
+
+Tetrahedron::Tetrahedron(unsigned v0, unsigned v1, unsigned v2, unsigned v3)
+	: m_type(TT_NORMAL),
+	  m_inbound_count(0),
+	  m_visited(false)
+{
+	m_vertices[0] = v0;
+	m_vertices[1] = v1;
+	m_vertices[2] = v2;
+	m_vertices[3] = v3;
+
+	m_faces[0] = 0;
+	m_faces[1] = 0;
+	m_faces[2] = 0;
+	m_faces[3] = 0;
+
+	m_neighbors[0] = 0;
+	m_neighbors[1] = 0;
+	m_neighbors[2] = 0;
+	m_neighbors[3] = 0;
+
+	m_face_types[0] = FT_UNDEFINED;
+	m_face_types[1] = FT_UNDEFINED;
+	m_face_types[2] = FT_UNDEFINED;
+	m_face_types[3] = FT_UNDEFINED;
+}
+
+
+Tetrahedron::~Tetrahedron()
+{
+}
+
+
+bool Tetrahedron::are_vertices_valid() const
+{
+	std::vector<unsigned> v(4);
+	v[0] = get_vertex(0);
+	v[1] = get_vertex(1);
+	v[2] = get_vertex(2);
+	v[3] = get_vertex(3);
+	std::sort(v.begin(), v.end());
+	for (unsigned j = 0; j < 3; ++j) {
+		if (v[j] == v[j + 1]) {
+			return false;
+		}
+	}
+	return true;
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Tetrahedron.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Tetrahedron.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Tetrahedron.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,293 @@
+#ifndef GTB_TETRAHEDRON_INCLUDED
+#define GTB_TETRAHEDRON_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_CXX_STRING_INCLUDED
+#include <string>
+#define GTB_CXX_STRING_INCLUDED
+#endif
+
+#ifndef GTB_ASSERTIONS_INCLUDED
+#include "assertions.hpp"
+#endif
+
+#ifndef GTB_C_ASSERT_INCLUDED
+#include <assert.h>
+#define GTB_C_ASSERT_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+class Tetrahedron {
+public:
+	Tetrahedron();
+	Tetrahedron(unsigned v0, unsigned v1, unsigned v2, unsigned v3);
+	~Tetrahedron();
+
+	typedef enum {
+		FT_UNDEFINED,
+		FT_INBOUND,
+		FT_EXTERIOR_INBOUND,
+		FT_OUTBOUND,
+		FT_EXTERIOR_OUTBOUND
+	} face_type_t;
+
+	typedef enum {
+		TT_NORMAL,
+		TT_DEGENERATE,
+		TT_VIRTUAL
+	} tetra_type_t;
+
+	unsigned get_vertex(unsigned i) const;
+
+	unsigned get_face(unsigned i) const;
+	void set_face(unsigned i, unsigned f);
+
+	int get_neighbor(unsigned i) const;
+	void set_neighbor(unsigned i, int n);
+
+	unsigned get_neighbor_octree_node(unsigned i) const;
+ 	void set_neighbor_octree_node(unsigned i, unsigned on);
+
+	face_type_t get_face_type(unsigned f) const;
+	void set_face_type(unsigned f, face_type_t t);
+	std::string get_face_type_name(unsigned f) const;
+
+	bool is_face_exterior(unsigned f) const;
+	bool is_exterior() const;
+	void get_face_indices(unsigned f, unsigned v[4]) const;
+
+	unsigned get_inbound_count() const;
+	void set_inbound_count(unsigned n);
+	void inc_inbound_count();
+	void dec_inbound_count();
+
+	bool is_visited() const;
+	void set_visited(bool visited);
+
+	unsigned get_octree_node() const;
+	void set_octree_node(unsigned node);
+
+	tetra_type_t get_type() const;
+	bool are_vertices_valid() const;
+
+private:
+	unsigned m_vertices[4];
+	unsigned m_faces[4];
+	union {
+		int m_neighbors[4];
+		int m_centroid[4];
+	};
+	unsigned m_neighbor_octree_node[4];
+	face_type_t m_face_types[4];
+	tetra_type_t m_type;
+	unsigned m_inbound_count;
+	bool m_visited;
+	unsigned m_octree_node;
+};
+
+
+inline unsigned Tetrahedron::get_vertex(unsigned i) const
+{
+	assert(i < 4);
+	return m_vertices[i];
+}
+
+
+inline unsigned Tetrahedron::get_face(unsigned i) const
+{
+	assert(i < 4);
+	return m_faces[i];
+}
+
+
+inline void Tetrahedron::set_face(unsigned i, unsigned f)
+{
+	assert(i < 4);
+	m_faces[i] = f;
+}
+
+
+inline int Tetrahedron::get_neighbor(unsigned i) const
+{
+	assert(i < 4);
+	return m_neighbors[i];
+}
+
+
+inline void Tetrahedron::set_neighbor(unsigned i, int n)
+{
+	assert(i < 4);
+	m_neighbors[i] = n;
+}
+
+
+inline unsigned Tetrahedron::get_neighbor_octree_node(unsigned i) const
+{
+	assert(i < 4);
+	return m_neighbor_octree_node[i];
+}
+
+
+inline void Tetrahedron::set_neighbor_octree_node(unsigned i, unsigned on)
+{
+	assert(i < 4);
+	m_neighbor_octree_node[i] = on;
+}
+
+
+inline unsigned Tetrahedron::get_octree_node() const
+{
+	return m_octree_node;
+}
+
+
+inline void Tetrahedron::set_octree_node(unsigned node)
+{
+	m_octree_node = node;
+}
+
+
+inline Tetrahedron::face_type_t Tetrahedron::get_face_type(unsigned f) const
+{
+	assert(f < 4);
+	return m_face_types[f];
+}
+
+
+inline void Tetrahedron::set_face_type(unsigned f, face_type_t t)
+{
+	assert(f < 4);
+	m_face_types[f] = t;
+}
+
+
+inline std::string Tetrahedron::get_face_type_name(unsigned f) const
+{
+	std::string s;
+	assert(f < 4);
+	switch (m_face_types[f]) {
+	case FT_UNDEFINED:
+		s = "undefined";
+		break;
+	case FT_INBOUND:
+		s = "inbound";
+		break;
+	case FT_EXTERIOR_INBOUND:
+		s = "exterior_inbound";
+		break;
+	case FT_OUTBOUND:
+		s = "outbound";
+		break;
+	case FT_EXTERIOR_OUTBOUND:
+		s = "exterior_outbound";
+		break;
+	default:
+		GTB_ERROR("invalid face type");
+	}
+	return s;
+}
+
+
+inline bool Tetrahedron::is_face_exterior(unsigned f) const
+{
+	assert(f < 4);
+	return m_neighbors[f] <= 0;
+}
+
+
+inline bool Tetrahedron::is_exterior() const
+{
+	return (is_face_exterior(0) ||
+		is_face_exterior(1) ||
+		is_face_exterior(2) ||
+		is_face_exterior(3));
+}
+
+
+inline void Tetrahedron::get_face_indices(unsigned f, unsigned v[4]) const
+{
+	assert(f < 4);
+
+	switch (f) {
+	case 0:
+		v[0] = m_vertices[1];
+		v[1] = m_vertices[2];
+		v[2] = m_vertices[3];
+		v[3] = m_vertices[0];
+		break;
+	case 1:
+		v[0] = m_vertices[0];
+		v[1] = m_vertices[2];
+		v[2] = m_vertices[3];
+		v[3] = m_vertices[1];
+		break;
+	case 2:
+		v[0] = m_vertices[0];
+		v[1] = m_vertices[1];
+		v[2] = m_vertices[3];
+		v[3] = m_vertices[2];
+		break;
+	case 3:
+		v[0] = m_vertices[0];
+		v[1] = m_vertices[1];
+		v[2] = m_vertices[2];
+		v[3] = m_vertices[3];
+		break;
+	default:
+		GTB_ERROR("should never get here");
+		break;
+	}
+}
+
+
+inline unsigned Tetrahedron::get_inbound_count() const
+{
+	return m_inbound_count;
+}
+
+
+inline void Tetrahedron::set_inbound_count(unsigned n)
+{
+	m_inbound_count = n;
+}
+
+
+inline void Tetrahedron::inc_inbound_count()
+{
+	m_inbound_count++;
+}
+
+
+inline void Tetrahedron::dec_inbound_count()
+{
+	GTB_REQUIRE(m_inbound_count > 0);
+	m_inbound_count--;
+}
+
+
+inline bool Tetrahedron::is_visited() const
+{
+	return m_visited;
+}
+
+
+inline void Tetrahedron::set_visited(bool visited)
+{
+	m_visited = visited;
+}
+
+
+inline Tetrahedron::tetra_type_t Tetrahedron::get_type() const
+{
+	return m_type;
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_TETRAHEDRON_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Time_series.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Time_series.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Time_series.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,12 @@
+#ifndef GTB_TIME_SERIES_INCLUDED
+#include "Time_series.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+// explicit instantiation
+template class Time_series<float>;
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Time_series.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Time_series.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Time_series.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,335 @@
+#ifndef GTB_TIME_SERIES_INCLUDED
+#define GTB_TIME_SERIES_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_SUBJECT_INCLUDED
+#include "Subject.hpp"
+#endif
+
+#ifndef GTB_ASSERTIONS_INCLUDED
+#include "assertions.hpp"
+#endif
+
+#ifndef GTB_IO_UTIL_INCLUDED
+#include "io_util.hpp"
+#endif
+
+#ifndef GTB_CXX_VECTOR_INCLUDED
+#include <vector>
+#define GTB_CXX_VECTOR_INCLUDED
+#endif
+
+#ifndef GTB_CXX_STRING_INCLUDED
+#include <string>
+#define GTB_CXX_STRING_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+template <class T>
+class Time_series : public Subject {
+public:
+	explicit Time_series(const char *file_name);
+	explicit Time_series(std::vector<T> &values);
+
+ 	class File_header {
+	public:
+		File_header(unsigned num_times, 
+			    unsigned num_values,
+			    const T &min_value,
+			    const T &max_value);
+
+		File_header(FILE *fp);
+
+		void write(FILE *fp) const;
+
+		unsigned get_num_times() const;
+		unsigned get_num_values() const;
+		const T &get_min_value() const;
+		const T &get_max_value() const;
+
+		void set_min_value(const T &t);
+		void set_max_value(const T &t);
+
+	protected:
+		unsigned m_num_times; 
+		unsigned m_num_values;
+		T m_min_value;
+		T m_max_value;
+	};
+	
+	unsigned get_num_times() const;
+	unsigned get_current_time() const;
+	unsigned get_num_values() const;
+	const T &get_min_value() const;
+	const T &get_max_value() const;
+	void set_min_value(const T &t) { m_min_value = t; }
+	void set_max_value(const T &t) { m_max_value = t; }
+	const T &get_value(unsigned i) const;
+	const std::vector<T> &get_values() const;
+	template <class F> void transform_values(F f);
+
+        void go_to_first_time();
+        void go_to_last_time();
+        void go_to_next_time();
+        void go_to_previous_time();
+	void go_to_time(unsigned t);
+
+protected:
+	void read_values();
+
+	std::string m_file_name;
+	unsigned m_num_times;
+	T m_min_value;
+	T m_max_value;
+	unsigned m_current_time;
+	std::vector<T> m_values;	
+};
+
+
+typedef Time_series<float> Scalar_time_series;
+
+class Vector_3f;
+typedef Time_series<Vector_3f> Vector_time_series;
+
+
+template <class T>
+Time_series<T>::Time_series(const char *file_name)
+	: m_file_name(file_name)
+{
+	FILE *fp;
+	GTB_FOPEN(fp, m_file_name.c_str(), "rb");
+	File_header header(fp);
+	fclose(fp);
+
+	m_num_times = header.get_num_times();
+	m_values.resize(header.get_num_values());
+	m_min_value = header.get_min_value();
+	m_max_value = header.get_max_value();
+
+	go_to_first_time();
+}
+
+
+template <class T>
+Time_series<T>::Time_series(std::vector<T> &values)
+	: m_num_times(1),
+	  m_current_time(0),
+	  m_values(values)
+{
+}
+
+
+template <class T>
+Time_series<T>::File_header::File_header(unsigned num_times, 
+					 unsigned num_values,
+					 const T &min_value,
+					 const T &max_value)
+	: m_num_times(num_times),
+	  m_num_values(num_values),
+	  m_min_value(min_value),
+	  m_max_value(max_value)
+{
+}
+
+
+template <class T>
+Time_series<T>::File_header::File_header(FILE *fp)
+{
+	unsigned n = 0;
+	n += fread(&m_num_times, sizeof(m_num_times), 1, fp);
+	n += fread(&m_num_values, sizeof(m_num_values), 1, fp);
+	n += fread(&m_min_value, sizeof(m_min_value), 1, fp);
+	n += fread(&m_max_value, sizeof(m_max_value), 1, fp);
+	if (n != 4) {
+		GTB_ERROR("failed to read header");
+	}
+}
+
+
+template <class T>
+void Time_series<T>::File_header::write(FILE *fp) const
+{
+	unsigned n = 0;
+	n += fwrite(&m_num_times, sizeof(m_num_times), 1, fp);
+	n += fwrite(&m_num_values, sizeof(m_num_values), 1, fp);
+	n += fwrite(&m_min_value, sizeof(m_min_value), 1, fp);
+	n += fwrite(&m_max_value, sizeof(m_max_value), 1, fp);
+	if (n != 4) {
+		GTB_ERROR("failed to write header");
+	}
+}
+
+
+template <class T>
+unsigned Time_series<T>::File_header::get_num_times() const
+{
+	return m_num_times;
+}
+
+
+template <class T>
+unsigned Time_series<T>::File_header::get_num_values() const
+{
+	return m_num_values;
+}
+
+
+template <class T>
+const T &Time_series<T>::File_header::get_min_value() const
+{
+	return m_min_value;
+}
+
+
+template <class T>
+const T &Time_series<T>::File_header::get_max_value() const
+{
+	return m_max_value;
+}
+
+
+template <class T>
+void Time_series<T>::File_header::set_min_value(const T &t)
+{
+	m_min_value = t;
+}
+
+
+template <class T>
+void Time_series<T>::File_header::set_max_value(const T &t)
+{
+	m_max_value = t;
+}
+
+
+template <class T>
+unsigned Time_series<T>::get_num_times() const
+{
+	return m_num_times;
+}
+
+
+template <class T>
+unsigned Time_series<T>::get_current_time() const
+{
+	return m_current_time;
+}
+
+
+template <class T>
+unsigned Time_series<T>::get_num_values() const
+{
+	return m_values.size();
+}
+
+
+template <class T>
+const T &Time_series<T>::get_min_value() const
+{
+	return m_min_value;
+}
+
+
+template <class T>
+const T &Time_series<T>::get_max_value() const
+{
+	return m_max_value;
+}
+
+
+template <class T>
+const T &Time_series<T>::get_value(unsigned i) const
+{
+    //printf("%d %d\n", i, m_values.size());
+	GTB_REQUIRE(i < m_values.size());
+	return m_values[i];
+}
+
+
+template <class T>
+const std::vector<T> &Time_series<T>::get_values() const
+{
+	return m_values;
+}
+
+
+template <class T>
+template <class F>
+void Time_series<T>::transform_values(F f)
+{
+	for (unsigned i = 0; i < m_values.size(); ++i) {
+		m_values[i] = f(m_values[i]);
+	}
+	notify();
+}
+
+
+template <class T>
+void Time_series<T>::go_to_first_time()
+{
+	m_current_time = 0;
+	read_values();
+}
+
+
+template <class T>
+void Time_series<T>::go_to_last_time()
+{
+	m_current_time = m_num_times - 1;
+	read_values();
+}
+
+
+template <class T>
+void Time_series<T>::go_to_next_time()
+{
+	m_current_time = (m_current_time + 1) % m_num_times;
+	read_values();
+}
+
+
+template <class T>
+void Time_series<T>::go_to_previous_time()
+{
+	m_current_time = (m_current_time + m_num_times - 1) % m_num_times;
+	read_values();
+}
+
+
+template <class T>
+void Time_series<T>::go_to_time(unsigned t)
+{
+	GTB_REQUIRE(t < m_num_times);
+	m_current_time = t;
+	read_values();
+}
+
+
+template <class T>
+void Time_series<T>::read_values()
+{
+	GTB_CHECK(m_values.size() > 0);
+	GTB_CHECK(m_current_time < m_num_times);
+	GTB_CHECK(m_file_name.size() != 0);
+	FILE *fp;
+	GTB_FOPEN(fp, m_file_name.c_str(), "rb");
+	long offset = sizeof(File_header)
+		+ m_current_time * m_values.size() * sizeof(T);
+	fseek(fp, offset, SEEK_SET);
+	if (fread(&m_values[0], m_values.size() * sizeof(T), 1, fp) != 1) {
+		GTB_ERROR("failed to read values");
+	}
+	fclose(fp);
+
+	notify();
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_TIME_SERIES_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Vector_3b.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Vector_3b.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Vector_3b.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,8 @@
+#ifndef GTB_VECTOR_3B_INCLUDED
+#include "Vector_3b.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Vector_3b.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Vector_3b.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Vector_3b.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,164 @@
+#ifndef GTB_VECTOR_3B_INCLUDED
+#define GTB_VECTOR_3B_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_ASSERTIONS_INCLUDED
+#include "assertions.hpp"
+#endif
+
+#ifndef GTB_GL_HEADERS_INCLUDED
+#include "gl_headers.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+class Vector_3b {
+public:
+	Vector_3b();
+	Vector_3b(GLbyte x, GLbyte y, GLbyte z);
+	explicit Vector_3b(GLbyte v[3]);
+	//Vector_3b(const Vector_3b &v);
+	//Vector_3b &operator=(const Vector_3b &v);
+
+	const GLbyte &get_x() const;
+	const GLbyte &get_y() const;
+	const GLbyte &get_z() const;
+
+	const GLbyte &operator[](unsigned i) const;
+	GLbyte &operator[](unsigned i);
+
+	Vector_3b &set_x(GLbyte x);
+	Vector_3b &set_y(GLbyte y);
+	Vector_3b &set_z(GLbyte z);
+	Vector_3b &reset(GLbyte x, GLbyte y, GLbyte z);
+
+	void flip();
+
+	void gl_normal() const;
+
+protected:
+	GLbyte m_v[3];
+};
+
+
+inline Vector_3b::Vector_3b()
+{
+}
+
+
+inline Vector_3b::Vector_3b(GLbyte x, GLbyte y, GLbyte z)
+{
+	m_v[0] = x;
+	m_v[1] = y;
+	m_v[2] = z;
+}
+
+
+inline Vector_3b::Vector_3b(GLbyte v[3])
+{
+	m_v[0] = v[0];
+	m_v[1] = v[1];
+	m_v[2] = v[2];
+}
+
+
+// inline Vector_3b::Vector_3b(const Vector_3b &v)
+// {
+// 	m_v[0] = v.m_v[0];
+// 	m_v[1] = v.m_v[1];
+// 	m_v[2] = v.m_v[2];
+// }
+
+
+// inline Vector_3b &Vector_3b::operator=(const Vector_3b &v)
+// {
+// 	m_v[0] = v.m_v[0];
+// 	m_v[1] = v.m_v[1];
+// 	m_v[2] = v.m_v[2];
+// 	return *this;
+// }
+
+
+inline const GLbyte &Vector_3b::get_x() const
+{
+	return m_v[0];
+}
+
+
+inline const GLbyte &Vector_3b::get_y() const
+{
+	return m_v[1];
+}
+
+
+inline const GLbyte &Vector_3b::get_z() const
+{
+	return m_v[2];
+}
+
+
+inline const GLbyte &Vector_3b::operator[](unsigned i) const
+{
+	GTB_REQUIRE(i < 3);
+	return m_v[i];
+}
+
+
+inline GLbyte &Vector_3b::operator[](unsigned i)
+{
+	GTB_REQUIRE(i < 3);
+	return m_v[i];
+}
+
+
+inline Vector_3b &Vector_3b::set_x(GLbyte x)
+{
+	m_v[0] = x;
+	return *this;
+}
+
+
+inline Vector_3b &Vector_3b::set_y(GLbyte y)
+{
+	m_v[1] = y;
+	return *this;
+}
+
+
+inline Vector_3b &Vector_3b::set_z(GLbyte z)
+{
+	m_v[2] = z;
+	return *this;
+}
+
+
+inline Vector_3b &Vector_3b::reset(GLbyte x, GLbyte y, GLbyte z)
+{
+	m_v[0] = x;
+	m_v[1] = y;
+	m_v[2] = z;
+	return *this;
+}
+
+
+inline void Vector_3b::flip()
+{
+	m_v[0] = -m_v[0];
+	m_v[1] = -m_v[1];
+	m_v[2] = -m_v[2];
+}
+
+
+inline void Vector_3b::gl_normal() const
+{
+	glNormal3bv(m_v);
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_VECTOR_3B_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Vector_3d.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Vector_3d.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Vector_3d.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,62 @@
+#ifndef GTB_VECTOR_3D_INCLUDED
+#include "Vector_3d.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+const Vector_3d VECTOR_3D_ZERO(0.0, 0.0, 0.0);
+const Vector_3d VECTOR_3D_POSITIVE_X(1.0, 0.0, 0.0);
+const Vector_3d VECTOR_3D_NEGATIVE_X(-1.0, 0.0, 0.0);
+const Vector_3d VECTOR_3D_POSITIVE_Y(0.0, 1.0, 0.0);
+const Vector_3d VECTOR_3D_NEGATIVE_Y(0.0, -1.0, 0.0);
+const Vector_3d VECTOR_3D_POSITIVE_Z(0.0, 0.0, 1.0);
+const Vector_3d VECTOR_3D_NEGATIVE_Z(0.0, 0.0, -1.0);
+
+
+Vector_3d &Vector_3d::rotate(const Vector_3d &axis, double theta)
+{
+	// From Goldstein
+	*this =	*this * cos(theta) +
+		axis * this->dot(axis) * (1.0 - cos(theta)) -
+		this->cross(axis) * sin(theta);
+	return *this;
+}
+
+
+// Finds the rotation that takes V to W (Graphics Gems I, p. 531).
+// (Here we pre-multiply, though, i.e., M * p, so we have to use the
+// transpose of what's shown there.)
+Matrix_4d Vector_3d::rotation(const Vector_3d &V, const Vector_3d &W)
+{
+	double d = V.dot(W);
+	if (gtb::eps_is_equal(d, 1.0, FLT_EPSILON)) {
+		return MATRIX_4D_IDENTITY;
+	}
+	if (gtb::eps_is_equal(d, -1.0, FLT_EPSILON)) {
+		return -MATRIX_4D_IDENTITY;
+	}
+
+	Vector_3d N = V.cross(W);
+	N.normalize();
+
+	Vector_3d M = N.cross(V);
+	M.normalize();
+
+	Matrix_4d Q(V[0], V[1], V[2], 0.0,
+		    M[0], M[1], M[2], 0.0,
+		    N[0], N[1], N[2], 0.0,
+		    0.0, 0.0, 0.0, 1.0);
+
+	Vector_3d W2 = Q * W;
+
+	Matrix_4d RT(W2[0], -W2[1], 0.0, 0.0,
+		     W2[1], W2[0], 0.0, 0.0,
+		     W2[2], W2[2], 1.0, 0.0,
+		     0.0, 0.0, 0.0, 1.0);
+
+	return Q.transpose() * RT * Q;
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Vector_3d.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Vector_3d.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Vector_3d.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,494 @@
+#ifndef GTB_VECTOR_3D_INCLUDED
+#define GTB_VECTOR_3D_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_GL_HEADERS_INCLUDED
+#include "gl_headers.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+class Point_3d;
+class Matrix_4d;
+
+
+class Vector_3d {
+public:
+	Vector_3d();
+	Vector_3d(const Vector_3d &v);
+	explicit Vector_3d(const Point_3d &p);
+	Vector_3d(double vx, double vy, double vz);
+	explicit Vector_3d(const double v[3]);
+	explicit Vector_3d(const double v);
+	Vector_3d &operator=(const Vector_3d &v);
+
+	const double &get_x() const;
+	const double &get_y() const;
+	const double &get_z() const;
+
+	const double &operator[](unsigned i) const;
+	double &operator[](unsigned i);
+
+	Vector_3d &set_x(double vx);
+	Vector_3d &set_y(double vy);
+	Vector_3d &set_z(double vz);
+	Vector_3d &reset(double vx, double vy, double vz);
+
+	bool eps_is_equal(const Vector_3d &v, double eps) const;
+	bool eps_is_zero(double eps) const;
+	bool eps_is_normalized(double eps) const;
+
+	Vector_3d operator-() const;
+	Vector_3d &operator*=(const Matrix_4d &m);
+	Vector_3d &operator+=(const Vector_3d &v);
+	Vector_3d &operator-=(const Vector_3d &v);
+	Vector_3d &operator*=(double a);
+	Vector_3d &operator/=(double a);
+
+	double operator*(const Vector_3d &v) const;
+	double operator*(const Point_3d &p) const;
+
+	friend Vector_3d operator+(const Vector_3d &u, const Vector_3d &v);
+	friend Point_3d operator+(const Point_3d &p, const Vector_3d &v);
+	friend Vector_3d operator-(const Vector_3d &u, const Vector_3d &v);
+	friend Point_3d operator-(const Point_3d &p, const Vector_3d &v);
+	friend Vector_3d operator*(double a, const Vector_3d &v);
+	friend Vector_3d operator*(const Vector_3d &v, double a);
+	friend Vector_3d operator*(const Matrix_4d &m, const Vector_3d &v);
+	friend Vector_3d operator/(const Vector_3d &v, double a);
+
+	double dot(const Vector_3d &v) const;
+	double dot(const Point_3d &p) const;
+	Vector_3d cross(const Vector_3d &v) const;
+	double length() const;
+	double squared_length() const;
+	Vector_3d &normalize();
+	Vector_3d &normalize(double &len);
+	Vector_3d &scale(double a);
+	Vector_3d &rotate(const Vector_3d &axis, double theta);
+	Vector_3d &transform(const Matrix_4d &m);
+	Vector_3d &affine_transform(const Matrix_4d &m);
+	void flip();
+
+	void gl_normal() const;
+
+	static Matrix_4d rotation(const Vector_3d &from, const Vector_3d &to);
+
+	friend class Point_3d;
+	friend void swap(Vector_3d &a, Vector_3d &b);
+
+protected:
+	double m_v[3];
+};
+
+
+extern const Vector_3d VECTOR_3D_ZERO;
+extern const Vector_3d VECTOR_3D_POSITIVE_X;
+extern const Vector_3d VECTOR_3D_NEGATIVE_X;
+extern const Vector_3d VECTOR_3D_POSITIVE_Y;
+extern const Vector_3d VECTOR_3D_NEGATIVE_Y;
+extern const Vector_3d VECTOR_3D_POSITIVE_Z;
+extern const Vector_3d VECTOR_3D_NEGATIVE_Z;
+
+
+GTB_END_NAMESPACE
+
+
+#ifndef GTB_POINT_3D_INCLUDED
+#include "Point_3d.hpp"
+#endif
+
+
+GTB_BEGIN_NAMESPACE
+
+
+inline Vector_3d::Vector_3d()
+{
+}
+
+
+inline Vector_3d::Vector_3d(const Vector_3d &v)
+{
+	m_v[0] = v.m_v[0];
+	m_v[1] = v.m_v[1];
+	m_v[2] = v.m_v[2];
+}
+
+
+inline Vector_3d::Vector_3d(double vx, double vy, double vz)
+{
+	m_v[0] = vx;
+	m_v[1] = vy;
+	m_v[2] = vz;
+}
+
+
+inline Vector_3d::Vector_3d(const double v[3])
+{
+	m_v[0] = v[0];
+	m_v[1] = v[1];
+	m_v[2] = v[2];
+}
+
+
+inline Vector_3d::Vector_3d(const double v) 
+{
+	m_v[0] = v;
+	m_v[1] = v;
+	m_v[2] = v;
+}
+
+
+inline Vector_3d::Vector_3d(const Point_3d &p)
+{
+	m_v[0] = p.m_p[0];
+	m_v[1] = p.m_p[1];
+	m_v[2] = p.m_p[2];
+}
+
+
+inline Vector_3d &Vector_3d::operator=(const Vector_3d &v)
+{
+	m_v[0] = v.m_v[0];
+	m_v[1] = v.m_v[1];
+	m_v[2] = v.m_v[2];
+	return *this;
+}
+
+
+inline const double &Vector_3d::get_x() const
+{
+	return m_v[0];
+}
+
+
+inline const double &Vector_3d::get_y() const
+{
+	return m_v[1];
+}
+
+
+inline const double &Vector_3d::get_z() const
+{
+	return m_v[2];
+}
+
+
+inline const double &Vector_3d::operator[](unsigned i) const
+{
+	GTB_REQUIRE(i < 3);
+	return m_v[i];
+}
+
+
+inline double &Vector_3d::operator[](unsigned i)
+{
+	GTB_REQUIRE(i < 3);
+	return m_v[i];
+}
+
+
+inline Vector_3d &Vector_3d::set_x(double vx)
+{
+	m_v[0] = vx;
+	return *this;
+}
+
+
+inline Vector_3d &Vector_3d::set_y(double vy)
+{
+	m_v[1] = vy;
+	return *this;
+}
+
+
+inline Vector_3d &Vector_3d::set_z(double vz)
+{
+	m_v[2] = vz;
+	return *this;
+}
+
+
+inline Vector_3d &Vector_3d::reset(double vx, double vy, double vz)
+{
+	m_v[0] = vx;
+	m_v[1] = vy;
+	m_v[2] = vz;
+	return *this;
+}
+
+
+inline bool Vector_3d::eps_is_equal(const Vector_3d &v, double eps) const
+{
+	return (gtb::eps_is_equal(m_v[0], v.m_v[0], eps) &&
+		gtb::eps_is_equal(m_v[1], v.m_v[1], eps) &&
+		gtb::eps_is_equal(m_v[2], v.m_v[2], eps));
+}
+
+
+inline bool Vector_3d::eps_is_zero(double eps) const
+{
+	return (gtb::eps_is_zero(m_v[0], eps) &&
+		gtb::eps_is_zero(m_v[1], eps) &&
+		gtb::eps_is_zero(m_v[2], eps));
+}
+
+
+inline Vector_3d Vector_3d::operator-() const
+{
+	return Vector_3d(-m_v[0],
+			 -m_v[1],
+			 -m_v[2]);
+}
+
+
+inline Vector_3d &Vector_3d::operator+=(const Vector_3d &v)
+{
+	m_v[0] += v.m_v[0];
+	m_v[1] += v.m_v[1];
+	m_v[2] += v.m_v[2];
+	return *this;
+}
+
+
+inline Vector_3d &Vector_3d::operator-=(const Vector_3d &v)
+{
+	m_v[0] -= v.m_v[0];
+	m_v[1] -= v.m_v[1];
+	m_v[2] -= v.m_v[2];
+	return *this;
+}
+
+
+inline Vector_3d &Vector_3d::operator*=(double a)
+{
+	m_v[0] *= a;
+	m_v[1] *= a;
+	m_v[2] *= a;
+	return *this;
+}
+
+
+inline Vector_3d &Vector_3d::operator*=(const Matrix_4d &m)
+{
+	double w = m_v[0] * m(3, 0) 
+		+ m_v[1] * m(3, 1) 
+		+ m_v[2] * m(3, 2) 
+		+ m(3, 3);
+
+	double wi = 1.0 / w;
+
+	return reset((m_v[0] * m(0, 0) 
+		      + m_v[1] * m(0, 1) 
+		      + m_v[2] * m(0, 2) 
+		      + m(0, 3)) * wi,
+
+		     (m_v[0] * m(1, 0) 
+		      + m_v[1] * m(1, 1)
+		      + m_v[2] * m(1, 2) 
+		      + m(1, 3)) * wi,
+
+		     (m_v[0] * m(2, 0)
+		      + m_v[1] * m(2, 1)
+		      + m_v[2] * m(2, 2)
+		      + m(2, 3)) * wi);
+}
+
+
+inline Vector_3d &Vector_3d::operator/=(double a)
+{
+	return *this *= 1.0 / a;
+}
+
+
+inline double Vector_3d::dot(const Vector_3d &v) const
+{
+	return (m_v[0] * v.m_v[0] +
+		m_v[1] * v.m_v[1] +
+		m_v[2] * v.m_v[2]);
+}
+
+
+inline double Vector_3d::dot(const Point_3d &p) const
+{
+	return (m_v[0] * p.m_p[0] +
+		m_v[1] * p.m_p[1] +
+		m_v[2] * p.m_p[2]);
+}
+
+
+inline double Vector_3d::operator*(const Vector_3d &v) const
+{
+	return dot(v);
+}
+
+
+inline double Vector_3d::operator*(const Point_3d &p) const
+{
+	return dot(p);
+}
+
+
+inline Vector_3d operator+(const Vector_3d &u, const Vector_3d &v)
+{
+	return Vector_3d(u.m_v[0] + v.m_v[0],
+			 u.m_v[1] + v.m_v[1],
+			 u.m_v[2] + v.m_v[2]);
+}
+
+
+inline Vector_3d operator-(const Vector_3d &u, const Vector_3d &v)
+{
+	return Vector_3d(u.m_v[0] - v.m_v[0],
+			 u.m_v[1] - v.m_v[1],
+			 u.m_v[2] - v.m_v[2]);
+}
+
+
+inline Vector_3d operator*(double a, const Vector_3d &v)
+{
+	return Vector_3d(a * v.m_v[0],
+			 a * v.m_v[1],
+			 a * v.m_v[2]);
+}
+
+
+inline Vector_3d operator*(const Vector_3d &v, double a)
+{
+	return a * v;
+}
+
+
+inline Vector_3d operator*(const Matrix_4d &m, const Vector_3d &v)
+{
+	double w = v.m_v[0] * m(3, 0)
+		+ v.m_v[1] * m(3, 1)
+		+ v.m_v[2] * m(3, 2)
+		+ m(3, 3);
+
+	double wi = 1.0 / w;
+
+	return Vector_3d((v.m_v[0] * m(0, 0)
+			  + v.m_v[1] * m(0, 1)
+			  + v.m_v[2] * m(0, 2)
+			  + m(0, 3)) * wi,
+
+			 (v.m_v[0] * m(1, 0)
+			  + v.m_v[1] * m(1, 1)
+			  + v.m_v[2] * m(1, 2)
+			  + m(1, 3)) * wi,
+
+			 (v.m_v[0] * m(2, 0)
+			  + v.m_v[1] * m(2, 1)
+			  + v.m_v[2] * m(2, 2)
+			  + m(2, 3)) * wi);
+}
+
+
+inline Vector_3d operator/(const Vector_3d &v, double a)
+{
+	return v * (1.0 / a);
+}
+
+
+inline Vector_3d Vector_3d::cross(const Vector_3d &v) const
+{
+	return Vector_3d((m_v[1] * v.m_v[2]) - (m_v[2] * v.m_v[1]),
+			 (m_v[2] * v.m_v[0]) - (m_v[0] * v.m_v[2]),
+			 (m_v[0] * v.m_v[1]) - (m_v[1] * v.m_v[0]));
+}
+
+
+inline double Vector_3d::length() const
+{
+	return sqrt(this->dot(*this));
+}
+
+
+inline double Vector_3d::squared_length() const
+{
+	return this->dot(*this);
+}
+
+
+inline bool Vector_3d::eps_is_normalized(double eps) const
+{
+	return gtb::eps_is_equal(squared_length(), 1.0, eps);
+}
+
+
+inline Vector_3d &Vector_3d::normalize()
+{
+	*this /= length();
+	return *this;
+}
+
+
+inline Vector_3d &Vector_3d::normalize(double &len)
+{
+	len = length();
+	*this /= len;
+	return *this;
+}
+
+
+inline Vector_3d &Vector_3d::scale(double a)
+{
+	*this *= a;
+	return *this;
+}
+
+
+inline Vector_3d &Vector_3d::transform(const Matrix_4d &m)
+{
+	return *this *= m;
+}
+
+
+inline Vector_3d &Vector_3d::affine_transform(const Matrix_4d &m)
+{
+	return reset(m_v[0] * m(0, 0)
+		     + m_v[1] * m(0, 1)
+		     + m_v[2] * m(0, 2)
+		     + m(0, 3),
+
+		     m_v[0] * m(1, 0)
+		     + m_v[1] * m(1, 1)
+		     + m_v[2] * m(1, 2)
+		     + m(1, 3),
+
+		     m_v[0] * m(2, 0)
+		     + m_v[1] * m(2, 1)
+		     + m_v[2] * m(2, 2)
+		     + m(2, 3));
+}
+
+
+inline void Vector_3d::flip()
+{
+	m_v[0] = -m_v[0];
+	m_v[1] = -m_v[1];
+	m_v[2] = -m_v[2];
+}
+
+
+inline void Vector_3d::gl_normal() const
+{
+	glNormal3dv(m_v);
+}
+
+
+inline void swap(Vector_3d &a, Vector_3d &b)
+{
+	Vector_3d tmp(a);
+	a = b;
+	b = tmp;
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_VECTOR_3D_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Vector_3f.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Vector_3f.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Vector_3f.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,62 @@
+#ifndef GTB_VECTOR_3F_INCLUDED
+#include "Vector_3f.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+const Vector_3f VECTOR_3F_ZERO(0.0, 0.0, 0.0);
+const Vector_3f VECTOR_3F_POSITIVE_X(1.0, 0.0, 0.0);
+const Vector_3f VECTOR_3F_NEGATIVE_X(-1.0, 0.0, 0.0);
+const Vector_3f VECTOR_3F_POSITIVE_Y(0.0, 1.0, 0.0);
+const Vector_3f VECTOR_3F_NEGATIVE_Y(0.0, -1.0, 0.0);
+const Vector_3f VECTOR_3F_POSITIVE_Z(0.0, 0.0, 1.0);
+const Vector_3f VECTOR_3F_NEGATIVE_Z(0.0, 0.0, -1.0);
+
+
+Vector_3f &Vector_3f::rotate(const Vector_3f &axis, float theta)
+{
+	// From Goldstein
+	*this =	*this * cos(theta) +
+		axis * this->dot(axis) * (1.0 - cos(theta)) -
+		this->cross(axis) * sin(theta);
+	return *this;
+}
+
+
+// Finds the rotation that takes V to W (Graphics Gems I, p. 531).
+// (Here we pre-multiply, though, i.e., M * p, so we have to use the
+// transpose of what's shown there.)
+Matrix_4d Vector_3f::rotation(const Vector_3f &V, const Vector_3f &W)
+{
+	float d = V.dot(W);
+	if (gtb::eps_is_equal(d, 1.0, FLT_EPSILON)) {
+		return MATRIX_4D_IDENTITY;
+	}
+	if (gtb::eps_is_equal(d, -1.0, FLT_EPSILON)) {
+		return -MATRIX_4D_IDENTITY;
+	}
+
+	Vector_3f N = V.cross(W);
+	N.normalize();
+
+	Vector_3f M = N.cross(V);
+	M.normalize();
+
+	Matrix_4d Q(V[0], V[1], V[2], 0.0,
+		    M[0], M[1], M[2], 0.0,
+		    N[0], N[1], N[2], 0.0,
+		    0.0, 0.0, 0.0, 1.0);
+
+	Vector_3f W2 = Q * W;
+
+	Matrix_4d RT(W2[0], -W2[1], 0.0, 0.0,
+		     W2[1], W2[0], 0.0, 0.0,
+		     W2[2], W2[2], 1.0, 0.0,
+		     0.0, 0.0, 0.0, 1.0);
+
+	return Q.transpose() * RT * Q;
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Vector_3f.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Vector_3f.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Vector_3f.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,494 @@
+#ifndef GTB_VECTOR_3F_INCLUDED
+#define GTB_VECTOR_3F_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_GL_HEADERS_INCLUDED
+#include "gl_headers.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+class Point_3f;
+class Matrix_4d;
+
+
+class Vector_3f {
+public:
+	Vector_3f();
+	Vector_3f(const Vector_3f &v);
+	explicit Vector_3f(const Point_3f &p);
+	Vector_3f(float vx, float vy, float vz);
+	explicit Vector_3f(const float v[3]);
+	explicit Vector_3f(const float v);
+	Vector_3f &operator=(const Vector_3f &v);
+
+	const float &get_x() const;
+	const float &get_y() const;
+	const float &get_z() const;
+
+	const float &operator[](unsigned i) const;
+	float &operator[](unsigned i);
+
+	Vector_3f &set_x(float vx);
+	Vector_3f &set_y(float vy);
+	Vector_3f &set_z(float vz);
+	Vector_3f &reset(float vx, float vy, float vz);
+
+	bool eps_is_equal(const Vector_3f &v, float eps) const;
+	bool eps_is_zero(float eps) const;
+	bool eps_is_normalized(float eps) const;
+
+	Vector_3f operator-() const;
+	Vector_3f &operator*=(const Matrix_4d &m);
+	Vector_3f &operator+=(const Vector_3f &v);
+	Vector_3f &operator-=(const Vector_3f &v);
+	Vector_3f &operator*=(float a);
+	Vector_3f &operator/=(float a);
+
+	float operator*(const Vector_3f &v) const;
+	float operator*(const Point_3f &p) const;
+
+	friend Vector_3f operator+(const Vector_3f &u, const Vector_3f &v);
+	friend Point_3f operator+(const Point_3f &p, const Vector_3f &v);
+	friend Vector_3f operator-(const Vector_3f &u, const Vector_3f &v);
+	friend Point_3f operator-(const Point_3f &p, const Vector_3f &v);
+	friend Vector_3f operator*(float a, const Vector_3f &v);
+	friend Vector_3f operator*(const Vector_3f &v, float a);
+	friend Vector_3f operator*(const Matrix_4d &m, const Vector_3f &v);
+	friend Vector_3f operator/(const Vector_3f &v, float a);
+
+	float dot(const Vector_3f &v) const;
+	float dot(const Point_3f &p) const;
+	Vector_3f cross(const Vector_3f &v) const;
+	float length() const;
+	float squared_length() const;
+	Vector_3f &normalize();
+	Vector_3f &normalize(float &len);
+	Vector_3f &scale(float a);
+	Vector_3f &rotate(const Vector_3f &axis, float theta);
+	Vector_3f &transform(const Matrix_4d &m);
+	Vector_3f &affine_transform(const Matrix_4d &m);
+	void flip();
+
+	void gl_normal() const;
+
+	static Matrix_4d rotation(const Vector_3f &from, const Vector_3f &to);
+
+	friend class Point_3f;
+	friend void swap(Vector_3f &a, Vector_3f &b);
+
+protected:
+	float m_v[3];
+};
+
+
+extern const Vector_3f VECTOR_3F_ZERO;
+extern const Vector_3f VECTOR_3F_POSITIVE_X;
+extern const Vector_3f VECTOR_3F_NEGATIVE_X;
+extern const Vector_3f VECTOR_3F_POSITIVE_Y;
+extern const Vector_3f VECTOR_3F_NEGATIVE_Y;
+extern const Vector_3f VECTOR_3F_POSITIVE_Z;
+extern const Vector_3f VECTOR_3F_NEGATIVE_Z;
+
+
+GTB_END_NAMESPACE
+
+
+#ifndef GTB_POINT_3F_INCLUDED
+#include "Point_3f.hpp"
+#endif
+
+
+GTB_BEGIN_NAMESPACE
+
+
+inline Vector_3f::Vector_3f()
+{
+}
+
+
+inline Vector_3f::Vector_3f(const Vector_3f &v)
+{
+	m_v[0] = v.m_v[0];
+	m_v[1] = v.m_v[1];
+	m_v[2] = v.m_v[2];
+}
+
+
+inline Vector_3f::Vector_3f(float vx, float vy, float vz)
+{
+	m_v[0] = vx;
+	m_v[1] = vy;
+	m_v[2] = vz;
+}
+
+
+inline Vector_3f::Vector_3f(const float v[3])
+{
+	m_v[0] = v[0];
+	m_v[1] = v[1];
+	m_v[2] = v[2];
+}
+
+
+inline Vector_3f::Vector_3f(const float v) 
+{
+	m_v[0] = v;
+	m_v[1] = v;
+	m_v[2] = v;
+}
+
+
+inline Vector_3f::Vector_3f(const Point_3f &p)
+{
+	m_v[0] = p.m_p[0];
+	m_v[1] = p.m_p[1];
+	m_v[2] = p.m_p[2];
+}
+
+
+inline Vector_3f &Vector_3f::operator=(const Vector_3f &v)
+{
+	m_v[0] = v.m_v[0];
+	m_v[1] = v.m_v[1];
+	m_v[2] = v.m_v[2];
+	return *this;
+}
+
+
+inline const float &Vector_3f::get_x() const
+{
+	return m_v[0];
+}
+
+
+inline const float &Vector_3f::get_y() const
+{
+	return m_v[1];
+}
+
+
+inline const float &Vector_3f::get_z() const
+{
+	return m_v[2];
+}
+
+
+inline const float &Vector_3f::operator[](unsigned i) const
+{
+	GTB_REQUIRE(i < 3);
+	return m_v[i];
+}
+
+
+inline float &Vector_3f::operator[](unsigned i)
+{
+	GTB_REQUIRE(i < 3);
+	return m_v[i];
+}
+
+
+inline Vector_3f &Vector_3f::set_x(float vx)
+{
+	m_v[0] = vx;
+	return *this;
+}
+
+
+inline Vector_3f &Vector_3f::set_y(float vy)
+{
+	m_v[1] = vy;
+	return *this;
+}
+
+
+inline Vector_3f &Vector_3f::set_z(float vz)
+{
+	m_v[2] = vz;
+	return *this;
+}
+
+
+inline Vector_3f &Vector_3f::reset(float vx, float vy, float vz)
+{
+	m_v[0] = vx;
+	m_v[1] = vy;
+	m_v[2] = vz;
+	return *this;
+}
+
+
+inline bool Vector_3f::eps_is_equal(const Vector_3f &v, float eps) const
+{
+	return (gtb::eps_is_equal(m_v[0], v.m_v[0], eps) &&
+		gtb::eps_is_equal(m_v[1], v.m_v[1], eps) &&
+		gtb::eps_is_equal(m_v[2], v.m_v[2], eps));
+}
+
+
+inline bool Vector_3f::eps_is_zero(float eps) const
+{
+	return (gtb::eps_is_zero(m_v[0], eps) &&
+		gtb::eps_is_zero(m_v[1], eps) &&
+		gtb::eps_is_zero(m_v[2], eps));
+}
+
+
+inline Vector_3f Vector_3f::operator-() const
+{
+	return Vector_3f(-m_v[0],
+			 -m_v[1],
+			 -m_v[2]);
+}
+
+
+inline Vector_3f &Vector_3f::operator+=(const Vector_3f &v)
+{
+	m_v[0] += v.m_v[0];
+	m_v[1] += v.m_v[1];
+	m_v[2] += v.m_v[2];
+	return *this;
+}
+
+
+inline Vector_3f &Vector_3f::operator-=(const Vector_3f &v)
+{
+	m_v[0] -= v.m_v[0];
+	m_v[1] -= v.m_v[1];
+	m_v[2] -= v.m_v[2];
+	return *this;
+}
+
+
+inline Vector_3f &Vector_3f::operator*=(float a)
+{
+	m_v[0] *= a;
+	m_v[1] *= a;
+	m_v[2] *= a;
+	return *this;
+}
+
+
+inline Vector_3f &Vector_3f::operator*=(const Matrix_4d &m)
+{
+	float w = m_v[0] * m(3, 0) 
+		+ m_v[1] * m(3, 1) 
+		+ m_v[2] * m(3, 2) 
+		+ m(3, 3);
+
+	float wi = 1.0 / w;
+
+	return reset((m_v[0] * m(0, 0) 
+		      + m_v[1] * m(0, 1) 
+		      + m_v[2] * m(0, 2) 
+		      + m(0, 3)) * wi,
+
+		     (m_v[0] * m(1, 0) 
+		      + m_v[1] * m(1, 1)
+		      + m_v[2] * m(1, 2) 
+		      + m(1, 3)) * wi,
+
+		     (m_v[0] * m(2, 0)
+		      + m_v[1] * m(2, 1)
+		      + m_v[2] * m(2, 2)
+		      + m(2, 3)) * wi);
+}
+
+
+inline Vector_3f &Vector_3f::operator/=(float a)
+{
+	return *this *= 1.0 / a;
+}
+
+
+inline float Vector_3f::dot(const Vector_3f &v) const
+{
+	return (m_v[0] * v.m_v[0] +
+		m_v[1] * v.m_v[1] +
+		m_v[2] * v.m_v[2]);
+}
+
+
+inline float Vector_3f::dot(const Point_3f &p) const
+{
+	return (m_v[0] * p.m_p[0] +
+		m_v[1] * p.m_p[1] +
+		m_v[2] * p.m_p[2]);
+}
+
+
+inline float Vector_3f::operator*(const Vector_3f &v) const
+{
+	return dot(v);
+}
+
+
+inline float Vector_3f::operator*(const Point_3f &p) const
+{
+	return dot(p);
+}
+
+
+inline Vector_3f operator+(const Vector_3f &u, const Vector_3f &v)
+{
+	return Vector_3f(u.m_v[0] + v.m_v[0],
+			 u.m_v[1] + v.m_v[1],
+			 u.m_v[2] + v.m_v[2]);
+}
+
+
+inline Vector_3f operator-(const Vector_3f &u, const Vector_3f &v)
+{
+	return Vector_3f(u.m_v[0] - v.m_v[0],
+			 u.m_v[1] - v.m_v[1],
+			 u.m_v[2] - v.m_v[2]);
+}
+
+
+inline Vector_3f operator*(float a, const Vector_3f &v)
+{
+	return Vector_3f(a * v.m_v[0],
+			 a * v.m_v[1],
+			 a * v.m_v[2]);
+}
+
+
+inline Vector_3f operator*(const Vector_3f &v, float a)
+{
+	return a * v;
+}
+
+
+inline Vector_3f operator*(const Matrix_4d &m, const Vector_3f &v)
+{
+	float w = v.m_v[0] * m(3, 0)
+		+ v.m_v[1] * m(3, 1)
+		+ v.m_v[2] * m(3, 2)
+		+ m(3, 3);
+
+	float wi = 1.0 / w;
+
+	return Vector_3f((v.m_v[0] * m(0, 0)
+			  + v.m_v[1] * m(0, 1)
+			  + v.m_v[2] * m(0, 2)
+			  + m(0, 3)) * wi,
+
+			 (v.m_v[0] * m(1, 0)
+			  + v.m_v[1] * m(1, 1)
+			  + v.m_v[2] * m(1, 2)
+			  + m(1, 3)) * wi,
+
+			 (v.m_v[0] * m(2, 0)
+			  + v.m_v[1] * m(2, 1)
+			  + v.m_v[2] * m(2, 2)
+			  + m(2, 3)) * wi);
+}
+
+
+inline Vector_3f operator/(const Vector_3f &v, float a)
+{
+	return v * (1.0 / a);
+}
+
+
+inline Vector_3f Vector_3f::cross(const Vector_3f &v) const
+{
+	return Vector_3f((m_v[1] * v.m_v[2]) - (m_v[2] * v.m_v[1]),
+			 (m_v[2] * v.m_v[0]) - (m_v[0] * v.m_v[2]),
+			 (m_v[0] * v.m_v[1]) - (m_v[1] * v.m_v[0]));
+}
+
+
+inline float Vector_3f::length() const
+{
+	return sqrt(this->dot(*this));
+}
+
+
+inline float Vector_3f::squared_length() const
+{
+	return this->dot(*this);
+}
+
+
+inline bool Vector_3f::eps_is_normalized(float eps) const
+{
+	return gtb::eps_is_equal(squared_length(), 1.0, eps);
+}
+
+
+inline Vector_3f &Vector_3f::normalize()
+{
+	*this /= length();
+	return *this;
+}
+
+
+inline Vector_3f &Vector_3f::normalize(float &len)
+{
+	len = length();
+	*this /= len;
+	return *this;
+}
+
+
+inline Vector_3f &Vector_3f::scale(float a)
+{
+	*this *= a;
+	return *this;
+}
+
+
+inline Vector_3f &Vector_3f::transform(const Matrix_4d &m)
+{
+	return *this *= m;
+}
+
+
+inline Vector_3f &Vector_3f::affine_transform(const Matrix_4d &m)
+{
+	return reset(m_v[0] * m(0, 0)
+		     + m_v[1] * m(0, 1)
+		     + m_v[2] * m(0, 2)
+		     + m(0, 3),
+
+		     m_v[0] * m(1, 0)
+		     + m_v[1] * m(1, 1)
+		     + m_v[2] * m(1, 2)
+		     + m(1, 3),
+
+		     m_v[0] * m(2, 0)
+		     + m_v[1] * m(2, 1)
+		     + m_v[2] * m(2, 2)
+		     + m(2, 3));
+}
+
+
+inline void Vector_3f::flip()
+{
+	m_v[0] = -m_v[0];
+	m_v[1] = -m_v[1];
+	m_v[2] = -m_v[2];
+}
+
+
+inline void Vector_3f::gl_normal() const
+{
+	glNormal3fv(m_v);
+}
+
+
+inline void swap(Vector_3f &a, Vector_3f &b)
+{
+	Vector_3f tmp(a);
+	a = b;
+	b = tmp;
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_VECTOR_3F_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Visitor.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Visitor.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Visitor.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,8 @@
+#ifndef GTB_VISITOR_INCLUDED
+#include "Visitor.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/Visitor.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Visitor.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Visitor.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,35 @@
+#ifndef GTB_VISITOR_INCLUDED
+#define GTB_VISITOR_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+class Shape;
+class Indexed_face_set;
+class Indexed_point_set;
+class Indexed_triangle_set;
+class Indexed_tetra_set;
+class LOD;
+class Octree;
+class Shape_proxy;
+
+class Visitor {
+public:
+	virtual ~Visitor() {}
+	virtual void visit(Shape &) {}
+	virtual void visit(Indexed_face_set &) {}
+	virtual void visit(Indexed_point_set &) {}
+	virtual void visit(Indexed_triangle_set &) {}
+	virtual void visit(Indexed_tetra_set &) {}
+	virtual void visit(LOD &) {}
+	virtual void visit(Octree &) {}
+	virtual void visit(Shape_proxy &) {}
+};
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_VISITOR_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/Writers.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Writers.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Writers.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,97 @@
+#include "Writers.hpp"
+#include <vector>
+#include <stdio.h>
+
+
+using namespace gtb;
+
+int gtb::residuals_write_off(const char *filename,
+                             const std::vector<Point_3f> &vertices,
+                             const std::vector<Tetrahedron> &tets,
+                             const std::vector<float> &residuals)
+{
+    FILE *fp;
+    GTB_FOPEN(fp, filename, "w");
+    
+    fprintf(fp, "%d %d\n", vertices.size(), tets.size());
+
+    for (unsigned i = 0; i < vertices.size(); i++)
+    {
+        fprintf(fp, "%f %f %f\n", vertices[i][0], vertices[i][1], vertices[i][2]);
+    }
+
+    for (unsigned ti = 0; ti < tets.size(); ti++)
+    {
+        const Tetrahedron &t = tets[ti];
+        fprintf(fp, "%d %d %d %d %.10f\n",
+                t.get_vertex(0),
+                t.get_vertex(1),
+                t.get_vertex(2),
+                t.get_vertex(3),
+                residuals[ti]);
+    }
+
+    fclose(fp);
+
+    return 0;
+}
+
+
+int gtb::residuals_write_vtk(const char *filename,
+                             const std::vector<Point_3f> &vertices,
+                             const std::vector<Tetrahedron> &tets,
+                             const std::vector<float> &residuals)
+{
+    const int ndof = 4;
+    int nno = vertices.size();
+    int nel = tets.size();
+
+    FILE *fp;
+    GTB_FOPEN(fp, filename, "w");
+
+    fprintf(fp, "# vtk DataFile Version 3.0\n");
+    fprintf(fp, "This line is a comment\n");
+    fprintf(fp, "ASCII\n");
+
+    fprintf(fp, "DATASET UNSTRUCTURED_GRID\n");
+
+    fprintf(fp, "POINTS %d float\n", nno);
+    for (int n = 0; n < nno; n++)
+    {
+        fprintf(fp, "%g %g %g\n",
+                vertices[n][0],
+                vertices[n][1],
+                vertices[n][2]);
+    }
+
+    fprintf(fp, "CELLS %d %d\n", nel, (nel + nel*ndof));
+    for (int e = 0; e < nel; e++)
+    {
+        const Tetrahedron &t = tets[e];
+        fprintf(fp,
+                "%d "
+                "%d %d %d %d\n",
+                ndof,
+                t.get_vertex(0),
+                t.get_vertex(1),
+                t.get_vertex(2),
+                t.get_vertex(3));
+    }
+
+    fprintf(fp, "CELL_TYPES %d\n", nel);
+    for (int e = 0; e < nel; e++)
+    {
+        fprintf(fp, "10\n");
+    }
+
+    fprintf(fp, "CELL_DATA %d\n", nel);
+    fprintf(fp, "SCALARS LocalResiduals float\n");
+    fprintf(fp, "LOOKUP_TABLE default\n");
+    for (int e = 0; e < nel; e++)
+    {
+        fprintf(fp, "%g\n", residuals[e]);
+    }
+
+    fclose(fp);
+    return 0;
+}

Added: cs/cigma/branches/cigma-0.9b1/tmc/Writers.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/Writers.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/Writers.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,26 @@
+#ifndef GTB_WRITERS_INCLUDED
+#define GTB_WRITERS_INCLUDED
+
+#include "namespace.hpp"
+#include "Point_3f.hpp"
+#include "Tetrahedron.hpp"
+#include "Time_series.hpp"
+
+GTB_BEGIN_NAMESPACE
+
+
+int residuals_write_off(const char *filename,
+                        const std::vector<Point_3f> &vertices,
+                        const std::vector<Tetrahedron> &tets,
+                        const std::vector<float> &residuals);
+
+int residuals_write_vtk(const char *filename,
+                        const std::vector<Point_3f> &vertices,
+                        const std::vector<Tetrahedron> &tets,
+                        const std::vector<float> &residuals);
+
+
+GTB_END_NAMESPACE
+
+
+#endif // GTB_WRITERS_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/anyoption.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/anyoption.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/anyoption.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,1175 @@
+// http://www.hackorama.com/anyoption/anyoption.cpp
+/*
+ * AnyOption 1.3  
+ *
+ * kishan at hackorama dot com  www.hackorama.com JULY 2001 
+ *
+ * + Acts as a common facade class for reading 
+ *   commandline options as well as options from
+ *   an optionfile with delimited type value pairs 
+ *
+ * + Handles the POSIX style single character options ( -w )
+ *   as well as the newer GNU long options ( --width )
+ * 
+ * + The option file assumes the traditional format of
+ *   first character based comment lines and type value
+ *   pairs with a delimiter , and flags which are not pairs
+ * 
+ *  	# this is a coment
+ *  	# next line is an option value pair
+ *  	width : 100
+ *     	# next line is a flag 
+ *      noimages   
+ * 
+ * + Supports printing out Help and Usage  
+ * 
+ * + Why not just use getopt() ? 
+ *
+ *   getopt() Its a POSIX standard not part of ANSI-C. 
+ *   So it may not be available on platforms like Windows.
+ *
+ * + Why it is so long ?
+ *
+ *   The actual code which does command line parsing 
+ *   and option file parsing are done in  few methods. 
+ *   Most of the extra code are for providing a flexible
+ *   common public interface to both a resourcefile and
+ *   and command line supporting POSIX style and  
+ *   GNU long option as well as mixing of both. 
+ * 
+ * + Please see "anyoption.h" for public method descriptions 
+ *   
+ */
+
+/* Updated Auguest 2004 
+ * Fix from  Michael D Peters (mpeters at sandia.gov) 
+ * to remove static local variables, allowing multiple instantiations 
+ * of the reader (for using multiple configuration files).  There is
+ * an error in the destructor when using multiple instances, so you
+ * cannot delete your objects (it will crash), but not calling the 
+ * destructor only introduces a small memory leak, so I
+ * have not bothered tracking it down.
+ *
+ * Also updated to use modern C++ style headers, rather than
+ * depricated iostream.h (it was causing my compiler problems)
+*/
+
+/* 
+ * Updated September 2006  
+ * Fix from Boyan Asenov for a bug in mixing up option indexes 
+ * leading to exception when mixing different options types
+ */
+
+#include "anyoption.h"
+
+AnyOption::AnyOption()
+{
+	init();
+}
+
+AnyOption::AnyOption(int maxopt)
+{
+	init( maxopt , maxopt );
+}
+
+AnyOption::AnyOption(int maxopt, int maxcharopt)
+{
+	init( maxopt , maxcharopt );
+}
+
+AnyOption::~AnyOption()
+{
+	if( mem_allocated )
+		cleanup();
+}
+
+void
+AnyOption::init()
+{
+	init( DEFAULT_MAXOPTS , DEFAULT_MAXOPTS );
+}
+
+void
+AnyOption::init(int maxopt, int maxcharopt )
+{
+
+	max_options 	= maxopt;
+	max_char_options = maxcharopt;
+	max_usage_lines	= DEFAULT_MAXUSAGE;
+	usage_lines	= 0 ;
+	argc 		= 0;
+	argv 		= NULL;
+	posix_style	= true;
+	verbose 	= false;
+	filename 	= NULL;
+	appname 	= NULL;	
+	option_counter 	= 0;
+	optchar_counter	= 0;
+	new_argv 	= NULL;
+	new_argc 	= 0 ;
+	max_legal_args 	= 0 ;
+	command_set 	= false;
+	file_set 	= false;
+	values 		= NULL;	
+	g_value_counter = 0;
+	mem_allocated 	= false;
+	command_set 	= false;
+	file_set	= false;
+	opt_prefix_char     = '-';
+	file_delimiter_char = ':';
+	file_comment_char   = '#';
+	equalsign 	= '=';
+	comment       = '#' ;
+	delimiter     = ':' ;
+	endofline     = '\n';
+	whitespace    = ' ' ;
+	nullterminate = '\0';
+	set = false;
+	once = true;
+	hasoptions = false;
+	autousage = false;
+
+	strcpy( long_opt_prefix , "--" );
+
+	if( alloc() == false ){
+		cout << endl << "OPTIONS ERROR : Failed allocating memory" ;
+		cout << endl ;
+		cout << "Exiting." << endl ;
+		exit (0);
+	}
+}
+
+bool
+AnyOption::alloc()
+{
+	int i = 0 ;
+	int size = 0 ;
+
+	if( mem_allocated )
+		return true;
+
+	size = (max_options+1) * sizeof(const char*);
+	options = (const char**)malloc( size );	
+	optiontype = (int*) malloc( (max_options+1)*sizeof(int) );	
+	optionindex = (int*) malloc( (max_options+1)*sizeof(int) );	
+	if( options == NULL || optiontype == NULL || optionindex == NULL )
+		return false;
+	else
+		mem_allocated  = true;
+	for( i = 0 ; i < max_options ; i++ ){
+		options[i] = NULL;
+		optiontype[i] = 0 ;
+		optionindex[i] = -1 ;
+	}
+	optionchars = (char*) malloc( (max_char_options+1)*sizeof(char) );
+	optchartype = (int*) malloc( (max_char_options+1)*sizeof(int) );	
+	optcharindex = (int*) malloc( (max_char_options+1)*sizeof(int) );	
+	if( optionchars == NULL || 
+            optchartype == NULL || 
+            optcharindex == NULL )
+        {
+		mem_allocated = false;
+		return false;
+	}
+	for( i = 0 ; i < max_char_options ; i++ ){
+		optionchars[i] = '0';
+		optchartype[i] = 0 ;
+		optcharindex[i] = -1 ;
+	}
+
+	size = (max_usage_lines+1) * sizeof(const char*) ;
+	usage = (const char**) malloc( size );
+
+	if( usage == NULL  ){
+		mem_allocated = false;
+		return false;
+	}
+	for( i = 0 ; i < max_usage_lines ; i++ )
+		usage[i] = NULL;
+
+	return true;
+}
+
+bool
+AnyOption::doubleOptStorage()
+{
+	options = (const char**)realloc( options,  
+			((2*max_options)+1) * sizeof( const char*) );
+	optiontype = (int*) realloc(  optiontype ,  
+			((2 * max_options)+1)* sizeof(int) );	
+	optionindex = (int*) realloc(  optionindex,  
+			((2 * max_options)+1) * sizeof(int) );	
+	if( options == NULL || optiontype == NULL || optionindex == NULL )
+		return false;
+	/* init new storage */
+	for( int i = max_options ; i < 2*max_options ; i++ ){
+		options[i] = NULL;
+		optiontype[i] = 0 ;
+		optionindex[i] = -1 ;
+	}
+	max_options = 2 * max_options ;
+	return true;
+}
+
+bool
+AnyOption::doubleCharStorage()
+{
+	optionchars = (char*) realloc( optionchars,  
+			((2*max_char_options)+1)*sizeof(char) );
+	optchartype = (int*) realloc( optchartype,  
+			((2*max_char_options)+1)*sizeof(int) );	
+	optcharindex = (int*) realloc( optcharindex,  
+			((2*max_char_options)+1)*sizeof(int) );	
+	if( optionchars == NULL || 
+	    optchartype == NULL || 
+	    optcharindex == NULL )
+		return false;
+	/* init new storage */
+	for( int i = max_char_options ; i < 2*max_char_options ; i++ ){
+		optionchars[i] = '0';
+		optchartype[i] = 0 ;
+		optcharindex[i] = -1 ;
+	}
+	max_char_options = 2 * max_char_options;	
+	return true;
+}
+
+bool
+AnyOption::doubleUsageStorage()
+{
+	usage = (const char**)realloc( usage,  
+			((2*max_usage_lines)+1) * sizeof( const char*) );
+	if ( usage == NULL )
+		return false;
+	for( int i = max_usage_lines ; i < 2*max_usage_lines ; i++ )
+		usage[i] = NULL;
+	max_usage_lines = 2 * max_usage_lines ;
+	return true;
+
+}
+
+
+void
+AnyOption::cleanup()
+{
+	free (options);
+	free (optiontype);
+	free (optionindex);	
+	free (optionchars);
+	free (optchartype);
+	free (optcharindex);
+	free (usage);
+	if( values != NULL )
+		free (values);
+	if( new_argv != NULL )
+		free (new_argv);
+}
+
+void
+AnyOption::setCommandPrefixChar( char _prefix )
+{
+	opt_prefix_char = _prefix;
+}
+
+void
+AnyOption::setCommandLongPrefix( char *_prefix )
+{
+	if( strlen( _prefix ) > MAX_LONG_PREFIX_LENGTH ){
+		*( _prefix + MAX_LONG_PREFIX_LENGTH ) = '\0'; 
+	}
+
+	strcpy (long_opt_prefix,  _prefix);
+}
+
+void
+AnyOption::setFileCommentChar( char _comment )
+{
+	file_delimiter_char = _comment;
+}
+
+
+void
+AnyOption::setFileDelimiterChar( char _delimiter )
+{
+	file_comment_char = _delimiter ;
+}
+
+bool
+AnyOption::CommandSet()
+{
+	return( command_set );
+}
+
+bool
+AnyOption::FileSet()
+{
+	return( file_set );
+}
+
+void
+AnyOption::noPOSIX()
+{
+	posix_style = false;
+}
+
+bool
+AnyOption::POSIX()
+{
+	return posix_style;
+}
+
+
+void
+AnyOption::setVerbose()
+{
+	verbose = true ;
+}
+
+void
+AnyOption::printVerbose()
+{
+	if( verbose )
+		cout << endl  ;
+}
+void
+AnyOption::printVerbose( const char *msg )
+{
+	if( verbose )
+		cout << msg  ;
+}
+
+void
+AnyOption::printVerbose( char *msg )
+{
+	if( verbose )
+		cout << msg  ;
+}
+
+void
+AnyOption::printVerbose( char ch )
+{
+	if( verbose )
+		cout << ch ;
+}
+
+bool
+AnyOption::hasOptions()
+{
+	return hasoptions;
+}
+
+void
+AnyOption::autoUsagePrint(bool _autousage)
+{
+	autousage = _autousage;
+}
+
+void
+AnyOption::useCommandArgs( int _argc, char **_argv )
+{
+	argc = _argc;
+	argv = _argv;
+	command_set = true;
+	appname = argv[0];
+	if(argc > 1) hasoptions = true;
+}
+
+void
+AnyOption::useFiileName( const char *_filename )
+{
+	filename = _filename;
+	file_set = true;
+}
+
+/*
+ * set methods for options 
+ */
+
+void
+AnyOption::setCommandOption( const char *opt )
+{
+	addOption( opt , COMMAND_OPT );
+	g_value_counter++;
+}
+
+void
+AnyOption::setCommandOption( char opt )
+{
+	addOption( opt , COMMAND_OPT );
+	g_value_counter++;
+}
+
+void
+AnyOption::setCommandOption( const char *opt , char optchar )
+{
+	addOption( opt , COMMAND_OPT );
+	addOption( optchar , COMMAND_OPT );
+	g_value_counter++;
+}
+
+void
+AnyOption::setCommandFlag( const char *opt )
+{
+	addOption( opt , COMMAND_FLAG );
+	g_value_counter++;
+}
+
+void
+AnyOption::setCommandFlag( char opt )
+{
+	addOption( opt , COMMAND_FLAG );
+	g_value_counter++;
+}
+
+void
+AnyOption::setCommandFlag( const char *opt , char optchar )
+{
+	addOption( opt , COMMAND_FLAG );
+	addOption( optchar , COMMAND_FLAG );
+	g_value_counter++;
+}
+
+void
+AnyOption::setFileOption( const char *opt )
+{
+	addOption( opt , FILE_OPT );
+	g_value_counter++;
+}
+
+void
+AnyOption::setFileOption( char opt )
+{
+	addOption( opt , FILE_OPT );
+	g_value_counter++;
+}
+
+void
+AnyOption::setFileOption( const char *opt , char optchar )
+{
+	addOption( opt , FILE_OPT );
+	addOption( optchar, FILE_OPT  );
+	g_value_counter++;
+}
+
+void
+AnyOption::setFileFlag( const char *opt )
+{
+	addOption( opt , FILE_FLAG );
+	g_value_counter++;
+}
+
+void
+AnyOption::setFileFlag( char opt )
+{
+	addOption( opt , FILE_FLAG );
+	g_value_counter++;
+}
+
+void
+AnyOption::setFileFlag( const char *opt , char optchar )
+{
+	addOption( opt , FILE_FLAG );
+	addOption( optchar , FILE_FLAG );
+	g_value_counter++;
+}
+
+void
+AnyOption::setOption( const char *opt )
+{
+	addOption( opt , COMMON_OPT );
+	g_value_counter++;
+}
+
+void
+AnyOption::setOption( char opt )
+{
+	addOption( opt , COMMON_OPT );
+	g_value_counter++;
+}
+
+void
+AnyOption::setOption( const char *opt , char optchar )
+{
+	addOption( opt , COMMON_OPT );
+	addOption( optchar , COMMON_OPT );
+	g_value_counter++;
+}
+
+void
+AnyOption::setFlag( const char *opt )
+{
+	addOption( opt , COMMON_FLAG );
+	g_value_counter++;
+}
+
+void
+AnyOption::setFlag( const char opt )
+{
+	addOption( opt , COMMON_FLAG );
+	g_value_counter++;
+}
+
+void
+AnyOption::setFlag( const char *opt , char optchar )
+{
+	addOption( opt , COMMON_FLAG );
+	addOption( optchar , COMMON_FLAG );
+	g_value_counter++;
+}
+
+void
+AnyOption::addOption( const char *opt, int type )
+{
+	if( option_counter >= max_options ){
+		if( doubleOptStorage() == false ){
+			addOptionError( opt );
+			return;
+		}
+	}
+	options[ option_counter ] = opt ;
+	optiontype[ option_counter ] =  type ;
+	optionindex[ option_counter ] = g_value_counter; 
+	option_counter++;
+}
+
+void
+AnyOption::addOption( char opt, int type )
+{
+	if( !POSIX() ){
+		printVerbose("Ignoring the option character \"");
+		printVerbose(  opt );
+		printVerbose( "\" ( POSIX options are turned off )" );
+		printVerbose();
+		return;
+	}
+
+
+	if( optchar_counter >= max_char_options ){
+		if( doubleCharStorage() == false ){
+			addOptionError( opt );
+			return;
+		}
+	}
+	optionchars[ optchar_counter ] =  opt ;
+	optchartype[ optchar_counter ] =  type ;
+	optcharindex[ optchar_counter ] = g_value_counter; 
+	optchar_counter++;
+}
+
+void
+AnyOption::addOptionError( const char *opt )
+{
+	cout << endl ;
+	cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
+	cout << "While adding the option : \""<< opt << "\"" << endl;
+	cout << "Exiting." << endl ;
+	cout << endl ;
+	exit(0);
+}
+
+void
+AnyOption::addOptionError( char opt )
+{
+	cout << endl ;
+	cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
+	cout << "While adding the option: \""<< opt << "\"" << endl;
+	cout << "Exiting." << endl ;
+	cout << endl ;
+	exit(0);
+}
+
+void
+AnyOption::processOptions()
+{
+	if( ! valueStoreOK() )
+		return;
+}
+
+void 
+AnyOption::processCommandArgs(int max_args)
+{
+	max_legal_args = max_args;
+	processCommandArgs();
+}
+ 
+void
+AnyOption::processCommandArgs( int _argc, char **_argv, int max_args )
+{
+	max_legal_args = max_args;
+	processCommandArgs(  _argc, _argv );
+}
+
+void
+AnyOption::processCommandArgs( int _argc, char **_argv )
+{
+	useCommandArgs( _argc, _argv );
+	processCommandArgs();
+}
+
+void
+AnyOption::processCommandArgs()
+{
+   	if( ! ( valueStoreOK() && CommandSet() )  )
+	   return;
+	   
+	if( max_legal_args == 0 )
+		max_legal_args = argc;
+	new_argv = (int*) malloc( (max_legal_args+1) * sizeof(int) );
+	for( int i = 1 ; i < argc ; i++ ){/* ignore first argv */
+		if(  argv[i][0] == long_opt_prefix[0] && 
+                     argv[i][1] == long_opt_prefix[1] ) { /* long GNU option */
+			int match_at = parseGNU( argv[i]+2 ); /* skip -- */
+			if( match_at >= 0 && i < argc-1 ) /* found match */
+				setValue( options[match_at] , argv[++i] );
+		}else if(  argv[i][0] ==  opt_prefix_char ) { /* POSIX char */
+			if( POSIX() ){ 
+				char ch =  parsePOSIX( argv[i]+1 );/* skip - */ 
+				if( ch != '0' && i < argc-1 ) /* matching char */
+					setValue( ch ,  argv[++i] );
+			} else { /* treat it as GNU option with a - */
+				int match_at = parseGNU( argv[i]+1 ); /* skip - */
+				if( match_at >= 0 && i < argc-1 ) /* found match */
+					setValue( options[match_at] , argv[++i] );
+			}
+		}else { /* not option but an argument keep index */
+			if( new_argc < max_legal_args ){
+                                new_argv[ new_argc ] = i ;
+                                new_argc++;
+                        }else{ /* ignore extra arguments */
+                                printVerbose( "Ignoring extra argument: " );
+				printVerbose( argv[i] );
+				printVerbose( );
+				printAutoUsage();
+                        }
+			printVerbose( "Unknown command argument option : " );
+			printVerbose( argv[i] );
+			printVerbose( );
+			printAutoUsage();
+		}
+	}
+}
+
+char 
+AnyOption::parsePOSIX( char* arg )
+{
+
+	for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){ 
+		char ch = arg[i] ;
+		if( matchChar(ch) ) { /* keep matching flags till an option */
+			/*if last char argv[++i] is the value */
+			if( i == strlen(arg)-1 ){ 
+				return ch;
+			}else{/* else the rest of arg is the value */
+				i++; /* skip any '=' and ' ' */
+				while( arg[i] == whitespace 
+			    		|| arg[i] == equalsign )
+					i++;	
+				setValue( ch , arg+i );
+				return '0';
+			}
+		}
+	}
+	printVerbose( "Unknown command argument option : " );
+	printVerbose( arg );
+	printVerbose( );
+	printAutoUsage();
+	return '0';
+}
+
+int
+AnyOption::parseGNU( char *arg )
+{
+	int split_at = 0;
+	/* if has a '=' sign get value */
+	for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){
+		if(arg[i] ==  equalsign ){
+			split_at = i ; /* store index */
+			i = strlen(arg); /* get out of loop */
+		}
+	}
+	if( split_at > 0 ){ /* it is an option value pair */
+		char* tmp = (char*) malloc(  (split_at+1)*sizeof(char) );
+		for( int i = 0 ; i < split_at ; i++ )
+			tmp[i] = arg[i];
+		tmp[split_at] = '\0';
+
+		if ( matchOpt( tmp ) >= 0 ){
+			setValue( options[matchOpt(tmp)] , arg+split_at+1 );
+			free (tmp);
+		}else{
+			printVerbose( "Unknown command argument option : " );
+			printVerbose( arg );
+			printVerbose( );
+			printAutoUsage();
+			free (tmp);
+			return -1;
+		}
+	}else{ /* regular options with no '=' sign  */
+		return  matchOpt(arg);
+	}
+	return -1;
+}
+
+
+int 
+AnyOption::matchOpt( char *opt )
+{
+	for( int i = 0 ; i < option_counter ; i++ ){
+		if( strcmp( options[i], opt ) == 0 ){
+			if( optiontype[i] ==  COMMON_OPT ||
+			    optiontype[i] ==  COMMAND_OPT )	
+			{ /* found option return index */
+				return i;
+			}else if( optiontype[i] == COMMON_FLAG ||
+			       optiontype[i] == COMMAND_FLAG )
+			{ /* found flag, set it */ 
+				setFlagOn( opt );
+				return -1;
+			}
+		}
+	}
+	printVerbose( "Unknown command argument option : " );
+	printVerbose( opt  ) ;
+	printVerbose( );
+	printAutoUsage();
+	return  -1;	
+}
+bool
+AnyOption::matchChar( char c )
+{
+	for( int i = 0 ; i < optchar_counter ; i++ ){
+		if( optionchars[i] == c ) { /* found match */
+			if(optchartype[i] == COMMON_OPT ||
+			     optchartype[i] == COMMAND_OPT )
+			{ /* an option store and stop scanning */
+				return true;	
+			}else if( optchartype[i] == COMMON_FLAG || 
+				  optchartype[i] == COMMAND_FLAG ) { /* a flag store and keep scanning */
+				setFlagOn( c );
+				return false;
+			}
+		}
+	}
+	printVerbose( "Unknown command argument option : " );
+	printVerbose( c ) ;
+	printVerbose( );
+	printAutoUsage();
+	return false;
+}
+
+bool
+AnyOption::valueStoreOK( )
+{
+	int size= 0;
+	if( !set ){
+		if( g_value_counter > 0 ){
+			size = g_value_counter * sizeof(char*);
+			values = (char**)malloc( size );	
+			for( int i = 0 ; i < g_value_counter ; i++)
+				values[i] = NULL;
+			set = true;
+		}
+	}
+	return  set;
+}
+
+/*
+ * public get methods 
+ */
+char*
+AnyOption::getValue( const char *option )
+{
+	if( !valueStoreOK() )
+		return NULL;
+
+	for( int i = 0 ; i < option_counter ; i++ ){
+		if( strcmp( options[i], option ) == 0 )
+			return values[ optionindex[i] ];
+	}
+	return NULL;
+}
+
+bool
+AnyOption::getFlag( const char *option )
+{
+	if( !valueStoreOK() )
+		return false;
+	for( int i = 0 ; i < option_counter ; i++ ){
+		if( strcmp( options[i], option ) == 0 )
+			return findFlag( values[ optionindex[i] ] );
+	}
+	return false;
+}
+
+char*
+AnyOption::getValue( char option )
+{
+	if( !valueStoreOK() )
+		return NULL;
+	for( int i = 0 ; i < optchar_counter ; i++ ){
+		if( optionchars[i] == option )
+			return values[ optcharindex[i] ];
+	}
+	return NULL;
+}
+
+bool
+AnyOption::getFlag( char option )
+{
+	if( !valueStoreOK() )
+		return false;
+	for( int i = 0 ; i < optchar_counter ; i++ ){
+		if( optionchars[i] == option )
+			return findFlag( values[ optcharindex[i] ] ) ;
+	}
+	return false;
+}
+
+bool
+AnyOption::findFlag( char* val )
+{
+	if( val == NULL )
+		return false;
+
+	if( strcmp( TRUE_FLAG , val ) == 0 )
+		return true;
+
+	return false;
+}
+
+/*
+ * private set methods 
+ */
+bool
+AnyOption::setValue( const char *option , char *value )
+{
+	if( !valueStoreOK() )
+		return false;
+        for( int i = 0 ; i < option_counter ; i++ ){
+                if( strcmp( options[i], option ) == 0 ){
+                        values[ optionindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
+                        strcpy( values[ optionindex[i] ], value );
+			return true;
+		}
+        }
+        return false;
+}
+
+bool
+AnyOption::setFlagOn( const char *option )
+{
+	if( !valueStoreOK() )
+		return false;
+        for( int i = 0 ; i < option_counter ; i++ ){
+                if( strcmp( options[i], option ) == 0 ){
+                        values[ optionindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
+                        strcpy( values[ optionindex[i] ]  ,  TRUE_FLAG );
+			return true;
+		}
+        }
+        return false;
+}
+
+bool
+AnyOption::setValue( char option , char *value )
+{
+	if( !valueStoreOK() )
+		return false;
+        for( int i = 0 ; i < optchar_counter ; i++ ){
+                if( optionchars[i] == option ){
+                        values[ optcharindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
+                        strcpy( values[ optcharindex[i] ],  value );
+			return true;
+		}
+        }
+        return false;
+}
+
+bool
+AnyOption::setFlagOn( char option )
+{
+	if( !valueStoreOK() )
+		return false;
+        for( int i = 0 ; i < optchar_counter ; i++ ){
+                if( optionchars[i] == option ){
+                        values[ optcharindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
+			strcpy( values[ optcharindex[i] ] , TRUE_FLAG );
+			return true;
+		}
+        }
+        return false;
+}
+
+
+int
+AnyOption::getArgc( )
+{
+	return new_argc;
+}
+
+char* 
+AnyOption::getArgv( int index )
+{
+	if( index < new_argc ){
+		return ( argv[ new_argv[ index ] ] );
+	}
+	return NULL;
+}
+
+/* dotfile sub routines */
+
+bool
+AnyOption::processFile()
+{
+	if( ! (valueStoreOK() && FileSet())  )
+		return false;
+	return  ( consumeFile(readFile()) );
+}
+
+bool
+AnyOption::processFile( const char *filename )
+{
+	useFiileName(filename );
+	return ( processFile() );
+}
+
+char*
+AnyOption::readFile()
+{
+	return ( readFile(filename) );
+}
+
+/*
+ * read the file contents to a character buffer 
+ */
+
+char*
+AnyOption::readFile( const char* fname )
+{
+        int length;
+        char *buffer;
+        ifstream is;
+        is.open ( fname , ifstream::in );
+        if( ! is.good() ){
+                is.close();
+                return NULL;
+        }
+        is.seekg (0, ios::end);
+        length = is.tellg();
+        is.seekg (0, ios::beg);
+        buffer = (char*) malloc(length*sizeof(char));
+        is.read (buffer,length);
+        is.close();
+        return buffer;
+}
+
+/*
+ * scans a char* buffer for lines that does not 
+ * start with the specified comment character.
+ */
+bool
+AnyOption::consumeFile( char *buffer )
+{
+
+        if( buffer == NULL ) 
+		return false;
+
+       	char *cursor = buffer;/* preserve the ptr */
+       	char *pline = NULL ;
+       	int linelength = 0;
+       	bool newline = true;
+       	for( unsigned int i = 0 ; i < strlen( buffer ) ; i++ ){
+       	if( *cursor == endofline ) { /* end of line */
+          	if( pline != NULL ) /* valid line */
+               		processLine( pline, linelength );
+                 	pline = NULL;
+                 	newline = true;
+           	}else if( newline ){ /* start of line */
+                 	newline = false;
+              		if( (*cursor != comment ) ){ /* not a comment */
+		    		pline = cursor ;
+                    		linelength = 0 ;
+                	}
+             	}
+            	cursor++; /* keep moving */
+            	linelength++;
+       	}
+     	free (buffer);
+	return true;
+}
+
+
+/*
+ *  find a valid type value pair separated by a delimiter 
+ *  character and pass it to valuePairs()
+ *  any line which is not valid will be considered a value
+ *  and will get passed on to justValue()
+ *
+ *  assuming delimiter is ':' the behaviour will be,
+ *
+ *  width:10    - valid pair valuePairs( width, 10 );
+ *  width : 10  - valid pair valuepairs( width, 10 );
+ *
+ *  ::::        - not valid 
+ *  width       - not valid
+ *  :10         - not valid 
+ *  width:      - not valid  
+ *  ::          - not valid 
+ *  :           - not valid 
+ *  
+ */
+
+void
+AnyOption::processLine( char *theline, int length  )
+{
+        bool found = false;
+        char *pline = (char*) malloc( (length+1)*sizeof(char) );
+        for( int i = 0 ; i < length ; i ++ )
+                pline[i]= *(theline++);
+        pline[length] = nullterminate;
+        char *cursor = pline ; /* preserve the ptr */
+        if( *cursor == delimiter || *(cursor+length-1) == delimiter ){
+                justValue( pline );/* line with start/end delimiter */
+        }else{
+                for( int i = 1 ; i < length-1 && !found ; i++){/* delimiter */
+                        if( *cursor == delimiter ){
+                                *(cursor-1) = nullterminate; /* two strings */
+                                found = true;
+                                valuePairs( pline , cursor+1 );
+                        }
+                        cursor++;
+                }
+                cursor++;
+                if( !found ) /* not a pair */
+                        justValue( pline );
+        }
+        free (pline);
+}
+
+/*
+ * removes trailing and preceeding whitespaces from a string
+ */
+char*
+AnyOption::chomp( char *str )
+{
+        while( *str == whitespace )
+                str++;
+        char *end = str+strlen(str)-1;
+        while( *end == whitespace )
+                end--;
+        *(end+1) = nullterminate;
+        return str;
+}
+
+void
+AnyOption::valuePairs( char *type, char *value )
+{
+	if ( strlen(chomp(type)) == 1  ){ /* this is a char option */
+		for( int i = 0 ; i < optchar_counter ; i++ ){
+			if(  optionchars[i] == type[0]  ){ /* match */
+				if( optchartype[i] == COMMON_OPT ||
+				    optchartype[i] == FILE_OPT )
+				{
+			 		setValue( type[0] , chomp(value) );
+			 		return;
+				}
+			}
+		}
+	}	
+	/* if no char options matched */
+	for( int i = 0 ; i < option_counter ; i++ ){
+		if( strcmp( options[i], type ) == 0 ){ /* match */
+			if( optiontype[i] == COMMON_OPT ||
+			    optiontype[i] == FILE_OPT )
+			{
+		 		setValue( type , chomp(value) );
+		 		return;
+			}
+		}
+	}
+        printVerbose( "Unknown option in resourcefile : " );
+	printVerbose( type );
+	printVerbose( );
+}
+
+void
+AnyOption::justValue( char *type )
+{
+
+	if ( strlen(chomp(type)) == 1  ){ /* this is a char option */
+		for( int i = 0 ; i < optchar_counter ; i++ ){
+			if(  optionchars[i] == type[0]  ){ /* match */
+				if( optchartype[i] == COMMON_FLAG ||
+				    optchartype[i] == FILE_FLAG )
+				{
+			 		setFlagOn( type[0] );
+			 		return;
+				}
+			}
+		}
+	}	
+	/* if no char options matched */
+	for( int i = 0 ; i < option_counter ; i++ ){
+		if( strcmp( options[i], type ) == 0 ){ /* match */
+			if( optiontype[i] == COMMON_FLAG ||
+			    optiontype[i] == FILE_FLAG )
+			{
+		 		setFlagOn( type );
+		 		return;
+			}
+		}
+	}
+        printVerbose( "Unknown option in resourcefile : " );
+	printVerbose( type  );
+	printVerbose( );
+}
+
+/*
+ * usage and help 
+ */
+
+
+void
+AnyOption::printAutoUsage()
+{
+	if( autousage ) printUsage();
+}
+
+void
+AnyOption::printUsage()
+{
+	
+	if( once ) {
+		once = false ;
+		cout << endl ;
+		for( int i = 0 ; i < usage_lines ; i++ )
+			cout << usage[i] << endl ;	
+		cout << endl ;
+	}
+}
+	
+	
+void
+AnyOption::addUsage( const char *line )
+{
+	if( usage_lines >= max_usage_lines ){
+		if( doubleUsageStorage() == false ){
+			addUsageError( line );
+			exit(1);
+		}
+	}
+	usage[ usage_lines ] = line ;	
+	usage_lines++;
+}
+
+void
+AnyOption::addUsageError( const char *line )
+{
+	cout << endl ;
+	cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
+	cout << "While adding the usage/help  : \""<< line << "\"" << endl;
+	cout << "Exiting." << endl ;
+	cout << endl ;
+	exit(0);
+
+}

Added: cs/cigma/branches/cigma-0.9b1/tmc/anyoption.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/anyoption.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/anyoption.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,271 @@
+// http://www.hackorama.com/anyoption/anyoption.h
+#ifndef _ANYOPTION_H
+#define _ANYOPTION_H
+
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+#include <string>
+
+#define COMMON_OPT 	1
+#define COMMAND_OPT 	2
+#define FILE_OPT 	3
+#define COMMON_FLAG 	4
+#define COMMAND_FLAG 	5
+#define FILE_FLAG 	6
+
+#define COMMAND_OPTION_TYPE  	1
+#define COMMAND_FLAG_TYPE 	2
+#define FILE_OPTION_TYPE  	3
+#define FILE_FLAG_TYPE 		4 
+#define UNKNOWN_TYPE 		5
+
+#define DEFAULT_MAXOPTS 	10
+#define MAX_LONG_PREFIX_LENGTH 	2
+
+#define DEFAULT_MAXUSAGE	3
+#define DEFAULT_MAXHELP         10	
+
+#define TRUE_FLAG "true" 
+
+using namespace std;
+
+class AnyOption 
+{
+
+public: /* the public interface */
+	AnyOption();
+	AnyOption(int maxoptions ); 
+	AnyOption(int maxoptions , int maxcharoptions); 
+	~AnyOption();
+
+	/* 
+         * following set methods specifies the  
+	 * special characters and delimiters 
+	 * if not set traditional defaults will be used
+         */
+
+	void setCommandPrefixChar( char _prefix );   /* '-' in "-w" */
+	void setCommandLongPrefix( char *_prefix );  /* '--' in "--width" */
+	void setFileCommentChar( char _comment );    /* '#' in shellscripts */
+	void setFileDelimiterChar( char _delimiter );/* ':' in "width : 100" */
+
+	/* 
+	 * provide the input for the options
+         * like argv[] for commndline and the 
+         * option file name  to use;
+	 */
+
+	void useCommandArgs( int _argc, char **_argv );
+	void useFiileName( const char *_filename );
+
+	/* 
+         * turn off the POSIX style options 
+         * this means anything starting with a '-' or "--"
+         * will be considered a valid option 
+         * which alo means you cannot add a bunch of 
+         * POIX options chars together like "-lr"  for "-l -r"
+         * 
+         */
+
+	void noPOSIX();
+
+	/*
+         * prints warning verbose if you set anything wrong 
+         */
+	void setVerbose();
+
+
+	/* 
+         * there are two types of options  
+         *
+         * Option - has an associated value ( -w 100 )
+         * Flag  - no value, just a boolean flag  ( -nogui )
+         * 
+	 * the options can be either a string ( GNU style )
+         * or a character ( traditional POSIX style ) 
+         * or both ( --width, -w )
+         *
+         * the options can be common to the commandline and 
+         * the optionfile, or can belong only to either of 
+         * commandline and optionfile
+         *
+         * following set methods, handle all the aboove 
+	 * cases of options.
+         */
+
+	/* options comman to command line and option file */
+	void setOption( const char *opt_string );
+	void setOption( char  opt_char );
+	void setOption( const char *opt_string , char opt_char );
+	void setFlag( const char *opt_string );
+	void setFlag( char  opt_char );
+	void setFlag( const char *opt_string , char opt_char );
+
+	/* options read from commandline only */
+	void setCommandOption( const char *opt_string );
+	void setCommandOption( char  opt_char );
+	void setCommandOption( const char *opt_string , char opt_char );
+	void setCommandFlag( const char *opt_string );
+	void setCommandFlag( char  opt_char );
+	void setCommandFlag( const char *opt_string , char opt_char );
+
+	/* options read from an option file only  */
+	void setFileOption( const char *opt_string );
+	void setFileOption( char  opt_char );
+	void setFileOption( const char *opt_string , char opt_char );
+	void setFileFlag( const char *opt_string );
+	void setFileFlag( char  opt_char );
+	void setFileFlag( const char *opt_string , char opt_char );
+
+	/*
+         * process the options, registerd using 
+         * useCommandArgs() and useFileName();
+         */
+	void processOptions();  
+	void processCommandArgs();
+	void processCommandArgs( int max_args );
+	bool processFile();
+
+	/*
+         * process the specified options 
+         */
+	void processCommandArgs( int _argc, char **_argv );
+	void processCommandArgs( int _argc, char **_argv, int max_args );
+	bool processFile( const char *_filename );
+	
+	/*
+         * get the value of the options 
+	 * will return NULL if no value is set 
+         */
+	char *getValue( const char *_option );
+	bool  getFlag( const char *_option );
+	char *getValue( char _optchar );
+	bool  getFlag( char _optchar );
+
+	/*
+	 * Print Usage
+	 */
+	void printUsage();
+	void printAutoUsage();
+	void addUsage( const char *line );
+	void printHelp();
+        /* print auto usage printing for unknown options or flag */
+	void autoUsagePrint(bool flag);
+	
+	/* 
+         * get the argument count and arguments sans the options
+         */
+	int   getArgc();
+	char* getArgv( int index );
+	bool  hasOptions();
+
+private: /* the hidden data structure */
+	int argc;		/* commandline arg count  */
+	char **argv;  		/* commndline args */
+	const char* filename; 	/* the option file */
+	char* appname; 	/* the application name from argv[0] */
+
+	int *new_argv; 		/* arguments sans options (index to argv) */
+	int new_argc;   	/* argument count sans the options */
+	int max_legal_args; 	/* ignore extra arguments */
+
+
+	/* option strings storage + indexing */
+	int max_options; 	/* maximum number of options */
+	const char **options; 	/* storage */
+	int *optiontype; 	/* type - common, command, file */
+	int *optionindex;	/* index into value storage */
+	int option_counter; 	/* counter for added options  */
+
+	/* option chars storage + indexing */
+	int max_char_options; 	/* maximum number options */
+	char *optionchars; 	/*  storage */
+	int *optchartype; 	/* type - common, command, file */
+	int *optcharindex; 	/* index into value storage */
+	int optchar_counter; 	/* counter for added options  */
+
+	/* values */
+	char **values; 		/* common value storage */
+	int g_value_counter; 	/* globally updated value index LAME! */
+
+	/* help and usage */
+	const char **usage; 	/* usage */
+	int max_usage_lines;	/* max usage lines reseverd */
+	int usage_lines;	/* number of usage lines */
+
+	bool command_set;	/* if argc/argv were provided */
+	bool file_set;		/* if a filename was provided */
+	bool mem_allocated;     /* if memory allocated in init() */
+	bool posix_style; 	/* enables to turn off POSIX style options */
+	bool verbose;		/* silent|verbose */
+	bool print_usage;	/* usage verbose */
+	bool print_help;	/* help verbose */
+	
+	char opt_prefix_char;		/*  '-' in "-w" */
+	char long_opt_prefix[MAX_LONG_PREFIX_LENGTH]; /* '--' in "--width" */
+	char file_delimiter_char;	/* ':' in width : 100 */
+	char file_comment_char;		/*  '#' in "#this is a comment" */
+	char equalsign;
+	char comment;
+	char delimiter;
+	char endofline;
+	char whitespace;
+	char nullterminate;
+
+	bool set;   //was static member
+	bool once;  //was static member
+	
+	bool hasoptions;
+	bool autousage;
+
+private: /* the hidden utils */
+	void init();	
+	void init(int maxopt, int maxcharopt );	
+	bool alloc();
+	void cleanup();
+	bool valueStoreOK();
+
+	/* grow storage arrays as required */
+	bool doubleOptStorage();
+	bool doubleCharStorage();
+	bool doubleUsageStorage();
+
+	bool setValue( const char *option , char *value );
+	bool setFlagOn( const char *option );
+	bool setValue( char optchar , char *value);
+	bool setFlagOn( char optchar );
+
+	void addOption( const char* option , int type );
+	void addOption( char optchar , int type );
+	void addOptionError( const char *opt);
+	void addOptionError( char opt);
+	bool findFlag( char* value );
+	void addUsageError( const char *line );
+	bool CommandSet();
+	bool FileSet();
+	bool POSIX();
+
+	char parsePOSIX( char* arg );
+	int parseGNU( char *arg );
+	bool matchChar( char c );
+	int matchOpt( char *opt );
+
+	/* dot file methods */
+	char *readFile();
+	char *readFile( const char* fname );
+	bool consumeFile( char *buffer );
+	void processLine( char *theline, int length );
+	char *chomp( char *str );
+	void valuePairs( char *type, char *value ); 
+	void justValue( char *value );
+
+	void printVerbose( const char *msg );
+	void printVerbose( char *msg );
+	void printVerbose( char ch );
+	void printVerbose( );
+
+
+};
+
+#endif /* ! _ANYOPTION_H */

Added: cs/cigma/branches/cigma-0.9b1/tmc/assertions.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/assertions.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/assertions.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,52 @@
+#ifndef GTB_ASSERTIONS_INCLUDED
+#define GTB_ASSERTIONS_INCLUDED
+
+#ifndef GTB_ERRORS_INCLUDED
+#include "errors.hpp"
+#endif
+
+#ifdef GTB_DISABLE_ASSERTIONS
+
+#define GTB_REQUIRE(condition)
+#define GTB_ENSURE(condition)
+#define GTB_CHECK(condition)
+#define GTB_INVARIANT(condition)
+
+#else // GTB_DISABLE_ASSERTIONS
+
+#define GTB_REQUIRE(condition) \
+do { \
+        if (!(condition)) { \
+                ::gtb::error(__FILE__, __LINE__, \
+			     "precondition violation: %s", # condition); \
+        } \
+} while (0)
+
+
+#define GTB_ENSURE(condition) \
+do { \
+        if (!(condition)) { \
+                ::gtb::error(__FILE__, __LINE__, \
+			     "postcondition violation: %s", # condition); \
+        } \
+} while (0)
+
+#define GTB_CHECK(condition) \
+do { \
+        if (!(condition)) { \
+                ::gtb::error(__FILE__, __LINE__, \
+			     "check failure: %s", # condition); \
+        } \
+} while (0)
+
+#define GTB_INVARIANT(condition) \
+do { \
+        if (!(condition)) { \
+                ::gtb::error(__FILE__, __LINE__, \
+			     "invariant violation: %s", # condition); \
+        } \
+} while (0)
+
+#endif // GTB_DISABLE_ASSERTIONS
+
+#endif // GTB_ASSERTIONS_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/c_decls.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/c_decls.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/c_decls.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,12 @@
+#ifndef GTB_C_DECLS_INCLUDED
+#define GTB_C_DECLS_INCLUDED
+
+#ifdef __cplusplus
+#define BEGIN_C_DECLS extern "C" {
+#define END_C_DECLS }
+#else
+#define BEGIN_C_DECLS /* empty */
+#define END_C_DECLS /* empty */
+#endif
+
+#endif /* GTB_C_DECLS_INCLUDED */

Added: cs/cigma/branches/cigma-0.9b1/tmc/common.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/common.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/common.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,32 @@
+#ifndef GTB_COMMON_INCLUDED
+#define GTB_COMMON_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_PROGRAM_NAME_INCLUDED
+#include "program_name.hpp"
+#endif
+
+#ifndef GTB_ERRORS_INCLUDED
+#include "errors.hpp"
+#endif
+
+#ifndef GTB_ASSERTIONS_INCLUDED
+#include "assertions.hpp"
+#endif
+
+#ifndef GTB_C_DECLS_INCLUDED
+#include "c_decls.hpp"
+#endif
+
+// #ifndef GTB_HEAP_SIZE_INCLUDED
+// #include "heap_size.hpp"
+// #endif
+
+#ifndef GTB_VERSION_INCLUDED
+#include "version.hpp"
+#endif
+
+#endif // GTB_COMMON_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/counter.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/counter.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/counter.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,55 @@
+#ifndef __COUNTER_H
+#define __COUNTER_H
+
+#include "common.hpp"
+
+GTB_BEGIN_NAMESPACE
+
+/*
+ * Copyright (c) 1999
+ * Shachar Fleishman shacharf at math.tau.ac.il
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted 
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+/*
+ * A thread safe counter.
+ * A class that behaves like int with atomic ++,-- operators.
+ */
+
+#ifdef WIN32
+class Counter
+{
+public:
+	typedef LONG value_type;
+
+	Counter(value_type v) : m_v(v) {}
+
+	operator value_type() { return m_v; }
+	value_type operator++() { return InterlockedIncrement(&m_v); }
+	value_type operator++(int) { return InterlockedExchangeAdd(&m_v, 1); }
+	value_type operator--() { return InterlockedDecrement(&m_v); }
+	value_type operator--(int) { return InterlockedExchangeAdd(&m_v, -1); }
+
+protected:
+	value_type m_v;
+};
+#else
+typedef int Counter;
+#endif // WIN32
+
+GTB_END_NAMESPACE
+
+#endif // __COUNTER_H
+
+// Local Variables:
+// mode:C++
+// End:

Added: cs/cigma/branches/cigma-0.9b1/tmc/dprintf.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/dprintf.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/dprintf.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,34 @@
+#undef DPRINTF
+#undef DPRINTF2
+#undef DPRINTF3
+#undef DPRINTF4
+#undef DPRINTF5
+#undef DPRINTF6
+#undef DPRINTF7
+
+#ifndef GTB_C_STDIO_INCLUDED
+#include <stdio.h>
+#define GTB_C_STDIO_INCLUDED
+#endif
+
+#ifdef DEBUG
+#	define DPRINTF(arg) fprintf(stderr, arg)
+#	define DPRINTF2(arg1, arg2) fprintf(stderr, arg1, arg2)
+#	define DPRINTF3(arg1, arg2, arg3) fprintf(stderr, arg1, arg2, arg3)
+#	define DPRINTF4(arg1, arg2, arg3, arg4) \
+		fprintf(stderr, arg1, arg2, arg3, arg4)
+#	define DPRINTF5(arg1, arg2, arg3, arg4, arg5) \
+		fprintf(stderr, arg1, arg2, arg3, arg4, arg5)
+#	define DPRINTF6(arg1, arg2, arg3, arg4, arg5, arg6) \
+		fprintf(stderr, arg1, arg2, arg3, arg4, arg5, arg6)
+#	define DPRINTF7(arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+		fprintf(stderr, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#else
+#	define DPRINTF(arg)
+#	define DPRINTF2(arg1, arg2)
+#	define DPRINTF3(arg1, arg2, arg3)
+#	define DPRINTF4(arg1, arg2, arg3, arg4)
+#	define DPRINTF5(arg1, arg2, arg3, arg4, arg5)
+#	define DPRINTF6(arg1, arg2, arg3, arg4, arg5, arg6)
+#	define DPRINTF7(arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#endif

Added: cs/cigma/branches/cigma-0.9b1/tmc/epsilon.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/epsilon.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/epsilon.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,8 @@
+#ifndef GTB_EPSILON_INCLUDED
+#include "epsilon.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/epsilon.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/epsilon.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/epsilon.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,86 @@
+#ifndef GTB_EPSILON_INCLUDED
+#define GTB_EPSILON_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+bool eps_is_zero(double x, double eps);
+bool eps_is_positive(double x, double eps);
+bool eps_is_positive_or_zero(double x, double eps);
+bool eps_is_negative(double x, double eps);
+bool eps_is_negative_or_zero(double x, double eps);
+
+bool eps_is_equal(double x, double y, double eps);
+bool eps_is_greater(double x, double y, double eps);
+bool eps_is_greater_or_equal(double x, double y, double eps);
+bool eps_is_less(double x, double y, double eps);
+bool eps_is_less_or_equal(double x, double y, double eps);
+
+
+inline bool eps_is_zero(double x, double eps)
+{
+	return (x > -eps) && (x < eps);
+}
+
+
+inline bool eps_is_positive(double x, double eps)
+{
+	return x >= eps;
+}
+
+
+inline bool eps_is_positive_or_zero(double x, double eps)
+{
+	return x > -eps;
+}
+
+
+inline bool eps_is_negative(double x, double eps)
+{
+	return (x <= -eps);
+}
+
+
+inline bool eps_is_negative_or_zero(double x, double eps)
+{
+	return x < eps;
+}
+
+
+inline bool eps_is_equal(double x, double y, double eps)
+{
+	return eps_is_zero(x - y, eps);
+}
+
+
+inline bool eps_is_greater(double x, double y, double eps)
+{
+	return eps_is_positive(x - y, eps);
+}
+
+
+inline bool eps_is_greater_or_equal(double x, double y, double eps)
+{
+	return eps_is_positive_or_zero(x - y, eps);
+}
+
+
+inline bool eps_is_less(double x, double y, double eps)
+{
+	return eps_is_negative(x - y, eps);
+}
+
+
+inline bool eps_is_less_or_equal(double x, double y, double eps)
+{
+	return eps_is_negative_or_zero(x - y, eps);
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_EPSILON_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/errors.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/errors.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/errors.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,73 @@
+#ifndef GTB_ERRORS_INCLUDED
+#include "errors.hpp"
+#endif
+
+#ifndef GTB_PROGRAM_NAME_INCLUDED
+#include "program_name.hpp"
+#endif
+
+#ifndef GTB_C_ERRNO_INCLUDED
+#include <errno.h>
+#define GTB_C_ERRNO_INCLUDED
+#endif
+
+#ifndef GTB_C_STDARG_INCLUDED
+#include <stdarg.h>
+#define GTB_C_STDARG_INCLUDED
+#endif
+
+#ifndef GTB_C_STDIO_INCLUDED
+#include <stdio.h>
+#define GTB_C_STDIO_INCLUDED
+#endif
+
+#ifndef GTB_C_STDLIB_INCLUDED
+#include <stdlib.h>
+#define GTB_C_STDLIB_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+void error(const char *file, int line, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	if (get_program_name != NULL) {
+		fprintf(stderr, "%s: ", get_program_name());
+	}
+	fprintf(stderr, "ERROR: %s:%d: ", file, line);
+	vfprintf(stderr, fmt, args);
+	va_end(args);
+	if (errno != 0) {
+		fprintf(stderr, ": ");
+		perror(NULL);
+	} else {
+		fprintf(stderr, "\n");
+	}
+	abort();
+}
+
+
+void warning(const char *file, int line, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	if (get_program_name() != NULL) {
+		fprintf(stderr, "%s: ", get_program_name());
+	}
+	fprintf(stderr, "WARNING: %s:%d: ", file, line);
+	vfprintf(stderr, fmt, args);
+	va_end(args);
+	if (errno != 0) {
+		fprintf(stderr, ": ");
+		perror(NULL);
+	} else {
+		fprintf(stderr, "\n");
+	}
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/errors.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/errors.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/errors.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,55 @@
+#ifndef GTB_ERRORS_INCLUDED
+#define GTB_ERRORS_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_C_STRING_INCLUDED
+#include <string.h>
+#define GTB_C_STRING_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+void error(const char *file, int line, const char *fmt, ...);
+void warning(const char *file, int line, const char *fmt, ...);
+
+
+GTB_END_NAMESPACE
+
+
+#define GTB_ERROR(arg) \
+	::gtb::error(__FILE__, __LINE__, arg)
+#define GTB_ERROR2(arg1, arg2) \
+	::gtb::error(__FILE__, __LINE__, arg1, arg2)
+#define GTB_ERROR3(arg1, arg2, arg3) \
+	::gtb::error(__FILE__, __LINE__, arg1, arg2, arg3)
+#define GTB_ERROR4(arg1, arg2, arg3, arg4) \
+	::gtb::error(__FILE__, __LINE__, arg1, arg2, arg3, arg4)
+#define GTB_ERROR5(arg1, arg2, arg3, arg4, arg5) \
+	::gtb::error(__FILE__, __LINE__, arg1, arg2, arg3, arg4, arg5)
+#define GTB_ERROR6(arg1, arg2, arg3, arg4, arg5, arg6) \
+	::gtb::error(__FILE__, __LINE__, arg1, arg2, arg3, arg4, arg5, arg6)
+
+
+#define GTB_WARNING(arg) \
+	::gtb::warning(__FILE__, __LINE__, arg)
+#define GTB_WARNING2(arg1, arg2) \
+	::gtb::warning(__FILE__, __LINE__, arg1, arg2)
+#define GTB_WARNING3(arg1, arg2, arg3) \
+	::gtb::warning(__FILE__, __LINE__, arg1, arg2, arg3)
+#define GTB_WARNING4(arg1, arg2, arg3, arg4) \
+	::gtb::warning(__FILE__, __LINE__, arg1, arg2, arg3, arg4)
+#define GTB_WARNING5(arg1, arg2, arg3, arg4, arg5) \
+	::gtb::warning(__FILE__, __LINE__, arg1, arg2, arg3, arg4, arg5)
+#define GTB_WARNING6(arg1, arg2, arg3, arg4, arg6) \
+	::gtb::warning(__FILE__, __LINE__, arg1, arg2, arg3, arg4, arg5, arg6)
+
+
+#define GTB_ERROR_STATUS(msg, status) \
+	::gtb::error(__FILE__, __LINE__, "%s: %s", msg, strerror(status))
+
+
+#endif // GTB_ERRORS_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/gl_headers.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/gl_headers.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/gl_headers.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,33 @@
+#ifndef GTB_GL_HEADERS_INCLUDED
+#define GTB_GL_HEADERS_INCLUDED
+
+#ifdef __APPLE_CC__
+#  include <OpenGL/OpenGL.h>
+//#  include <OpenGL/CGLMacro.h>
+#  include <OpenGL/gl.h>
+// #  include <OpenGL/glext.h>
+// #  include <GLUT/glut.h>
+#elif defined __sgi
+#  include <GL/gl.h>
+// #  include <GL/glx.h>
+// #  include <GL/glut.h>
+#else
+#  if 01
+#    include <GL/gl.h>
+#  endif
+// #  if 01
+// #    include <GL/glx.h>
+// #  endif
+// #  if 01
+// #    include <GL/glext.h>
+// #  endif
+// #  if 01
+// #    include <GL/glut.h>
+// #  endif
+#endif
+
+#endif // GTB_GL_HEADERS_INCLUDED
+
+// Local Variables:
+// mode:C++
+// End:

Added: cs/cigma/branches/cigma-0.9b1/tmc/graphics.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/graphics.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/graphics.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,280 @@
+#ifndef GTB_GRAPHICS_INCLUDED
+#define GTB_GRAPHICS_INCLUDED
+
+#ifndef GTB_BOUNDING_BOX_3D_INCLUDED
+#include "Bounding_box_3d.hpp"
+#endif
+
+// #ifndef GTB_CACHE_INCLUDED
+// #include "Cache.hpp"
+// #endif
+
+// #ifndef GTB_CACHE_ENTRY_INCLUDED
+// #include "Cache_entry.hpp"
+// #endif
+
+// #ifndef GTB_CAMERA_INCLUDED
+// #include "Camera.hpp"
+// #endif
+
+// #ifndef GTB_CAMERA_PATH_INCLUDED
+// #include "Camera_path.hpp"
+// #endif
+
+// #ifndef GTB_CIRCLE_3F_INCLUDED
+// #include "Circle_3f.hpp"
+// #endif
+
+// #ifndef GTB_COLOR_3F_INCLUDED
+// #include "Color_3f.hpp"
+// #endif
+
+// #ifndef GTB_COLOR_3UB_INCLUDED
+// #include "Color_3ub.hpp"
+// #endif
+
+// #ifndef GTB_COLOR_4F_INCLUDED
+// #include "Color_4f.hpp"
+// #endif
+
+// #ifndef GTB_COLOR_4UB_INCLUDED
+// #include "Color_4ub.hpp"
+// #endif
+
+// #ifndef GTB_COLOR_ID_INCLUDED
+// #include "Color_id.hpp"
+// #endif
+
+// #ifndef GTB_CONE_3F_INCLUDED
+// #include "Cone_3f.hpp"
+// #endif
+
+// #ifndef GTB_COORDINATE_SYSTEM_INCLUDED
+// #include "Coordinate_system.hpp"
+// #endif
+
+// #ifndef GTB_FLYER_INCLUDED
+// #include "Flyer.hpp"
+// #endif
+
+// #ifndef GTB_GL_INCLUDED
+// #include "GL.hpp"
+// #endif
+
+// #ifndef GTB_GROUP_INCLUDED
+// #include "Group.hpp"
+// #endif
+
+// #ifndef GTB_ICOSAHEDRON_INCLUDED
+// #include "Icosahedron.hpp"
+// #endif
+
+// #ifndef GTB_IMAGE_INCLUDED
+// #include "Image.hpp"
+// #endif
+
+// #ifndef GTB_IMAGE_TILE_INCLUDED
+// #include "Image_tile.hpp"
+// #endif
+
+// #ifndef GTB_IMAGE_TILE_SET_INCLUDED
+// #include "Image_tile_set.hpp"
+// #endif
+
+// #ifndef GTB_INDEXED_FACE_SET_INCLUDED
+// #include "Indexed_face_set.hpp"
+// #endif
+
+// #ifndef GTB_INDEXED_POINT_SET_INCLUDED
+// #include "Indexed_point_set.hpp"
+// #endif
+
+// #ifndef GTB_INDEXED_TRIANGLE_INCLUDED
+// #include "Indexed_triangle.hpp"
+// #endif
+
+// #ifndef GTB_INDEXED_TRIANGLE_SET_INCLUDED
+// #include "Indexed_triangle_set.hpp"
+// #endif
+
+// #ifndef GTB_ITEM_BUFFER_INCLUDED
+// #include "Item_buffer.hpp"
+// #endif
+
+// #ifndef GTB_LOD_INCLUDED
+// #include "LOD.hpp"
+// #endif
+
+// #ifndef GTB_LIGHT_INCLUDED
+// #include "Light.hpp"
+// #endif
+
+#ifndef GTB_LINE_3F_INCLUDED
+#include "Line_3f.hpp"
+#endif
+
+// #ifndef GTB_MATERIAL_INCLUDED
+// #include "Material.hpp"
+// #endif
+
+// #ifndef GTB_OCTREE_INCLUDED
+// #include "Octree.hpp"
+// #endif
+
+// #ifndef GTB_OCTREE_NODE_INCLUDED
+// #include "Octree_node.hpp"
+// #endif
+
+// #ifndef GTB_OCTREE_RAY_TRACER_INCLUDED
+// #include "Octree_ray_tracer.hpp"
+// #endif
+
+// #ifndef GTB_OCTREE_RENDERER_INCLUDED
+// #include "Octree_renderer.hpp"
+// #endif
+
+// #ifndef GTB_PLANE_3D_INCLUDED
+// #include "Plane_3d.hpp"
+// #endif
+
+#ifndef GTB_PLANE_3F_INCLUDED
+#include "Plane_3f.hpp"
+#endif
+
+#ifndef GTB_PLANE_RST_3D_INCLUDED
+#include "Plane_RST_3d.hpp"
+#endif
+
+// #ifndef GTB_POINT_2D_INCLUDED
+// #include "Point_2d.hpp"
+// #endif
+
+// #ifndef GTB_POINT_2F_INCLUDED
+// #include "Point_2f.hpp"
+// #endif
+
+#ifndef GTB_POINT_3D_INCLUDED
+#include "Point_3d.hpp"
+#endif
+
+#ifndef GTB_POINT_3F_INCLUDED
+#include "Point_3f.hpp"
+#endif
+
+#ifndef GTB_POINT_4F_INCLUDED
+#include "Point_4f.hpp"
+#endif
+
+// #ifndef GTB_POLYGON_3D_INCLUDED
+// #include "Polygon_3d.hpp"
+// #endif
+
+// #ifndef GTB_RAY_3D_INCLUDED
+// #include "Ray_3d.hpp"
+// #endif
+
+// #ifndef GTB_RAY_3F_INCLUDED
+// #include "Ray_3f.hpp"
+// #endif
+
+// #ifndef GTB_RENDERING_CONTEXT_INCLUDED
+// #include "Rendering_context.hpp"
+// #endif
+
+// #ifndef GTB_SEGMENT_3F_INCLUDED
+// #include "Segment_3f.hpp"
+// #endif
+
+#ifndef GTB_SHAPE_INCLUDED
+#include "Shape.hpp"
+#endif
+
+// #ifndef GTB_SHAPE_FILE_INCLUDED
+// #include "Shape_file.hpp"
+// #endif
+
+// #ifndef GTB_SHAPE_PROXY_INCLUDED
+// #include "Shape_proxy.hpp"
+// #endif
+
+// #ifndef GTB_SPHERE_3D_INCLUDED
+// #include "Sphere_3d.hpp"
+// #endif
+
+// #ifndef GTB_SPHERE_3F_INCLUDED
+// #include "Sphere_3f.hpp"
+// #endif
+
+// #ifndef GTB_SWITCH_INCLUDED
+// #include "Switch.hpp"
+// #endif
+
+// #ifndef GTB_TIFF_RGBA_IMAGE_INCLUDED
+// //#include "Tiff_rgba_image.hpp"
+// #endif
+
+// #ifndef GTB_TRIANGLE_3F_INCLUDED
+// #include "Triangle_3f.hpp"
+// #endif
+
+// #ifndef GTB_VBO_INCLUDED
+// #include "VBO.hpp"
+// #endif
+
+// #ifndef GTB_VBO_CONFIG_INCLUDED
+// #include "VBO_config.hpp"
+// #endif
+
+// #ifndef GTB_VECTOR_2D_INCLUDED
+// #include "Vector_2d.hpp"
+// #endif
+
+// #ifndef GTB_VECTOR_2F_INCLUDED
+// #include "Vector_2f.hpp"
+// #endif
+
+#ifndef GTB_VECTOR_3B_INCLUDED
+#include "Vector_3b.hpp"
+#endif
+
+#ifndef GTB_VECTOR_3D_INCLUDED
+#include "Vector_3d.hpp"
+#endif
+
+#ifndef GTB_VECTOR_3F_INCLUDED
+#include "Vector_3f.hpp"
+#endif
+
+// #ifndef GTB_VERTEX_CLUSTERING_INCLUDED
+// #include "Vertex_clustering.hpp"
+// #endif
+
+// #ifndef GTB_VERTEX_PICKER_INCLUDED
+// #include "Vertex_picker.hpp"
+// #endif
+
+// #ifndef GTB_VIEW_INCLUDED
+// #include "View.hpp"
+// #endif
+
+// #ifndef GTB_VIEWPORT_INCLUDED
+// #include "Viewport.hpp"
+// #endif
+
+// #ifndef GTB_GL_HEADERS_INCLUDED
+// #include "gl_headers.hpp"
+// #endif
+
+// #ifndef GTB_GR_UTIL_INCLUDED
+// #include "gr_util.hpp"
+// #endif
+
+#ifndef GTB_KDTET_INCLUDED
+#include "kdtree_tetrahedra.hpp"
+#endif
+
+// #ifndef GTB_TEXT_INCLUDED
+// #include "text.hpp"
+// #endif
+
+#endif // GTB_GRAPHICS_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/gtb_config.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/gtb_config.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/gtb_config.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,269 @@
+/* gtb/common/gtb_config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define if you have the ARB vertex buffer object extension. */
+#define HAVE_ARB_VERTEX_BUFFER_OBJECT
+
+/* Define if you have the ARB vertex program extension. */
+#define HAVE_ARB_VERTEX_PROGRAM
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H
+
+/* Define if you have the ATI vertex buffer object extension. */
+/* #undef HAVE_ATI_VERTEX_ARRAY_OBJECT */
+
+/* Define to 1 if you have the <dirent> header file. */
+#define HAVE_DIRENT_H
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/* #undef HAVE_DLFCN_H */
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the `drand48' function. */
+/* #undef HAVE_DRAND48 */
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H
+
+/* Define to 1 if you have the <float.h> header file. */
+#define HAVE_FLOAT_H
+
+/* Define to 1 if you have the `gethostbyaddr' function. */
+/* #undef HAVE_GETHOSTBYADDR */
+
+/* Define to 1 if you have the `gethostbyname' function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+/* #undef HAVE_GETTIMEOFDAY */
+
+/* Define to 1 if you have the <GL/glext.h> header file. */
+#define HAVE_GL_GLEXT_H
+
+/* Define to 1 if you have the <GL/glut.h> header file. */
+#define HAVE_GL_GLUT_H
+
+/* Define to 1 if you have the <GL/glx.h> header file. */
+#define HAVE_GL_GLX_H
+
+/* Define to 1 if you have the <GL/gl.h> header file. */
+#define HAVE_GL_GL_H
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+/* #undef HAVE_INET_NTOA */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/* #undef HAVE_INTTYPES_H */
+
+/* Define if you have the CG library or equivalent. */
+/* #undef HAVE_LIBCG */
+
+/* Define if you have the GL library or equivalent. */
+/* #undef HAVE_LIBGL */
+
+/* Define if you have the GLUT library or equivalent. */
+/* #undef HAVE_LIBGLUT */
+
+/* Define if you have the libm library or equivalent. */
+/* #undef HAVE_LIBM */
+
+/* Define if you have the MPE library or equivalent. */
+/* #undef HAVE_LIBMPE */
+
+/* Define if you have the MPI library or equivalent. */
+/* #undef HAVE_LIBMPI */
+
+/* Define if you have the libpthread library or equivalent. */
+/* #undef HAVE_LIBPTHREAD */
+
+/* Define if you have the Tsai library or equivalent. */
+/* #undef HAVE_LIBTSAI */
+
+/* Define if you have the X11 library or equivalent. */
+/* #undef HAVE_LIBX11 */
+
+/* Define if you have the Z library or equivalent. */
+/* #undef HAVE_LIBZ */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H
+
+/* Define to 1 if your system has a working `malloc' function. */
+/* #undef HAVE_MALLOC */
+
+/* Define to 1 if you have the <memory.h> header file. */
+/* #undef HAVE_MEMORY_H */
+
+/* Define to 1 if you have the `memset' function. */
+/* #undef HAVE_MEMSET */
+
+/* Define to 1 if you have the `mkdir' function. */
+/* #undef HAVE_MKDIR */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H
+
+/* Define if you have the nvidia fence extension. */
+#define HAVE_NV_FENCE
+
+/* Define if you have the nvidia occlusion query extension. */
+#define HAVE_NV_OCCLUSION_QUERY
+
+/* Define if you have the nvidia vertex program extension. */
+#define HAVE_NV_VERTEX_PROGRAM
+
+/* Define to 1 if you have the `opendir' function. */
+/* #undef HAVE_OPENDIR */
+
+/* Define to 1 if you have the `pow' function. */
+/* #undef HAVE_POW */
+
+/* Define to 1 if you have the `sbrk' function. */
+#define HAVE_SBRK
+
+/* Define to 1 if you have the `select' function. */
+/* #undef HAVE_SELECT */
+
+/* Define to 1 if you have the `sendfile' function. */
+/* #undef HAVE_SENDFILE */
+
+/* Define to 1 if you have the `socket' function. */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the `sqrt' function. */
+/* #undef HAVE_SQRT */
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+/* #undef HAVE_STAT_EMPTY_STRING_BUG */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strchr' function. */
+/* #undef HAVE_STRCHR */
+
+/* Define to 1 if you have the `strerror' function. */
+/* #undef HAVE_STRERROR */
+
+/* Define to 1 if you have the <strings.h> header file. */
+/* #undef HAVE_STRINGS_H */
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H
+
+/* Define to 1 if you have the `strstr' function. */
+/* #undef HAVE_STRSTR */
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+/* #undef HAVE_SYS_SELECT_H */
+
+/* Define to 1 if you have the <sys/sendfile.h> header file. */
+#define HAVE_SYS_SENDFILE_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+/* #undef HAVE_SYS_TYPES_H */
+
+/* Define to 1 if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H
+
+/* Define to 1 if you have the `uname' function. */
+/* #undef HAVE_UNAME */
+
+#ifndef WIN32
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H
+
+#endif
+
+/* /\* Define to 1 if you have the <values.h> header file. *\/ */
+/* #define HAVE_VALUES_H */
+
+/* Define to 1 if you have the `vprintf' function. */
+/* #undef HAVE_VPRINTF */
+
+/* Define to 1 if you have the <X11/Xlib.h> header file. */
+#define HAVE_XLIB_H
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+   slash. */
+/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
+
+/* Name of package */
+/* #undef PACKAGE */
+
+/* Define to the address where bug reports for this package should be sent. */
+/* #undef PACKAGE_BUGREPORT */
+
+/* Define to the full name of this package. */
+/* #undef PACKAGE_NAME */
+
+/* Define to the full name and version of this package. */
+/* #undef PACKAGE_STRING */
+
+/* Define to the one symbol short name of this package. */
+/* #undef PACKAGE_TARNAME */
+
+/* Define to the version of this package. */
+/* #undef PACKAGE_VERSION */
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+/* #undef RETSIGTYPE */
+
+/* Define to the type of arg 1 for `select'. */
+/* #undef SELECT_TYPE_ARG1 */
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+/* #undef SELECT_TYPE_ARG234 */
+
+/* Define to the type of arg 5 for `select'. */
+/* #undef SELECT_TYPE_ARG5 */
+
+/* Define to 1 if you have the ANSI C header files. */
+/* #undef STDC_HEADERS */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+/* #undef TIME_WITH_SYS_TIME */
+
+/* Version number of package */
+/* #undef VERSION */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define as `__inline' if that's what the C compiler calls it, or to nothing
+   if it is not supported. */
+/* #undef inline */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define socklen_t type on systems that do not have it. */
+/* #undef socklen_t */

Added: cs/cigma/branches/cigma-0.9b1/tmc/icc_patch.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/icc_patch.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/icc_patch.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,16 @@
+#ifndef ICC_PATCH_INCLUDED
+#define ICC_PATCH_INCLUDED
+
+#if defined(__ICC)
+/* icc doesn't like GNU __extension__ functions */
+#undef htons
+#undef ntohs
+#undef htonl
+#undef ntohl
+#define htons(x) __bswap_constant_16(x)
+#define ntohs(x) __bswap_constant_16(x)
+#define htonl(x) __bswap_constant_32(x)
+#define ntohl(x) __bswap_constant_32(x)
+#endif /* defined(_ICC) */
+
+#endif /* ICC_PATCH_INCLUDED */

Added: cs/cigma/branches/cigma-0.9b1/tmc/io_util.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/io_util.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/io_util.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,326 @@
+#ifndef GTB_IO_UTIL_INCLUDED
+#include "io_util.hpp"
+#endif
+
+#ifndef GTB_ASSERTIONS_INCLUDED
+#include "assertions.hpp"
+#endif
+
+#ifndef GTB_C_ERRNO_INCLUDED
+#include <errno.h>
+#define GTB_C_ERRNO_INCLUDED
+#endif
+
+#include "gtb_config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef GTB_C_ASSERT_INCLUDED
+#include <assert.h>
+#define GTB_C_ASSERT_INCLUDED
+#endif
+
+#ifndef GTB_C_CTYPE_INCLUDED
+#include <ctype.h>
+#define GTB_C_CTYPE_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+std::string get_file_base_name(const char *file_name)
+{
+	assert(NULL != file_name);
+	unsigned n = strlen(file_name);
+
+	// degenerate case
+	if (0 == n) {
+		return "";
+	}
+
+	// find right end
+	unsigned r = n - 1;
+	while ((r > 0) && ('/' == file_name[r])) {
+		r--;
+	}
+
+	// find left end
+	unsigned l = r;
+	while ((l > 0) && ('/' != file_name[l])) {
+		l--;
+	}
+	if (('/' == file_name[l]) && (l < r)) {
+		l++;
+	}
+
+	// copy base name
+	std::string s;
+	for (unsigned i = l; i <= r; i++) {
+		GTB_CHECK(i < n);
+		s += file_name[i];
+	}
+	return s;
+}
+
+
+std::string get_file_base_name(const char *file_name, const char *suffix)
+{
+	assert(NULL != file_name);
+	assert(NULL != suffix);
+	int n = strlen(file_name);
+
+	// degenerate case
+	if (0 == n) {
+		return "";
+	}
+
+	// find right end
+	int r = n - 1;
+	while ((r > 0) && ('/' == file_name[r])) {
+		r--;
+	}
+
+	// check for suffix
+	int m = strlen(suffix);
+	if (r - (m - 1) >= 0) {
+		const char *p = file_name + r - (m - 1);
+		if (strcmp(p, suffix) == 0) {
+			if (m == n) {
+				return "";
+			}
+			assert(r >= m);
+			r -= m;
+		}
+	}
+
+	// find left end
+	int l = r;
+	while ((l > 0) && ('/' != file_name[l])) {
+		l--;
+	}
+	if (('/' == file_name[l]) && (l < r)) {
+		l++;
+	}
+
+	// copy base name
+	assert(l >= 0);
+	assert(r >= l);
+	std::string s;
+	for (int i = l; i <= r; i++) {
+		GTB_CHECK(i < n);
+		s += file_name[i];
+	}
+	return s;
+}
+
+
+std::string get_file_extension(const char *file_name)
+{
+	assert(NULL != file_name);
+	unsigned n = strlen(file_name);
+
+	// degenerate case
+	if (0 == n) {
+		return "";
+	}
+
+	// check for directory
+	if ('/' == file_name[n - 1]) {
+		fprintf(stderr, "%s is a directory\n", file_name);
+		exit(EXIT_FAILURE);
+	}
+
+	// find '.'
+	unsigned r = n - 1;
+	unsigned l = n - 1;
+	while ((l > 0) && ('.' != file_name[l])) {
+		l--;
+	}
+
+	// no extension case
+	if ('.' != file_name[l]) {
+		return "";
+	}
+
+	// skip '.'
+	l++;
+
+	// copy extension
+	std::string s;
+	for (unsigned i = l; i <= r; i++) {
+		GTB_CHECK(i < n);
+		s += file_name[i];
+	}
+	return s;
+}
+
+
+bool file_exists(const char *file_name)
+{
+	int old_errno = errno;
+	bool ret;
+	struct stat buf;
+	if ((stat(file_name, &buf) == 0) && S_ISREG(buf.st_mode)) {
+		ret = true;
+	} else {
+		ret = false;
+	}
+	errno = old_errno;
+	return ret;
+}
+
+
+bool dir_exists(const char *dir_name)
+{
+	int old_errno = errno;
+	bool ret;
+	struct stat buf;
+	if ((stat(dir_name, &buf) == 0) && S_ISDIR(buf.st_mode)) {
+		ret = true;
+	} else {
+		ret = false;
+	}
+	errno = old_errno;
+	return ret;
+}
+
+
+ino_t get_file_inode(const char *file_name)
+{
+	struct stat buf;
+	if (stat(file_name, &buf) != 0) {
+		GTB_ERROR2("failed to stat %s\n", file_name);
+	}
+	if (!S_ISREG(buf.st_mode)) {
+		GTB_ERROR2("%s is not a regular file\n", file_name);
+	}
+	return buf.st_ino;
+}
+
+
+ino_t get_file_inode(int fd)
+{
+	struct stat buf;
+	if (fstat(fd, &buf) != 0) {
+		GTB_ERROR("failed to stat file\n");
+	}
+	if (!S_ISREG(buf.st_mode)) {
+		GTB_ERROR("not a regular file\n");
+	}
+	return buf.st_ino;
+}
+
+
+off_t get_file_size(const char *file_name)
+{
+	struct stat buf;
+	if (stat(file_name, &buf) != 0) {
+		GTB_ERROR2("failed to stat %s\n", file_name);
+	}
+	if (!S_ISREG(buf.st_mode)) {
+		GTB_ERROR2("not a regular %s\n", file_name);
+	}
+	return buf.st_size;
+}
+
+
+off_t get_file_size(int fd)
+{
+	struct stat buf;
+	if (fstat(fd, &buf) != 0) {
+		GTB_ERROR("failed to stat file\n");
+	}
+	if (!S_ISREG(buf.st_mode)) {
+		GTB_ERROR("not a regular file\n");
+	}
+	return buf.st_size;
+}
+
+
+void make_dir(const char *name)
+{
+#ifdef WIN32
+	if (mkdir(name) != 0) {
+		GTB_ERROR("failed to make dir");
+	}
+#else
+	mode_t mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
+	if (mkdir(name, mode) != 0) {
+		GTB_ERROR2("failed to make dir %s", name);
+	}
+#endif
+}
+
+
+bool read_line(FILE *fp, std::string &s)
+{
+	s = "";
+	char buf[100];
+	int n = 0;
+	while (fgets(buf, sizeof(buf), fp) != NULL) {
+		s += buf;
+		n++;
+		int len = strlen(buf);
+		if ((len > 0) && (buf[len - 1] == '\n')) {
+			break;
+		}
+	}
+	return n > 0;
+}
+
+
+bool read_line_drop_newline(FILE *fp, std::string &s)
+{
+	s = "";
+	char buf[100];
+	int n = 0;
+	while (fgets(buf, sizeof(buf), fp) != NULL) {
+		n++;
+		int len = strlen(buf);
+		if ((len > 0) && (buf[len - 1] == '\n')) {
+			buf[len - 1] = '\0';
+			s += buf;
+			break;
+		} else {
+			s += buf;
+		}
+	}
+	return n > 0;
+}
+
+
+bool name_has_extension(const char *name, const char *ext)
+{
+	bool ret = false;
+	int l1 = strlen(name);
+	int l2 = strlen(ext);
+	if (l2 < l1) {
+		bool differ = false;
+		int i, j;
+		for (i = (l1 - l2), j = 0;
+		     (i < l1) && (j < l2);
+		     i++, j++) {
+			if (toupper(name[i]) != toupper(ext[j])) {
+				differ = true;
+				break;
+			}
+		}
+		if (!differ) {
+			ret = true;
+		}
+	}
+	return ret;
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/io_util.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/io_util.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/io_util.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,59 @@
+#ifndef GTB_IO_UTIL_INCLUDED
+#define GTB_IO_UTIL_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_ERRORS_INCLUDED
+#include "errors.hpp"
+#endif
+
+#ifndef GTB_CXX_STRING_INCLUDED
+#include <string>
+#define GTB_CXX_STRING_INCLUDED
+#endif
+
+#ifndef GTB_C_STDIO_INCLUDED
+#include <stdio.h>
+#define GTB_C_STDIO_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+std::string get_file_base_name(const char *file_name);
+std::string get_file_base_name(const char *file_name, const char *suffix);
+std::string get_file_extension(const char *file_name);
+
+bool file_exists(const char *file_name);
+bool dir_exists(const char *dir_name);
+
+ino_t get_file_inode(const char *file_name);
+ino_t get_file_inode(int fd);
+
+off_t get_file_size(const char *file_name);
+off_t get_file_size(int fd);
+
+void make_dir(const char *name);
+
+bool read_line(FILE *fp, std::string &s);
+bool read_line_drop_newline(FILE *fp, std::string &s);
+
+bool name_has_extension(const char *name, const char *ext);
+
+
+GTB_END_NAMESPACE
+
+
+#define GTB_FOPEN(fp, file_name, mode)				\
+do {								\
+	fp = fopen(file_name, mode);				\
+	if (fp == NULL) {					\
+		GTB_ERROR3("can't open \"%s\" in \"%s\" mode",	\
+			   file_name, mode);			\
+	}							\
+} while (0)
+
+
+#endif // GTB_IO_UTIL_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/kdtree_tetrahedra.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/kdtree_tetrahedra.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/kdtree_tetrahedra.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,529 @@
+#ifndef GTB_KDTET_INCLUDED
+#define GTB_KDTET_INCLUDED
+
+#include "Bounding_box_3d.hpp"
+#include "Point_3f.hpp"
+#include "Indexed_tetra_set.hpp"
+#include "common.hpp"
+
+#ifndef GTB_C_ASSERT_INCLUDED
+#include <assert.h>
+#define GTB_C_ASSERT_INCLUDED
+#endif
+
+#include <vector>
+#include <queue>
+#include "Point_3d.hpp"
+#include "Point_3f.hpp"
+#include "Vector_3d.hpp"
+#include "ptrs.h"
+
+#ifdef WIN32
+#define random rand
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+struct kdtree_exception_no_more_values {};
+extern kdtree_exception_no_more_values _exception_no_more_values;
+
+#define KDT_INFINIT_NEIGHBORS 0x7fffffff
+
+/*---------------------- Helper functions --------------*/
+void SplitBBox(
+	const Bounding_box_3d& bbox,      // Input bounding box
+	int axis,
+	double position,        // axis, position define where to split
+	Bounding_box_3d& lbbox, 
+	Bounding_box_3d& rbbox            // Result is store in [lr]bbox
+	);
+/*---------------------- [ Helper functions ] --------------*/
+
+//
+// template arguments:
+//    T - the type of object that is stored in the tree
+//
+template<class T>
+class KDTet
+{
+public:
+	typedef unsigned int size_type;
+	typedef std::vector<T> result_sequence;
+
+	KDTet(float MAX_TET_PER_CELL, Indexed_tetra_set *its, Scalar_time_series *sts);
+	KDTet(float MAX_TET_PER_CELL, Indexed_tetra_set *its, Vector_time_series *sts);
+	~KDTet()
+		{
+			delete root;
+		}
+
+	const Bounding_box_3d& GetBBox() const { return bbox; }
+
+	void MakeTree();
+
+	/*--------------------- tree data structures -----------------*/
+
+	struct Node
+	{
+		Node() {}
+		virtual ~Node() {}
+
+		enum node_type {leaf, tree, single}; // Types of nodes
+
+		virtual node_type Type() const=0;
+	};
+
+	struct TreeNode : public Node
+	{
+		~TreeNode()
+			{
+				delete l;
+				delete r;
+			}
+
+		typename Node::node_type Type() const { return Node::tree; }
+
+		// Which axis is cut by this node
+		// Numbering complies with VX, VY, VZ defined in algebra3.h
+		enum t_axis {XAxis=0, YAxis, ZAxis};
+
+		double cut_point;       // where along the axis is this node cut.
+		// Absolute coordinates.
+
+		Node *l, *r;            // Left and right sons
+		t_axis axis;
+	}; // TreeNode
+
+	struct LeafNode : public Node
+	{
+		LeafNode() {}
+		typename Node::node_type Type() const { return Node::leaf; }
+        
+		void Insert(T v) {
+			objects.push_back(v);
+		}
+
+		template<class IT>
+		void Insert(IT first, IT last)
+			{		
+				objects.insert(objects.end(), first, last);
+			}
+
+		template<class IT>
+		void Remove(IT first, IT last) {
+			objects.erase(first, last);
+		}
+
+		//
+		// Reserve space for additional K items, return previous # of elements
+		//
+		int Resize(int K)
+			{
+				int n = objects.size();
+				objects.resize(n+K);
+				return n;
+			}
+
+		typedef std::vector<T> t_objects_list;
+		t_objects_list objects; // List of objects in the node
+    
+		typename t_objects_list::value_type& operator[](int n) {
+			return objects[n];
+		}
+
+	}; // LeafNode
+
+	struct SingleObject : public Node
+	{
+		T* object;
+		explicit SingleObject() : Node() {}
+		SingleObject(T* r_object) : Node(), object(r_object) {}
+		SingleObject(const SingleObject& rhs) : Node(), object(rhs.object) {}
+
+		void set(T* r_object) { object = r_object; }
+		typename Node::node_type Type() const { return Node::single; }
+	};
+
+
+	LeafNode* Find(const Point_3d& p, TreeNode*& parent) const;
+	bool FindAndEvalTet(LeafNode *node, const Point_3f& p, float *ret) const;
+	bool FindAndEvalTet(LeafNode *node, const Point_3f& p, Vector_3f *ret) const;
+	void FindAndEvalTetNN(LeafNode *node, const Point_3f& p, float *ret) const;
+	void FindAndEvalTetAvg3N(LeafNode *node, const Point_3f& p, float *ret) const;
+
+protected:
+	//
+	// Search for the leaf node that contains p
+	//
+	// Return:
+	//   bbox - for the leaf node containing p
+	//   parent
+	//
+	LeafNode* Find(const Point_3d& p, Bounding_box_3d& bbox, TreeNode*& parent) const;
+
+	void MakeTree(TreeNode* root);
+
+	//
+	// Split a leaf node, returning a pointer to the
+	// parent of the node that holds a new subtree
+	//
+	Node* Split (
+		LeafNode* cell         // Input cell to split
+		);
+
+private:
+	void tree_depth(Node* root_, int depth, int& max_depth, int& sum_depths, int& num_leaves, int& num_objects, int& num_nodes) const;
+
+	float max_tet_per_cell;
+	Indexed_tetra_set *its;
+	Scalar_time_series *sts;
+    Vector_time_series *vts;
+	Bounding_box_3d bbox;
+        Node* root;
+
+}; // KDTet
+
+
+template<class T>
+inline KDTet<T>::KDTet(float MAX_TET_PER_CELL, Indexed_tetra_set *in_its, Scalar_time_series *in_sts) :
+	max_tet_per_cell(MAX_TET_PER_CELL),
+	its(in_its),
+	sts(in_sts),
+	bbox(in_its->get_bounding_box()),
+	root(new LeafNode)
+{
+	unsigned num_tets = in_its->get_tetrahedra().size();
+	for (unsigned ti = 0; ti < num_tets; ti++) {
+		LeafNode* node = static_cast<LeafNode*>(root);
+		node->Insert(ti);
+	}
+}
+
+template<class T>
+inline KDTet<T>::KDTet(float MAX_TET_PER_CELL, Indexed_tetra_set *in_its, Vector_time_series *in_vts) :
+	max_tet_per_cell(MAX_TET_PER_CELL),
+	its(in_its),
+	vts(in_vts),
+	bbox(in_its->get_bounding_box()),
+	root(new LeafNode)
+{
+	unsigned num_tets = in_its->get_tetrahedra().size();
+	for (unsigned ti = 0; ti < num_tets; ti++) {
+		LeafNode* node = static_cast<LeafNode*>(root);
+		node->Insert(ti);
+	}
+}
+
+template<class T>
+void KDTet<T>::MakeTree()
+{
+	if (root->Type() == Node::leaf)
+	{
+		root = Split(static_cast<LeafNode*>(root));
+	}
+	else
+	{
+		MakeTree(static_cast<TreeNode*>(root));
+	}
+}
+
+template<class T>
+void KDTet<T>::MakeTree(TreeNode* arg_root)
+{
+	if (arg_root->l->Type() == Node::leaf)
+	{
+		arg_root->l = Split(static_cast<LeafNode*>(arg_root->l));
+	}
+	else
+	{
+		MakeTree(static_cast<TreeNode*>(arg_root->l));
+	}
+
+	if (arg_root->r->Type() == Node::leaf)
+	{
+		arg_root->r = Split(static_cast<LeafNode*>(arg_root->r));
+	}
+	else
+	{
+		MakeTree(static_cast<TreeNode*>(arg_root->r));
+	}
+}
+
+template<class T>
+bool  KDTet<T>::FindAndEvalTet(LeafNode *node, const Point_3f& p, float *ret) const
+{
+	typename LeafNode::t_objects_list::iterator f = node->objects.begin();
+	typename LeafNode::t_objects_list::iterator l = node->objects.end();
+	const std::vector<Tetrahedron> &tets = its->get_tetrahedra();
+	for (; f != l; ++f)
+	{
+		const Tetrahedron &t = tets[*f];
+		if (!its->approx_inside_tetra(t, p)) continue;
+		float value;
+		if (its->interpol_tetra(sts, t, p, &value)) {
+			*ret = value;
+			return true;
+		}
+	}
+	return false;
+}
+
+template<class T>
+bool  KDTet<T>::FindAndEvalTet(LeafNode *node, const Point_3f& p, Vector_3f *ret) const
+{
+	typename LeafNode::t_objects_list::iterator f = node->objects.begin();
+	typename LeafNode::t_objects_list::iterator l = node->objects.end();
+	const std::vector<Tetrahedron> &tets = its->get_tetrahedra();
+	for (; f != l; ++f)
+	{
+		const Tetrahedron &t = tets[*f];
+		if (!its->approx_inside_tetra(t, p)) continue;
+		Vector_3f value;
+		if (its->interpol_tetra(vts, t, p, &value)) {
+			*ret = value;
+			return true;
+		}
+	}
+	return false;
+}
+
+
+template<class T>
+void KDTet<T>::FindAndEvalTetAvg3N(LeafNode *node, const Point_3f& p, float *ret) const
+{
+	typename LeafNode::t_objects_list::iterator f = node->objects.begin();
+	typename LeafNode::t_objects_list::iterator l = node->objects.end();
+	const std::vector<Tetrahedron> &tets = its->get_tetrahedra();
+	const std::vector<Point_3f> &verts = its->get_vertices();
+
+	float min_distance = FLT_MAX;
+	float nearest_values[3] = {0, 0, 0};
+
+	for (; f != l; ++f)
+	{
+		const Tetrahedron &t = tets[*f];
+		for (unsigned j=0; j<4; j++) {
+			unsigned vi = t.get_vertex(j);
+			const Point_3f &v = verts[vi];
+			float d = Point_3f::distance(v, p);
+			if (d < min_distance) {
+				min_distance = d;
+				nearest_values[2] = nearest_values[1];
+				nearest_values[1] = nearest_values[0];
+				nearest_values[0] = sts->get_value(vi);
+			}
+		}
+	}
+	
+	*ret = (nearest_values[0] + nearest_values[1] + nearest_values[2]) / 3;
+}
+
+
+template<class T>
+void KDTet<T>::FindAndEvalTetNN(LeafNode *node, const Point_3f& p, float *ret) const
+{
+	typename LeafNode::t_objects_list::iterator f = node->objects.begin();
+	typename LeafNode::t_objects_list::iterator l = node->objects.end();
+	const std::vector<Tetrahedron> &tets = its->get_tetrahedra();
+	const std::vector<Point_3f> &verts = its->get_vertices();
+
+	float min_distance = FLT_MAX;
+	float nearest_value = 0;
+
+	for (; f != l; ++f)
+	{
+		const Tetrahedron &t = tets[*f];
+		for (unsigned j=0; j<4; j++) {
+			unsigned vi = t.get_vertex(j);
+			const Point_3f &v = verts[vi];
+			float d = Point_3f::distance(v, p);
+			if (d < min_distance) {
+				min_distance = d;
+				nearest_value = sts->get_value(vi);
+			}
+		}
+	}
+	*ret = nearest_value;
+}
+
+
+template<class T>
+typename KDTet<T>::LeafNode* KDTet<T>::Find(const Point_3d& p, typename KDTet<T>::TreeNode*& parent) const
+{
+	if (root->Type() == Node::leaf)
+	{
+		parent = 0;
+		return static_cast<LeafNode*>(root);
+	}
+	else
+	{
+		parent = static_cast<TreeNode*>(root);
+		while (1)
+		{
+			if (parent->cut_point < p[parent->axis])
+			{
+				// we're going right
+				if (parent->r->Type() == Node::leaf)
+				{
+					return static_cast<LeafNode*>(parent->r);
+				}
+				parent = static_cast<TreeNode*>(parent->r);
+			}
+			else
+			{
+				// we're going left
+				if (parent->l->Type() == Node::leaf)
+				{
+					return static_cast<LeafNode*>(parent->l);
+				}
+				parent = static_cast<TreeNode*>(parent->l);
+			}
+		}
+	}
+}
+
+
+template<class T>
+typename KDTet<T>::LeafNode* KDTet<T>::Find(const Point_3d& p, Bounding_box_3d& leafbbox, typename KDTet<T>::TreeNode*& parent) const
+{
+	leafbbox = bbox;
+	if (root->Type() == Node::leaf)
+	{
+		parent = 0;
+		return static_cast<LeafNode*>(root);
+	}
+	else
+	{
+		parent = static_cast<TreeNode*>(root);
+		Bounding_box_3d lbbox, rbbox;
+		while (1)
+		{
+			SplitBBox(leafbbox, parent->axis, parent->cut_point, lbbox, rbbox);
+			if (parent->cut_point < p[parent->axis])
+			{
+				// we're going right
+				leafbbox = rbbox;
+				if (parent->r->Type() == Node::leaf)
+				{
+					return static_cast<LeafNode*>(parent->r);
+				}
+				parent = static_cast<TreeNode*>(parent->r);
+			}
+			else
+			{
+				// we're going left
+				leafbbox = lbbox;
+				if (parent->l->Type() == Node::leaf)
+				{
+					return static_cast<LeafNode*>(parent->l);
+				}
+				parent = static_cast<TreeNode*>(parent->l);
+			}
+		}
+	}
+}
+
+template<class T>
+typename KDTet<T>::Node* KDTet<T>::Split (
+	typename KDTet<T>::LeafNode* cell  // Input cell to split
+	)
+{
+	unsigned n_objects = cell->objects.size();
+	if (n_objects < max_tet_per_cell)
+		return cell;
+
+	typename TreeNode::t_axis axis;
+	std::vector<Point_3f> &vertices = its->get_vertices();
+	const std::vector<Tetrahedron> &tets = its->get_tetrahedra();
+//	    const std::vector<Point_3f> &centroids = its->get_centroids();
+
+	double cut_point;
+	{
+		Point_3f p[3];
+		for (unsigned j=0; j<3; j++) {
+			unsigned idx = random() % n_objects;
+#if 1
+			unsigned tid = cell->objects[idx];
+			p[j] = Point_3f::centroid(vertices[tets[tid].get_vertex(0)],
+						  vertices[tets[tid].get_vertex(1)],
+						  vertices[tets[tid].get_vertex(2)],
+						  vertices[tets[tid].get_vertex(3)]);
+#else
+			p[j] = centroids[cell->objects[idx]];
+#endif
+		}
+		Point_3f min_point(
+			min3(p[0][0],p[1][0],p[2][0]),
+			min3(p[0][1],p[1][1],p[2][1]),
+			min3(p[0][2],p[1][2],p[2][2]));
+		Point_3f max_point(
+			max3(p[0][0],p[1][0],p[2][0]),
+			max3(p[0][1],p[1][1],p[2][1]),
+			max3(p[0][2],p[1][2],p[2][2]));
+
+		Vector_3f box_dimentions = max_point - min_point;
+
+		int k;
+		max3(box_dimentions[0], box_dimentions[1], box_dimentions[2], k);
+		axis = static_cast<typename TreeNode::t_axis>(k);
+		cut_point = min_point[axis] + box_dimentions[axis]*0.51;
+	}
+
+	//
+	// Make the split
+	//
+//	    printf("Splitting at %d %g\n", axis, cut_point);
+
+	LeafNode* rightnode = new LeafNode;
+
+	typename LeafNode::t_objects_list::iterator last_left = cell->objects.end();
+	typename LeafNode::t_objects_list::iterator f = cell->objects.begin();
+	while (f < last_left)
+	{
+		const Tetrahedron &t = tets[*f];
+		bool is_in_left_cell = false;
+		bool is_in_right_cell = false;
+		for (unsigned vi=0; vi < 4; vi++)
+		{
+			Point_3f v = vertices[t.get_vertex(vi)];
+			if (v[axis] <= cut_point)
+			{
+				is_in_left_cell = true;
+			}
+			else
+			{
+				is_in_right_cell = true;
+			}
+		}
+		if (is_in_left_cell && !is_in_right_cell) {
+			++f;
+		} else if (is_in_right_cell && !is_in_left_cell) {
+			--last_left;
+			rightnode->objects.push_back(*f);
+			*f = *last_left;
+		} else {
+			rightnode->objects.push_back(*f);
+			++f;
+		}
+	}
+
+	if (last_left == cell->objects.end())
+	{
+		// we have many objects that are equal
+		delete rightnode;
+		return cell;
+	}
+
+	cell->Remove(last_left, cell->objects.end());
+
+	TreeNode* subroot = new TreeNode;
+	subroot->cut_point = cut_point;
+	subroot->axis = axis;
+	subroot->l = Split(cell);
+	subroot->r = Split(rightnode);
+	return subroot;
+}
+
+GTB_END_NAMESPACE
+
+#endif // GTB_KDTET_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/math.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/math.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/math.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,21 @@
+#ifndef GTB_MATH_INCLUDED
+#define GTB_MATH_INCLUDED
+
+#ifndef GTB_EPSILON_INCLUDED
+#include "epsilon.hpp"
+#endif
+
+#ifndef GTB_MATH_UTIL_INCLUDED
+#include "math_util.hpp"
+#endif
+
+#ifndef GTB_MATRIX_4D_INCLUDED
+#include "Matrix_4d.hpp"
+#endif
+
+#ifndef GTB_CXX_ALGORITHM_INCLUDED
+#include <algorithm>
+#define GTB_CXX_ALGORITHM_INCLUDED
+#endif
+
+#endif // GTB_MATH_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/math_util.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/math_util.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/math_util.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,61 @@
+#ifndef GTB_MATH_UTIL_INCLUDED
+#include "math_util.hpp"
+#endif
+
+#include "gtb_config.h"
+
+#ifdef HAVE_VALUES_H
+#include <values.h>
+#endif
+
+const double GTB_E = 2.7182818284590452354;
+const double GTB_LOG2E = 1.4426950408889634074;
+const double GTB_LOG10E = 0.43429448190325182765;
+const double GTB_LN2 = 0.69314718055994530942;
+const double GTB_LN10 = 2.30258509299404568402;
+const double GTB_PI = 3.14159265358979323846;
+const double GTB_PI_2 = 1.57079632679489661923;
+const double GTB_PI_4 = 0.78539816339744830962;
+const double GTB_1_PI = 0.31830988618379067154;
+const double GTB_2_PI = 0.63661977236758134308;
+const double GTB_2_SQRTPI = 1.12837916709551257390;
+const double GTB_SQRT2 = 1.41421356237309504880;
+const double GTB_SQRT1_2 = 0.70710678118654752440;
+const double GTB_PI_OVER_180 = 0.01745329251994329576;
+const double GTB_180_OVER_PI = 57.29577951308232087684;
+const double GTB_CM_PER_INCH = 2.54;
+const double GTB_MM_PER_INCH = 25.4;
+const unsigned GTB_POINTS_PER_INCH = 72;
+
+GTB_BEGIN_NAMESPACE
+
+
+// Computing (A * B) mod N Efficiently in ANSI C
+// Henry G. Baker
+// http://linux.rice.edu/~rahul/hbaker/AB-mod-N.html
+unsigned ab_mod_n(unsigned a, unsigned b, unsigned n)
+{
+	//fprintf(stderr, "a: %d  b: %d  n: %d\n", a, b, n);
+	double dn = n;		// 31 bits of n > 0
+	double da = a;		// 31 bits of a >= 0
+	double db = b;		// 31 bits of b >= 0
+	double dp = da * db;	// ~53 bits of a * b
+	double dq = dp / dn;	// ~51 bits of a * b / n
+	unsigned long qpp = (unsigned long) (dq + 0.5);	// q''=round(q)
+	unsigned long rp = a * b - qpp * n;	// r'
+	unsigned r = (rp & 0x80000000) ? (rp + n) : rp;
+	return r;
+}
+
+
+double drand()
+{
+#ifdef HAVE_DRAND48
+	return drand48();
+#else
+	return (double) rand() / (double) INT_MAX;
+#endif
+}
+
+
+GTB_END_NAMESPACE

Added: cs/cigma/branches/cigma-0.9b1/tmc/math_util.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/math_util.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/math_util.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,253 @@
+#ifndef GTB_MATH_UTIL_INCLUDED
+#define GTB_MATH_UTIL_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+#ifndef GTB_C_MATH_INCLUDED
+#include <math.h>
+#define GTB_C_MATH_INCLUDED
+#endif
+
+#ifndef GTB_C_STDLIB_INCLUDED
+#include <stdlib.h>
+#define GTB_C_STDLIB_INCLUDED
+#endif
+
+#include <algorithm>
+
+extern const double GTB_E;
+extern const double GTB_LOG2E;
+extern const double GTB_LOG10E;
+extern const double GTB_LN2;
+extern const double GTB_LN10;
+extern const double GTB_PI;
+extern const double GTB_PI_2;
+extern const double GTB_PI_4;
+extern const double GTB_1_PI;
+extern const double GTB_2_PI;
+extern const double GTB_2_SQRTPI;
+extern const double GTB_SQRT2;
+extern const double GTB_SQRT1_2;
+extern const double GTB_PI_OVER_180;
+extern const double GTB_180_OVER_PI;
+extern const double GTB_CM_PER_INCH;
+extern const double GTB_MM_PER_INCH;
+extern const unsigned GTB_POINTS_PER_INCH;
+
+GTB_BEGIN_NAMESPACE
+
+
+double deg_to_rad(double x);
+double rad_to_deg(double x);
+double log2(double x);
+double power_of_two_ceiling(double x);
+unsigned ab_mod_n(unsigned a, unsigned b, unsigned n);
+double drand();
+unsigned factorial(unsigned x);
+int rand32();
+
+template <class T> T abs(T x);
+template <class T> T clamp(T x, T low, T high);
+template <class T> T max3(const T &a, const T &b, const T &c);
+template <class T> T max3(const T &x, const T &y, const T &z, int &k);
+template <class T> T min3(const T &a, const T &b, const T &c);
+template <class T> T min3(const T &x, const T &y, const T &z, int &k);
+template <class T> T ipow(T x, int exponent);
+template <class T> T sqr(const T &x);
+template<class T> void assign_if_less(T &x, const T &y);
+template<class T> unsigned logn(T v);
+template<class T> T pwr2(T v);
+template<class T> T round2up(T v);
+
+
+inline double deg_to_rad(double x)
+{
+	return x * GTB_PI_OVER_180;
+}
+
+
+inline double rad_to_deg(double x)
+{
+	return x * GTB_180_OVER_PI;
+}
+
+
+inline double log2(double x)
+{
+        return log10(x) / log10(2.0);
+}
+
+
+inline double power_of_two_ceiling(double x)
+{
+        return pow((double)2, ceil(log2(x)));
+}
+
+
+inline unsigned factorial(unsigned x)
+{
+	unsigned result = 1;
+	while (x) {
+		result *= x;
+		--x;
+	}
+	return result;
+}
+
+
+inline int rand32()
+{
+	return (rand() << 15) + rand();
+}
+
+
+template <class T>
+inline T abs(T x)
+{
+	return (x >= 0) ? x : -x;
+}
+
+
+template <class T>
+inline T clamp(T x, T low, T high)
+{
+	if (x < low) {
+		return low;
+	} else if (x > high) {
+		return high;
+	} else {
+		return x;
+	}
+}
+
+
+template <class T>
+inline T max3(const T &a, const T &b, const T &c)
+{
+	return std::max(std::max(a, b), c);
+}
+
+
+// Similar to max3.  k is the index [0..2] of the largest item.
+template <class T>
+inline T max3(const T &x, const T &y, const T &z, int &k)
+{
+	if (x > y) {
+		if (x > z) {
+			k = 0;
+			return x;
+		} else {
+			k = 2;
+			return z;
+		}
+	} else if (y > z) {
+		k = 1;
+		return y;
+	} else {
+		k = 2;
+		return z;
+	}
+}
+
+
+template <class T>
+inline T min3(const T &a, const T &b, const T &c)
+{
+	return std::min(std::min(a, b), c);
+}
+
+
+// Similar to max3.  k is the index [0..2] of the largest item.
+template <class T>
+inline T min3(const T &x, const T &y, const T &z, int &k)
+{
+	if (x < y) {
+		if (x < z) {
+			k = 0;
+			return x;
+		} else {
+			k = 2;
+			return z;
+		}
+	} else if (y < z) {
+		k = 1;
+		return y;
+	} else {
+		k = 2;
+		return z;
+	}
+}
+
+
+template <class T>
+inline T ipow(T x, int exponent)
+{
+	T r=1;
+	while (exponent--) {
+		r *= x;
+	}
+	return r;
+}
+
+
+template <class T>
+inline T sqr(const T &x)
+{
+	return x * x;
+}
+
+
+template<class T>
+inline void assign_if_less(T &x, const T &y)
+{
+	if (x < y) {
+		x = y;
+	}
+}
+
+
+// returns the number of bits required to store v
+template<class T>
+inline unsigned logn(T v)
+{
+	T last_low_bit = 0;
+	T add1 = 0;
+	T result = 0;
+
+	while (v) {
+		add1 |= last_low_bit;
+		last_low_bit = v & 1;
+		v >>= 1;
+		++result;
+	}
+	return result - 1 + add1;
+}
+
+
+// returns v to the power of 2
+template<class T>
+inline T pwr2(T v)
+{
+	T result = 1;
+
+	while (v) {
+		result <<= 1;
+		--v;
+	}
+	return result;
+}
+
+
+// returns v rounded up to the nearst power of 2
+template<class T>
+inline T round2up(T v)
+{
+	return pwr2(logn(v));
+}
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_MATH_UTIL_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/namespace.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/namespace.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/namespace.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,19 @@
+#ifndef GTB_NAMESPACE_INCLUDED
+#define GTB_NAMESPACE_INCLUDED
+
+#ifdef WIN32
+#include "windows.hpp"
+#endif
+
+#ifndef MAX
+#define MAX(a,b)            (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a,b)            (((a) < (b)) ? (a) : (b))
+#endif
+
+#define GTB_BEGIN_NAMESPACE namespace gtb {
+#define GTB_END_NAMESPACE }
+
+#endif // GTB_NAMESPACE_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/null_template_args.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/null_template_args.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/null_template_args.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,10 @@
+#ifndef GTB_NULL_TEMPLATE_ARGS_INCLUDED
+#define GTB_NULL_TEMPLATE_ARGS_INCLUDED
+
+/* #undef GTB_NULL_TEMPLATE_ARGS
 */
+
+#endif // GTB_NULL_TEMPLATE_ARGS_INCLUDED
+
+// Local Variables:
+// mode:C++
+// End:

Added: cs/cigma/branches/cigma-0.9b1/tmc/patterns.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/patterns.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/patterns.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,16 @@
+#ifndef GTB_PATTERNS_INCLUDED
+#define GTB_PATTERNS_INCLUDED
+
+#ifndef GTB_OBSERVER_INCLUDED
+#include "Observer.hpp"
+#endif
+
+#ifndef GTB_SUBJECT_INCLUDED
+#include "Subject.hpp"
+#endif
+
+#ifndef GTB_VISITOR_INCLUDED
+#include "Visitor.hpp"
+#endif
+
+#endif // GTB_PATTERNS_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/program_name.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/program_name.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/program_name.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,35 @@
+#ifndef GTB_PROGRAM_NAME_INCLUDED
+#include "program_name.hpp"
+#endif
+
+#ifndef GTB_CXX_STRING_INCLUDED
+#include <string>
+#define GTB_CXX_STRING_INCLUDED
+#endif
+
+#ifndef GTB_C_ASSERT_INCLUDED
+#include <assert.h>
+#define GTB_C_ASSERT_INCLUDED
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+static std::string program_name;
+
+
+const char *get_program_name()
+{
+	return program_name.c_str();
+}
+
+
+void set_program_name(const char *argv0)
+{
+	assert(argv0 != NULL);
+	program_name = argv0;
+}
+
+
+GTB_END_NAMESPACE
+

Added: cs/cigma/branches/cigma-0.9b1/tmc/program_name.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/program_name.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/program_name.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,17 @@
+#ifndef GTB_PROGRAM_NAME_INCLUDED
+#define GTB_PROGRAM_NAME_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+void set_program_name(const char *argv0);
+const char *get_program_name();
+
+
+GTB_END_NAMESPACE
+
+#endif // GTB_PROGRAM_NAME_INCLUDED

Added: cs/cigma/branches/cigma-0.9b1/tmc/ptrs.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/ptrs.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/ptrs.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,316 @@
+// -*-c++-*- 
+/*
+ * Copyright (c) 1999
+ * Shachar Fleishman shacharf at math.tau.ac.il
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted 
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+/*
+Auto pointers, smart pointers and auto free/close classes
+
+  aptr - Autopointer class, A class that behaves like a pointer but frees
+         it's contentens when destructed.
+  aaptr - Same as aptr but for array pointers
+  sptr - Smart pointer, A class that behaves like a pointer with a reference
+         count. When the reference count reaches zero, the pointer if freed.
+  afree - An auto free class, given an object and a function that frees
+          the object, the afree class will free the object upon destruction.
+  piter - An iterator adaptor that retrieves the pointer to the object.
+
+  The aptr class sample:
+  {
+    aptr<C> c = new C(10);
+
+        c->doit();
+  } // c is deleted.
+
+  Using sptr is simlilat to aptr, except that when you need another copy
+  of a pointer to the same object, you use the sptr<T> instead of T*. you
+  can use either the constructor or the operator= to initialize any pointer
+  from the second reference to the object on.
+
+  afree Sample:
+        {
+                afree<FILE*> aclose(fopen(file_name, "w"), fclose);
+
+                ...
+        } // calls fclose(f);
+
+*/
+
+#ifndef __PTRS_H
+#define __PTRS_H
+
+#include "counter.h"
+#include "common.hpp"
+#include <iterator>
+#include <memory>
+
+GTB_BEGIN_NAMESPACE
+
+template <class T>
+class aptr
+{
+public:
+    typedef T* ptr;
+    typedef const T* const_ptr;
+    typedef T& reference;
+    
+    aptr(ptr p) : m_p(p) {}
+    ~aptr() { delete m_p; }
+    
+    ptr operator=(ptr p) { delete m_p; return m_p = p; }
+    
+    bool operator==(const_ptr p) { return m_p == p; }
+    
+    reference operator*() { return *m_p; }
+    ptr operator->() { return m_p; }
+    const_ptr operator->() const { return m_p; }
+    
+    operator T*() { return m_p; }
+    operator const T*() const { return m_p; }
+    
+    ptr operator+(int d) { return m_p + d; }
+    ptr operator-(int d) { return m_p - d; }
+    
+    ptr get() { return m_p; }
+    const_ptr get() const { return m_p; }
+    ptr release() { ptr v = m_p; m_p = 0; return v;}
+    void set(ptr p) { m_p = p; }
+    
+protected:
+    ptr m_p;
+};
+
+template <class T>
+class aaptr
+{
+public:
+        typedef T* ptr;
+        typedef const T* const_ptr;
+        typedef T& reference;
+
+        aaptr(ptr p) : m_p(p) {}
+        ~aaptr() { delete[] m_p; }
+
+        ptr operator=(ptr p) { delete[] m_p; return m_p = p; }
+        bool operator==(const_ptr p) { return m_p == p; }
+
+        reference operator*() { return *m_p; }
+        ptr operator->() { return m_p; }
+
+        operator T*() { return m_p; }
+        operator const T*() const { return m_p; }
+
+        ptr operator+(int d) { return m_p + d; }
+        ptr operator-(int d) { return m_p - d; }
+
+        ptr get() { return m_p; }
+        void release() { m_p = 0; }
+        void set(ptr p) { m_p = p; }
+
+        T& operator[](int p) { return m_p[p]; }
+protected:
+        ptr m_p;
+};
+
+
+template <class T>
+class sptr
+{
+public:
+    typedef T* ptr;
+    typedef const T* const_ptr;
+    typedef T& reference;
+    
+    sptr() : m_p(0), m_counter(new Counter(1)) {} // Allow storing sptr<X> in stl containers such as map
+    sptr(ptr p) : m_p(p) { m_counter = new Counter(1); }
+    sptr(const sptr &p) : m_p(p.m_p), m_counter(p.m_counter) { ++*m_counter; }
+    ~sptr() { p_erase(); }
+    
+    sptr& operator=(const sptr& p) { p_erase(); m_p = p.m_p; m_counter = p.m_counter; ++*m_counter; return *this; }
+    
+    /*
+     * Assign a new pointer, this routine creates a new sptr,
+     * similar to sptr<T> p(new T);
+     */
+    void assign(ptr p) { p_erase(); m_counter=new Counter(1); m_p = p; }
+
+    ptr release() 
+    {
+        ptr v = m_p;
+        if (--*m_counter)
+        {
+            // BUGBUG change behaviour such that m_p==0 ==> no counter.
+            m_counter = new Counter(1);
+        }
+        else
+        {
+            ++*m_counter;
+        }
+        m_p = 0;
+        return v;
+    }
+    
+    bool operator==(const sptr& p) const { return m_p == p.m_p; }
+    bool operator==(const ptr& p) const { return m_p == p; }
+    bool operator<(const sptr& p) const { return m_p < p.m_p; }
+    bool operator<(const ptr& p) const { return m_p < p; }
+
+    bool operator>(const sptr& p) const { return m_p > p.m_p; } // BUGBUG VC BUG?
+
+    reference operator*() { return *m_p; }
+    ptr operator->() { return m_p; }
+    const_ptr operator->() const { return m_p; }
+    
+    operator T*() { return m_p; }
+    operator const T*() const { return m_p; }
+    
+    ptr operator+(int d) { return m_p + d; }
+    ptr operator-(int d) { return m_p - d; }
+    
+    ptr get() { return m_p; }
+    const_ptr get() const { return m_p; }
+
+protected:
+    ptr m_p;
+    Counter* m_counter;
+    
+    void p_erase() { if ( !--*m_counter) {delete m_p; delete m_counter;} }
+};
+
+template <class T>
+class afree
+{
+public:
+    typedef void (*f_free)(T);
+    typedef int (*int_f_free)(T);
+    typedef long (*long_f_free)(T);
+    
+    typedef T value_type;
+    
+    afree(T v, f_free free_function, T null_value = T(0) ) : 
+        m_v(v), m_free(free_function) , m_null_value(null_value) {}
+    afree(T v, int_f_free free_function, T null_value = T(0) ) : 
+        m_v(v), m_free(reinterpret_cast<f_free>(free_function)), 
+        m_null_value(null_value) {}
+    afree(T v, long_f_free free_function, T null_value = T(0) ) : 
+        m_v(v), m_free(reinterpret_cast<f_free>(free_function)),
+        m_null_value(null_value)  {}
+    ~afree() { if (m_v != m_null_value) m_free(m_v); }
+    
+    operator T&() { return m_v; }
+    T& operator ->() { return m_v; }
+protected:
+    T m_v;
+    f_free m_free;
+    T m_null_value;
+};
+
+//
+// TEMPLATE CLASS auto_ptr
+// Taken from VC STL, release keeps the pointer.
+//
+// Allows me to store pointers in containers
+// And... mix owned and non-owned pointers in the one
+// container.
+//
+template<class T>
+class auto_ptr2 {
+public:
+    typedef T element_type;
+
+    explicit auto_ptr2(element_type *p = 0) throw() :
+        m_owner(p != 0), m_ptr(p)
+    {
+    }
+
+    auto_ptr2(const auto_ptr2& p) throw():
+        m_owner(p.m_owner), m_ptr(p.release())
+    {
+    }    
+
+    auto_ptr2& operator=(const auto_ptr2& rhs) throw()
+    {
+        if (this != &rhs)
+        {
+            if (m_ptr != rhs.get())
+            {
+                if (m_owner) delete m_ptr;
+                m_owner = rhs.m_owner;
+            }
+            else if (rhs.m_owner) m_owner = true;
+            m_ptr = rhs.release();
+        }
+        return *this; 
+    }
+
+    ~auto_ptr2()
+    {
+        if (m_owner) delete m_ptr;
+    }
+
+    element_type& operator*() const throw()
+    {
+        return *get();
+    }
+
+    element_type *operator->() const throw()
+    {
+        return get();
+    }
+
+    element_type *get() const throw()
+    {
+        return m_ptr;
+    }
+
+    element_type *release() const throw()
+    {
+        m_owner = false;
+        return m_ptr;
+    }
+private:
+    mutable bool m_owner;
+    element_type *m_ptr;
+}; //auto_ptr2
+
+//
+// Iterator adaptor that retrieves the pointer to the object
+//
+template <class CONT>
+class piter : public std::iterator<std::random_access_iterator_tag,
+				   typename CONT::value_type,
+				   int>
+{
+public:
+    typedef typename CONT::value_type* value_type;
+    typedef typename CONT::iterator iterator;
+    iterator i;
+
+    piter() {}
+    piter(iterator iter) : i(iter) {}
+
+    typename CONT::value_type* operator*() { return &(*i); }
+    piter& operator++() { ++i; return *this; }
+    int operator-(const piter& rhs) const { return i - rhs.i; }
+
+    bool operator ==(const piter& rhs) { return i == rhs.i; }
+    bool operator !=(const piter& rhs) { return i != rhs.i; }
+
+    piter& operator=(const piter& rhs) { i = rhs.i; return *this; }
+    piter& operator=(iterator rhs) { i = rhs;  return *this; }
+
+};
+GTB_END_NAMESPACE
+
+#endif // __PTRS_H

Added: cs/cigma/branches/cigma-0.9b1/tmc/stlext.h
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/stlext.h	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/stlext.h	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,96 @@
+#ifndef __STLEXT_H
+#define __STLEXT_H
+
+// Need to find the right place for this as well
+
+#include <functional>
+
+#if 0
+template<class _Bfn>
+class void_binder1st : 
+public std::unary_function<typename _Bfn::second_argument_type, typename _Bfn::result_type> 
+{
+public:
+	void_binder1st(const _Bfn& _X,
+		const typename _Bfn::first_argument_type& _Y)
+		: op(_X), value(_Y) {}
+	void operator()(const typename _Bfn::second_argument_type& _X) const
+	{
+        op(value, _X); 
+    }
+protected:
+	_Bfn op;
+	_Bfn::first_argument_type value;
+	};
+#else
+template <class _Operation>
+class void_binder1st
+  : public std::unary_function<typename _Operation::second_argument_type, void> {
+protected:
+  _Operation op;
+  typename _Operation::first_argument_type value;
+public:
+  void_binder1st(const _Operation& __x,
+            const typename _Operation::first_argument_type& __y)
+	: op(__x), value(__y) {}
+  void
+  operator()(const typename _Operation::second_argument_type& __x) const {
+    op(value, __x);
+  }
+};
+
+#endif
+
+template<class _Bfn, class _Ty> inline
+void_binder1st<_Bfn> void_bind1st(const _Bfn& XX, const _Ty& YY)
+{
+    return (void_binder1st<_Bfn>(XX, _Bfn::first_argument_type(YY))); 
+}
+
+template<class _Ty, class AA>
+class void_mem_fun1_t : public std::binary_function<_Ty*, AA, void>
+{
+private:
+	void (_Ty::*_Ptr)(AA);
+
+public:
+	explicit void_mem_fun1_t(void (_Ty::*_Pm)(AA)) : _Ptr(_Pm) {}
+	void operator()(_Ty *PP, AA _Arg) const
+    {
+        (PP->*_Ptr)(_Arg); 
+    }
+};
+
+template<class _Ty, class AA> 
+inline void_mem_fun1_t<_Ty, AA> void_mem_fun1(void (_Ty::*_Pm)(AA))
+{
+    return (void_mem_fun1_t<_Ty, AA>(_Pm)); 
+}
+
+/*--------------- function object AssignOP ----------------*/
+//
+// Assign value to an iterator
+
+template<class ITERATOR, class T>
+struct AssignOP_t : public std::unary_function<T, void>
+{
+    mutable ITERATOR it;
+
+    AssignOP_t(ITERATOR IT) : it(IT) {}
+
+    void operator() (const T& x) const
+    {
+//        if (x == bpnumber) DebugBreak(); // DEBUG ONLY
+        // Is this a bug? shouldn't it be *it = x?
+        *it = x;
+    }
+};
+
+template<class T, class ITERATOR>
+AssignOP_t<ITERATOR, T> AssignOp(ITERATOR it)
+{
+    return AssignOP_t<ITERATOR, T>(it);
+}
+
+
+#endif // __STLEXT_H

Added: cs/cigma/branches/cigma-0.9b1/tmc/tet_sampling.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/tet_sampling.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/tet_sampling.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,35 @@
+#include "tet_sampling.hpp"
+
+// This C++ function takes in input four 3D points describing the
+// vertexes of a tetrahedron and returns a random point with uniform
+// distribution inside it. We assume that the Point3 class has operators
+// overloaded with the obvious meaning of product between vectors and scalar,
+// sum between vectors, etc.
+//
+// from:
+//    C. Rocchini and P. Cignoni.
+//    Generating random points in a tetrahedron.
+//    Journal of graphics tools, 5(4):9-12, 2000
+//    
+
+Vector_3f Pick(Vector_3f &v0, Vector_3f &v1, Vector_3f &v2, Vector_3f &v3)
+{
+	double s = drand();
+	double t = drand();
+	double u = drand();
+	if (s+t>1.0) { // cut'n fold the cube into a prism
+		s = 1.0 - s;
+		t = 1.0 - t;
+	}
+	if (t+u>1.0) { // cut'n fold the prism into a tetrahedron
+		double tmp = u;
+		u = 1.0 - s - t;
+		t = 1.0 - tmp;
+	} else if (s+t+u>1.0) {
+		double tmp = u;
+		u = s + t + u - 1.0;
+		s = 1 - t - tmp;
+	}
+	double a=1-s-t-u; // a,s,t,u are the barycentric coordinates of the random point.
+	return v0*(float)a + v1*(float)s + v2*(float)t + v3*(float)u;
+}

Added: cs/cigma/branches/cigma-0.9b1/tmc/tet_sampling.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/tet_sampling.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/tet_sampling.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,5 @@
+#include "graphics.hpp"
+
+using namespace gtb;
+
+Vector_3f Pick(Vector_3f &v0, Vector_3f &v1, Vector_3f &v2, Vector_3f &v3);

Added: cs/cigma/branches/cigma-0.9b1/tmc/tmc.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/tmc.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/tmc.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,210 @@
+#include "common.hpp"
+#include "graphics.hpp"
+#include "Indexed_tetra_set.hpp"
+#include "Time_series.hpp"
+#include "Indexed_tetra_set_off_reader.hpp"
+#include <sstream>
+#include <iostream>
+#include "tet_sampling.hpp"
+#include "vect_stats.hpp"
+
+using namespace gtb;
+using namespace std;
+
+#define DEFAULT_TET_PER_LEAF 100
+#define DEFAULT_SAMPLES_PER_TET 0
+
+#define BUILDING_KDTREE_PROMPT "Building kd-tree..."
+#define SAMPLING_VERTICES_PROMPT "Sampling at the vertices...."
+#define SAMPLING_TETS_PROMPT "Sampling inside the tets..."
+
+
+void print_mesh_info(Indexed_tetra_set *its, Scalar_time_series *sts)
+{
+	float min_val = sts->get_min_value();
+	float max_val = sts->get_max_value();
+	printf("num tetrahedra: %d\n", its->get_num_tetrahedra());
+	printf("scalar values: [%g, %g]\n", min_val, max_val);
+}
+
+
+void usage(char **argv)
+{
+	printf("\nUsage: %s [OPTIONS] sampled_mesh.off compared_mesh.off\n", argv[0]);
+	printf("-k <max number of tets per kd-tree leaf> (default=%d)\n", DEFAULT_TET_PER_LEAF);
+	printf("-t <num random samples per tet> (default=%d)\n", DEFAULT_SAMPLES_PER_TET);
+}
+
+
+int main(int argc, char **argv)
+{
+	printf("TMC (TetMesh Comparator) Version 1.0 (June 15, 2005)\n");
+	printf("Copyright (C) 2005, Louis Bavoil <bavoil at sci.utah.edu>\n");
+	printf("This program is distributed under the GNU GPL license version 2.\n");
+
+	if (argc < 3) {
+		usage(argv);
+		exit(EXIT_FAILURE);
+	}
+
+	float max_tet_per_leaf = DEFAULT_TET_PER_LEAF;
+	unsigned num_samples_per_tet = DEFAULT_SAMPLES_PER_TET;
+	const char *samp_file_name = NULL;
+	const char *comp_file_name = NULL;
+
+	argc--;
+	argv++;
+	while (argc > 0) {
+		if ((strcmp("-k", argv[0]) == 0) && (argc > 1)) {
+			max_tet_per_leaf = atof(argv[1]);
+			argc -= 2;
+			argv += 2;
+		} else if ((strcmp("-t", argv[0]) == 0) && (argc > 1)) {
+			num_samples_per_tet = atoi(argv[1]);
+			argc -= 2;
+			argv += 2;
+		} else if (samp_file_name == NULL) {
+			samp_file_name = argv[0];
+			argc--;
+			argv++;
+		} else if (comp_file_name == NULL) {
+			comp_file_name = argv[0];
+			argc--;
+			argv++;
+		} else {
+			usage(argv);
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	if (!samp_file_name || !comp_file_name) {
+		usage(argv);
+		exit(EXIT_FAILURE);
+	}
+
+	///////////////////////////////////////////////////////////////////////////////
+
+	Indexed_tetra_set_off_reader reader;
+	FILE *samp_off_fp, *comp_off_fp;
+	Indexed_tetra_set *samp_its, *comp_its;
+	Scalar_time_series *samp_sts, *comp_sts;
+
+	printf("\nSampled mesh: %s\n", samp_file_name);
+	GTB_FOPEN(samp_off_fp, samp_file_name, "r");
+	reader.read(samp_off_fp, &samp_its, &samp_sts);
+	print_mesh_info(samp_its, samp_sts);
+
+	printf("\nCompared mesh: %s\n", comp_file_name);
+	GTB_FOPEN(comp_off_fp, comp_file_name, "r");
+	reader.read(comp_off_fp, &comp_its, &comp_sts);
+	print_mesh_info(comp_its, comp_sts);
+
+	const float range = samp_sts->get_max_value() - samp_sts->get_min_value();
+	const std::vector<Point_3f> &vertices = samp_its->get_vertices();
+	const std::vector<Tetrahedron> &tets = samp_its->get_tetrahedra();
+
+	printf("\n%s\n", BUILDING_KDTREE_PROMPT);
+	KDTet<unsigned> comp_tree(max_tet_per_leaf, comp_its, comp_sts);
+	comp_tree.MakeTree();
+
+	///////////////////////////////////////////////////////////////////////////////
+
+	printf("%s\r", SAMPLING_VERTICES_PROMPT);
+
+	std::vector<float> errors;
+	unsigned num_eval_misses = 0;
+
+	for (unsigned vi=0; vi < vertices.size(); vi++) {
+
+		Point_3f s_f = vertices[vi];
+		Point_3d s_d(s_f[0], s_f[1], s_f[2]);
+
+		KDTet<unsigned>::TreeNode *parent;
+		KDTet<unsigned>::LeafNode *node = comp_tree.Find(s_d, parent);
+
+		float comp_val;
+		if (!comp_tree.FindAndEvalTet(node, s_f, &comp_val)) {
+			num_eval_misses++;
+			continue;
+		}
+
+		float samp_val = samp_sts->get_value(vi);
+		errors.push_back(fabs(comp_val - samp_val));
+
+		if (vi % 1000 == 0) {
+			printf("\r%s %.0f%%",
+			       SAMPLING_VERTICES_PROMPT,
+			       (float)vi/vertices.size()*100);
+			fflush(stdout);
+		}
+	}
+
+	printf("\r%s        \n", SAMPLING_VERTICES_PROMPT);
+
+	///////////////////////////////////////////////////////////////////////////////
+
+	if (num_samples_per_tet> 0 ) {
+		printf("%s\r", SAMPLING_TETS_PROMPT);
+
+		for (unsigned ti=1; ti < tets.size(); ti++) {
+			const Tetrahedron &t = tets[ti];
+
+			Vector_3f v0(vertices[t.get_vertex(0)]);
+			Vector_3f v1(vertices[t.get_vertex(1)]);
+			Vector_3f v2(vertices[t.get_vertex(2)]);
+			Vector_3f v3(vertices[t.get_vertex(3)]);
+
+			for (unsigned i=0; i < num_samples_per_tet; i++) {
+				Vector_3f pick = Pick(v0, v1, v2, v3);
+				Point_3f s_f(pick[0], pick[1], pick[2]);
+				Point_3d s_d(s_f[0], s_f[1], s_f[2]);
+				
+				KDTet<unsigned>::TreeNode *parent;
+				KDTet<unsigned>::LeafNode *node = comp_tree.Find(s_d, parent);
+			
+				float comp_val;
+				if (!comp_tree.FindAndEvalTet(node, s_f, &comp_val)) {
+					num_eval_misses++;
+					continue;
+				}
+
+				float samp_val;
+				if (!samp_its->interpol_tetra(samp_sts, t, s_f, &samp_val)) {
+					num_eval_misses++;
+					continue;
+				}
+
+				errors.push_back(fabs(comp_val - samp_val));
+			}
+
+			if (ti % 1000 == 0) {
+				printf("\r%s %.0f%%",
+				       SAMPLING_TETS_PROMPT,
+				       (float)ti/tets.size()*100);
+				fflush(stdout);
+			}
+		}
+
+		printf("\r%s     \n", SAMPLING_TETS_PROMPT);
+	}
+
+	///////////////////////////////////////////////////////////////////////////////
+
+	printf("\nSampling:\n");
+	printf("num samples per tet: \t%d\n", num_samples_per_tet);
+	printf("total num of samples:\t%d\n", (int)errors.size());
+	printf("ignored samples:     \t%d (%f%%)\n", num_eval_misses,
+	       (float)num_eval_misses*100/vertices.size());
+
+	printf("\nField Error:\n");
+	float max_err = vect_max(errors);
+	float mean_err = vect_mean(errors);
+	float std_dev = vect_std_dev(errors, mean_err);
+	float root_ms_err = sqrt(vect_mean_squared(errors));
+	printf("max:             \t%e (%f%%)\n", max_err, max_err*100/range);
+	printf("mean:            \t%e (%f%%)\n", mean_err, mean_err*100/range);
+	printf("std dev:         \t%e (%f%%)\n", std_dev, std_dev*100/range);
+	printf("root mean squared:\t%e (%f%%)\n", root_ms_err, root_ms_err*100/range);
+
+	return 0;
+}

Added: cs/cigma/branches/cigma-0.9b1/tmc/vect_stats.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/vect_stats.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/vect_stats.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,61 @@
+#include "vect_stats.hpp"
+
+float vect_max(std::vector<float> &v) {
+	float max = 0;
+	for (unsigned i=0; i < v.size(); i++) {
+		max = std::max(max, v[i]);
+	}
+	return max;
+}
+
+
+float vect_min(std::vector<float> &v) {
+	float min = FLT_MAX;
+	for (unsigned i=0; i < v.size(); i++) {
+		min = std::min(min, v[i]);
+	}
+	return min;
+}
+
+
+float vect_mean(std::vector<float> &v) {
+	float mean = 0;
+	for (unsigned i=0; i < v.size(); i++) {
+		mean += v[i];
+	}
+	mean /= v.size();
+	return mean;
+}
+
+
+float vect_mean_squared(std::vector<float> &v) {
+        float mean = 0;
+        for (unsigned i=0; i < v.size(); i++) {
+                mean += v[i]*v[i];
+        }
+        mean /= v.size();
+        return mean;
+}
+
+
+float vect_std_dev(std::vector<float> &v, float mean) {
+	float dev = 0;
+	unsigned N = v.size();
+	for (unsigned i=0; i < N; i++) {
+		float diff = v[i] - mean;
+		dev += diff*diff;
+	}
+	dev /= (N - 1);
+	return sqrt(dev);
+}
+
+
+float vect_avg_dev(std::vector<float> &v, float mean) {
+	float dev = 0;
+	unsigned N = v.size();
+	for (unsigned i=0; i < N; i++) {
+		dev += fabs(v[i] - mean);
+	}
+	dev /= N;
+	return dev;
+}

Added: cs/cigma/branches/cigma-0.9b1/tmc/vect_stats.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/vect_stats.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/vect_stats.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,10 @@
+#include "graphics.hpp"
+
+using namespace gtb;
+
+float vect_max(std::vector<float> &v);
+float vect_min(std::vector<float> &v);
+float vect_mean(std::vector<float> &v);
+float vect_mean_squared(std::vector<float> &v);
+float vect_std_dev(std::vector<float> &v, float mean);
+float vect_avg_dev(std::vector<float> &v, float mean);

Added: cs/cigma/branches/cigma-0.9b1/tmc/version.cpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/version.cpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/version.cpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,49 @@
+#ifndef GTB_VERSION_INCLUDED
+#include "version.hpp"
+#endif
+
+#ifndef GTB_C_STDLIB_INCLUDED
+#include <stdlib.h>
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+const unsigned major_version = 0;
+const unsigned minor_version = 6;
+const unsigned micro_version = 27;
+const unsigned binary_age =    0;
+const unsigned interface_age = 0;
+
+
+const char *check_version(unsigned required_major,
+			  unsigned required_minor,
+			  unsigned required_micro)
+{
+	if (required_major > GTB_MAJOR_VERSION) {
+		return "gtb version too old (major mismatch)";
+	}
+	if ((int) required_major < GTB_MAJOR_VERSION) {
+		return "gtb version too new (major mismatch)";
+	}
+	if (required_minor > GTB_MINOR_VERSION) {
+		return "gtb version too old (minor mismatch)";
+	}
+	if ((int) required_minor < GTB_MINOR_VERSION) {
+		return "gtb version too new (minor mismatch)";
+	}
+	if ((int) required_micro < GTB_MICRO_VERSION - GTB_BINARY_AGE) {
+		return "gtb version too new (micro mismatch)";
+	}
+	if (required_micro > GTB_MICRO_VERSION) {
+		return "gtb version too old (micro mismatch)";
+	}
+	return NULL;
+}
+
+
+GTB_END_NAMESPACE
+
+// Local Variables:
+// mode:C++
+// End:

Added: cs/cigma/branches/cigma-0.9b1/tmc/version.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/version.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/version.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,41 @@
+#ifndef GTB_VERSION_INCLUDED
+#define GTB_VERSION_INCLUDED
+
+#ifndef GTB_NAMESPACE_INCLUDED
+#include "namespace.hpp"
+#endif
+
+GTB_BEGIN_NAMESPACE
+
+
+// run time check
+extern const unsigned major_version;
+extern const unsigned minor_version;
+extern const unsigned micro_version;
+extern const unsigned binary_age;
+extern const unsigned interface_age;
+const char *check_version(unsigned required_major,
+			  unsigned required_minor,
+			  unsigned required_micro);
+
+GTB_END_NAMESPACE
+
+
+// compile time check
+#define GTB_MAJOR_VERSION				(0)
+#define GTB_MINOR_VERSION				(6)
+#define GTB_MICRO_VERSION				(27)
+#define GTB_BINARY_AGE					(0)
+#define GTB_INTERFACE_AGE				(0)
+#define	GTB_CHECK_VERSION(major,minor,micro)	\
+    (GTB_MAJOR_VERSION > (major) || \
+     (GTB_MAJOR_VERSION == (major) && GTB_MINOR_VERSION > (minor)) || \
+     (GTB_MAJOR_VERSION == (major) && GTB_MINOR_VERSION == (minor) && \
+      GTB_MICRO_VERSION >= (micro)))
+
+
+#endif // GTB_VERSION_INCLUDED
+
+// Local Variables:
+// mode:C++
+// End:

Added: cs/cigma/branches/cigma-0.9b1/tmc/windows.hpp
===================================================================
--- cs/cigma/branches/cigma-0.9b1/tmc/windows.hpp	2007-07-09 16:52:17 UTC (rev 7613)
+++ cs/cigma/branches/cigma-0.9b1/tmc/windows.hpp	2007-07-09 16:53:39 UTC (rev 7614)
@@ -0,0 +1,93 @@
+#define NOMINMAX
+#include <windows.h>
+
+// Warnings
+
+#pragma warning( disable : 4786 4284 34)
+
+//
+// Enable malloc debug
+//
+#if 0
+//#include <malloc.h>
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#endif // #if 0/1
+
+// [ malloc debug ] 
+
+// OpenGL stuff
+
+#include <GL/glut.h>
+#include <GL/glext.h>
+
+//#define GL_BGR GL_BGR_EXT
+//#define GL_BGRA GL_BGRA_EXT
+
+// C stuff
+
+#include <assert.h>
+#include <errno.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+//#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <direct.h>
+#include <sys/timeb.h>
+
+#define S_ISREG(mode) (mode & _S_IFREG)
+#define S_ISDIR(mode) (mode & _S_IFDIR)
+
+#ifndef PATH_MAX
+#define PATH_MAX 512
+#endif
+
+typedef int socklen_t;
+
+// C++ stuff
+
+#include <algorithm>
+#include <iostream>
+#include <list>
+#include <map>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <stack>
+#include <queue>
+
+/*
+
+
+template<class T>
+inline const T &min(const T &x, const T &y)
+{
+	return (x < y) ? x : y;
+}
+
+template<class T>
+inline const T &max(const T &x, const T &y)
+{
+	return (x > y) ? x : y;
+}
+
+*/
+
+#define for if (0); else for
+
+#define REAL_IS_DOUBLE 1
+#define hypot _hypot
+#define copysign _copysign
+
+#define sleep Sleep
+
+#define HAVE_STRICMP 1
+
+#define M_PI 3.14159265358979323846



More information about the cig-commits mailing list