Up: Home page for Qhull (local)
Up: News about Qhull
Up: Qhull Wiki and
FAQ (local)
To: Qhull manual: contents
To: Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
Functions (local)
Qhull is a general dimension code for computing convex hulls, Delaunay triangulations, halfspace intersections about a point, Voronoi diagrams, furthest-site Delaunay triangulations, and furthest-site Voronoi diagrams. These structures have applications in science, engineering, statistics, and mathematics. See Fukuda's introduction to convex hulls, Delaunay triangulations, Voronoi diagrams, and linear programming. For a detailed introduction, see O'Rourke ['94], Computational Geometry in C.
There are six programs. Except for rbox, they use the same code. Each program includes instructions and examples.
- qconvex -- convex hulls
- qdelaunay -- Delaunay triangulations and furthest-site Delaunay triangulations
- qhalf -- halfspace intersections about a point
- qhull -- all structures with additional options
- qvoronoi -- Voronoi diagrams and furthest-site Voronoi diagrams
- rbox -- generate point distributions for qhull
Qhull implements the Quickhull algorithm for computing the convex hull. Qhull includes options for hull volume, facet area, multiple output formats, and graphical output. It can approximate a convex hull.
Qhull handles roundoff errors from floating point arithmetic. It generates a convex hull with "thick" facets. A facet's outer plane is clearly above all of the points; its inner plane is clearly below the facet's vertices. Any exact convex hull must lie between the inner and outer plane.
Qhull uses merged facets, triangulated output, or joggled input. Triangulated output triangulates non-simplicial, merged facets. Joggled input also guarantees simplicial output, but it is less accurate than merged facets. For merged facets, Qhull reports the maximum outer and inner plane.
Brad Barber, Arlington, MA
Copyright © 1995-2020 C.B. Barber
Qhull constructs convex hulls, Delaunay triangulations, halfspace intersections about a point, Voronoi diagrams, furthest-site Delaunay triangulations, and furthest-site Voronoi diagrams.
For convex hulls and halfspace intersections, Qhull may be used for 2-d up to 8-d. For Voronoi diagrams and Delaunay triangulations, Qhull may be used for 2-d up to 7-d. In higher dimensions, the size of the output grows rapidly and Qhull does not work well with virtual memory. If n is the size of the input and d is the dimension (d>=3), the size of the output and execution time grows by n^(floor(d/2) [see Performance]. For example, do not try to build a 16-d convex hull of 1000 points. It will have on the order of 1,000,000,000,000,000,000,000,000 facets.
On a 1.7 GHz i7, Qhull computes the 2-d convex hull of 3,000,000 evenly spaced, cocircular points in 4.7 seconds. It computes the 2-d Delaunay triangulation and 3-d convex hull of 600,000 points in 5.9 seconds. It computes the 3-d Delaunay triangulation and 4-d convex hull of 120,000 points in 4.6 seconds. It computes the 4-d Delaunay triangulation and 5-d convex hull of 30,000 points in 5.1 seconds. It computes the 5-d Delaunay triangulation and 6-d convex hull of 6,000 points in 7.8 seconds. It computes the 6-d Delaunay triangulation and 7-d convex hull of 1,000 points in 7.6 seconds. It computes the 7-d Delaunay triangulation and 8-d convex hull of 300 points in 8.6 seconds. It computes the 8-d Delaunay triangulation and 9-d convex hull of 120 points in 5.7 seconds. It computes the 9-d Delaunay triangulation and 10-d convex hull of 70 points in 4.8 seconds. The 10-d convex hull of 70 cospherical points has about 375,000 facets.
Qhull does not support constrained Delaunay triangulations, triangulation of non-convex surfaces, mesh generation of non-convex objects, or medium-sized inputs in 9-D and higher.
This is a big package with many options. For 32-bit code, it is one of the fastest available. It is the only 3-d and higher code that handles precision problems due to floating point arithmetic. For example, it implements the identity function for extreme points (see Imprecision in Qhull).
Qhull does not handle all precision problems (Limitations of merged facets). For example, errors may occur for the 4-D Delaunay triangulation of nearly adjacent points in the unit cube. If every input site has a nearly adjacent point within a 10^-13 ball, precision errors and topological errors are likely to occur. A bounding box may alleviate these errors. Nearly adjacent points within substantially smaller or larger balls are OK.
Joggled input, option 'QJn', is an alternative to merged facets (Merged facets or joggled input). It randomly perturbs the input. If precision problems occur, Qhull restarts with a larger, random perturbation. Joggled input is a simple solution without the limitations of merged facets. For example, Qhull constructs a convex hull even if all of the input points are identical.
If you need a short code for convex hull, Delaunay triangulation, or Voronoi volumes consider Clarkson's hull program. If you need 2-d Delaunay triangulations consider Shewchuk's triangle program. It is much faster than Qhull and it allows constraints. Both programs use exact arithmetic. They are in http://www.netlib.org/voronoi/.
If your input is in general position (i.e., no coplanar or colinear points), Tomilov's quickhull.hpp (documentation-ru), or Qhull version 1.0 may meet your needs. Both programs detect precision problems, but do not handle them.
CGAL is a library of efficient and reliable geometric algorithms. It uses C++ templates and the Boost library to produce dimension-specific code. This allows more efficient use of memory than Qhull's general-dimension code. For 64-bit code, CGAL uses significantly less memory than Qhull and runs faster. CGAL simulates arbitrary precision while Qhull handles round-off error with thick facets. Compare the two approaches with Robustness Issues in CGAL, and Imprecision in Qhull.
Leda is a library for writing computational geometry programs and other combinatorial algorithms. It includes routines for computing 3-d convex hulls, 2-d Delaunay triangulations, and 3-d Delaunay triangulations. It provides rational arithmetic and graphical output. It runs on most platforms.
If your problem is in high dimensions with a few, non-simplicial facets, try Fukuda's cdd. It is much faster than Qhull for these distributions.
Custom software for 2-d and 3-d convex hulls may be faster than Qhull. Custom software should use less memory. Qhull uses general-dimension data structures and code. The data structures support non-simplicial facets.
Qhull is not suitable for mesh generation or triangulation of arbitrary surfaces. You may use Qhull if the surface is convex or completely visible from an interior point (e.g., a star-shaped polyhedron). First, project each site to a sphere that is centered at the interior point. Then, compute the convex hull of the projected sites. The facets of the convex hull correspond to a triangulation of the surface. For mesh generation of arbitrary surfaces, see Schneiders' Finite Element Mesh Generation.
Qhull is not suitable for constrained Delaunay triangulations. With a lot of work, you can write a program that uses Qhull to add constraints by adding additional points to the triangulation.
Qhull is not suitable for the subdivision of arbitrary objects. Use qdelaunay to subdivide a convex object.
»definition
The convex hull of a point set P is the smallest convex set that contains P. If P is finite, the convex hull defines a matrix A and a vector b such that for all x in P, Ax+b <= [0,...].
Qhull computes the convex hull in 2-d, 3-d, 4-d, and higher dimensions. Qhull represents a convex hull as a list of facets. Each facet has a set of vertices, a set of neighboring facets, and a halfspace. A halfspace is defined by a unit normal and an offset (i.e., a row of A and an element of b).
Qhull accounts for round-off error. It returns "thick" facets defined by two parallel hyperplanes. The outer planes contain all input points. The inner planes exclude all output vertices. See Imprecise convex hulls.
Qhull may be used for the Delaunay triangulation or the Voronoi diagram of a set of points. It may be used for the intersection of halfspaces.
»input format
The input data on stdin consists of:
- first line contains the dimension
- second line contains the number of input points
- remaining lines contain point coordinates
For example:
3 #sample 3-d input 5 0.4 -0.5 1.0 1000 -1e-5 -100 0.3 0.2 0.1 1.0 1.0 1.0 0 0 0Input may be entered by hand. End the input with a control-D (^D) character.
To input data from a file, use I/O redirection or 'TI file'. The filename may not include spaces or quotes.
A comment starts with a non-numeric character and continues to the end of line. The first comment is reported in summaries and statistics. With multiple qhull commands, use option 'FQ' to place a comment in the output.
The dimension and number of points can be reversed. Comments and line breaks are ignored. Error reporting is better if there is one point per line.
»option format
Use options to specify the output formats and control Qhull. The qhull program takes all options. The other programs use a subset of the options. They disallow experimental and inappropriate options.
- qconvex == qhull
- qdelaunay == qhull d Qbb
- qhalf == qhull H
- qvoronoi == qhull v Qbb
Single letters are used for output formats and precision constants. The other options are grouped into menus for formats ('F'), Geomview ('G'), printing ('P'), Qhull control ('Q'), and tracing ('T'). The menu options may be listed together (e.g., 'GrD3' for 'Gr' and 'GD3'). Options may be in any order. Capitalized options take a numeric argument (except for 'PG' and 'F' options). Use option 'FO' to print the selected options.
Qhull uses zero-relative indexing. If there are n points, the index of the first point is 0 and the index of the last point is n-1.
The default options are:
Except for bounding box ('Qbk:n', etc.), drop facets ('Pdk:n', etc.), and Qhull command ('FQ'), only the last occurence of an option counts. Bounding box and drop facets may be repeated for each dimension. Option 'FQ' may be repeated any number of times.
The Unix tcsh and ksh shells make it easy to try out different options. In Windows 95, use a command window with doskey and a window scroller (e.g., peruse).
»output format
To write the results to a file, use I/O redirection or 'TO file'. Windows 95 users should use 'TO file' or the console. If a filename is surrounded by single quotes, it may include spaces.
The default output option is a short summary ('s') to stdout. There are many others (see output and formats). You can list vertex incidences, vertices and facets, vertex coordinates, or facet normals. You can view Qhull objects with Geomview, Mathematica, or Maple. You can print the internal data structures. You can call Qhull from your application (see Qhull library).
For example, 'qhull o' lists the vertices and facets of the convex hull.
Error messages and additional summaries ('s') go to stderr. Unless redirected, stderr is the console.
»algorithm
Qhull implements the Quickhull algorithm for convex hull [Barber et al. '96]. This algorithm combines the 2-d Quickhull algorithm with the n-d beneath-beyond algorithm [c.f., Preparata & Shamos '85]. It is similar to the randomized algorithms of Clarkson and others [Clarkson & Shor '89; Clarkson et al. '93; Mulmuley '94]. For a demonstration, see How Qhull adds a point. The main advantages of Quickhull are output sensitive performance (in terms of the number of extreme points), reduced space requirements, and floating-point error handling.
»data structures
Qhull produces the following data structures for dimension d:
- A coordinate is a real number in floating point format.
- A point is an array of d coordinates. With option 'QJ', the coordinates are joggled by a small amount.
- A vertex is an input point.
- A hyperplane is d normal coefficients and an offset. The length of the normal is one. The hyperplane defines a halfspace. If V is a normal, b is an offset, and x is a point inside the convex hull, then Vx+b <0.
- An outer plane is a positive offset from a hyperplane. When Qhull is done, all points will be below all outer planes.
- An inner plane is a negative offset from a hyperplane. When Qhull is done, all vertices will be above the corresponding inner planes.
- An orientation is either 'top' or 'bottom'. It is the topological equivalent of a hyperplane's geometric orientation.
- A simplicial facet is a set of d neighboring facets, a set of d vertices, a hyperplane equation, an inner plane, an outer plane, and an orientation. For example in 3-d, a simplicial facet is a triangle.
- A centrum is a point on a facet's hyperplane. A centrum is the average of a facet's vertices. Neighboring facets are convex if each centrum is below the neighbor facet's hyperplane.
- A ridge is a set of d-1 vertices, two neighboring facets, and an orientation. For example in 3-d, a ridge is a line segment.
- A non-simplicial facet is a set of ridges, a hyperplane equation, a centrum, an outer plane, and an inner plane. The ridges determine a set of neighboring facets, a set of vertices, and an orientation. Qhull produces a non-simplicial facet when it merges two facets together. For example, a cube has six non-simplicial facets.
For examples, use option 'f'. See polyhedron operations (local) for further design documentation.
»Imprecision in Qhull
»Examples of Qhull
See Examples of Qhull. Most of these examples require Geomview. Some of the examples have pictures .
See Qhull options.
See Qhull code.
Geomview is an interactive geometry viewing program. Geomview provides a good visualization of Qhull's 2-d and 3-d results.
Qhull includes Examples of Qhull that may be viewed with Geomview.
Geomview can help visulalize a 3-d Delaunay triangulation or the surface of a 4-d convex hull, Use option 'QVn' to select the 3-D facets adjacent to a vertex.
You may use Geomview to create movies that animate your objects (c.f., How can I create a video animation?). Geomview helped create the mathematical videos "Not Knot", "Outside In", and "The Shape of Space" from the Geometry Center.
»Installing Geomview
Geomview is an open source project under SourceForge.
For build instructions see Downloading Geomview. Geomview builds under Linux, Unix, Macintosh OS X, and Windows.
Geomview has installable packages for Debian and Ubuntu. The OS X build needs Xcode, an X11 SDK, and Lesstif or Motif. The Windows build uses Cygwin (see Building Geomview below for instructions).
If using Xforms (e.g., for Geomview's External Modules), install the 'libXpm-devel' package from cygwin and move the xforms directory into your geomview directory, e.g.,
mv xforms-1.2.4 geomview-1.9.5/xformsGeomview's ndview provides multiple views into 4-d and higher objects. This module is out-of-date (geomview-users: 4dview). Download NDview-sgi.tar.Z at newpieces and 4dview at Geomview/modules.
»Using Geomview
Use Geomview to view Examples of Qhull. You can spin the convex hull, fly a camera through its facets, and see how Qhull produces thick facets in response to round-off error.
Follow these instructions to view 'eg,01.cube' from Examples of Qhull
- Launch an XTerm command shell
- If needed, start the X terminal server, Use 'xinit' or 'startx' in /usr/X11R6/bin
xinit -- -multiwindow -clipboard
startx- Start an XTerm command shell. In Windows, click the Cygwin/bash icon on your desktop.
- Set the DISPLAY variable, e.g.,
export DISPLAY=:0
export DISPLAY=:0 >>~/.bashenv- Use Qhull's Geomview options to create a geomview object
- rbox c D3 | qconvex G >eg.01.cube
- On windows, convert the output to Unix text format with 'd2u'
rbox c D3 | qconvex G | d2u >eg.01.cube
d2u eg.*- Run Geomview
- Start Geomview with your example
./geomview eg.01.cube- Follow the instructions in Gemoview Tutorial
- Geomview creates the Geomview control panel with Targets and External Module, the Geomview toolbar with buttons for controlling Geomview, and the Geomview camera window showing a cube.
- Clear the camera window by selecting your object in the Targets list and 'Edit > Delete' or 'dd'
- Load the Geomview files panel. Select 'Open' in the 'File' menu.
- Set 'Filter' in the files panel to your example directory followed by '/*' (e.g., '/usr/local/qhull-2015.2/eg/*')
- Click 'Filter' in the files panel to view your examples in the 'Files' list.
- Load another example into the camera window by selecting it and clicking 'OK'.
- Review the instructions for Interacting with Geomview
- When viewing multiple objects at once, you may want to turn off normalization. In the 'Inspect > Apperance' control panel, set 'Normalize' to 'None'.
Geomview defines GCL (a textual API for controlling Geomview) and OOGL (a textual file format for defining objects).
- To control Geomview, you may use any program that reads and writes from stdin and stdout. For example, it could report Qhull's information about a vertex identified by a double-click 'pick' event.
- GCL command language for controlling Geomview
- OOGL file format for defining objects (tutorial).
- External Modules for interacting with Geomview via GCL
- Interact with your objects via pick commands in response to right-mouse double clicks. Enable pick events with the interest command.
»Building Geomview for Windows
Compile Geomview under Cygwin. For detailed instructions, see Building Savi and Geomview under Windows. These instructions are somewhat out-of-date. Updated instructions follow.
How to compile Geomview under 32-bit Cygwin (October 2015)
- Note: L. Wood has run into multiple issues with Geomview on Cygwin. He recommends Virtualbox/Ubuntu and a one-click install of geomview via the Ubuntu package. See his Savi/Geomview link above.
- Install 32-bit Cygwin as follows. For additional guidance, see Cygwin's Installing and Updating Cygwin Packages and Setup cygwin.
- Launch the cygwin installer.
- Select a mirror from Cygwin mirrors (e.g., http://mirrors.kernel.org/sourceware/cygwin/ in California).
- Select the packages to install. Besides the cygwin packages listed in the Savi/Windows instructions consider adding
- Default -- libXm-devel (required for /usr/include/Xm/Xm.h)
- Devel -- bashdb, gcc-core (in place of gcc), gdb
- Lib -- libGL-devel, libGLU1 (required, obsolete), libGLU-devel (required, obsolete), libjpeg-devel(XForms), libXext-devel (required), libXpm-devel (Xforms) libGL and lib
- Math -- bc
- Net -- autossh, inetutils, openssh
- System -- chere
- Utils -- dos2unix (required for qhull), keychain
- If installing perl, ActiveState Perl may be a better choice than cygwin's perl. Perl is not used by Geomview or Qhull.
- Cygwin Package Search -- Search for cygwin programs and packages
- Click 'Next' to download and install the packages.
- If the download is incomplete, try again.
- If you try again after a successful install, cygwin will uninstall and reinstall all modules..
- Click on the 'Cywin Terminal' icon on the Desktop. It sets up a user directory in /home from /etc/skel/...
- Mount your disk drives
mount c: /c # Ignore the warning /c does not exist- Consider installing the Road Bash scripts (/etc/road-*) from Road. They define aliases and functions for Unix command shells (Unix, Linux, Mac OS X, Windows),
- Download Road Bash and unzip the downloaded file
- Copy .../bash/etc/road-* to the Cywin /etc directory (by default, C:\cygwin\etc).
- Using the cygwin terminal, convert the road scripts to Unix format
d2u /etc/road-*- Try it
source /etc/road-home.bashrc- Install it
cp /etc/road-home.bashrc ~/.bashrc- Launch the X terminal server from 'Start > All programs > Cygwin-X > Xwin Server'. Alternatively, run 'startx'
- Launch an XTerm shell
- Right click the Cywin icon on the system tray in the Windows taskbar.
- Select 'System Tools > XTerm'
- Download and extract Geomview -- Downloading Geomview
- Compile Geomview
- ./configure
- make
- If './configure' fails, check 'config.log' at the failing step. Look carefully for missing libraries, etc. The Geomview FAQ contains suggestions (e.g., "configure claims it can't find OpenGl").
- If 'make' fails, read the output carefully for error messages. Usually it is a missing include file or package. Locate and install the missing cygwin packages (Cygwin Package Search).
»What to do if something goes wrong
Please report bugs to qhull_bug@qhull.org. Please report if Qhull crashes. Please report if Qhull generates an "internal error". Please report if Qhull produces a poor approximate hull in 2-d, 3-d or 4-d. Please report documentation errors. Please report missing or incorrect links.
If you do not understand something, try a small example. The rbox program is an easy way to generate test cases. The Geomview program helps to visualize the output from Qhull.
If Qhull does not compile, it is due to an incompatibility between your system and ours. The first thing to check is that your compiler is ANSI standard. Qhull produces a compiler error if __STDC__ is not defined. You may need to set a flag (e.g., '-A' or '-ansi').
If Qhull compiles but crashes on the test case (rbox D4), there's still incompatibility between your system and ours. Sometimes it is due to memory management. This can be turned off with qh_NOmem in mem.h. Please let us know if you figure out how to fix these problems.
If you doubt the output from Qhull, add option 'Tv'. It checks that every point is inside the outer planes of the convex hull. It checks that every facet is convex with its neighbors. It checks the topology of the convex hull.
Qhull resolves most precision issues. It reports a precision error for lower dimensional inputs. It may report a precision error for non-simplicial facets with multiple merges or nearly adjacent vertices. See Limitations of merged facets for more information.
Qhull reports precision errors if you turn off merged facets with option 'Q0'. This can get as bad as facets with flipped orientation or two facets with the same vertices. You'll get a long help message if you run into such a case. They are easy to generate with rbox.
If you do find a problem, try to simplify it before reporting the error. Try different size inputs to locate the smallest one that causes an error. You're welcome to hunt through the code using the execution trace ('T4') as a guide. This is especially true if you're incorporating Qhull into your own program.
When you report an error, please attach a data set to the end of your message. Include the options that you used with Qhull, the results of option 'FO', and any messages generated by Qhull. This allows me to see the error for myself. Qhull is maintained part-time.
Please send correspondence to Brad Barber at qhull@qhull.org and report bugs to qhull_bug@qhull.org . Let me know how you use Qhull. If you mention it in a paper, please send a reference and abstract.
If you would like to get Qhull announcements (e.g., a new version) and news (any bugs that get fixed, etc.), let us know and we will add you to our mailing list. For Internet news about geometric algorithms and convex hulls, look at comp.graphics.algorithms and sci.math.num-analysis. For Qhull news look at qhull-news.html.
»Authors
C. Bradford Barber Hannu Huhdanpaa bradb@shore.net hannu@qhull.org»Acknowledgments
A special thanks to David Dobkin for his guidance. A special thanks to Albert Marden, Victor Milenkovic, the Geometry Center, and Harvard University for supporting this work.
A special thanks to Mark Phillips, Robert Miner, and Stuart Levy for running the Geometry Center web site long after the Geometry Center closed. Stuart moved the web site to the University of Illinois at Champaign-Urbana. Mark and Robert are founders of Geometry Technologies. Mark, Stuart, and Tamara Munzner are the original authors of Geomview.
A special thanks to Endocardial Solutions, Inc. of St. Paul, Minnesota for their support of the code documentation (src/libqhull_r/index.htm, local). They use Qhull to build 3-d models of heart chambers.
Qhull 1.0 and 2.0 were developed under National Science Foundation grants NSF/DMS-8920161 and NSF-CCR-91-15793 750-7504. If you find it useful, please let us know.
The Geometry Center was supported by grant DMS-8920161 from the National Science Foundation, by grant DOE/DE-FG02-92ER25137 from the Department of Energy, by the University of Minnesota, and by Minnesota Technology, Inc.
»References
Aurenhammer, F., "Voronoi diagrams -- A survey of a fundamental geometric data structure," ACM Computing Surveys, 1991, 23:345-405.
Barber, C. B., D.P. Dobkin, and H.T. Huhdanpaa, "The Quickhull Algorithm for Convex Hulls," ACM Transactions on Mathematical Software, 22(4):469-483, Dec 1996, www.qhull.org [http://portal.acm.org; http://citeseerx.ist.psu.edu].
Clarkson, K.L. and P.W. Shor, "Applications of random sampling in computational geometry, II", Discrete Computational Geometry, 4:387-421, 1989
Clarkson, K.L., K. Mehlhorn, and R. Seidel, "Four results on randomized incremental construction," Computational Geometry: Theory and Applications, vol. 3, p. 185-211, 1993.
Devillers, et. al., "Walking in a triangulation," ACM Symposium on Computational Geometry, June 3-5,2001, Medford MA.
Dobkin, D.P. and D.G. Kirkpatrick, "Determining the separation of preprocessed polyhedra--a unified approach," in Proc. 17th Inter. Colloq. Automata Lang. Program., in Lecture Notes in Computer Science, Springer-Verlag, 443:400-413, 1990.
Edelsbrunner, H, Geometry and Topology for Mesh Generation, Cambridge University Press, 2001.
Gartner, B., "Fast and robust smallest enclosing balls", Algorithms - ESA '99, LNCS 1643.
Golub, G.H. and van Loan, C.F., Matric Computations, Baltimore, Maryland, USA: John Hopkins Press, 1983
Fortune, S., "Computational geometry," in R. Martin, editor, Directions in Geometric Computation, Information Geometers, 47 Stockers Avenue, Winchester, SO22 5LB, UK, ISBN 1-874728-02-X, 1993.
Milenkovic, V., "Robust polygon modeling," Computer-Aided Design, vol. 25, p. 546-566, September 1993.
Mucke, E.P., I. Saias, B. Zhu, Fast randomized point location without preprocessing in Two- and Three-dimensional Delaunay Triangulations, ACM Symposium on Computational Geometry, p. 274-283, 1996 [GeomDir].
Mulmuley, K., Computational Geometry, An Introduction Through Randomized Algorithms, Prentice-Hall, NJ, 1994.
O'Rourke, J., Computational Geometry in C, Cambridge University Press, 1994.
Preparata, F. and M. Shamos, Computational Geometry, Springer-Verlag, New York, 1985.
Up: Home page for Qhull (local)
Up:News about Qhull
Up: Qhull Wiki and FAQ (local)
To: Qhull manual: contents
To: Programs Options Output Formats Geomview Print Qhull Precision Trace Functions (local)
Dn: Imprecision in Qhull
Dn: Description of Qhull examples
Dn: Qhull code
Comments to: qhull@qhull.org
Created: Sept. 25, 1995 --- Last modified: see top