I create JFreeChart program that can:
move points of splines
don't allow to cross black splines (boundary splines)
create new splines in real-time (as Grapher)
mouse wheel zoom
For adding new series to dataset I use this function:
public static XYSeriesCollection createSplineDataset(File[] polFiles) {
dataset = new XYSeriesCollection();
for (File polFile : polFiles) {
XYSeries series = new XYSeries(polFile.getName());
Scanner s = null;
try {
s = new Scanner(new File(polFile.getAbsolutePath()));
}catch (FileNotFoundException ex) {
System.out.println("Scanner error!");
}
s.useLocale(Locale.US);
while (s.hasNext()) {
float x = s.nextFloat();
float y = s.nextFloat();
series.add(x, y);
}
dataset.addSeries(series);
}
return dataset;
}
Main program (there 500+ strings of code, so this is part of it):
public class SplineDemo {
// declaration of variables
private static void display(){
final File[] polFiles = new File("FORPLOT").listFiles();
polFiles[0] = new File("FORPLOT/InitPolin1");
polFiles[1] = new File("FORPLOT/InitPolin0");
for (int i = 2; i <= 36; i++)
polFiles[i] = new File("FORPLOT/P"+(i-2));
dataset = JFunc.createSplineDataset(polFiles); // create dataset
// --------some code-----------
NumberAxis domain = new NumberAxis("\u03C1");
NumberAxis range = new NumberAxis("g(\u03C1)");
SplineRenderer r = new SplineRenderer(20);
xyplot = new XYPlot(dataset, domain, range, r);
final XYLineAndShapeRenderer render = (XYLineAndShapeRenderer) xyplot.getRenderer();
render.setBaseShapesVisible(true);
final JFreeChart chart = new JFreeChart(xyplot);
// --------some code-----------
chartPanel = new ChartPanel(chart){
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
};
chart.removeLegend();
chartPanel.addMouseListener(new MouseListener() {
//------ for creating new splines and to move points of splines ---------
});
chartPanel.addMouseWheelListener(new MouseWheelListener() {
//--------- zoom ------------
});
chartPanel.addMouseMotionListener(new MotionListener());
chartPanel.addChartMouseListener(new ChartMouseListener() {
//------ for creating new splines and to move points of splines ---------
});
chartPanel.setDomainZoomable(false);
chartPanel.setRangeZoomable(false);
chartPanel.setPopupMenu(null);
frame = new JFrame(Title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(chartPanel);
//------ buttons -------
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.addComponentListener(new ComponentListener() {
#Override
public void componentResized(ComponentEvent ce) {
// ---- to move points when window was resized
}
});
}
public static class MotionListener implements MouseMotionListener {
//------ to move points -----------
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
display();
}
});
}
}
So, #trashgod adviced here to modify useBuffer but it didn't help me.
So, my problem is that when at there are 1-5 splines at the same time plotted, everything works ideally quickly. When them becomes more than 30 splines as on a screenshot, working is decelerated (for example, points aren't in time behind a mouse in case of moving, zoom works slower, etc.). In what the problem can consist? Here the report from YourKit, but I don't understand it. Slowly the new draw of all diagrams or what works?
I don't understand how 30 diagrams can already brake so. What will be in case of 100+? If it is necessary, I can throw off a full code and project in zip archive
The XYSplineRenderer "connects data points with natural cubic splines." Not unexpectedly, its performance scales poorly for thousands points. If the goal is to render smoothed data, it may be advantageous to do the interpolation in the background, as suggested here, and revert to the parent XYLineAndShapeRenderer for rendering only.
In addition, scores of curves, each having hundreds of points, may be difficult to distinguish visually. Consider controlling the visibility of related series, a shown in this example that uses JCheckBox to toggle the display of individual series.
Related
I'm experiencing a rendering/painting issue with a simple drawing of a line in Swing when it is applied to a component which contains an already existing graph created using Graphstream.
Issue is when the mouse is dragged and painting method called, the underlying graph is updated and the whole frame flickers and line is not drawn smoothly.
Is there a way to freeze the rendering of the underlying graph?
I have tried several approaches but all seem to produce the same result. Below the latest example I tried setting a forelayout renderer on the view.
I believe it is a simple issue related to an incorrect approach to drawing on the canvas without properly managing the concurrency or update of the repaint/render of this foreground layer.
Also, as seen below, I remove all listeners from the graph before adding my own custom one (otherwise when dragging the mouse, a bounding box/selection rectangle is drawn by the graphstream library, or a node is dragged). Is there a better way also here to deactivate the drawing and mouse interaction done by graphstream.
import org.graphstream.graph.Graph;
import org.graphstream.graph.implementations.DefaultGraph;
import org.graphstream.ui.graphicGraph.GraphicGraph;
import org.graphstream.ui.swing_viewer.DefaultView;
import org.graphstream.ui.swing_viewer.SwingViewer;
import org.graphstream.ui.view.LayerRenderer;
import org.graphstream.ui.view.Viewer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class LinesDrawingOnGraphExample extends JFrame {
static Point pointStart = null;
static Point pointEnd = null;
static LayerRenderer lineRenderer;
static DefaultView view;
public static void main(String args[]) throws Exception {
JFrame f = new JFrame("Draw a Red Line on graph");
f.setSize(300, 300);
f.setLocation(300, 300);
f.setResizable(false);
//build graph
Graph graph = new DefaultGraph("g");
graph.addNode("A");
graph.addNode("B");
graph.addNode("C");
graph.addNode("D");
graph.addNode("E");
graph.addNode("F");
graph.addNode("G");
graph.addNode("H");
graph.addNode("I");
graph.addEdge("AB", "A", "B");
graph.addEdge("BC", "B", "C");
graph.addEdge("CA", "C", "A");
//set viewer
Viewer viewer = new SwingViewer(graph, Viewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
view = (DefaultView) viewer.addDefaultView(false);
viewer.enableAutoLayout();
viewer.replayGraph(graph);
//backup existing default graph listeners
MouseListener[] ml = ((DefaultView) viewer.getDefaultView()).getMouseListeners();
MouseMotionListener[] ml2 = ((DefaultView) viewer.getDefaultView()).getMouseMotionListeners();
//remove them (remove the bounding box which is drawn on mouse drag)
for (MouseListener mouseListener : ml) {
view.removeMouseListener(mouseListener);
}
for (MouseMotionListener mouseListener : ml2) {
view.removeMouseMotionListener(mouseListener);
}
//add new mouse listeners for drawing
MouseAdapter newListener = new DrawListener();
view.addMouseListener(newListener);
view.addMouseMotionListener(newListener);
//use graph forelayout for drawing the line
lineRenderer = new LayerRenderer<Graphics2D>() {
#Override
public void render(Graphics2D g, GraphicGraph graphicGraph, double v, int i, int i1, double v1, double v2, double v3, double v4) {
if (pointStart != null && pointEnd != null) {
g.setColor(Color.RED);
g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);
}
}
};
view.setForeLayoutRenderer(lineRenderer);
JPanel p = new JPanel(new BorderLayout());
p.add(view, BorderLayout.CENTER);
f.add(p);
f.setVisible(true);
}
private static class DrawListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
pointStart = e.getPoint();
}
public void mouseReleased(MouseEvent e) {
pointStart = null;
}
public void mouseDragged(MouseEvent e) {
pointEnd = e.getPoint();
view.render((Graphics2D) view.getGraphics());
}
}
}
I am trying to create a program in Java that is sort of like a board game. I have gameTiles, currently with only one color as I try to get the layout right. I want the tiles to appear about halfway of the width of the window and extend to the bottom, maybe anywhere from 9x9 or 11x11 different tiles. I have tried to use the grid layout to get these to be close together, not necessarily touching but close enough to look like a board game. However, no matter what I try, the tiles are space so far apart, and change shape when I resize window. I have been using the GridLayout manager to try to achieve this. Here is my code.
import java.awt.GridLayout;
import javax.swing.JFrame;
public class GameWindow extends JFrame {
public GameWindow(String title){
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1200,400);
}
/**
* #param args
*/
public static void main(String[] args) {
GameWindow gameWindow = new GameWindow("Game");
gameWindow.setLayout(new GridLayout(0,2));
GameTile greenTile = new GameTile(0,true,0,10);
GameTile greenTile2 = new GameTile(0,true,0,10);
gameWindow.add(greenTile);
gameWindow.add(greenTile2);
gameWindow.setVisible(true);
}
}
This is the GameWindow.java file. The GameTile.java I have so far (which is still mainly not finished just for testing) is as follows:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
/**
* #author Zachary Parks
*
*/
public class GameTile extends JPanel {
private Color color;
private Color[] colors = {Color.BLUE, Color.YELLOW, Color.BLACK};
private int score, multiplier,initialX,initialY;
private boolean positiveEffect;
public GameTile(int colorTile, boolean effect, int initX, int initY){
color = colors[colorTile];
score = getScore(color);
multiplier = getMultiplier(color);
positiveEffect = effect;
initialX = initX;
initialY = initY;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Image image = null;
try {
image = ImageIO.read(new File("greentile.png"));
} catch (IOException e) {
e.printStackTrace();
}
g.drawImage(image,initialX,initialY,this);
}
private int getMultiplier(Color color2) {
return 0;
}
private int getScore(Color color2) {
return 0;
}
/**
* Method that returns the data from the tile in
* array of int. 0 index = added score, 1 index = tile effect score
* #return
*/
public int[] getData() {
int [] scoreData = null;
scoreData[0] = score*multiplier;
return null;
}
}
A lot of the code is still in progress, like the GameTile's properties, all I'm trying at this point is get the tiles next to each other.
This is what I am getting:
To add tiles like a grid. A tileSize variable is great to have. Let's say the image/tile is 32 pixels.
public static final tileSize = 32;
With this, we can now add tiles using a for loop:
for(int x = 0; x < SCREEN_WIDTH / GameTile.tileSize; x++) { // loop through as many tiles fit the x-axis.
for(int y = 0; y < SCREEN_HEIGHT / GameTile.tileSize; y++) { // do the same with y-axis
GameTile greenTile = new GameTile(0,true, x * GameTile.tileSize , y * GameTile.tileSize);
gameWindow.add(greenTile);
}
}
SCREEN_WIDTH and SCREEN_HEIGHT is the size of your JFrame.
Keep in mind this loops through the whole screen, you wanted the half but it's easily configurable.
Please format your code next time (tab in), much easier to read and help you.
I highly recommend moving image = ImageIO.read(new File("greentile.png")); into the constructor, right now you're loading the image every framerate for every gameTile which will cause performance drop.
Also do not have a JPanel for every GameTile. Instead keep it in your main drawing class and loop through all GameTiles using an ArrayList
public static ArrayList<GameTile> gameTiles = new ArrayList<GameTile>();
protected void paintComponent(Graphics g) {
for(int i = 0; i < gameTiles.size(); i++) {
gameTiles.get(i).draw(g);
}
So instead of adding a JPanel to the JFrame for every gameTile, we draw gameTiles at the specified coordinates. Good luck!
To answer your question in the comment field: the code will look similar to this
public class GameWindow extends JPanel {
public static ArrayList<GameTile> gameTiles = new ArrayList<GameTile>();
public static void main(String[] args) {
new GameWindow();
}
public GameWindow() {
JFrame frame = new JFrame();
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.setVisible(true);
// add all the tiles (I just use x and y as parameters here)
gameTiles.add(new GameTile(10, 10));
gameTiles.add(new GameTile(50, 10));
}
public void paintComponent(Graphics g) {
for(int i = 0; i < gameTiles.size(); i++) {
gameTiles.get(i).draw(g);
}
}
}
And inside your GameTile class, remove the extends JPanel. And rename the paintComponent as draw or something alike.
However, no matter what I try, the tiles are space so far apart, and change shape when I resize window
A GridLayout expands each cell to fill the space available to the component. If you only have two cells each cell will take up half the width of the frame.
So the solution is to wrap your tile panel into another panel that will respect the preferred size of the tiles. So don't set the layout of the frame, set the layout of a panel holding the tiles:
Something like:
JPanel tilePanel = new JPane( new GridLayout(0, 2, 5, 5) );
tilePanel.add( new GameTile(...) );
tilePanel.add( new GameTile(...) );
JPanel wrapper = new JPanel( new GridBagLayout() );
wrapper.add(tilePanel, new GridBagConstraints() );
frame.add(wrapper, BorderLayout.CENTER );
The above code will cause the tiles to be centered in the frame.
frame.add(wrapper, BorderLayout.LINE_END);
The above will cause the tiles to display on the right of the frame vertically centered.
I have difficulties drawing an image on a JFreeChart - XYLineChart. The main problem is the x and y coordinates of the annotation is updated dynamically in real time.So with my code adding the annotation and clearing it for the new one to be drawn causes flickering which is annoying for the user.
I have checked some examples of flickering problems on JAVA using update() , paint () or repaint() methods using graphics but seems not implementable on a JFreeChart.
Do you have any ideas how to get rid of the flicker or a workaround to use one bufferedImage on the JFreeChart instead of an annotation ?
To be more specific here is the drawn line and the image :
Screenshot
So this cross hair (as the buffered image) should go on the plot line up and down with the updated values of x and y axis.But this motion causes the flickering unfortunately.
Here is the part of my code where I draw the image - I cannot provide SSCCE I guess since there are more than 15 classes and 5k of written code :
// After a button clicked on panel
SomeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
// The chart and XYPlot is already drawn at this point
// Reading the image
try {
myPicture = ImageIO
.read(new File("\\\\Users2\\blabla\\Data\\MyPictures\\x.png"));
} catch (IOException e) {
e.printStackTrace();
}
// Setting up a timer
timer2 = new java.util.Timer();
Object source = event.getSource();
if (source == SomeButton) {
// Setting up a task
task2 = new java.util.TimerTask() {
#Override
public void run() {
double x1;
double y1;
try {
// Getting different x and y values from a microcontroller instantaneously
if (microContConnected()) {
x1 = microCont.getX();
y1 = microCont.getY();
// creating the annotation
XYImageAnnotation ImageAnn = new XYImageAnnotation(x1, y1, myPicture);
// Here is the drawing and clearing made !
plot.addAnnotation(ImageAnn);
pause(50);
plot.clearAnnotations();
}
} catch (SerialPortException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
timer2.scheduleAtFixedRate(task2, 50, 50);
}
}
});
It seems I found a solution myself ; instead of adding the image to plot I use the renderer and there is no pause function between adding and removing the picture with new coordinates.. also sequence of adding and removed are reversed. Surprising for me to work this way I must say. There is no flickering left; it's as smooth as a clipped graphics or double buffered. :) Here is the new code :
// renderer
final XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
// Reading the image
try {
myPicture = ImageIO.read(new File("\\\\Users2\\blabla\\Data\\MyPictures\\x.png"));
} catch (IOException e) {
e.printStackTrace();
}
// Setting up a timer
timer2 = new java.util.Timer();
Object source = event.getSource();
if (source == someButton) {
task2 = new java.util.TimerTask() {
#Override
public void run() {
if (check == true) {
if (microContConnected()) {
x1 = microCont.getX();
y1 = microCont.getY();
renderer.removeAnnotations();
XYImageAnnotation img2 = new XYImageAnnotation(
x1, y1, myPicture);
renderer.addAnnotation(img2,
Layer.FOREGROUND);
}
}
}
};
timer2.scheduleAtFixedRate(task2, 50, 50);
}
I am a new in java, and I need to implement a paint application, and I'm kinda stuck at the beggining, I managed to draw lines to a JPanel which I added to a JFrame, but each line drawn resets the entire drawing, and in the draw area remains only the last line drawn. I hope I made myself understood, here his the code:
class Shapes extends JFrame {
public JFrame mf = new JFrame("Paint");
DrawArea da = new DrawArea();
JToggleButton lineButton = new JToggleButton(new ImageIcon("line.gif"));
JToggleButton brushButton = new JToggleButton();
JToggleButton pencilButton = new JToggleButton();
JToggleButton eraserButton = new JToggleButton(new ImageIcon("eraser_icon.png"));
JToggleButton rectangleButton = new JToggleButton();
JToggleButton ovalButton = new JToggleButton();
Shapes() {
da.setBounds(120, 50, 500, 350);
da.setBackground(Color.YELLOW);
mf.setSize(700, 500);
mf.setLayout(null);
lineButton.setBounds(0, 50, 40, 40);
brushButton.setBounds(40, 50, 40, 40);
eraserButton.setBounds(0, 90, 40, 40);
pencilButton.setBounds(40, 90, 40, 40);
rectangleButton.setBounds(0, 130, 40, 40);
ovalButton.setBounds(40, 130, 40, 40);
mf.setBackground(Color.red);
mf.add(lineButton);
mf.add(brushButton);
mf.add(pencilButton);
mf.add(eraserButton);
mf.add(rectangleButton);
mf.add(ovalButton);
mf.add(da);
mf.show();
mf.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
mf.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
System.out.println("x:" + e.getX() + "y:" + e.getY() + "\n" + "x2:" + e.getXOnScreen() + "y2:" + e.getYOnScreen());
}
});
eraserButton.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e)
{
eraserButton.setSelectedIcon(new ImageIcon("eraser_icon_selected.png"));
}
});
lineButton.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e)
{
lineButton.setSelectedIcon(new ImageIcon("line_selected.png"));
}
});
da.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
da.setXvalue(e.getX());
da.setYvalue(e.getY());
}
public void mouseReleased(MouseEvent e) {
da.setX2value(e.getX());
da.setY2value(e.getY());
da.repaint();
}
});
da.addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
da.repaint();
da.setX2value(e.getX());
da.setY2value(e.getY());
}
});
}
}
public class DrawArea extends JPanel {
int x1value,y1value,x2value,y2value;
public int getX2value() {
return x2value;
}
public void setX2value(int x2value) {
this.x2value = x2value;
}
public int getY2value() {
return y2value;
}
public void setY2value(int y2value) {
this.y2value = y2value;
}
public JPanel dra=new JPanel();
public int getXvalue() {
return x1value;
}
public void setXvalue(int xvalue) {
this.x1value = xvalue;
}
public int getYvalue() {
return y1value;
}
public void setYvalue(int yvalue) {
this.y1value = yvalue;
}
public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.red);
g.drawLine(getXvalue(),getYvalue(),getX2value(),getY2value());
}
}
class Paint extends JPanel
{
public static void main(String args[])
{
Shapes s=new Shapes();
}
}
See Custom Painting Approaches for two solutions. The examples draw rectangles, but the concept is the same for lines.
Override paintComponent(), not paint(). Read this tutorial. When a panel needs to be redrawn, you call that panels repaint() method.
Paint is called by the window manager any time it considers that area 'unfresh'. If you do it the way you're doing it right now, you will draw the last line drawn every time.
The proper way to do this would be to make a BufferedImage in memory and draw on that. Then, in the paint method, blit the BufferedImage onto the surface. This also makes scrolling and zooming quite easy to do.
Whenever you perform such an action, invalidate the surface so that the window manager will call the paint method for you.
You are only storing one line, and overwriting it each time, so when the component is repainted, the old one is erased and the new one is redrawn.
The expectation of paintComponent and the like is that your implementation will draw EVERY graphical element that you want to appear, each time it is called.
Instead of storing x1, y1, x2, y2, you should make a LineSegment class or similar that stores those values. Then, when you paint, you call g.drawLine() for each LineSegment object that you've stored (presumably in an ArrayList or similar). Then, when the component is redrawn, all of your line segments should appear on the screen.
A little bit off topic, but I had a few uncomfortable minutes cause I used update() instead of repaint(). I advice to everyone working with SWING to spend some time checking which methods should handled as thread safe and which ones has to be on EDT (Event Dispatcher Thread) to make sure you won't get some unexpected errors.
This is a good article about this.
Also, at the beginning think through if you want to have an undo/redo system in your app...
If so, than how many steps you want to allow being withdrawn. If you want to allow this feature than you cannot just draw and forget about what you draw last time.
Also it would be not memory efficient to store all the images you draw so far. I'm not an expert and I'm not saying this is the best practice but I would go this way:
I would make two lists.
One of them would store the applied drawing actions,
the other would contain the withdrawn drawing actions.
Drawing action would be an interface and some class would implement it for each specific kind of drawing action (LineDrawAction, CirceDrawAction...).
When you draw a new line or whatever you would empty the withdrawn actions list and add it to the applied action list. When someone undo the last action, than I would just remove the last drawing actions from the applied list and would add to the withdrawn list (etc...). Depending on if you want to allow only the last x action to be undone when a list reaches this x limit I would remove the first drawing action from the list or queue and would finally draw to the picture - this means permanent drawing and this cannot be undone.
I hope it's clear and useful even if not a direct answer to your question.
I want that when I click on a specific point on the screen, a function call that return the point in 3d scene that I click.
For example, when I click on the top left of the screen, it should return x = 0, y = 1, z= 1; please help me create a method to do this.
edit:
Root = new BranchGroup();
setLayout(new BorderLayout());
add(canvas3D,BorderLayout.CENTER);
SimpleUniverse universe = new SimpleUniverse(canvas3D);
Shape();
universe.addBranchGraph(Root);
ViewingPlatform viewingPlatform = universe.getViewingPlatform();
OrbitBehavior behavior = new OrbitBehavior(canvas3D);
behavior.setSchedulingBounds(bounds);
viewingPlatform.setViewPlatformBehavior(behavior);
viewingPlatform.setNominalViewingTransform();
}
I'm using SimpleUniverse in NetBeans.
I'm afraid the answer isn't straight forward. Depending on what is in your scene the mouse coordinates should change when you click on the screen. For instance if you have two objects so that the front one occludes the back one then you'd want to get the front objects coordinates. This is called mouse picking and there are several techniques for it. I found a few forums that explain how it's done and have code examples.
Basically the idea is that you imagine there being a laser (or something else that casts a ray) between you the user and the screen. This thing then projects a ray through the point on the screen surface where the mouse was clicked "into" the screen. Anything that is on the rays path will then be picked and optionally the occlusion order of objects in the ray's path is resolved to give you the object closest to the "screen".
I am not familiar with J3D, but scraped the following code together from a few tutorials. It should get you started at least. The this you are looking for is this line Point3D intercept = ... at the bottom.
http://www.java3d.org/selection.html
package j3d_picking;
import java.awt.*;
import javax.swing.*;
import javax.media.j3d.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.picking.behaviors.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.picking.PickIntersection;
import com.sun.j3d.utils.picking.PickResult;
import com.sun.j3d.utils.picking.PickTool;
import javax.vecmath.Point3d;
public class HelloJava3D
extends JFrame
{
public HelloJava3D()
{
GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
Canvas3D canvas3D = new Canvas3D(config);
BranchGroup scene = createSceneGraph();
// SimpleUniverse is a Convenience Utility class
SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
// This moves the ViewPlatform back a bit so the
// objects in the scene can be viewed.
simpleU.getViewingPlatform().setNominalViewingTransform();
BoundingSphere behaveBounds = new BoundingSphere();
ExamplePickBehavior behavior = new ExamplePickBehavior(canvas3D, scene, behaveBounds);
scene.addChild(behavior);
scene.compile();
simpleU.addBranchGraph(scene);
getContentPane().add(canvas3D, BorderLayout.CENTER);
} // end of HelloJava3D (constructor)
public BranchGroup createSceneGraph()
{
// Create the root of the branch graph
BranchGroup objRoot = new BranchGroup();
// Create a simple shape leaf node, add it to the scene graph.
// ColorCube is a Convenience Utility class
ColorCube cube = new ColorCube(0.4);
cube.setCapability(Node.ENABLE_PICK_REPORTING);
PickTool.setCapabilities(cube, PickTool.INTERSECT_FULL);
objRoot.addChild(cube);
return objRoot;
} // end of createSceneGraph method of HelloJava3D
public static void main(String[] args)
{
JFrame frame = new HelloJava3D();
frame.setTitle("Hello Java3D");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(0, 0, 400, 300);
frame.setVisible(true);
}
private class ExamplePickBehavior extends PickMouseBehavior
{
public ExamplePickBehavior(Canvas3D canvas, BranchGroup bg, Bounds bounds)
{
super(canvas, bg, bounds);
setSchedulingBounds(bounds);
pickCanvas.setMode(PickTool.GEOMETRY_INTERSECT_INFO);
// allows PickIntersection objects to be returned
}
public void updateScene(int xpos, int ypos)
{
pickCanvas.setShapeLocation(xpos, ypos);
// register mouse pointer location on the screen (canvas)
Point3d eyePos = pickCanvas.getStartPosition();
// get the viewer's eye location
PickResult pickResult = null;
pickResult = pickCanvas.pickClosest();
// get the intersected shape closest to the viewer
if (pickResult != null) {
PickIntersection pi = pickResult.getClosestIntersection(eyePos);
// get the closest intersect to the eyePos point
Point3d intercept = pi.getPointCoordinatesVW();
System.out.println(intercept);
// extract the intersection pt in scene coords space
// use the intersection pt in some way...
}
} // end of updateScene( )
} // end of ExamplePickBehavior class
}
enter code hereThe Java code below , prints the 3d object's (shapes) center coordinates in the 3d screen. Result is (x=-0.5 ,y=0.0 ,z=0.4)
public class secim2 extends MouseAdapter{
private PickCanvas pickCanvas;
public secim2(){
JFrame pencere=new JFrame();
pencere.setSize(300, 300);
pencere.setVisible(true);
JFrame frame = new JFrame(" 3D Box Select");
GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
Canvas3D canvas = new Canvas3D(config);
SimpleUniverse universe = new SimpleUniverse(canvas);
BranchGroup group = new BranchGroup();
// create a color cube
Transform3D transform= new Transform3D();
Vector3d vector = new Vector3d(-0.5, 0.0, 0.4);
Transform3D transform = new Transform3D();
transform.setTranslation(vector);
TransformGroup transformGroup = new TransformGroup(transform);
ColorCube cube = new ColorCube(0.1f);
transformGroup.addChild(cube);
group.addChild(transformGroup);
universe.getViewingPlatform().setNominalViewingTransform();
universe.addBranchGraph(group);
pickCanvas = new PickCanvas(canvas, group);
pickCanvas.setMode(PickCanvas.GEOMETRY_INTERSECT_INFO);
pencere.add(canvas);
canvas.addMouseListener(this);
}
public void mouseClicked(MouseEvent e)
{
pickCanvas.setShapeLocation(e);
PickResult result = pickCanvas.pickClosest();
if (result == null) {
} else {
Primitive p = (Primitive)result.getNode(PickResult.PRIMITIVE);
Shape3D s = (Shape3D)result.getNode(PickResult.SHAPE3D);
if (p != null) {
System.out.println(p.getClass().getName());
} else if (s != null) {
System.out.println(s.getClass().getName());
Vector3f position = new Vector3f();
s.getLocalToVworld(transform);
transform.get(position);
System.out.print(position);
// System.out.print( s.getLocalToVworld(transform2);
} else{
System.out.println("null");
}
}
}
}
public class tuval1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
new secim2();
}
}