mirror of https://github.com/rusefi/jzy3d-api.git
Mouse projection supports margin, mouse over format labels, Painter directly provide modelToScreen and screenToModel
This commit is contained in:
parent
b3abb5d6e5
commit
72c612b888
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package org.jzy3d.plot3d.primitives.axis;
|
||||
|
||||
public enum Axis {
|
||||
X, Y, Z
|
||||
}
|
|
@ -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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
|
|
|
@ -92,4 +92,9 @@ public class ViewportConfiguration {
|
|||
vc.setMode(mode);
|
||||
return vc;
|
||||
}
|
||||
|
||||
public int[] toArray() {
|
||||
int[] a = {x, y, width, height};
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue