Matplot3D for Java: A Pure Java 3D Scientific Visualization Library

Matplot3D for Java is a lightweight, pure Java library for rendering three-dimensional scientific and mathematical visualizations. Designed to offer functionality similar to Python’s Matplotlib in a Java environment, it enables developers to generate interactive or static 3D plots without relying on external graphics libraries such as OpenGL, JavaFX, or Java 3D. The entire implementation depends only on standard JRE classes, packaged into a ~300 KB JAR file.

The API emphasizes simplicity and rapid integration into existing Java GUI applications or headless server environments where image generation for web use is required. It supports a wide range of plot types including surface meshes, vector field streamlines, scatter plots, bar charts, geometric primitives, waterfall plots, and contour-enhanced surfaces.

Key features of version 5.0 include:

  • Improved rendering performance through optimized internal algorithms
  • Refactored APIs for processors and animation control
  • New visual effects like emissive lighting
  • Introduction of GridMeshProcessor for parametric surface rendering
  • Addition of VectorFieldProcessor for 3D streamline visualization
  • Inclusion of Simple3DElementProcessor for basic shapes (spheres, cylinders, cones, cuboids)
  • Deprecation of FunctionProcessor, with its capabilities merged into DataGridProcessor

Below are representative code examples demonstrating core functionalities.

Möbius Strip via Parametric Mapping

public class MobiusStripDemo {
    public static void main(String[] args) {
        var processor = new GridMeshProcessor();
        var plotManager = new Matplot3D4JMgr(processor);

        GridMeshMapper mapper = (u, v) -> {
            double theta = u;
            double width = v;
            double baseRadius = 12;
            double radius = 3.6 * Math.cos(1.5 * theta) + baseRadius;
            double twist = 1.75 * theta;

            double x = (radius + width * Math.cos(twist)) * Math.cos(theta);
            double y = (radius + width * Math.cos(twist)) * Math.sin(theta);
            double z = width * Math.sin(twist) + 3.6 * Math.sin(1.5 * theta);

            return new Point3D(x, y, z);
        };

        double[] thetaVals = FunctionSpaceUtil.lineSpace(0, 4 * Math.PI, 300);
        double[] widthVals = FunctionSpaceUtil.lineSpace(-3.1, 3.1, 5);

        processor.addData(mapper, thetaVals, widthVals, "mobius",
            new TopBottomColorStyle(ColorStyle.DEFAULT_COLORS_REVERSE_ARRAY), 1.0f);

        plotManager.setCoordianteSysShowType(Matplot3D4JMgr.COORDINATE_SYS_ALWAYS_FURTHER);
        plotManager.setTitle("Möbius Strip");
        plotManager.show();
    }
}

Vector Field Streamlines

public class SimpleVectorFieldDemo {
    public static void main(String[] args) {
        var processor = new VectorFieldProcessor();
        var plot = new Matplot3D4JMgr(processor);

        var upperFlow = new Point3dVector3dMapper() {
            public Vector3D f(Point3D p) {
                return p.y() > 0 ? new Vector3D(1, 0, 0) : Vector3D.ZERO;
            }
            public void setAdditionalPrar(Object ignored) {}
        };

        var lowerFlow = new Point3dVector3dMapper() {
            public Vector3D f(Point3D p) {
                return p.y() < 0 ? new Vector3D(-0.1, 0, 0) : Vector3D.ZERO;
            }
            public void setAdditionalPrar(Object ignored) {}
        };

        processor.addData(upperFlow, "upper", Color.RED, new Range(-9, 9), new Range(-9, 9), new Range(-9, 9));
        processor.addData(lowerFlow, "lower", Color.BLUE, new Range(-9, 9), new Range(-9, 9), new Range(-9, 9));

        var seeds = new ArrayList<Point3D>();
        for (double z = -9; z <= 9; z += 1.2) {
            for (double y = -9; y <= 9; y += 1.2) {
                seeds.add(new Point3D(0, y, z));
            }
        }

        processor.setPropertyToAll("seeds", seeds);
        processor.setPropertyToAll("alphaNoise", 0.0);

        plot.setTitle("3D Vector Field Streamlines");
        plot.setAppearanceTheme(Matplot3D4JMgr.APPEARANCE_THEME_DARK);
        plot.showMotion(-1, 15, 0);
    }
}

Function-Based Surface Plot

