Introduce basic 2d chart

This commit is contained in:
Martin Pernollet 2014-10-05 00:42:56 +02:00
parent 830b6d5334
commit 77dc241c80
14 changed files with 1067 additions and 637 deletions

View File

@ -109,7 +109,7 @@ public class ChartComponentFactory implements IChartComponentFactory {
public IScreenshotKeyController newScreenshotKeyController(Chart chart) {
// trigger screenshot on 's' letter
String file = SCREENSHOT_FOLDER + "capture-"
+ Utils.dat2str(new Date()) + ".png";
+ Utils.dat2str(new Date(), "yyyy-MM-dd-HH-mm-ss") + ".png";
IScreenshotKeyController screenshot;
if (!chart.getWindowingToolkit().equals("newt"))

View File

@ -0,0 +1,91 @@
package org.jzy3d.chart2d;
import java.util.HashMap;
import java.util.Map;
import javax.media.opengl.GLCapabilities;
import org.jzy3d.chart.AWTChart;
import org.jzy3d.chart.factories.IChartComponentFactory;
import org.jzy3d.chart.factories.IChartComponentFactory.Toolkit;
import org.jzy3d.chart2d.primitives.LineSerie2d;
import org.jzy3d.chart2d.primitives.Serie2d;
import org.jzy3d.maths.BoundingBox3d;
import org.jzy3d.plot3d.primitives.axes.layout.IAxeLayout;
import org.jzy3d.plot3d.primitives.axes.layout.renderers.DateTickRenderer;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.jzy3d.plot3d.rendering.view.View;
import org.jzy3d.plot3d.rendering.view.ViewportMode;
import org.jzy3d.plot3d.rendering.view.modes.ViewPositionMode;
// TODO:
// AXEBOX ticks too long
// AXEBOX Y label sur le côté
// X Labels centrés
//
// Interface de LineSerie fournie par Chart2d package, using x, y float args
public class Chart2d extends AWTChart{
public Chart2d() {
super();
}
public Chart2d(IChartComponentFactory factory, Quality quality, String windowingToolkit, GLCapabilities capabilities) {
super(factory, quality, windowingToolkit, capabilities);
}
public Chart2d(IChartComponentFactory factory, Quality quality, String windowingToolkit) {
super(factory, quality, windowingToolkit);
}
public Chart2d(IChartComponentFactory components, Quality quality) {
super(components, quality);
}
public Chart2d(Quality quality, String windowingToolkit) {
super(quality, windowingToolkit);
}
public Chart2d(Quality quality) {
super(quality);
}
public Chart2d(String windowingToolkit) {
super(windowingToolkit);
}
public Chart2d(float timeMax, float ymin, float ymax, String xlabel, String ylabel){
this(new Chart2dComponentFactory(), Quality.Intermediate, Toolkit.newt.toString());
IAxeLayout axe = getAxeLayout();
axe.setYAxeLabel(ylabel);
axe.setXAxeLabel( xlabel );
axe.setZAxeLabelDisplayed(false);
axe.setTickLineDisplayed(false);
axe.setXTickRenderer( new DateTickRenderer( "mm:ss" ) );
View view = getView();
view.setViewPositionMode(ViewPositionMode.TOP);
view.setBoundManual(new BoundingBox3d(0, timeMax, ymin, ymax, -1, 1));
view.setSquared(true);
view.getCamera().setViewportMode(ViewportMode.STRETCH_TO_FILL);
}
public Serie2d getSerie(String name){
Serie2d s = null;
if(!series.keySet().contains(name)){
s = new LineSerie2d(name);
addDrawable(s.getDrawable());
}
else{
s = series.get(name);
}
return s;
}
Map<String,Serie2d> series = new HashMap<String,Serie2d>();
}

View File

@ -0,0 +1,47 @@
package org.jzy3d.chart2d;
import org.jzy3d.chart.Chart;
import org.jzy3d.chart.factories.AWTChartComponentFactory;
import org.jzy3d.chart.factories.IChartComponentFactory;
import org.jzy3d.plot3d.rendering.canvas.ICanvas;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.jzy3d.plot3d.rendering.scene.Scene;
import org.jzy3d.plot3d.rendering.view.View;
public class Chart2dComponentFactory extends AWTChartComponentFactory{
@Override
public View newView(Scene scene, ICanvas canvas, Quality quality) {
return new View2d(this, scene, canvas, quality);
}
public static Chart chart() {
return chart(Quality.Intermediate);
}
public static Chart chart(Quality quality) {
Chart2dComponentFactory f = new Chart2dComponentFactory();
return f.newChart(quality, Toolkit.newt);
}
public static Chart chart(String toolkit) {
Chart2dComponentFactory f = new Chart2dComponentFactory();
return f.newChart(Chart.DEFAULT_QUALITY, toolkit);
}
public static Chart chart(Quality quality, Toolkit toolkit) {
Chart2dComponentFactory f = new Chart2dComponentFactory();
return f.newChart(quality, toolkit);
}
public static Chart chart(Quality quality, String toolkit) {
Chart2dComponentFactory f = new Chart2dComponentFactory();
return f.newChart(quality, toolkit);
}
@Override
public Chart newChart(IChartComponentFactory factory, Quality quality, String toolkit){
return new Chart2d(factory, quality, toolkit);
}
}

View File

@ -0,0 +1,18 @@
package org.jzy3d.chart2d;
import org.jzy3d.chart.factories.IChartComponentFactory;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.plot3d.rendering.canvas.ICanvas;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.jzy3d.plot3d.rendering.scene.Scene;
import org.jzy3d.plot3d.rendering.view.AWTView;
public class View2d extends AWTView {
public View2d(IChartComponentFactory factory, Scene scene, ICanvas canvas, Quality quality) {
super(factory, scene, canvas, quality);
}
public Coord3d computeSceneScaling() {
return squarify();
}
}

View File

@ -0,0 +1,63 @@
package org.jzy3d.chart2d.primitives;
import java.util.List;
import org.jzy3d.colors.Color;
import org.jzy3d.maths.Coord2d;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.plot3d.primitives.AbstractDrawable;
import org.jzy3d.plot3d.primitives.Point;
import org.jzy3d.plot3d.primitives.SynchronizedLineStrip;
public class LineSerie2d implements Serie2d {
protected SynchronizedLineStrip line = new SynchronizedLineStrip();
protected String name;
public LineSerie2d(String name){
this.name = name;
}
@Override
public void add(float x, float y) {
line.add(new Point(new Coord3d(x, y, 0)));
}
@Override
public void add(double x, double y) {
line.add(new Point(new Coord3d(x, y, 0)));
}
@Override
public void add(Coord2d c) {
line.add(new Point(new Coord3d(c.x, c.y, 0)));
}
@Override
public void add(List<Coord2d> c) {
for(Coord2d c2: c){
line.add(new Point(new Coord3d(c2.x, c2.y, 0)));
}
}
@Override
public void setColor(Color color){
line.setWireframeColor(color);
}
@Override
public Color getColor(){
return line.getWireframeColor();
}
@Override
public String getName() {
return name;
}
@Override
public SynchronizedLineStrip getDrawable() {
return line;
}
}

View File

@ -0,0 +1,20 @@
package org.jzy3d.chart2d.primitives;
import java.util.List;
import org.jzy3d.colors.Color;
import org.jzy3d.maths.Coord2d;
import org.jzy3d.plot3d.primitives.AbstractDrawable;
public interface Serie2d {
public void add(float x, float y);
public void add(double x, double y);
public void add(Coord2d c);
public void add(List<Coord2d> c);
public String getName();
public void setColor(Color color);
public Color getColor();
public AbstractDrawable getDrawable();
}

View File

@ -0,0 +1,132 @@
package org.jzy3d.plot3d.primitives;
import java.util.List;
import javax.media.opengl.GL;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.plot3d.rendering.compat.GLES2CompatUtils;
import org.jzy3d.plot3d.transform.Transform;
public class SynchronizedLineStrip extends LineStrip {
public SynchronizedLineStrip() {
super(100);
}
public SynchronizedLineStrip(int n) {
super(n);
}
public SynchronizedLineStrip(List<Coord3d> coords) {
super(coords);
}
public SynchronizedLineStrip(Point c1, Point c2) {
super(c1, c2);
}
public void drawLine(GL gl) {
gl.glLineWidth(width);
// gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);
// gl.glPolygonOffset(1.0f, 1.0f);
if (gl.isGL2()) {
gl.getGL2().glBegin(GL.GL_LINE_STRIP);
synchronized (points) {
if (wfcolor == null) {
for (Point p : points) {
gl.getGL2().glColor4f(p.rgb.r, p.rgb.g, p.rgb.b, p.rgb.a);
gl.getGL2().glVertex3f(p.xyz.x, p.xyz.y, p.xyz.z);
}
} else {
for (Point p : points) {
gl.getGL2().glColor4f(wfcolor.r, wfcolor.g, wfcolor.b, wfcolor.a);
gl.getGL2().glVertex3f(p.xyz.x, p.xyz.y, p.xyz.z);
}
}
}
gl.getGL2().glEnd();
} else {
GLES2CompatUtils.glBegin(GL.GL_LINE_STRIP);
synchronized (points) {
if (wfcolor == null) {
for (Point p : points) {
GLES2CompatUtils.glColor4f(p.rgb.r, p.rgb.g, p.rgb.b, p.rgb.a);
GLES2CompatUtils.glVertex3f(p.xyz.x, p.xyz.y, p.xyz.z);
}
} else {
for (Point p : points) {
GLES2CompatUtils.glColor4f(wfcolor.r, wfcolor.g, wfcolor.b, wfcolor.a);
GLES2CompatUtils.glVertex3f(p.xyz.x, p.xyz.y, p.xyz.z);
}
}
}
GLES2CompatUtils.glEnd();
}
}
public void drawPoints(GL gl) {
if (showPoints) {
if (gl.isGL2()) {
gl.getGL2().glBegin(GL.GL_POINTS);
synchronized (points) {
for (Point p : points) {
if (wfcolor == null)
gl.getGL2().glColor4f(p.rgb.r, p.rgb.g, p.rgb.b, p.rgb.a);
else
gl.getGL2().glColor4f(wfcolor.r, wfcolor.g, wfcolor.b, wfcolor.a);
gl.getGL2().glVertex3f(p.xyz.x, p.xyz.y, p.xyz.z);
}
}
gl.getGL2().glEnd();
} else {
GLES2CompatUtils.glBegin(GL.GL_POINTS);
synchronized (points) {
for (Point p : points) {
if (wfcolor == null)
GLES2CompatUtils.glColor4f(p.rgb.r, p.rgb.g, p.rgb.b, p.rgb.a);
else
GLES2CompatUtils.glColor4f(wfcolor.r, wfcolor.g, wfcolor.b, wfcolor.a);
GLES2CompatUtils.glVertex3f(p.xyz.x, p.xyz.y, p.xyz.z);
}
}
GLES2CompatUtils.glEnd();
}
}
}
/* */
public void applyGeometryTransform(Transform transform) {
synchronized (points) {
for (Point p : points) {
p.xyz = transform.compute(p.xyz);
}
}
updateBounds();
}
public void updateBounds() {
bbox.reset();
synchronized (points) {
for (Point p : points)
bbox.add(p);
}
}
public void add(Point point) {
synchronized (points) {
points.add(point);
}
bbox.add(point);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -261,10 +261,22 @@ public class AxeBoxLayout implements IAxeLayout{
public void setZTickLabelDisplayed(boolean tickLabelDisplayed) {
zTickLabelDisplayed = tickLabelDisplayed;
}
public boolean isTickLineDisplayed() {
return tickLineDisplayed;
}
public void setTickLineDisplayed(boolean tickLineDisplayed) {
this.tickLineDisplayed = tickLineDisplayed;
}
/**********************************************************/
/**********************************************************/
protected boolean tickLineDisplayed = true;
protected String xAxeLabel;
protected String yAxeLabel;

View File

@ -41,6 +41,10 @@ public interface IAxeLayout {
public boolean isYTickLabelDisplayed();
public boolean isZTickLabelDisplayed();
public boolean isTickLineDisplayed();
public void setTickLineDisplayed(boolean status);
public void setXTickProvider(ITickProvider provider);
public void setYTickProvider(ITickProvider provider);
public void setZTickProvider(ITickProvider provider);
@ -72,4 +76,5 @@ public interface IAxeLayout {
public Color getXTickColor();
public Color getYTickColor();
public Color getZTickColor();
}

View File

@ -21,119 +21,111 @@ import com.jogamp.opengl.util.gl2.GLUT;
*
* @author Martin
*/
public class TextBitmapRenderer extends AbstractTextRenderer implements
ITextRenderer {
/**
* The TextBitmap class provides support for drawing ASCII characters Any
* non ascii caracter will be replaced by a square.
*/
public TextBitmapRenderer() {
super();
font = GLUT.BITMAP_HELVETICA_10;
fontHeight = 10;
}
public class TextBitmapRenderer extends AbstractTextRenderer implements ITextRenderer {
/**
* The TextBitmap class provides support for drawing ASCII characters Any
* non ascii caracter will be replaced by a square.
*/
public TextBitmapRenderer() {
super();
font = GLUT.BITMAP_HELVETICA_10;
fontHeight = 10;
}
@Override
public void drawSimpleText(GL gl, GLU glu, Camera cam, String s,
Coord3d position, Color color) {
if (gl.isGL2()) {
gl.getGL2().glColor3f(color.r, color.g, color.b);
gl.getGL2().glRasterPos3f(position.x, position.y, position.z);
} else {
GLES2CompatUtils.glColor3f(color.r, color.g, color.b);
GLES2CompatUtils.glRasterPos3f(position.x, position.y, position.z);
}
@Override
public void drawSimpleText(GL gl, GLU glu, Camera cam, String s, Coord3d position, Color color) {
if (gl.isGL2()) {
gl.getGL2().glColor3f(color.r, color.g, color.b);
gl.getGL2().glRasterPos3f(position.x, position.y, position.z);
} else {
GLES2CompatUtils.glColor3f(color.r, color.g, color.b);
GLES2CompatUtils.glRasterPos3f(position.x, position.y, position.z);
}
glut.glutBitmapString(font, s);
}
glut.glutBitmapString(font, s);
}
/**
* Draw a string at the specified position and compute the 3d volume
* occupied by the string according to the current Camera configuration.
*/
@Override
public BoundingBox3d drawText(GL gl, GLU glu, Camera cam, String s,
Coord3d position, Halign halign, Valign valign, Color color,
Coord2d screenOffset, Coord3d sceneOffset) {
if (gl.isGL2()) {
gl.getGL2().glColor3f(color.r, color.g, color.b);
} else {
GLES2CompatUtils.glColor3f(color.r, color.g, color.b);
}
/**
* Draw a string at the specified position and compute the 3d volume
* occupied by the string according to the current Camera configuration.
*/
@Override
public BoundingBox3d drawText(GL gl, GLU glu, Camera cam, String text, Coord3d position, Halign halign, Valign valign, Color color, Coord2d screenOffset, Coord3d sceneOffset) {
if (gl.isGL2()) {
gl.getGL2().glColor3f(color.r, color.g, color.b);
} else {
GLES2CompatUtils.glColor3f(color.r, color.g, color.b);
}
if (cam == null)
return null;
if (cam == null)
return null;
Coord3d posScreen = cam.modelToScreen(gl, glu, position);
Coord3d posScreen = cam.modelToScreen(gl, glu, position);
// System.out.println(posScreen);
// System.out.println(posScreen);
// compute a corrected position according to layout
float strlen = glut.glutBitmapLength(font, text);
float x = 0.0f;
float y = 0.0f;
// compute a corrected position according to layout
float strlen = glut.glutBitmapLength(font, s);
float x = 0.0f;
float y = 0.0f;
if (halign == Halign.RIGHT)
x = posScreen.x;
else if (halign == Halign.CENTER)
x = posScreen.x - strlen / 2;
else if (halign == Halign.LEFT)
x = posScreen.x - strlen;
if (halign == Halign.RIGHT)
x = posScreen.x;
else if (halign == Halign.CENTER)
x = posScreen.x - strlen / 2;
else if (halign == Halign.LEFT)
x = posScreen.x - strlen;
if (valign == Valign.TOP)
y = posScreen.y;
else if (valign == Valign.GROUND)
y = posScreen.y;
else if (valign == Valign.CENTER)
y = posScreen.y - fontHeight / 2;
else if (valign == Valign.BOTTOM)
y = posScreen.y - fontHeight;
if (valign == Valign.TOP)
y = posScreen.y;
else if (valign == Valign.GROUND)
y = posScreen.y;
else if (valign == Valign.CENTER)
y = posScreen.y - fontHeight / 2;
else if (valign == Valign.BOTTOM)
y = posScreen.y - fontHeight;
Coord3d posScreenShifted = new Coord3d(x + screenOffset.x, y + screenOffset.y, posScreen.z);
Coord3d posReal;
Coord3d posScreenShifted = new Coord3d(x + screenOffset.x, y
+ screenOffset.y, posScreen.z);
Coord3d posReal;
try {
posReal = cam.screenToModel(gl, glu, posScreenShifted);
} catch (RuntimeException e) {
// TODO: solve this bug due to a Camera.PERSPECTIVE mode.
System.err.println("TextBitmap.drawText(): could not process text position: " + posScreen + " " + posScreenShifted);
return new BoundingBox3d();
}
try {
posReal = cam.screenToModel(gl, glu, posScreenShifted);
} catch (RuntimeException e) { // TODO: really solve this bug due to a
// Camera.PERSPECTIVE mode.
System.err
.println("TextBitmap.drawText(): could not process text position: "
+ posScreen + " " + posScreenShifted);
return new BoundingBox3d();
}
// Draws actual string
if (gl.isGL2()) {
gl.getGL2().glRasterPos3f(posReal.x + sceneOffset.x, posReal.y + sceneOffset.y, posReal.z + sceneOffset.z);
} else {
GLES2CompatUtils.glRasterPos3f(posReal.x + sceneOffset.x, posReal.y + sceneOffset.y, posReal.z + sceneOffset.z);
}
// Draws actual string
if (gl.isGL2()) {
gl.getGL2().glRasterPos3f(posReal.x + sceneOffset.x, posReal.y + sceneOffset.y,
posReal.z + sceneOffset.z);
} else {
GLES2CompatUtils.glRasterPos3f(posReal.x + sceneOffset.x, posReal.y + sceneOffset.y,
posReal.z + sceneOffset.z);
}
glut.glutBitmapString(font, s);
//gl.getGL2().glRotatef(90, 0, 0, 1);
glut.glutBitmapString(font, text);
// Compute bounds of text
Coord3d botLeft = new Coord3d();
Coord3d topRight = new Coord3d();
botLeft.x = posScreenShifted.x;
botLeft.y = posScreenShifted.y;
botLeft.z = posScreenShifted.z;
topRight.x = botLeft.x + strlen;
topRight.y = botLeft.y + fontHeight;
topRight.z = botLeft.z;
// Compute bounds of text
Coord3d botLeft = new Coord3d();
Coord3d topRight = new Coord3d();
botLeft.x = posScreenShifted.x;
botLeft.y = posScreenShifted.y;
botLeft.z = posScreenShifted.z;
topRight.x = botLeft.x + strlen;
topRight.y = botLeft.y + fontHeight;
topRight.z = botLeft.z;
BoundingBox3d txtBounds = new BoundingBox3d();
txtBounds.add(cam.screenToModel(gl, glu, botLeft));
txtBounds.add(cam.screenToModel(gl, glu, topRight));
return txtBounds;
}
BoundingBox3d txtBounds = new BoundingBox3d();
txtBounds.add(cam.screenToModel(gl, glu, botLeft));
txtBounds.add(cam.screenToModel(gl, glu, topRight));
return txtBounds;
}
/********************************************************************/
/********************************************************************/
protected static GLUT glut = new GLUT();
protected int fontHeight;
protected int font;
protected static GLUT glut = new GLUT();
protected int fontHeight;
protected int font;
}

View File

@ -43,7 +43,7 @@ public class Transform {
sequence.add(next);
}
/*******************************************************************/
/* */
/**
* Appends a Transformer to the sequence that this Transform must performs.
@ -64,7 +64,7 @@ public class Transform {
sequence.add(next);
}
/***********************************************************/
/* */
/**
* Load the identity matrix and executes the stored sequence of Transformer.

View File

@ -10,70 +10,66 @@ import org.jzy3d.plot3d.rendering.compat.GLES2CompatUtils;
/** Translate drawable to (0,0,0) or back to its previous position. */
public class TranslateDrawable implements Transformer {
public TranslateDrawable(AbstractDrawable drawable, boolean reverse) {
super();
this.reverse = reverse;
this.drawable = drawable;
}
public TranslateDrawable(AbstractDrawable drawable, boolean reverse) {
super();
this.reverse = reverse;
this.drawable = drawable;
}
public void execute(GL gl) {
if (drawable != null) {
BoundingBox3d bounds = drawable.getBounds();
if (bounds != null) {
Coord3d center = bounds.getCenter();
public void execute(GL gl) {
if (drawable != null) {
BoundingBox3d bounds = drawable.getBounds();
if (bounds != null) {
Coord3d center = bounds.getCenter();
if (gl.isGLES()) {
float reverseCoef = (reverse ? -1.0f : 1.0f);
GLES2CompatUtils.glTranslatef(reverseCoef * center.x
/ 2, reverseCoef * center.y / 2, reverseCoef
* center.z / 2);
} else {
if (reverse)
gl.getGL2().glTranslatef(-center.x / 2, -center.y / 2,
-center.z / 2);
else
gl.getGL2().glTranslatef(center.x / 2, center.y / 2,
center.z / 2);
}
if (gl.isGLES()) {
float reverseCoef = (reverse ? -1.0f : 1.0f);
GLES2CompatUtils.glTranslatef(reverseCoef * center.x / 2, reverseCoef * center.y / 2, reverseCoef * center.z / 2);
} else {
if (reverse)
gl.getGL2().glTranslatef(-center.x / 2, -center.y / 2, -center.z / 2);
else
gl.getGL2().glTranslatef(center.x / 2, center.y / 2, center.z / 2);
}
}
}
}
}
}
}
public Coord3d compute(Coord3d input) {
if (drawable != null) {
BoundingBox3d bounds = drawable.getBounds();
if (bounds != null) {
Coord3d center = bounds.getCenter();
if (reverse)
return input.sub(center.div(2));
else
return input.add(center.div(2));
}
}
return null;
}
public Coord3d compute(Coord3d input) {
if (drawable != null) {
BoundingBox3d bounds = drawable.getBounds();
if (bounds != null) {
Coord3d center = bounds.getCenter();
if (reverse)
return input.sub(center.div(2));
else
return input.add(center.div(2));
}
}
return null;
}
public AbstractDrawable getDrawable() {
return drawable;
}
public AbstractDrawable getDrawable() {
return drawable;
}
public void setDrawable(AbstractDrawable drawable) {
this.drawable = drawable;
}
public void setDrawable(AbstractDrawable drawable) {
this.drawable = drawable;
}
public boolean isReverse() {
return reverse;
}
public boolean isReverse() {
return reverse;
}
public void setReverse(boolean reverse) {
this.reverse = reverse;
}
public void setReverse(boolean reverse) {
this.reverse = reverse;
}
public String toString() {
return "(TranslateDrawable)" + drawable;
}
public String toString() {
return "(TranslateDrawable)" + drawable;
}
protected AbstractDrawable drawable;
protected boolean reverse;
protected AbstractDrawable drawable;
protected boolean reverse;
}

View File

@ -29,6 +29,10 @@ import org.jzy3d.plot3d.rendering.view.layout.ColorbarViewportLayout;
import org.jzy3d.plot3d.rendering.view.layout.IViewportLayout;
public class AWTChartComponentFactory extends ChartComponentFactory {
public static Chart chart() {
return chart(Quality.Intermediate);
}
public static Chart chart(Quality quality) {
AWTChartComponentFactory f = new AWTChartComponentFactory();
return f.newChart(quality, Toolkit.newt);