diff --git a/jzy3d-api/src/api/org/jzy3d/chart2d/Chart2dGroup.java b/jzy3d-api/src/api/org/jzy3d/chart2d/Chart2dGroup.java index 24fd7286..1c972c75 100644 --- a/jzy3d-api/src/api/org/jzy3d/chart2d/Chart2dGroup.java +++ b/jzy3d-api/src/api/org/jzy3d/chart2d/Chart2dGroup.java @@ -9,7 +9,6 @@ import java.util.Map; import org.jzy3d.chart.Chart; import org.jzy3d.colors.Color; import org.jzy3d.plot2d.primitives.Serie2d; -import org.jzy3d.plot3d.rendering.canvas.IScreenCanvas; import org.jzy3d.plot3d.rendering.view.modes.ViewBoundMode; public class Chart2dGroup { diff --git a/jzy3d-api/src/api/org/jzy3d/maths/Coord3d.java b/jzy3d-api/src/api/org/jzy3d/maths/Coord3d.java index b3288587..dd4f9f73 100644 --- a/jzy3d-api/src/api/org/jzy3d/maths/Coord3d.java +++ b/jzy3d-api/src/api/org/jzy3d/maths/Coord3d.java @@ -15,30 +15,29 @@ import java.util.List; * @author Martin Pernollet * */ -public class Coord3d implements Serializable{ +public class Coord3d implements Serializable { /** * */ private static final long serialVersionUID = -1636927109633279805L; - public static List list(int size){ + public static List list(int size) { return new ArrayList(size); } - + public static Range getZRange(List coords) { float min = Float.POSITIVE_INFINITY; float max = Float.NEGATIVE_INFINITY; - - for(Coord3d c: coords){ - if(c.z>max) + + for (Coord3d c : coords) { + if (c.z > max) max = c.z; - if(c.z *
  • X represent azimuth *
  • Y represent elevation @@ -273,15 +275,13 @@ public class Coord3d implements Serializable{ Math.sin(x) * Math.cos(y) * z, // elevation Math.sin(y) * z); // range } - + public Coord3d cartesianSelf() { - x = (float)(Math.cos(x) * Math.cos(y) * z); // azimuth - y = (float)(Math.sin(x) * Math.cos(y) * z);// elevation - z = (float)(Math.sin(y) * z); // range + x = (float) (Math.cos(x) * Math.cos(y) * z); // azimuth + y = (float) (Math.sin(x) * Math.cos(y) * z);// elevation + z = (float) (Math.sin(y) * z); // range return this; } - - /** * Converts the current Coord3d into polar coordinates and return the result @@ -318,7 +318,7 @@ public class Coord3d implements Serializable{ return new Coord3d(a, e, r); } } - + public Coord3d polarSelf() { double a; double e; @@ -345,9 +345,9 @@ public class Coord3d implements Serializable{ e = Math.atan(z / d); - x = (float)a; - y = (float)e; - z = (float)r; + x = (float) a; + y = (float) e; + z = (float) r; return this; } } @@ -387,22 +387,20 @@ public class Coord3d implements Serializable{ } public final Coord3d cross(Coord3d v) { - return new Coord3d( - y * v.z - z * v.y, - z * v.x - x * v.z, - x * v.y - y * v.x - ); + return new Coord3d(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); } /** - * Applies a rotation represented by the AxisAngle - * notation using the Rodrigues' rotation formula. + * Applies a rotation represented by the AxisAngle notation using the + * Rodrigues' rotation formula. *

    * math implemented using * http://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula * - * @param angleDeg angle of rotation about the given axis [deg] - * @param axis unit vector describing an axis of rotation + * @param angleDeg + * angle of rotation about the given axis [deg] + * @param axis + * unit vector describing an axis of rotation * @return rotated copy of the original vector */ public final Coord3d rotate(float angleDeg, Coord3d axis) { @@ -414,10 +412,7 @@ public class Coord3d implements Serializable{ float kdotv = k.dot(v); Coord3d kXv = k.cross(v); - return new Coord3d( - v.x * c + kXv.x * s + k.x * kdotv * (1 - c), - v.y * c + kXv.y * s + k.y * kdotv * (1 - c), - v.z * c + kXv.z * s + k.z * kdotv * (1 - c)); + return new Coord3d(v.x * c + kXv.x * s + k.x * kdotv * (1 - c), v.y * c + kXv.y * s + k.y * kdotv * (1 - c), v.z * c + kXv.z * s + k.z * kdotv * (1 - c)); } public final Coord3d interpolateTo(Coord3d v, float f) { @@ -441,28 +436,118 @@ public class Coord3d implements Serializable{ /**************************************************************/ @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(x); - result = prime * result + Float.floatToIntBits(y); - result = prime * result + Float.floatToIntBits(z); - return result; - } + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Float.floatToIntBits(x); + result = prime * result + Float.floatToIntBits(y); + result = prime * result + Float.floatToIntBits(z); + return result; + } - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; - if (!(obj instanceof Coord3d)) return false; + if (!(obj instanceof Coord3d)) + return false; - Coord3d other = (Coord3d) obj; - if (Float.floatToIntBits(x) != Float.floatToIntBits(other.x)) return false; - if (Float.floatToIntBits(y) != Float.floatToIntBits(other.y)) return false; - if (Float.floatToIntBits(z) != Float.floatToIntBits(other.z)) return false; - return true; - } + Coord3d other = (Coord3d) obj; + if (Float.floatToIntBits(x) != Float.floatToIntBits(other.x)) + return false; + if (Float.floatToIntBits(y) != Float.floatToIntBits(other.y)) + return false; + if (Float.floatToIntBits(z) != Float.floatToIntBits(other.z)) + return false; + return true; + } + + /**************************************************************/ + + /** + * Compute the component-wise minimum values of a set of coordinates. + * + * @param coords + * @return minimum value on each dimension + */ + public static Coord3d min(List coords) { + Coord3d min = new Coord3d(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY); + for (Coord3d c : coords) { + if (c.x < min.x) + min.x = c.x; + + if (c.y < min.y) + min.y = c.y; + + if (c.z < min.z) + min.z = c.z; + } + return min; + } + + /** + * Compute the component-wise minimum values of a set of coordinates. + * + * @param coords + * @return maximum value on each dimension + */ + public static Coord3d max(List coords) { + Coord3d max = new Coord3d(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY); + for (Coord3d c : coords) { + if (c.x > max.x) + max.x = c.x; + + if (c.y > max.y) + max.y = c.y; + + if (c.z > max.z) + max.z = c.z; + } + return max; + } + + public static void add(List coords, float x, float y, float z) { + add(coords, new Coord3d(x, y, z)); + } + + public static void add(List coords, Coord3d add) { + for (Coord3d c : coords) { + c.addSelf(add); + } + } + + public static void sub(List coords, float x, float y, float z) { + sub(coords, new Coord3d(x, y, z)); + } + + public static void sub(List coords, Coord3d add) { + for (Coord3d c : coords) { + c.subSelf(add); + } + } + + public static void mul(List coords, float x, float y, float z) { + mul(coords, new Coord3d(x, y, z)); + } + + public static void mul(List coords, Coord3d multiplier) { + for (Coord3d c : coords) { + c.mulSelf(multiplier); + } + } + + public static void div(List coords, float x, float y, float z) { + div(coords, new Coord3d(x, y, z)); + } + + public static void div(List coords, Coord3d div) { + for (Coord3d c : coords) { + c.divSelf(div); + } + } /**************************************************************/ diff --git a/jzy3d-api/src/api/org/jzy3d/plot3d/primitives/AbstractComposite.java b/jzy3d-api/src/api/org/jzy3d/plot3d/primitives/AbstractComposite.java index cd308797..b8f0b987 100644 --- a/jzy3d-api/src/api/org/jzy3d/plot3d/primitives/AbstractComposite.java +++ b/jzy3d-api/src/api/org/jzy3d/plot3d/primitives/AbstractComposite.java @@ -13,6 +13,7 @@ import org.jzy3d.maths.BoundingBox3d; import org.jzy3d.maths.Utils; import org.jzy3d.plot3d.rendering.view.Camera; import org.jzy3d.plot3d.transform.Transform; +import org.jzy3d.plot3d.transform.space.SpaceTransformer; import com.jogamp.opengl.GL; import com.jogamp.opengl.glu.GLU; @@ -118,6 +119,17 @@ public abstract class AbstractComposite extends AbstractWireframeable implements } } } + + public void setSpaceTransformer(SpaceTransformer spaceTransformer) { + this.spaceTransformer = spaceTransformer; + + synchronized (components) { + for (AbstractDrawable c : components) { + if (c != null) + c.setSpaceTransformer(spaceTransformer); + } + } + } /** Return the transform that was affected to this composite. */ @Override diff --git a/jzy3d-api/src/api/org/jzy3d/plot3d/primitives/axes/AxeBox.java b/jzy3d-api/src/api/org/jzy3d/plot3d/primitives/axes/AxeBox.java index 6bd90ae2..f36db8a6 100644 --- a/jzy3d-api/src/api/org/jzy3d/plot3d/primitives/axes/AxeBox.java +++ b/jzy3d-api/src/api/org/jzy3d/plot3d/primitives/axes/AxeBox.java @@ -517,7 +517,7 @@ public class AxeBox implements IAxe { } } Coord3d tickPosition = new Coord3d(xlab, ylab, zlab); - + if (layout.isTickLineDisplayed()) { if (gl.isGL2()) { drawTickLine(gl, color, xpos, ypos, zpos, xlab, ylab, zlab); diff --git a/jzy3d-api/src/api/org/jzy3d/plot3d/rendering/canvas/ICanvas.java b/jzy3d-api/src/api/org/jzy3d/plot3d/rendering/canvas/ICanvas.java index ae375784..000bda01 100644 --- a/jzy3d-api/src/api/org/jzy3d/plot3d/rendering/canvas/ICanvas.java +++ b/jzy3d-api/src/api/org/jzy3d/plot3d/rendering/canvas/ICanvas.java @@ -53,22 +53,28 @@ public interface ICanvas { /** * A generic interface for mouse listener to remain Windowing toolkit - * independant. * Implementation of this method should simply cast the input - * assuming it will correspond to canvas-compatible mouse listener. + * independant. + * + * Implementation of this method should simply cast the input assuming it + * will correspond to canvas-compatible mouse listener. */ public void addMouseController(Object o); /** * A generic interface for mouse listener to remain Windowing toolkit - * independant. * Implementation of this method should simply cast the input - * assuming it will correspond to canvas-compatible mouse listener. + * independant. + * + * Implementation of this method should simply cast the input assuming it + * will correspond to canvas-compatible mouse listener. */ public void addKeyController(Object o); /** * A generic interface for key listener to remain Windowing toolkit - * independant. * Implementation of this method should simply cast the input - * assuming it will correspond to canvas-compatible key listener. + * independant. + * + * Implementation of this method should simply cast the input assuming it + * will correspond to canvas-compatible key listener. */ public void removeMouseController(Object o); diff --git a/jzy3d-api/src/api/org/jzy3d/plot3d/text/renderers/TextBitmapRenderer.java b/jzy3d-api/src/api/org/jzy3d/plot3d/text/renderers/TextBitmapRenderer.java index b20c6f23..09e396d3 100644 --- a/jzy3d-api/src/api/org/jzy3d/plot3d/text/renderers/TextBitmapRenderer.java +++ b/jzy3d-api/src/api/org/jzy3d/plot3d/text/renderers/TextBitmapRenderer.java @@ -22,6 +22,8 @@ import com.jogamp.opengl.util.gl2.GLUT; * @author Martin */ public class TextBitmapRenderer extends AbstractTextRenderer implements ITextRenderer { + protected static Logger LOGGER = Logger.getLogger(TextBitmapRenderer.class); + /** * GL Font code and size in pixel to initialize rendeer. */ @@ -91,10 +93,13 @@ public class TextBitmapRenderer extends AbstractTextRenderer implements ITextRen posReal = cam.screenToModel(gl, glu, posScreenShifted); } catch (RuntimeException e) { // TODO: solve this bug due to a Camera.PERSPECTIVE mode. - Logger.getLogger(TextBitmapRenderer.class).error("TextBitmap.drawText(): could not process text position: " + posScreen + " " + posScreenShifted); + LOGGER.error("TextBitmap.drawText(): could not process text position: " + posScreen + " " + posScreenShifted); return new BoundingBox3d(); } + //LOGGER.info(text + " @ " + position + " projected to : " + posScreen + " shifted to " + posScreenShifted); + //LOGGER.info(text + " @ " + posReal + " with offset : " + sceneOffset); + // Draws actual string glRasterPos(gl, sceneOffset, posReal); glut.glutBitmapString(font, text); diff --git a/jzy3d-api/src/awt/org/jzy3d/chart/controllers/mouse/camera/AWTCameraMouseController.java b/jzy3d-api/src/awt/org/jzy3d/chart/controllers/mouse/camera/AWTCameraMouseController.java index 7f7b4c44..16021f0b 100644 --- a/jzy3d-api/src/awt/org/jzy3d/chart/controllers/mouse/camera/AWTCameraMouseController.java +++ b/jzy3d-api/src/awt/org/jzy3d/chart/controllers/mouse/camera/AWTCameraMouseController.java @@ -9,7 +9,6 @@ import java.awt.event.MouseWheelListener; import org.jzy3d.chart.Chart; import org.jzy3d.chart.controllers.camera.AbstractCameraController; import org.jzy3d.chart.controllers.mouse.AWTMouseUtilities; -import org.jzy3d.chart.controllers.thread.camera.CameraThreadController; import org.jzy3d.maths.Coord2d; diff --git a/jzy3d-api/src/awt/org/jzy3d/plot3d/rendering/view/AWTImageRenderer3d.java b/jzy3d-api/src/awt/org/jzy3d/plot3d/rendering/view/AWTImageRenderer3d.java new file mode 100644 index 00000000..0782aad1 --- /dev/null +++ b/jzy3d-api/src/awt/org/jzy3d/plot3d/rendering/view/AWTImageRenderer3d.java @@ -0,0 +1,88 @@ +package org.jzy3d.plot3d.rendering.view; + +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; + +import javafx.scene.image.Image; + +import org.jzy3d.plot3d.rendering.view.AWTRenderer3d; +import org.jzy3d.plot3d.rendering.view.View; + +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.glu.GLU; +import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil; + +/** A renderer generating AWT {@link BufferedImage}s and notifying a {@link DisplayListener} when + * it is updated. + * + * @author Martin Pernollet + */ +public class AWTImageRenderer3d extends AWTRenderer3d { + + public interface DisplayListener{ + public void onDisplay(Object image); + } + + protected List listeners = new ArrayList(); + + public AWTImageRenderer3d() { + super(); + } + + public AWTImageRenderer3d(View view, boolean traceGL, boolean debugGL, GLU glu) { + super(view, traceGL, debugGL, glu); + } + + @Override + public void display(GLAutoDrawable canvas) { + GL gl = canvas.getGL(); + + if (view != null) { + view.clear(gl); + view.render(gl, glu); + + // Convert as JavaFX Image and notify all listeners + BufferedImage image = makeScreenshotAsBufferedImage(gl); + fireDisplay(image); + + if (doScreenshotAtNextDisplay) { + //makeScreenshotAsJavaFXImage(gl); + doScreenshotAtNextDisplay = false; + } + } + } + + protected BufferedImage makeScreenshotAsBufferedImage(GL gl) { + AWTGLReadBufferUtil screenshot = makeScreenshot(gl); + return screenshot.readPixelsToBufferedImage(gl, true); + } + + private AWTGLReadBufferUtil makeScreenshot(GL gl) { + AWTGLReadBufferUtil screenshot = new AWTGLReadBufferUtil(GLProfile.getGL2GL3(), true); + screenshot.readPixels(gl, true); + image = screenshot.getTextureData(); + return screenshot; + } + + public AWTImageRenderer3d(View view, boolean traceGL, boolean debugGL) { + super(view, traceGL, debugGL); + } + + public void addDisplayListener(DisplayListener listener) { + listeners.add(listener); + } + + protected void fireDisplay(Object image) { + for(DisplayListener listener : listeners){ + listener.onDisplay(image); + } + } + + public AWTImageRenderer3d(View view) { + super(view); + } + +} \ No newline at end of file diff --git a/jzy3d-api/src/swing/org/jzy3d/bridge/swing/ChartGroupWindow.java b/jzy3d-api/src/swing/org/jzy3d/bridge/swing/ChartGroupWindow.java index 213653fd..fce419a6 100644 --- a/jzy3d-api/src/swing/org/jzy3d/bridge/swing/ChartGroupWindow.java +++ b/jzy3d-api/src/swing/org/jzy3d/bridge/swing/ChartGroupWindow.java @@ -4,7 +4,7 @@ import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; -import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import javax.swing.JFrame; @@ -15,43 +15,46 @@ import org.jzy3d.ui.LookAndFeel; /** A frame to show a list of charts */ public class ChartGroupWindow extends JFrame { - private static final long serialVersionUID = 7519209038396190502L; + private static final long serialVersionUID = 7519209038396190502L; - public ChartGroupWindow(Collection charts) throws IOException { - LookAndFeel.apply(); + public ChartGroupWindow(Chart... charts) { + this(Arrays.asList(charts)); + } - setGridLayout(charts); + public ChartGroupWindow(Collection charts) { + LookAndFeel.apply(); - windowExitListener(); - this.pack(); - setVisible(true); - setBounds(new java.awt.Rectangle(10, 10, 800, 600)); - } + setGridLayout(charts); - private void setGridLayout(Collection charts) { - setLayout(new GridLayout(charts.size(), 1)); + windowExitListener(); + this.pack(); + setVisible(true); + setBounds(new java.awt.Rectangle(10, 10, 800, 600)); + } - for (Chart c : charts) { - addChartToGridLayout(c); - } - } - - public void addChartToGridLayout(Chart chart) { - JPanel chartPanel = new JPanel(new BorderLayout()); - //Border b = BorderFactory.createLineBorder(java.awt.Color.black); - //chartPanel.setBorder(b); - chartPanel.add((java.awt.Component) chart.getCanvas(), - BorderLayout.CENTER); - add(chartPanel); - } + private void setGridLayout(Collection charts) { + setLayout(new GridLayout(charts.size(), 1)); - public void windowExitListener() { - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - ChartGroupWindow.this.dispose(); - System.exit(0); - } - }); - } + for (Chart c : charts) { + addChartToGridLayout(c); + } + } + + public void addChartToGridLayout(Chart chart) { + JPanel chartPanel = new JPanel(new BorderLayout()); + // Border b = BorderFactory.createLineBorder(java.awt.Color.black); + // chartPanel.setBorder(b); + chartPanel.add((java.awt.Component) chart.getCanvas(), BorderLayout.CENTER); + add(chartPanel); + } + + public void windowExitListener() { + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + ChartGroupWindow.this.dispose(); + System.exit(0); + } + }); + } } \ No newline at end of file diff --git a/jzy3d-api/src/swing/org/jzy3d/ui/views/ImagePanel.java b/jzy3d-api/src/swing/org/jzy3d/ui/views/ImagePanel.java index 87794bfd..3eac0234 100644 --- a/jzy3d-api/src/swing/org/jzy3d/ui/views/ImagePanel.java +++ b/jzy3d-api/src/swing/org/jzy3d/ui/views/ImagePanel.java @@ -8,25 +8,41 @@ import javax.swing.ImageIcon; import javax.swing.JPanel; public class ImagePanel extends JPanel { + public static Image getImageByPath(String img) { + return new ImageIcon(img).getImage(); + } + public ImagePanel(String img) { - this(new ImageIcon(img).getImage()); + this(getImageByPath(img)); } public ImagePanel(Image img) { - this.img = img; + setImage(img); + setLayout(null); + } + + public ImagePanel() { + setLayout(null); + } + + public void setImage(Image img) { + this.img = img; Dimension size = new Dimension(img.getWidth(null), img.getHeight(null)); setPreferredSize(size); setMinimumSize(size); setMaximumSize(size); setSize(size); - setLayout(null); - } + } + + public Image getImage(){ + return img; + } @Override public void paintComponent(Graphics g) { g.drawImage(img, 0, 0, null); } - private Image img; + protected Image img; private static final long serialVersionUID = 1L; }