{"id":20755571,"url":"https://github.com/hageldave/jplotter","last_synced_at":"2025-05-09T00:11:09.941Z","repository":{"id":37210427,"uuid":"184679288","full_name":"hageldave/JPlotter","owner":"hageldave","description":"OpenGL based 2D Plotting Library for Java using AWT and LWJGL","archived":false,"fork":false,"pushed_at":"2024-10-18T23:49:08.000Z","size":4736,"stargazers_count":46,"open_issues_count":8,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-31T19:44:10.517Z","etag":null,"topics":["awt-gui","bezier","contour","coordinatesystem","graphics","java","opengl","opengl3","plot","plots","quiver","scatter","svg","visualization"],"latest_commit_sha":null,"homepage":"https://github.com/hageldave/JPlotter/wiki","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hageldave.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-03T00:49:30.000Z","updated_at":"2025-01-27T21:35:45.000Z","dependencies_parsed_at":"2023-02-16T23:15:55.351Z","dependency_job_id":"2995ccdb-609f-4524-9a8e-55c31009a320","html_url":"https://github.com/hageldave/JPlotter","commit_stats":{"total_commits":916,"total_committers":10,"mean_commits":91.6,"dds":0.5556768558951966,"last_synced_commit":"b9f93161ef08861b7f4abee177f41d0c2b35de6c"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hageldave%2FJPlotter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hageldave%2FJPlotter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hageldave%2FJPlotter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hageldave%2FJPlotter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hageldave","download_url":"https://codeload.github.com/hageldave/JPlotter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253166521,"owners_count":21864482,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["awt-gui","bezier","contour","coordinatesystem","graphics","java","opengl","opengl3","plot","plots","quiver","scatter","svg","visualization"],"created_at":"2024-11-17T09:26:16.052Z","updated_at":"2025-05-09T00:11:09.917Z","avatar_url":"https://github.com/hageldave.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JPlotter\nOpenGL based 2D Plotting Library for Java using AWT/Swing and [LWJGL](https://github.com/LWJGL/lwjgl3) through [lwjgl3-awt](https://github.com/LWJGLX/lwjgl3-awt). \nAn AWT [Graphics2D](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Graphics2D.html) fallback solution was introduced to support systems lacking OpenGL-3.3 as well as MacOS. \n\n[![Build Status](https://github.com/hageldave/JPlotter/actions/workflows/maven.yml/badge.svg)](https://github.com/hageldave/JPlotter/actions/workflows/maven.yml)\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.hageldave.jplotter/jplotter.svg)](https://search.maven.org/search?q=g:com.github.hageldave.jplotter)\n\nJPlotter's concept is pretty straight forward, you get a `JPlotterCanvas` that is backed by OpenGL (or not in case of fallback).\nWhat is displayed by this canvas depends on the set `Renderer`.\nMost likely you want to set a `CoordSysRenderer` that displays a coordinate system.\nWithin that coordinate system you may want to display points or lines, which you can do by again using a `Renderer` (or multiple) as content.\nA `PointsRenderer` can be used to draw points as in a scatter plot, or a `LinesRenderer` can be used to make a line chart or contour plot.\n\nJPlotter is also capable of exporting plots as Scalable Vector Graphics (SVG) through [Apache Batik](https://xmlgraphics.apache.org/batik/)\nas well as exporting to portable document format (PDF) through [Apache PDFBox](https://pdfbox.apache.org/).\n\nMore details and information can be found in the **[Wiki](https://github.com/hageldave/JPlotter/wiki)**.\n\n## Maven\nJPlotter is available as Maven artifact at the Central Maven Repository.\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.hageldave.jplotter\u003c/groupId\u003e\n  \u003cartifactId\u003ejplotter\u003c/artifactId\u003e\n  \u003cversion\u003e1.0.4\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## Teaser Image\nSee the **[Gallery](https://github.com/hageldave/JPlotter/wiki/Gallery)** for more images.\n\n![teaser img](https://raw.githubusercontent.com/wiki/hageldave/JPlotter/images/isolines_viz.png)\n\n## Code Example\nBefore visualizing anything, some data has to be generated first.\nLets sample the sine function so we can later plot a line.\n```java\nDoubleUnaryOperator fx = Math::sin;\nint numCurveSamples = 100;\ndouble[] curveX = new double[numCurveSamples];\ndouble[] curveY = new double[numCurveSamples];\nfor(int i=0; i\u003cnumCurveSamples; i++){\n   double x = i*Math.PI*2/numCurveSamples;\n   double y = fx.applyAsDouble(x);\n   curveX[i]=x;  curveY[i]=y;\n}\n```\nLets also mix in some random samples for plotting points.\n```java\nint numPointSamples = 400;\ndouble[] pointsX = new double[numPointSamples];\ndouble[] pointsY = new double[numPointSamples];\ndouble[] diffToCurve = new double[numPointSamples];\nfor(int i=0; i\u003cnumPointSamples; i++){\n   double x = Math.random()*Math.PI*2;\n   double y = Math.random()*Math.PI*2-Math.PI;\n   diffToCurve[i] = y-fx.applyAsDouble(x);\n   pointsX[i]=x;  pointsY[i]=y;\n}\n```\nNow that data is set up, we are good to go and can think about representation of the data.\nThe sine samples should be visualized as a line, whereas the random samples should be displayed as points.\nLets also divide the points into 3 classes:\n1. y(x) \u003c sin(x)-0.5\n2. sin(x)-0.5 \u003c= y(x) \u003c= sin(x)+0.5\n3. sin(x)+0.5 \u003c y(x)\n```java\nLines sineLine = new Lines();\nint sineColor = 0xff66c2a5;\nsineLine.setGlobalThicknessMultiplier(2)\n   .setStrokePattern(0xf790)\n   .addLineStrip(curveX, curveY)\n   .forEach(segment -\u003e segment.setColor(sineColor));\nPoints pointsC1 = new Points(DefaultGlyph.CROSS);\nPoints pointsC2 = new Points(DefaultGlyph.CIRCLE);\nPoints pointsC3 = new Points(DefaultGlyph.CROSS);\nint c1Color = 0xff8da0cb, c2Color = sineColor, c3Color = 0xfffc8d62;\nfor(int i=0; i\u003cnumPointSamples; i++){\n   if(diffToCurve[i] \u003c -0.5){\n      pointsC1.addPoint(pointsX[i], pointsY[i]).setColor(c1Color);\n   } else if(diffToCurve[i] \u003e 0.5) {\n      pointsC3.addPoint(pointsX[i], pointsY[i]).setColor(c3Color);\n   } else {\n      pointsC2.addPoint(pointsX[i], pointsY[i]).setColor(c2Color);\n   }\n}\n```\nAlright next we put everything into a coordinate system.\n```java\nCoordSysRenderer coordsys = new CoordSysRenderer();\nCompleteRenderer content = new CompleteRenderer();\ncoordsys.setContent( content\n      .addItemToRender(sineLine)\n      .addItemToRender(pointsC1)\n      .addItemToRender(pointsC2)\n      .addItemToRender(pointsC3));\n// lets set the coordinate view to cover the whole sampling space\ncoordsys.setCoordinateView(-.5, -3.3, 6.5, 3.3);\n```\nWe can also add a legend to the plot so that a viewer can make more sense of the viz.\n```java\nLegend legend = new Legend();\ncoordsys.setLegendRightWidth(80);\ncoordsys.setLegendRight(legend\n      .addLineLabel(2, sineColor, \"f(x)\")\n      .addGlyphLabel(DefaultGlyph.CROSS, c1Color, \"\u003c f(x)-0.5\")\n      .addGlyphLabel(DefaultGlyph.CIRCLE, c2Color, \"~ f(x)\")\n      .addGlyphLabel(DefaultGlyph.CROSS, c3Color, \"\u003e f(x)+0.5\"));\n```\nWe will use a blank canvas to display our coordinate system.\nFor exploring the plot we can add some controls for zooming.\n```java\nboolean useOpenGL = true;\nJPlotterCanvas canvas = useOpenGL ? new BlankCanvas() : new BlankCanvasFallback();\ncanvas.setRenderer(coordsys);\n// lets add some controls for exploring the data\nnew CoordSysScrollZoom(canvas,coordsys).setZoomFactor(1.7).register();\nnew CoordSysViewSelector(canvas,coordsys) {\n   {extModifierMask=0;/* no need for shift to be pressed */}\n   public void areaSelected(double minX, double minY, double maxX, double maxY) {\n      coordsys.setCoordinateView(minX, minY, maxX, maxY);\n   }\n}.register();\n```\nNice, now we conclude with some typical AWT/Swing code to launch the viz in a JFrame.\n```java\nJFrame frame = new JFrame(\"Example Viz\");\nframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\nframe.getContentPane().add(canvas.asComponent());\ncanvas.asComponent().setPreferredSize(new Dimension(480, 400));\ncanvas.asComponent().setBackground(Color.white);\n\n// register a listener that will cleanup GL resources on window closing\ncanvas.addCleanupOnWindowClosingListener(frame);\n\nSwingUtilities.invokeLater(()-\u003e{\n   frame.pack();\n   frame.setVisible(true);\n});\n```\nWe can also add a pop up menu for exporting to SVG, PDF or PNG.\n```java\nPopupMenu menu = new PopupMenu();\ncanvas.asComponent().add(menu);\ncanvas.asComponent().addMouseListener(new MouseAdapter() {\n   public void mouseClicked(MouseEvent e) {\n      if(SwingUtilities.isRightMouseButton(e))\n         menu.show(canvas.asComponent(), e.getX(), e.getY());\n   }\n});\n\n// Exporting SVG\nMenuItem svgExport = new MenuItem(\"SVG export\");\nsvgExport.addActionListener(e-\u003e{\n   Document svg = SVGUtils.containerToSVG(frame.getContentPane());\n   SVGUtils.documentToXMLFile(svg, new File(\"example_export.svg\"));\n   System.out.println(\"exported SVG.\");\n});\nmenu.add(svgExport);\n\n// Exporting PDF\nMenuItem pdfExport = new MenuItem(\"PDF export\");\npdfExport.addActionListener(e-\u003e{\n    PDDocument doc = PDFUtils.containerToPDF(frame.getContentPane());\n    doc.save(\"example_export.pdf\");\n    doc.close();\n});\nmenu.add(pdfExport);\n\n// Exporting PNG\nMenuItem pngExport = new MenuItem(\"PNG export\");\npngExport.addActionListener(e-\u003e{\n   Img img = new Img(frame.getContentPane().getSize());\n   img.paint(g -\u003e frame.getContentPane().paintAll(g));\n   ImageSaver.saveImage(img.getRemoteBufferedImage(), \"example_export.png\");\n   System.out.println(\"exported PNG.\");\n});\nmenu.add(pngExport);\n```\n![Example Viz](https://raw.githubusercontent.com/wiki/hageldave/JPlotter/images/example_viz.png)\n\n*[```Source```](https://github.com/hageldave/JPlotter/blob/master/jplotter/src/test/java/hageldave/jplotter/Example.java)*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhageldave%2Fjplotter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhageldave%2Fjplotter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhageldave%2Fjplotter/lists"}