clean doc and tutorial code

This commit is contained in:
Martin Pernollet 2021-01-23 17:33:49 +01:00
parent 2779241744
commit 150ee55b84
14 changed files with 294 additions and 144 deletions

163
README.md
View File

@ -1,7 +1,11 @@
jzy3d-api
Jzy3d
=========
Jzy3d is a framework for easily drawing 3d and 2d charts in Java, using either fast native GPU rendering or CPU based rendering. The framework targets simplicity and portability (AWT, SWT, NEWT, Swing, GPU/CPU, etc).
Jzy3d is a framework for easily drawing 3d and 2d charts in Java, using either fast native GPU rendering or CPU based rendering to enhance portability across combination of OS/JVM/GPU.
The framework targets simplicity and portability (AWT, SWT, NEWT, Swing, JavaFX, Offscreen rendering using either GPU or CPU), running on MacOS, Windows and Linux. Jzy3d available for other languages/platforms such as [Scala, Groovy, Matlab](http://jzy3d.org/community.php), [C#](https://github.com/jzy3d/nzy3d-api), and even [Python](https://github.com/jzy3d/pyzy3d) through a bridge allowing either Py4j or Jython.
The API can be used [freely in commercial applications](license.txt). You can explore the [tutorials](jzy3d-tutorials). an then purchase the [extended developper guide](http://jzy3d.org/guide.php) to support the development effort.
# How to use
@ -25,39 +29,18 @@ Refer to the [tutorial README](jzy3d-tutorials/README.md) file to get help on cr
</tr>
</table>
As this library focuses on portability of the charts, the Surface tutorial package demonstrates the same chart running on AWT, SWT, Swing using native OpenGL powered by JOGL. In addition, `SurfaceDemoEmulGL` shows how to use CPU based rendering as a fallback, which only vary to the native demo by using a dedicated `EmulGLPainterFactory` :
As this library focuses on portability of the charts, the `org.jzy3d.demos.surface` package in [jzy3d-tutorials](jzy3d-tutorials) demonstrates the same chart running on AWT, SWT, Swing using native OpenGL powered by JOGL and jGL CPU rendering.
```java
public class SurfaceDemoEmulGL {
public static void main(String[] args) {
Shape surface = surface();
EmulGLChartFactory factory = new EmulGLChartFactory();
Quality q = Quality.Advanced;
Chart chart = factory.newChart(q);
chart.add(surface);
chart.open();
// --------------------------------
// Controllers
CameraThreadController rotation = new CameraThreadController(chart);
rotation.setStep(0.025f);
rotation.setUpdateViewDefault(true);
AWTCameraMouseController mouse = (AWTCameraMouseController) chart.addMouseCameraController();
mouse.addSlaveThreadController(rotation);
rotation.setUpdateViewDefault(true);
mouse.setUpdateViewDefault(false);
chart.setAnimated(true);
public class SurfaceDemoAWT extends AWTAbstractAnalysis {
public static void main(String[] args) throws Exception {
SurfaceDemoAWT d = new SurfaceDemoAWT();
AnalysisLauncher.open(d);
}
private static Shape surface() {
SurfaceBuilder builder = new SurfaceBuilder();
@Override
public void init() {
// Define a function to plot
Mapper mapper = new Mapper() {
@Override
public double f(double x, double y) {
@ -65,32 +48,95 @@ public class SurfaceDemoEmulGL {
}
};
// Define range and precision for the function to plot
Range range = new Range(-3, 3);
int steps = 50;
int steps = 80;
Shape surface = builder.orthonormal(new OrthonormalGrid(range, steps, range, steps), mapper);
ColorMapper colorMapper =
new ColorMapper(new ColorMapRainbow(), surface, new Color(1, 1, 1, 0.65f));
surface.setColorMapper(colorMapper);
// Create the object to represent the function over the given range.
final Shape surface = new SurfaceBuilder().orthonormal(new OrthonormalGrid(range, steps), mapper);
surface.setColorMapper(new ColorMapper(new ColorMapRainbow(), surface, new Color(1, 1, 1, .5f)));
surface.setFaceDisplayed(true);
surface.setWireframeDisplayed(true);
surface.setWireframeColor(Color.BLACK);
surface.setWireframeWidth(1);
return surface;
// Create a chart
GLCapabilities c = new GLCapabilities(GLProfile.get(GLProfile.GL2));
IPainterFactory p = new AWTPainterFactory(c);
IChartFactory f = new AWTChartFactory(p);
chart = f.newChart(Quality.Advanced);
chart.getScene().getGraph().add(surface);
}
}
```
# Architecture
# What's inside
## Features
Multiple chart types
* Surface charts
* Bar charts
* Scatter charts
* Volume charts
* 3D and 2D graphs charts
* Rich chart options
* Many primitives (spheres, triangles, polygons, ...)
Flexible layout
* Colorbars
* Colormappers for coloring objects
* Axis box layout with detailed tick definition and tick rendering tools
* Contour functions
* Tooltips
* Background images
* 2D post renderers
* Lights
Algorithms
* Grid based and Delaunay surface tesselation methods
* 3d line strip interpolation to smooth pathes (Bernstein 3d)
* 2d envelopes (Convex hulls)
* Polygon ordering for improved transparency rendering
* Dual depth peeling: scene graph order independent transparency (expected for 1.0)
* Matlab-like array processors and statistics tools
* Experimental Support Vector Machine integration (Svm3d)
Interactions
* Mouse interaction with objects (selection & picking methods)
* Mouse interaction with chart (rotation, zoom, scale)
* Key interaction with chart (rotation, zoom, scale)
* Thread Controllers
* Animation of objects' structures (surface, series of lines, etc)
High and low level OpenGL programming
* Hide complexity and provide out of the box solutions for common low level OpenGL tasks
* Fully cutomizable framework with access to all OpenGL native features through JOGL
Cross platforms and compatible
* Straightforward integration to either AWT, Swing, Eclipse RCP (SWT), or JavaFX
* Windows, Unix, and MacOS. Android supposed to work if enable appropriate JOGL jars
* Offscreen rendering
* Multiple file formats (Ply, Obj, Matlab, CSV)
* [C#](https://github.com/jzy3d/nzy3d-api) port
* [Python](https://github.com/jzy3d/pyzy3d) binding
* [Scala](https://github.com/jzy3d/jzy3d-sbt) example
* [Matlab](https://fr.mathworks.com/matlabcentral/fileexchange/35026-opengl-3d-graphics-in-matlab-using-jzy3d-a-demo) integration
Extensions
* <a href="https://github.com/jzy3d/jzy3d-graphs">jzy3d-graph</a> : 3d graphs layout and rendering using Gephi toolkit
* <a href="https://github.com/jzy3d/jzy3d-spectro">jzy3d-spectro</a> : 3d spectrogram
* <a href="https://github.com/jzy3d/bigpicture">jzy3d-bigpicture</a> : drivers to few big data storage to draw massive amount of points
## Architecture
Creating a chart implies building and wiring the below high-level components.
<img src="doc/Components.png"/>
## Customize chart with factories
### Customize chart with factories
The ```IChartFactory``` builds all objects that will define how the chart will look (```Axis```, ```View```, ```Camera```, ```Chart```).
@ -112,6 +158,19 @@ Jzy3d depends on the following libraries that are available on [Jzy3d Maven repo
* [jPLY](https://github.com/jzy3d/jPLY) supports the PLY format for loading 3d objects
* [vecmath](https://github.com/jzy3d/vecmath) is a clone of a former java package
# How to build
```
mvn install
```
# How to get help
* Google [Discussion group](https://groups.google.com/g/jzy3d?pli=1)
* Gitlab [Discussions](https://github.com/jzy3d/jzy3d-api/discussions)
* StackOverflow [Tag](https://stackoverflow.com/questions/tagged/jzy3d)
* If you are looking for professional services related to 3d rendering, contact [me](martin@jzy3d.org)
# Changes in 2.0 version
@ -154,26 +213,6 @@ SurfaceBuilder is not static anymore to be overridable.
## Deletions
# Extensions
Additional modules kept separated demonstrate side works on Jzy3d
- <a href="https://github.com/jzy3d/bigpicture">jzy3d-bigpicture</a> : drivers to few big data storage to draw massive amount of points
- <a href="https://github.com/jzy3d/jzy3d-graphs">jzy3d-graph</a> : 3d graphs layout and rendering using Gephi toolkit
- <a href="https://github.com/jzy3d/jzy3d-spectro">jzy3d-spectro</a> : 3d spectrogram
# Build
```
mvn install
```
# License
New BSD
# More information
http://www.jzy3d.org
<!--Travis build status : [![Build Status](https://travis-ci.org/jzy3d/jzy3d-api.svg?branch=master)](https://travis-ci.org/jzy3d/jzy3d-api)-->

View File

@ -116,7 +116,7 @@ See ```WaterfallDemo```
See ```LizardVolumeDemo```
<img src="doc/demo-volume.png"/>
<img src="doc/demo-volume-rotated.png"/>
# 2D Line charts

View File

@ -1,10 +1,7 @@
package org.jzy3d.demos.surface;
import java.io.IOException;
import org.jzy3d.analysis.AWTAbstractAnalysis;
import org.jzy3d.bridge.awt.FrameAWT;
import org.jzy3d.chart.Chart;
import org.jzy3d.analysis.AnalysisLauncher;
import org.jzy3d.chart.factories.AWTChartFactory;
import org.jzy3d.chart.factories.AWTPainterFactory;
import org.jzy3d.chart.factories.IChartFactory;
@ -18,7 +15,6 @@ import org.jzy3d.plot3d.builder.SurfaceBuilder;
import org.jzy3d.plot3d.builder.concrete.OrthonormalGrid;
import org.jzy3d.plot3d.primitives.Shape;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
@ -31,22 +27,9 @@ import com.jogamp.opengl.awt.GLCanvas;
public class SurfaceDemoAWT extends AWTAbstractAnalysis {
public static void main(String[] args) throws Exception {
SurfaceDemoAWT d = new SurfaceDemoAWT();
openAndPrintFrame(d);
// AnalysisLauncher.open(d);
AnalysisLauncher.open(d);
}
private static void openAndPrintFrame(SurfaceDemoAWT d) throws InterruptedException, IOException {
d.init();
Chart chart = d.getChart();
chart.addMouseCameraController();
FrameAWT f = (FrameAWT) chart.open();
// Thread.sleep(1000);
String file = "./target/" + d.getClass().getSimpleName() + ".png";
Frame.print(chart, f, file);
}
@Override
public void init() {
// Define a function to plot
@ -62,8 +45,7 @@ public class SurfaceDemoAWT extends AWTAbstractAnalysis {
int steps = 80;
// Create the object to represent the function over the given range.
final Shape surface =
new SurfaceBuilder().orthonormal(new OrthonormalGrid(range, steps, range, steps), mapper);
final Shape surface = new SurfaceBuilder().orthonormal(new OrthonormalGrid(range, steps), mapper);
surface.setColorMapper(new ColorMapper(new ColorMapRainbow(), surface, new Color(1, 1, 1, .5f)));
surface.setFaceDisplayed(true);
surface.setWireframeDisplayed(true);

View File

@ -46,8 +46,7 @@ public class SurfaceDemoAWTNewt extends AWTAbstractAnalysis {
int steps = 80;
// Create the object to represent the function over the given range.
final Shape surface =
new SurfaceBuilder().orthonormal(new OrthonormalGrid(range, steps, range, steps), mapper);
final Shape surface = new SurfaceBuilder().orthonormal(new OrthonormalGrid(range, steps), mapper);
surface.setColorMapper(new ColorMapper(new ColorMapRainbow(), surface, new Color(1, 1, 1, .5f)));
surface.setFaceDisplayed(true);
surface.setWireframeDisplayed(true);

View File

@ -79,11 +79,9 @@ public class SurfaceDemoEmulGL {
Range range = new Range(-3, 3);
int steps = 50;
Shape surface = builder.orthonormal(new OrthonormalGrid(range, steps, range, steps), mapper);
ColorMapper colorMapper =
new ColorMapper(new ColorMapRainbow(), surface, new Color(1, 1, 1, ALPHA_FACTOR));// 0.65f));
Shape surface = builder.orthonormal(new OrthonormalGrid(range, steps), mapper);
ColorMapper colorMapper = new ColorMapper(new ColorMapRainbow(), surface, new Color(1, 1, 1, ALPHA_FACTOR));// 0.65f));
surface.setColorMapper(colorMapper);
surface.setFaceDisplayed(true);
surface.setWireframeDisplayed(true);

View File

@ -20,10 +20,7 @@ public class SurfaceDemoFallback {
public static void main(String[] args) {
Shape surface = surface();
// -------------------------------
// Create a chart
Quality quality = Quality.Advanced;
FallbackChartFactory factory = new FallbackChartFactory();
Chart chart = factory.newChart(quality);
chart.getScene().getGraph().add(surface);
@ -44,7 +41,6 @@ public class SurfaceDemoFallback {
Range range = new Range(-3, 3);
int steps = 80;
Shape surface = Surface.shape(mapper, range, steps, new ColorMapRainbow(), .5f);
return surface;
return Surface.shape(mapper, range, steps, new ColorMapRainbow(), .5f);
}
}

View File

@ -1,11 +1,7 @@
package org.jzy3d.demos.surface;
import java.io.IOException;
import org.jzy3d.analysis.AbstractAnalysis;
import org.jzy3d.analysis.AnalysisLauncher;
import org.jzy3d.bridge.swing.FrameSwing;
import org.jzy3d.chart.Chart;
import org.jzy3d.chart.factories.SwingChartFactory;
import org.jzy3d.colors.Color;
import org.jzy3d.colors.ColorMapper;
@ -16,7 +12,6 @@ import org.jzy3d.plot3d.builder.SurfaceBuilder;
import org.jzy3d.plot3d.builder.concrete.OrthonormalGrid;
import org.jzy3d.plot3d.primitives.Shape;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import com.jogamp.opengl.awt.GLJPanel;
/**
@ -32,24 +27,8 @@ public class SurfaceDemoSwing extends AbstractAnalysis {
public static void main(String[] args) throws Exception {
SurfaceDemoSwing d = new SurfaceDemoSwing();
AnalysisLauncher.open(d);
// openAndPrintFrame(d);
}
private static void openAndPrintFrame(SurfaceDemoSwing d)
throws InterruptedException, IOException {
d.init();
Chart chart = d.getChart();
chart.addMouseCameraController();
FrameSwing frame = (FrameSwing) d.getChart().open();
Thread.sleep(1000); // wait for frame to be ready for printing
String file = "./target/" + d.getClass().getSimpleName() + ".png";
Frame.print(chart, frame, file);
}
@Override
public void init() {
// Define a function to plot
@ -65,8 +44,7 @@ public class SurfaceDemoSwing extends AbstractAnalysis {
int steps = 80;
// Create the object to represent the function over the given range.
final Shape surface =
new SurfaceBuilder().orthonormal(new OrthonormalGrid(range, steps, range, steps), mapper);
final Shape surface = new SurfaceBuilder().orthonormal(new OrthonormalGrid(range, steps), mapper);
surface.setColorMapper(new ColorMapper(new ColorMapRainbow(), surface, new Color(1, 1, 1, .5f)));
surface.setFaceDisplayed(true);
surface.setWireframeDisplayed(false);

View File

@ -1,4 +1,4 @@
package org.jzy3d.demos.surface;
package org.jzy3d.tests.emulgl;
import java.io.File;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package org.jzy3d.demos.surface;
package org.jzy3d.tests.frameCheck;
import java.awt.image.BufferedImage;
import java.io.File;

View File

@ -0,0 +1,80 @@
package org.jzy3d.tests.frameCheck;
import java.io.IOException;
import org.jzy3d.analysis.AWTAbstractAnalysis;
import org.jzy3d.bridge.awt.FrameAWT;
import org.jzy3d.chart.Chart;
import org.jzy3d.chart.factories.AWTChartFactory;
import org.jzy3d.chart.factories.AWTPainterFactory;
import org.jzy3d.chart.factories.IChartFactory;
import org.jzy3d.chart.factories.IPainterFactory;
import org.jzy3d.colors.Color;
import org.jzy3d.colors.ColorMapper;
import org.jzy3d.colors.colormaps.ColorMapRainbow;
import org.jzy3d.maths.Range;
import org.jzy3d.plot3d.builder.Mapper;
import org.jzy3d.plot3d.builder.SurfaceBuilder;
import org.jzy3d.plot3d.builder.concrete.OrthonormalGrid;
import org.jzy3d.plot3d.primitives.Shape;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.jzy3d.tests.frameCheck.Frame;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
/**
* Demo an AWT chart using JOGL {@link GLCanvas}.
*
* @author martin
*/
public class SurfaceDemoAWT extends AWTAbstractAnalysis {
public static void main(String[] args) throws Exception {
SurfaceDemoAWT d = new SurfaceDemoAWT();
openAndPrintFrame(d);
// AnalysisLauncher.open(d);
}
private static void openAndPrintFrame(SurfaceDemoAWT d) throws InterruptedException, IOException {
d.init();
Chart chart = d.getChart();
chart.addMouseCameraController();
FrameAWT f = (FrameAWT) chart.open();
// Thread.sleep(1000);
String file = "./target/" + d.getClass().getSimpleName() + ".png";
Frame.print(chart, f, file);
}
@Override
public void init() {
// Define a function to plot
Mapper mapper = new Mapper() {
@Override
public double f(double x, double y) {
return x * Math.sin(x * y);
}
};
// Define range and precision for the function to plot
Range range = new Range(-3, 3);
int steps = 80;
// Create the object to represent the function over the given range.
final Shape surface =
new SurfaceBuilder().orthonormal(new OrthonormalGrid(range, steps, range, steps), mapper);
surface.setColorMapper(new ColorMapper(new ColorMapRainbow(), surface, new Color(1, 1, 1, .5f)));
surface.setFaceDisplayed(true);
surface.setWireframeDisplayed(true);
surface.setWireframeColor(Color.BLACK);
// Create a chart
GLCapabilities c = new GLCapabilities(GLProfile.get(GLProfile.GL2));
IPainterFactory p = new AWTPainterFactory(c);
IChartFactory f = new AWTChartFactory(p);
chart = f.newChart(Quality.Advanced);
chart.getScene().getGraph().add(surface);
}
}

View File

@ -0,0 +1,78 @@
package org.jzy3d.tests.frameCheck;
import java.io.IOException;
import org.jzy3d.analysis.AbstractAnalysis;
import org.jzy3d.analysis.AnalysisLauncher;
import org.jzy3d.bridge.swing.FrameSwing;
import org.jzy3d.chart.Chart;
import org.jzy3d.chart.factories.SwingChartFactory;
import org.jzy3d.colors.Color;
import org.jzy3d.colors.ColorMapper;
import org.jzy3d.colors.colormaps.ColorMapRainbow;
import org.jzy3d.maths.Range;
import org.jzy3d.plot3d.builder.Mapper;
import org.jzy3d.plot3d.builder.SurfaceBuilder;
import org.jzy3d.plot3d.builder.concrete.OrthonormalGrid;
import org.jzy3d.plot3d.primitives.Shape;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.jzy3d.tests.frameCheck.Frame;
import com.jogamp.opengl.awt.GLJPanel;
/**
* Demo an Swing chart using JOGL {@link GLJPanel}.
*
* @author martin
*/
public class SurfaceDemoSwing extends AbstractAnalysis {
public SurfaceDemoSwing() {
super(new SwingChartFactory());
}
public static void main(String[] args) throws Exception {
SurfaceDemoSwing d = new SurfaceDemoSwing();
AnalysisLauncher.open(d);
// openAndPrintFrame(d);
}
private static void openAndPrintFrame(SurfaceDemoSwing d)
throws InterruptedException, IOException {
d.init();
Chart chart = d.getChart();
chart.addMouseCameraController();
FrameSwing frame = (FrameSwing) d.getChart().open();
Thread.sleep(1000); // wait for frame to be ready for printing
String file = "./target/" + d.getClass().getSimpleName() + ".png";
Frame.print(chart, frame, file);
}
@Override
public void init() {
// Define a function to plot
Mapper mapper = new Mapper() {
@Override
public double f(double x, double y) {
return x * Math.sin(x * y);
}
};
// Define range and precision for the function to plot
Range range = new Range(-3, 3);
int steps = 80;
// Create the object to represent the function over the given range.
final Shape surface =
new SurfaceBuilder().orthonormal(new OrthonormalGrid(range, steps, range, steps), mapper);
surface.setColorMapper(new ColorMapper(new ColorMapRainbow(), surface, new Color(1, 1, 1, .5f)));
surface.setFaceDisplayed(true);
surface.setWireframeDisplayed(false);
// Create a chart
chart = new SwingChartFactory().newChart(Quality.Advanced);
chart.add(surface);
}
}

View File

@ -1,4 +1,4 @@
package org.jzy3d.integration;
package org.jzy3d.tests.integration;
import java.util.Random;

View File

@ -1,4 +1,4 @@
package org.jzy3d.integration;
package org.jzy3d.tests.integration;
import org.junit.Test;
import org.jzy3d.chart.Chart;

View File

@ -1,31 +1,31 @@
Copyright (c) 2009-2014, Martin Pernollet and contributors
All rights reserved.
Copyright (c) Since 2009, Martin Pernollet and contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
with the distribution.
3. Neither the name of Martin Pernollet nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
3. Neither the name of Martin Pernollet nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.