public class FunctionSurfaceDemo {
    public static void main(String[] args) {
        var processor = new DataGridProcessor();
        var mgr = new Matplot3D4JMgr(processor);

        Function func = (x, y) -> Math.sin(x * y / 2.2) * 0.8;
        double pi = Math.PI;
        Range xRange = new Range(-1.5 * pi, 1.5 * pi);
        Range yRange = new Range(-1.5 * pi, 1.5 * pi);

        var dataGrid = FunctionSpaceUtil.getDataByFunction(func, xRange, yRange, 200, 300);
        processor.addData(dataGrid, "", xRange, yRange, new TopBottomColorStyle(), 1.0f);

        processor.setPropertyToAll("isDoubleSide", true);
        processor.setPropertyToAll("isShowGrid", false);

        mgr.setScaleX(1.3);
        mgr.setScaleY(1.3);
        mgr.setScaleZ(1.5);
        mgr.setTitle("z = 0.8 · sin(x·y / 2.2)");
        mgr.setCoordianteSysShowType(Matplot3D4JMgr.COORDINATE_SYS_ALWAYS_FURTHER);
        mgr.show();
    }
}

Contour-Enhanced Terrain Map

public class ContourDataGridDemo {
    public static void main(String[] args) {
        var processor = new ContourDataGridProcessor();
        var mgr = new Matplot3D4JMgr(processor);

        Double[][] elevation = new Double[100][100];
        for (int i = 0; i < 100; i++) {
            for (int j = 0; j < 100; j++) {
                elevation[i][j] = -0.1 * Math.pow(100 - i - j, 2) + 1000;
            }
        }

        Double[][] temperature = new Double[50][50];
        for (int i = 0; i < 50; i++) {
            for (int j = 0; j < 50; j++) {
                temperature[i][j] = Math.sqrt(Math.pow(i - 25, 2) + Math.pow(j - 25, 2));
            }
        }

        processor.addData(elevation, temperature, Color.GRAY, "terrain",
            new Range(0, 100), new Range(100, 200), 20, 20, 1.0f);
        processor.setClose3DObject(true);

        mgr.setScaleX(5);
        mgr.setScaleY(5);
        mgr.setScaleZ(0.2);
        mgr.setTitle("Contour Surface Example");
        mgr.setCoordianteSysShowType(Matplot3D4JMgr.COORDINATE_SYS_ALWAYS_FURTHER);
        mgr.show();
    }
}

3D Scatter Plot

public class ScatterDemo {
    public static void main(String[] args) {
        var processor = new ScatterDataProcessor();
        var mgr = new Matplot3D4JMgr(processor);

        var rand = new Random();
        var group1 = new ArrayList<Point3D>();
        var group2 = new ArrayList<Point3D>();
        var group3 = new ArrayList<Point3D>();

        for (int i = 0; i < 100; i++) {
            group1.add(new Point3D(rand.nextDouble() + 1, rand.nextDouble(), rand.nextDouble() + 1));
            group2.add(new Point3D(rand.nextDouble() + 1, rand.nextDouble() + 1, rand.nextDouble()));
            group3.add(new Point3D(rand.nextDouble(), rand.nextDouble() + 1, rand.nextDouble()));
        }

        processor.addData("Group A", group1);
        processor.addData("Group B", group2);
        processor.addData("Group C", group3);
        processor.setPropertyToAll("isShowEdge", true);

        mgr.setTitle("3D Scatter Plot");
        mgr.setCoordianteSysShowType(Matplot3D4JMgr.COORDINATE_SYS_ALWAYS_FURTHER);
        mgr.show();
    }
}

Basic 3D Primitives

public class SimpleElementsDemo {
    public static void main(String[] args) {
        var processor = new Simple3DElementProcessor();
        var mgr = new Matplot3D4JMgr(processor);

        processor.addSphere(new Point3D(-1.5, 1.5, 0), 1, 39, 20, Color.YELLOW);
        processor.addCuboid(new Point3D(1.5, 1.5, 0), 1.3, 1.5, 1.7, Color.GREEN);
        processor.addCone(new Point3D(-1.5, -1.5, -0.9), new Point3D(-1.5, -1.5, 1.0), 1, 30, Color.RED);
        processor.addCylinder(new Point3D(1.5, -1.5, -0.9), new Point3D(1.5, -1.5, 1.0), 1, 30, Color.BLUE);

        mgr.setTitle("Basic 3D Shapes");
        mgr.setCoordianteSysShowType(Matplot3D4JMgr.COORDINATE_SYS_ALWAYS_FURTHER);
        mgr.show();
    }
}

Waterfall and Bar Charts

The library also supports specialized chart types like waterfall plots (for sequential 2D profiles in 3D space) and grouped 3D bar charts with customizable colors and spacing, enabling clear comparison across categories and series.

All examples run on Java 8+ (64-bit), with best performance on modern LTS versions like Java 17 or 21. The core dependency is a single JAR (Matplot3d_4j_sydh_x64_V5.0.jar), while a separate demo JAR provides runnable visual examples.

Tags: java 3D Visualization Scientific Computing Data Visualization Matplot3D

Posted on Thu, 25 Jun 2026 16:16:19 +0000 by osiris1603