Mouse projection supports margin, mouse over format labels, Painter directly provide modelToScreen and screenToModel

This commit is contained in:
martin 2022-08-30 20:23:20 +02:00
parent b3abb5d6e5
commit 72c612b888
13 changed files with 434 additions and 245 deletions

View File

@ -15,12 +15,13 @@ import org.jzy3d.chart.controllers.camera.AbstractCameraController;
import org.jzy3d.chart.controllers.mouse.AWTMouseUtilities;
import org.jzy3d.colors.AWTColor;
import org.jzy3d.colors.Color;
import org.jzy3d.maths.Array;
import org.jzy3d.maths.BoundingBox3d;
import org.jzy3d.maths.Coord2d;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.painters.IPainter;
import org.jzy3d.plot2d.rendering.AWTGraphicsUtils;
import org.jzy3d.plot3d.primitives.axis.Axis;
import org.jzy3d.plot3d.primitives.axis.layout.renderers.ITickRenderer;
import org.jzy3d.plot3d.rendering.view.AWTView;
import org.jzy3d.plot3d.rendering.view.AbstractAWTRenderer2d;
import org.jzy3d.plot3d.rendering.view.View;
@ -136,6 +137,10 @@ public class AWTCameraMouseController extends AbstractCameraController
// start creating a selection
mouseSelection.start2D = startMouse;
mouseSelection.start3D = screenToModel(e);
if(mouseSelection.stop3D==null)
System.err.println("Mouse.onMousePressed projeciton is null ");
}
@ -192,7 +197,7 @@ public class AWTCameraMouseController extends AbstractCameraController
mouseSelection.stop2D = mouse;
mouseSelection.stop3D = screenToModel(e);
view.shoot();
}
@ -370,7 +375,13 @@ public class AWTCameraMouseController extends AbstractCameraController
Coord3d mouse = new Coord3d(x(e), y, 0);
// Project to 3D
return screenToModel(mouse);
Coord3d model = screenToModel(mouse);
if(model==null) {
System.err.println("MouseEvent can not be projected for " + mouse);
}
return model;
}
protected Coord3d screenToModel(Coord3d mouse) {
@ -381,6 +392,8 @@ public class AWTCameraMouseController extends AbstractCameraController
int viewport[] = new int[4];
// If there is a layout that allows something else than the 3D view to be displayed
// (e.g. a colorbar), then we only get the viewport of this part
if (layout instanceof ViewAndColorbarsLayout) {
ViewAndColorbarsLayout viewLayout = (ViewAndColorbarsLayout) layout;
ViewportConfiguration viewportConf = viewLayout.getSceneViewport();
@ -394,52 +407,24 @@ public class AWTCameraMouseController extends AbstractCameraController
viewport[2] = viewportConf.getWidth();
viewport[3] = viewportConf.getHeight();
}
// Otherwise we simply use the default viewport
else {
viewport = painter.getViewPortAsInt();
}
painter.acquireGL();
float modelView[] = painter.getModelViewAsFloat();
float projection[] = painter.getProjectionAsFloat();
Coord3d model = screenToModel(painter, mouse, viewport, modelView, projection);
Coord3d model = painter.screenToModel(mouse, viewport, modelView, projection);
painter.releaseGL();
return model;
}
public Coord3d screenToModel(IPainter painter, Coord3d screen) {
int viewport[] = painter.getViewPortAsInt();
float modelView[] = painter.getModelViewAsFloat();
float projection[] = painter.getProjectionAsFloat();
return screenToModel(painter, screen, viewport, modelView, projection);
}
private Coord3d screenToModel(IPainter painter, Coord3d screen, int[] viewport, float[] modelView,
float[] projection) {
Array.print("Mouse.screenToModel : viewport : ", viewport);
// Array.print("Camera.screenToModel : modelView : ", modelView);
// Array.print("Camera.screenToModel : projection : ", projection);
// double modelView[] = painter.getModelViewAsDouble();
// double projection[] = painter.getProjectionAsDouble();
float worldcoord[] = new float[3];// wx, wy, wz;// returned xyz coords
boolean s = painter.gluUnProject(screen.x, screen.y, screen.z, modelView, 0, projection, 0,
viewport, 0, worldcoord, 0);
if (s) {
return new Coord3d(worldcoord[0], worldcoord[1], worldcoord[2]);
}
else {
System.out.println("NULL Coord");
//Array.print("viewport : ", viewport);
//Array.print("modelview : ", modelView);
//Array.print("projection : ", projection);
return null;
}
}
// ----------------------------------------------------------------------------
@ -447,13 +432,6 @@ public class AWTCameraMouseController extends AbstractCameraController
// ----------------------------------------------------------------------------
class MouseMoveRenderer extends AbstractAWTRenderer2d {
// MouseEvent e;
// Coord3d projection;
class MouseProjection {
}
@Override
public void paint(Graphics g, int canvasWidth, int canvasHeight) {
Graphics2D g2d = (Graphics2D) g;
@ -473,9 +451,9 @@ public class AWTCameraMouseController extends AbstractCameraController
int interline = 2;
int space = interline + g2d.getFont().getSize();
// g2d.drawString(projection.toString(), e.getX(), e.getY());
g2d.drawString("x=" + mousePosition.projection.x, mousePosition.event.getX(),
g2d.drawString(format(Axis.X, mousePosition.projection.x), mousePosition.event.getX(),
mousePosition.event.getY());
g2d.drawString("y=" + mousePosition.projection.y, mousePosition.event.getX(),
g2d.drawString(format(Axis.Y, mousePosition.projection.y), mousePosition.event.getX(),
mousePosition.event.getY() + space);
// g2d.drawString("z=" + mousePosition.projection.z, mousePosition.e.getX(),
// mousePosition.e.getY() + space * 2);
@ -483,7 +461,52 @@ public class AWTCameraMouseController extends AbstractCameraController
}
}
}
}
protected String format(Axis axis, float value) {
String label;
ITickRenderer renderer;
switch(axis) {
case X:
label = getChart().getAxisLayout().getXAxisLabel();
renderer = getChart().getAxisLayout().getXTickRenderer();
if(label==null)
label = "x";
if(renderer==null)
return label + "=" + value;
else
return label + "=" + renderer.format(value);
case Y:
label = getChart().getAxisLayout().getYAxisLabel();
renderer = getChart().getAxisLayout().getYTickRenderer();
if(label==null)
label = "y";
if(renderer==null)
return label + "=" + value;
else
return label + "=" + renderer.format(value);
case Z:
label = getChart().getAxisLayout().getZAxisLabel();
renderer = getChart().getAxisLayout().getZTickRenderer();
if(label==null)
label = "z";
if(renderer==null)
return label + "=" + value;
else
return label + "=" + renderer.format(value);
default :
return "" + value;
}
}
class MousePosition {

View File

@ -1,5 +1,6 @@
package org.jzy3d.chart.controllers.mouse.camera;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@ -7,6 +8,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.awt.event.InputEvent;
import org.junit.Assert;
import org.junit.Test;
import org.jzy3d.chart.Chart;
import org.jzy3d.chart.factories.IChartFactory;
@ -16,6 +18,10 @@ import org.jzy3d.maths.Coord3d;
import org.jzy3d.maths.Scale;
import org.jzy3d.mocks.jzy3d.MouseMock;
import org.jzy3d.painters.IPainter;
import org.jzy3d.plot3d.primitives.axis.Axis;
import org.jzy3d.plot3d.primitives.axis.layout.AxisLayout;
import org.jzy3d.plot3d.primitives.axis.layout.renderers.DefaultDecimalTickRenderer;
import org.jzy3d.plot3d.primitives.axis.layout.renderers.ScientificNotationTickRenderer;
import org.jzy3d.plot3d.rendering.canvas.IScreenCanvas;
import org.jzy3d.plot3d.rendering.view.View;
import org.jzy3d.plot3d.rendering.view.View2DLayout;
@ -132,6 +138,7 @@ public class TestAWTCameraMouseController {
// TODO TEST : when mouse goes on colorbar : do not continue to drag
// TODO TEST : when mouse release out of canvas
// TODO TEST : valider que le mouse move ne provoque pas de display dans le cas d'une vue 3D.
@Test
@ -160,6 +167,8 @@ public class TestAWTCameraMouseController {
// -------------------------------------------------------------------------
// Given a view behavior
when(view.is2D()).thenReturn(true); // 2D mode
when(view.is2D_XY()).thenReturn(true);
when(view.getViewPoint()).thenReturn(new Coord3d(0,0,10));
@ -167,18 +176,29 @@ public class TestAWTCameraMouseController {
when(layout.isHorizontalAxisFlip()).thenReturn(false);
when(layout.isVerticalAxisFlip()).thenReturn(false);
when(viewportLayout.getSceneViewport()).thenReturn(new ViewportConfiguration(800, 600, 0, 0));
ViewportConfiguration viewport = new ViewportConfiguration(800, 600, 0, 0);
when(viewportLayout.getSceneViewport()).thenReturn(viewport);
// Given a painter behavior, returning predefined mouse 2D projections to 3D
// We pre flip Y component since implementation will flip the received Y component
when(painter.screenToModel(new Coord3d(10,-10,0))).thenReturn(new Coord3d(1,11,0));
when(painter.screenToModel(new Coord3d(15,-15,0))).thenReturn(new Coord3d(2,22,0));
when(painter.screenToModel(new Coord3d(20,-20,0))).thenReturn(new Coord3d(3,33,0));
when(painter.screenToModel(new Coord3d(25,-25,0))).thenReturn(new Coord3d(4,44,0));
// We pre flip Y component since mouse implementation will flip the received Y component
// We provide the viewport that will be provided to the painter, which should not be the
// complete canvas one if a legend is activated
// Given a mouse controller UNDER TEST
// Mock painter to answer to a Zoom gesture
// (otherwise the mock painter will return null coords, leading to an error)
when(painter.screenToModel(eq(new Coord3d(10,-10,0)), eq(viewport.toArray()), any(), any())).thenReturn(new Coord3d(1,11,0));
when(painter.screenToModel(eq(new Coord3d(15,-15,0)), eq(viewport.toArray()), any(), any())).thenReturn(new Coord3d(2,22,0));
when(painter.screenToModel(eq(new Coord3d(20,-20,0)), eq(viewport.toArray()), any(), any())).thenReturn(new Coord3d(3,33,0));
when(painter.screenToModel(eq(new Coord3d(25,-25,0)), eq(viewport.toArray()), any(), any())).thenReturn(new Coord3d(4,44,0));
// Mock painter to answer to an UnZoom gesture
when(painter.screenToModel(eq(new Coord3d(50,50,0)), eq(viewport.toArray()), any(), any())).thenReturn(new Coord3d(4,44,0));
when(painter.screenToModel(eq(new Coord3d(45,-45,0)), eq(viewport.toArray()), any(), any())).thenReturn(new Coord3d(4,44,0));
// Given a mouse controller UNDER TEST, finally <<<<<<<<<<<<<<<
AWTCameraMouseController mouse = new AWTCameraMouseController(chart);
// -------------------------------------------------------------------------
@ -202,6 +222,95 @@ public class TestAWTCameraMouseController {
// Then bounds are reset to auto bounds
verify(view, times(1)).setBoundMode(eq(ViewBoundMode.AUTO_FIT));
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// Verify it still works if layout is not of type ViewAndColorbarLayout
// i.e. when use default painter.getViewPortAsInt()
// Disable layout mock
when(view.getLayout()).thenReturn(null);
// Mock painter to return the default viewport
int [] defViewport = {0, 0, 400, 200};
when(painter.getViewPortAsInt()).thenReturn(defViewport);
// Mock painter to return the match this viewport
// (otherwise the mock painter will return null coords, leading to an error)
// we use different return value to ensure the later verify on view can not depend on the previous
// test
when(painter.screenToModel(eq(new Coord3d(10,-10,0)), eq(defViewport), any(), any())).thenReturn(new Coord3d(10,1100,0));
when(painter.screenToModel(eq(new Coord3d(15,-15,0)), eq(defViewport), any(), any())).thenReturn(new Coord3d(20,2200,0));
when(painter.screenToModel(eq(new Coord3d(20,-20,0)), eq(defViewport), any(), any())).thenReturn(new Coord3d(30,3300,0));
when(painter.screenToModel(eq(new Coord3d(25,-25,0)), eq(viewport.toArray()), any(), any())).thenReturn(new Coord3d(40,4400,0));
// -------------------------------------------------------------------------
// When mouse click, drag and release
mouse.mousePressed(MouseMock.event(10, 10, InputEvent.BUTTON1_DOWN_MASK));
mouse.mouseDragged(MouseMock.event(15, 15, InputEvent.BUTTON1_DOWN_MASK));
mouse.mouseDragged(MouseMock.event(20, 20, InputEvent.BUTTON1_DOWN_MASK));
mouse.mouseReleased(MouseMock.event(25, 25, InputEvent.BUTTON1_DOWN_MASK));
// Then selection is performed on the following bounding box
verify(view, times(1)).setBoundsManual(eq(new BoundingBox3d(10,30,1100,3300,0,1)));
}
@Test
public void testFormat() {
// Given
AxisLayout layout = mock(AxisLayout.class);
/*IAxis axis = mock(IAxis.class);
View view = mock(View.class);
when(axis.getLayout()).thenReturn(layout);
when(view.getAxis()).thenReturn(axis);*/
IScreenCanvas canvas = mock(IScreenCanvas.class);
IChartFactory factory = mock(IChartFactory.class);
when(factory.newCameraThreadController(null)).thenReturn(null);
Chart chart = mock(Chart.class);
// when(chart.getView()).thenReturn(view);
when(chart.getAxisLayout()).thenReturn(layout);
when(chart.getCanvas()).thenReturn(canvas);
when(chart.getFactory()).thenReturn(factory);
// -----------------------------------
// When no specific config for axis
AWTCameraMouseController mouse = new AWTCameraMouseController(chart);
Assert.assertEquals("x=1.2345678", mouse.format(Axis.X, 1.2345678f));
Assert.assertEquals("y=2.2345679", mouse.format(Axis.Y, 2.2345678f));
Assert.assertEquals("z=3.2345679", mouse.format(Axis.Z, 3.2345678f));
// watch expected value string without formatter, differ from input!!
// -----------------------------------
// When specific axis names
when(layout.getXAxisLabel()).thenReturn("The X axis");
when(layout.getYAxisLabel()).thenReturn("The Y axis");
when(layout.getZAxisLabel()).thenReturn("The Z axis");
Assert.assertEquals("The X axis=1.2345678", mouse.format(Axis.X, 1.2345678f));
Assert.assertEquals("The Y axis=2.2345679", mouse.format(Axis.Y, 2.2345678f));
Assert.assertEquals("The Z axis=3.2345679", mouse.format(Axis.Z, 3.2345678f));
// watch expected value string without formatter, differ from input!!
// -----------------------------------
// When specific tick renderer
when(layout.getXTickRenderer()).thenReturn(new DefaultDecimalTickRenderer(3));
when(layout.getYTickRenderer()).thenReturn(new ScientificNotationTickRenderer());
when(layout.getZTickRenderer()).thenReturn(new ScientificNotationTickRenderer());
Assert.assertEquals("The X axis=1,23", mouse.format(Axis.X, 1.2345678f));
Assert.assertEquals("The Y axis=2,2e+00", mouse.format(Axis.Y, 2.2345678f));
Assert.assertEquals("The Z axis=3,2e+00", mouse.format(Axis.Z, 3.2345678f));
}

View File

@ -2,7 +2,9 @@ package org.jzy3d.painters;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import org.jzy3d.colors.Color;
import org.jzy3d.maths.Array;
import org.jzy3d.maths.BoundingBox3d;
import org.jzy3d.maths.Coord2d;
import org.jzy3d.maths.Coord3d;
@ -123,8 +125,8 @@ public abstract class AbstractPainter implements IPainter {
@Override
public void box(BoundingBox3d box, Color color, float width, SpaceTransformer spaceTransformer) {
//if(box==null)
// return;
// if(box==null)
// return;
color(color);
glLineWidth(width);
@ -222,7 +224,8 @@ public abstract class AbstractPainter implements IPainter {
}
/**
* A convenient shortcut to invoke a clipping plane using an ID in [0;5] instead of the original OpenGL ID value.
* A convenient shortcut to invoke a clipping plane using an ID in [0;5] instead of the original
* OpenGL ID value.
*/
@Override
public void clip(int plane, ClipEq equation, double value) {
@ -288,60 +291,251 @@ public abstract class AbstractPainter implements IPainter {
}
/**
* Transform a 2d screen coordinate into a 3d coordinate. The z component of the screen coordinate
* indicates a depth value between the near and far clipping plane of the {@link Camera}.
*
* A null coordinate can be returned if the projection could not be performed for some reasons.
* This may occur if projection or modelview matrices are not invertible or if these matrices
* where unavailable (hence resulting to zero matrices) while invoking this method. Zero matrices
* can be avoided by ensuring the GL context is current using {@link IPainter#acquireGL()}
*
* @see {@link IPainter#gluUnProject(float, float, float, float[], int, float[], int, int[], int, float[], int)}
*/
@Override
public Coord3d screenToModel(Coord3d screen) {
return getCamera().screenToModel(this, screen);
int viewport[] = getViewPortAsInt();
float modelView[] = getModelViewAsFloat();
float projection[] = getProjectionAsFloat();
return screenToModel(screen, viewport, modelView, projection);
}
/**
* Transform a 2d screen coordinate into a 3d coordinate.
*
* Allow to pass custom viewport, modelview matrix and projection matrix. To use current one,
* invoke {@link AbstractPainter#screenToModel(Coord3d)}
*/
@Override
public Coord3d screenToModel(Coord3d screen, int[] viewport, float[] modelView,
float[] projection) {
// Array.print("Painter.screenToModel : viewport : ", viewport);
// Array.print("Camera.screenToModel : modelView : ", modelView);
// Array.print("Camera.screenToModel : projection : ", projection);
// double modelView[] = painter.getModelViewAsDouble();
// double projection[] = painter.getProjectionAsDouble();
float worldcoord[] = new float[3];// wx, wy, wz;// returned xyz coords
boolean s =
gluUnProject(screen.x, screen.y, screen.z, modelView, projection, viewport, worldcoord);
if (s) {
return new Coord3d(worldcoord[0], worldcoord[1], worldcoord[2]);
} else {
// System.out.println("NULL Coord");
// Array.print("viewport : ", viewport);
// Array.print("modelview : ", modelView);
// Array.print("projection : ", projection);
return null;
}
}
/**
* Transform a 3d point coordinate into its screen position.
*
* @see {@link Camera#modelToScreen(IPainter, Coord3d)}
*
* This method requires the GL context to be current. If not called inside a rendering loop, that
* method may not apply correctly and output {0,0,0}. In that case and if the chart is based on
* JOGL (native), one may force the context to be current using
*
* <pre>
* <code>
* NativeDesktopPainter p = (NativeDesktopPainter)chart.getPainter();
* p.getCurrentContext(chart.getCanvas()).makeCurrent(); // make context current
*
* Coord3d screen2dCoord = camera.modelToScreen(chart.getPainter(), world3dCoord);
*
* p.getCurrentContext(chart.getCanvas()).release(); // release context to let other use it
* </code>
* </pre>
*
* A null coordinate can be returned if the projection could not be performed for some reasons.
*/
@Override
public Coord3d modelToScreen(Coord3d point) {
return getCamera().modelToScreen(this, point);
int viewport[] = getViewPortAsInt();
float modelView[] = getModelViewAsFloat();
float projection[] = getProjectionAsFloat();
float screenCoord[] = new float[3];// wx, wy, wz;// returned xyz coords
boolean s = gluProject(point.x, point.y, point.z, modelView, projection, viewport,
screenCoord);
if (s) {
return new Coord3d(screenCoord[0], screenCoord[1], screenCoord[2]);
} else {
return null;
}
}
/**
* Transform a 3d point coordinate into its screen position.
*
* This method requires the GL context to be current. If not called inside a rendering loop, that
* method may not apply correctly and output {0,0,0}. In that case and if the chart is based on
* JOGL (native), one may force the context to be current using
*
* <pre>
* <code>
* NativeDesktopPainter p = (NativeDesktopPainter)chart.getPainter();
* p.getCurrentContext(chart.getCanvas()).makeCurrent(); // make context current
*
* Coord3d screen2dCoord = camera.modelToScreen(chart.getPainter(), world3dCoord);
*
* p.getCurrentContext(chart.getCanvas()).release(); // release context to let other use it
* </code>
* </pre>
*
* A null coordinate can be returned if the projection could not be performed for some reasons.
*/
@Override
public Coord3d[] modelToScreen(Coord3d[] points) {
return getCamera().modelToScreen(this, points);
int viewport[] = getViewPortAsInt();
float screenCoord[] = new float[3];
Coord3d[] projection = new Coord3d[points.length];
for (int i = 0; i < points.length; i++) {
boolean s = gluProject(points[i].x, points[i].y, points[i].z, getModelViewAsFloat(),
getProjectionAsFloat(), viewport, screenCoord);
if (s)
projection[i] = new Coord3d(screenCoord[0], screenCoord[1], screenCoord[2]);
}
return projection;
}
@Override
public Coord3d[][] modelToScreen(Coord3d[][] points) {
return getCamera().modelToScreen(this, points);
int viewport[] = getViewPortAsInt();
float screenCoord[] = new float[3];
Coord3d[][] projection = new Coord3d[points.length][points[0].length];
for (int i = 0; i < points.length; i++) {
for (int j = 0; j < points[i].length; j++) {
boolean s = gluProject(points[i][j].x, points[i][j].y, points[i][j].z,
getModelViewAsFloat(), getProjectionAsFloat(), viewport, screenCoord);
if (s)
projection[i][j] = new Coord3d(screenCoord[0], screenCoord[1], screenCoord[2]);
}
}
return projection;
}
@Override
public List<Coord3d> modelToScreen(List<Coord3d> points) {
return getCamera().modelToScreen(this, points);
int viewport[] = getViewPortAsInt();
float screenCoord[] = new float[3];
List<Coord3d> projection = new Vector<Coord3d>();
for (Coord3d point : points) {
boolean s = gluProject(point.x, point.y, point.z, getModelViewAsFloat(), getProjectionAsFloat(), viewport, screenCoord);
if (s)
projection.add(new Coord3d(screenCoord[0], screenCoord[1], screenCoord[2]));
}
return projection;
}
@Override
public ArrayList<ArrayList<Coord3d>> modelToScreen(ArrayList<ArrayList<Coord3d>> polygons) {
return getCamera().modelToScreen(this, polygons);
public List<ArrayList<Coord3d>> modelToScreen(ArrayList<ArrayList<Coord3d>> polygons) {
int viewport[] = getViewPortAsInt();
float screenCoord[] = new float[3];
ArrayList<ArrayList<Coord3d>> projections = new ArrayList<ArrayList<Coord3d>>(polygons.size());
for (ArrayList<Coord3d> polygon : polygons) {
ArrayList<Coord3d> projection = new ArrayList<Coord3d>(polygon.size());
for (Coord3d point : polygon) {
boolean s = gluProject(point.x, point.y, point.z, getModelViewAsFloat(),
getProjectionAsFloat(), viewport, screenCoord);
if (s)
projection.add(new Coord3d(screenCoord[0], screenCoord[1], screenCoord[2]));
}
projections.add(projection);
}
return projections;
}
@Override
public PolygonArray modelToScreen(PolygonArray polygon) {
return getCamera().modelToScreen(this, polygon);
int viewport[] = getViewPortAsInt();
float screenCoord[] = new float[3];
int len = polygon.length();
float[] x = new float[len];
float[] y = new float[len];
float[] z = new float[len];
for (int i = 0; i < len; i++) {
boolean s = gluProject(polygon.x[i], polygon.y[i], polygon.z[i],
getModelViewAsFloat(), getProjectionAsFloat(), viewport, screenCoord);
if (s) {
x[i] = screenCoord[0];
y[i] = screenCoord[1];
z[i] = screenCoord[2];
}
}
return new PolygonArray(x, y, z);
}
@Override
public PolygonArray[][] modelToScreen(PolygonArray[][] polygons) {
return getCamera().modelToScreen(this, polygons);
}
@Override
public boolean gluUnProject(float winX, float winY, float winZ, float[] model, float[] proj, int[] view, float[] objPos) {
return gluUnProject(winX, winY, winZ, model, 0, proj, 0, view, 0, objPos, 0);
int viewport[] = getViewPortAsInt();
float screencoord[] = new float[3];
PolygonArray[][] projections = new PolygonArray[polygons.length][polygons[0].length];
for (int i = 0; i < polygons.length; i++) {
for (int j = 0; j < polygons[i].length; j++) {
PolygonArray polygon = polygons[i][j];
int len = polygon.length();
float[] x = new float[len];
float[] y = new float[len];
float[] z = new float[len];
for (int k = 0; k < len; k++) {
boolean s = gluProject(polygon.x[k], polygon.y[k], polygon.z[k],
getModelViewAsFloat(), getProjectionAsFloat(), viewport, screencoord);
if (s) {
x[k] = screencoord[0];
y[k] = screencoord[1];
z[k] = screencoord[2];
}
}
projections[i][j] = new PolygonArray(x, y, z);
}
}
return projections;
}
@Override
public boolean gluProject(float objX, float objY, float objZ, float[] model, float[] proj, int[] view, float[] winPos) {
public boolean gluUnProject(float winX, float winY, float winZ, float[] model, float[] proj,
int[] view, float[] objPos) {
return gluUnProject(winX, winY, winZ, model, 0, proj, 0, view, 0, objPos, 0);
}
@Override
public boolean gluProject(float objX, float objY, float objZ, float[] model, float[] proj,
int[] view, float[] winPos) {
return gluProject(objX, objY, objZ, model, 0, proj, 0, view, 0, winPos, 0);
}
@ -349,10 +543,11 @@ public abstract class AbstractPainter implements IPainter {
public boolean isJVMScaleLargerThanNativeScale(Coord2d scaleHardware, Coord2d scaleJVM) {
return scaleJVM.x > scaleHardware.x || scaleJVM.y > scaleHardware.y;
}
@Override
public boolean isJVMScaleLargerThanNativeScale() {
return isJVMScaleLargerThanNativeScale(getCanvas().getPixelScale(), getCanvas().getPixelScaleJVM());
return isJVMScaleLargerThanNativeScale(getCanvas().getPixelScale(),
getCanvas().getPixelScaleJVM());
}
}

View File

@ -222,6 +222,9 @@ public interface IPainter {
// public void lights(boolean status);
// public void polygonOffset(boolean status);
// ----------------------------
// OpenGL matrices
public int[] getViewPortAsInt();
public double[] getProjectionAsDouble();
@ -232,7 +235,12 @@ public interface IPainter {
public float[] getModelViewAsFloat();
// ----------------------------
// Utilities to project from 2D to 3D or 3D to 2D
public Coord3d screenToModel(Coord3d screen);
public Coord3d screenToModel(Coord3d screen, int[] viewport, float[] modelView, float[] projection);
public Coord3d modelToScreen(Coord3d point);
@ -242,7 +250,7 @@ public interface IPainter {
public List<Coord3d> modelToScreen(List<Coord3d> points);
public ArrayList<ArrayList<Coord3d>> modelToScreen(ArrayList<ArrayList<Coord3d>> polygons);
public List<ArrayList<Coord3d>> modelToScreen(ArrayList<ArrayList<Coord3d>> polygons);
public PolygonArray modelToScreen(PolygonArray polygon);

View File

@ -0,0 +1,5 @@
package org.jzy3d.plot3d.primitives.axis;
public enum Axis {
X, Y, Z
}

View File

@ -31,7 +31,7 @@ public class AxisLabelRotator {
* @return
*/
public float computeSegmentRotation2D(IPainter painter, Coord3d[] axisSegment) {
Coord3d[] axs = painter.getCamera().modelToScreen(painter, axisSegment);
Coord3d[] axs = painter.modelToScreen(axisSegment);
return computeSegmentRotation(axs[0], axs[1]);
}

View File

@ -56,8 +56,8 @@ public class ProjectionUtils {
// project
t.tic();
ArrayList<ArrayList<Coord3d>> projections =
painter.getCamera().modelToScreen(painter, polygons);
List<ArrayList<Coord3d>> projections =
painter.modelToScreen(polygons);
t.toc();
report += " Projections :" + t.elapsedMilisecond();

View File

@ -50,7 +50,7 @@ public class SelectableScatter extends Scatter implements ISingleColorable, Sele
@Override
public void project(IPainter painter, Camera cam) {
projection = cam.modelToScreen(painter, getData());
projection = painter.modelToScreen(getData());
}
public Coord3d[] getProjection() {

View File

@ -33,7 +33,7 @@ public class SelectableSphere extends Sphere implements Selectable {
@Override
public void project(IPainter painter, Camera cam) {
projection = cam.modelToScreen(painter, anchors);
projection = painter.modelToScreen(anchors);
}
public List<Coord3d> getProjection() {

View File

@ -376,31 +376,7 @@ public class Camera extends AbstractViewportManager {
* @see
*/
public Coord3d screenToModel(IPainter painter, Coord3d screen) {
int viewport[] = painter.getViewPortAsInt();
float modelView[] = painter.getModelViewAsFloat();
float projection[] = painter.getProjectionAsFloat();
//Array.print("Camera.screenToModel : viewport : ", viewport);
// Array.print("Camera.screenToModel : modelView : ", modelView);
// Array.print("Camera.screenToModel : projection : ", projection);
// double modelView[] = painter.getModelViewAsDouble();
// double projection[] = painter.getProjectionAsDouble();
float worldcoord[] = new float[3];// wx, wy, wz;// returned xyz coords
boolean s = painter.gluUnProject(screen.x, screen.y, screen.z, modelView, 0, projection, 0,
viewport, 0, worldcoord, 0);
if (s) {
return new Coord3d(worldcoord[0], worldcoord[1], worldcoord[2]);
}
else {
//Array.print("viewport : ", viewport);
//Array.print("modelview : ", modelView);
//Array.print("projection : ", projection);
return null;
}
return painter.screenToModel(screen);
}
/**
@ -424,141 +400,9 @@ public class Camera extends AbstractViewportManager {
* A null coordinate can be returned if the projection could not be performed for some reasons.
*/
public Coord3d modelToScreen(IPainter painter, Coord3d point) {
int viewport[] = painter.getViewPortAsInt();
float modelView[] = painter.getModelViewAsFloat();
float projection[] = painter.getProjectionAsFloat();
float screenCoord[] = new float[3];// wx, wy, wz;// returned xyz coords
boolean s = painter.gluProject(point.x, point.y, point.z, modelView, projection, viewport,
screenCoord);
if (s) {
return new Coord3d(screenCoord[0], screenCoord[1], screenCoord[2]);
} else {
return null;
}
return painter.modelToScreen(point);
}
public Coord3d[] modelToScreen(IPainter painter, Coord3d[] points) {
int viewport[] = painter.getViewPortAsInt();
float screenCoord[] = new float[3];
Coord3d[] projection = new Coord3d[points.length];
for (int i = 0; i < points.length; i++) {
boolean s = painter.gluProject(points[i].x, points[i].y, points[i].z, painter.getModelViewAsFloat(),
painter.getProjectionAsFloat(), viewport, screenCoord);
if (s)
projection[i] = new Coord3d(screenCoord[0], screenCoord[1], screenCoord[2]);
}
return projection;
}
public Coord3d[][] modelToScreen(IPainter painter, Coord3d[][] points) {
int viewport[] = painter.getViewPortAsInt();
float screenCoord[] = new float[3];
Coord3d[][] projection = new Coord3d[points.length][points[0].length];
for (int i = 0; i < points.length; i++) {
for (int j = 0; j < points[i].length; j++) {
boolean s = painter.gluProject(points[i][j].x, points[i][j].y, points[i][j].z,
painter.getModelViewAsFloat(), painter.getProjectionAsFloat(), viewport, screenCoord);
if (s)
projection[i][j] = new Coord3d(screenCoord[0], screenCoord[1], screenCoord[2]);
}
}
return projection;
}
public List<Coord3d> modelToScreen(IPainter painter, List<Coord3d> points) {
int viewport[] = painter.getViewPortAsInt();
float screenCoord[] = new float[3];
List<Coord3d> projection = new Vector<Coord3d>();
for (Coord3d point : points) {
boolean s = painter.gluProject(point.x, point.y, point.z, painter.getModelViewAsFloat(), painter.getProjectionAsFloat(), viewport, screenCoord);
if (s)
projection.add(new Coord3d(screenCoord[0], screenCoord[1], screenCoord[2]));
}
return projection;
}
public ArrayList<ArrayList<Coord3d>> modelToScreen(IPainter painter,
ArrayList<ArrayList<Coord3d>> polygons) {
int viewport[] = painter.getViewPortAsInt();
float screenCoord[] = new float[3];
ArrayList<ArrayList<Coord3d>> projections = new ArrayList<ArrayList<Coord3d>>(polygons.size());
for (ArrayList<Coord3d> polygon : polygons) {
ArrayList<Coord3d> projection = new ArrayList<Coord3d>(polygon.size());
for (Coord3d point : polygon) {
boolean s = painter.gluProject(point.x, point.y, point.z, painter.getModelViewAsFloat(),
painter.getProjectionAsFloat(), viewport, screenCoord);
if (s)
projection.add(new Coord3d(screenCoord[0], screenCoord[1], screenCoord[2]));
}
projections.add(projection);
}
return projections;
}
public PolygonArray modelToScreen(IPainter painter, PolygonArray polygon) {
int viewport[] = painter.getViewPortAsInt();
float screenCoord[] = new float[3];
int len = polygon.length();
float[] x = new float[len];
float[] y = new float[len];
float[] z = new float[len];
for (int i = 0; i < len; i++) {
boolean s = painter.gluProject(polygon.x[i], polygon.y[i], polygon.z[i],
painter.getModelViewAsFloat(), painter.getProjectionAsFloat(), viewport, screenCoord);
if (s) {
x[i] = screenCoord[0];
y[i] = screenCoord[1];
z[i] = screenCoord[2];
}
}
return new PolygonArray(x, y, z);
}
public PolygonArray[][] modelToScreen(IPainter painter, PolygonArray[][] polygons) {
int viewport[] = painter.getViewPortAsInt();
float screencoord[] = new float[3];
PolygonArray[][] projections = new PolygonArray[polygons.length][polygons[0].length];
for (int i = 0; i < polygons.length; i++) {
for (int j = 0; j < polygons[i].length; j++) {
PolygonArray polygon = polygons[i][j];
int len = polygon.length();
float[] x = new float[len];
float[] y = new float[len];
float[] z = new float[len];
for (int k = 0; k < len; k++) {
boolean s = painter.gluProject(polygon.x[k], polygon.y[k], polygon.z[k],
painter.getModelViewAsFloat(), painter.getProjectionAsFloat(), viewport, screencoord);
if (s) {
x[k] = screencoord[0];
y[k] = screencoord[1];
z[k] = screencoord[2];
}
}
projections[i][j] = new PolygonArray(x, y, z);
}
}
return projections;
}
/*******************************************************************/

View File

@ -92,4 +92,9 @@ public class ViewportConfiguration {
vc.setMode(mode);
return vc;
}
public int[] toArray() {
int[] a = {x, y, width, height};
return a;
}
}

View File

@ -130,7 +130,7 @@ public class TexturedCube extends Composite implements Selectable, ITranslucent
@Override
public void project(IPainter painter, Camera cam) {
lastProjection = cam.modelToScreen(painter, getBounds().getVertices());
lastProjection = painter.modelToScreen(getBounds().getVertices());
lastHull = ConvexHull.hull(lastProjection);
}

View File

@ -99,7 +99,7 @@ public class TexturedCylinder extends Composite implements Selectable, ITransluc
@Override
public void project(IPainter painter, Camera cam) {
lastProjection = cam.modelToScreen(painter, getBounds().getVertices());
lastProjection = painter.modelToScreen(getBounds().getVertices());
lastHull = ConvexHull.hull(lastProjection);
}