How can I create a player of 3d data? - javafx

I have a file of 3D data (time,x,y,z) and I want to create a JavaFX interactive animation with play, pause buttons, and the option of rotating the 3d objects.
I don't find in JavaFX any base example, it seems like I have to recreate my own mediaplayer.

Have a look at this library, F(X)yz is an open source
JavaFX 3D library that provides additional primitives, composite objects, controls and data visualizations that the base JavaFX 8 3D packages do not have.
There are several components that may help you. For instance, all the TexturedMesh subclasses are 3D shapes that allow using mathematical expressions to create contour plots (by using textures).
As an example, have a look at the icosahedron test.
private IcosahedronMesh ico;
private DensityFunction<Point3D> dens = p-> (double)p.x*p.y*p.z;
#Override
public void start(Stage primaryStage) throws Exception {
...
ico = new IcosahedronMesh(5,1f);
ico.setTextureModeVertices3D(1530,dens);
Group sceneRoot = new Group(ico);
Scene scene = new Scene(sceneRoot, 800, 600, true, SceneAntialiasing.BALANCED);
...
}
This short snippet will create something like this:
Now you can add some animation:
long lastEffect = System.nanoTime();
AtomicInteger count=new AtomicInteger();
AnimationTimer timerEffect = new AnimationTimer() {
#Override public void handle(long now) {
if (now > lastEffect + 50_000_000l) {
double t=count.getAndIncrement()%10;
dens = p->(double)(p.x+t)*(p.y+t)*(p.z+t);
ico.setDensity(dens);
lastEffect = now;
}
}
};
timerEffect.start();
and you will see something like this.
You could add on top of the subscene the usual media player controls, and bind them to the animation. Also you can add other animations to rotate the 3D shapes.
So the only thing you will have to add is a way of passing your data files to the shapes... You can add a feature request on the F(X)yz repository, providing some specific format of the data, the shapes you need...
For more information, you can also have a look at this post.

Related

JavaFX - How to use ImageView methods on Object type?

I'm trying to create an EventHandler for the mouse dragged event. I'll use this same handler to do the same thing with several ImageViews. Now this is what I did.
static EventHandler<MouseEvent> dragHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
e.getSource().toFront();
e.getSource().setTranslateX(e.getSceneX() );
e.getSource().setTranslateY(e.getSceneY() );
}
};
But apparently I can't use toFront or setTranslate methods or anything that I used for ImageViews because e.getSource returns an Object and these are ImageView methods that are not available to Object type. And apparently I can't simply cast that into an ImageView either by doing
(ImageView)( e.getSource() ).toFront();
I could simply use inner classes and lambda expressions but I thought there must be a more efficient way than just copy pasting the same lines like 15 times for each ImageView. So please enlighten me if there is.
Thanks in advance.
Casting would work, but the precedence of casting is below that of dereferencing (.), so your code example tries to downcast the result of (e.getSource()).toFront(), which doesn't work (as that has no type, since toFront() is void).
So
((ImageView) e.getSource() ).toFront();
would work.
However, it's usually better to register a different handler for each image view. There's no need to repeat code: just use any standard programming technique to avoid doing so. E.g. you can write a method:
private void registerEventHandler(ImageView imageView) {
imageView.setOnMouseDragged(e -> {
imageView.toFront();
imageView.setTranslateX(e.getSceneX() );
imageView.setTranslateY(e.getSceneY() );
});
// register other event handlers, as needed.
}
and then call the method for each image view (in a loop, if you have them in some suitable data structure).
Alternatively, you could create a method that creates the image views and registers any necessary handlers.
As well as being arguably cleaner code, these techniques also avoid the downcast, which in general is a good thing.

How to bind lists like an updating ForEach?

Here is a sample code:
public class Example3 {
class Point {
int x, y; // these can be properties if it matters
}
class PointRepresentation {
Point point; // this can be a property if it matters
public PointRepresentation(Point point) {
this.point = point;
}
}
Example3() {
ObservableList<Point> points = FXCollections.observableArrayList();
ObservableList<PointRepresentation> representations = FXCollections.observableArrayList();
points.forEach(point -> representations.add(new PointRepresentation(point)));
}
}
I have a data holder Point and a data representor PointRepresentation. I have a list of points and i would like that for each point in the list there would be an equivalent representation object in the second list. The code I gave works for the initialization but if there is any change later the above will not update.
What I am doing now is using a change listener to synchronize the lists (add and remove elements based on the change object) and it's OK but i am wondering if there's a simpler solution. I was looking for something like a "for each bind" that means: for each element in one list there is one in the other with the specified relation between them [in my case its that constructor]. In pseudocode:
representations.bindForEach(points, point -> new PointRepresentation(point));
Things I looked at: extractors for the list but that sends updates when a property in the objects they hold change and not when the list itself changes. So in my case if x in the point changes i can make an extractor that notifies it. Another thing I looked at is http://docs.oracle.com/javase/8/javafx/api/javafx/beans/binding/ListBinding.html, so maybe a custom binding does it but I don't know if it's simpler.
Also is there a similar solution for arrays instead of lists? i saw the http://docs.oracle.com/javase/8/javafx/api/javafx/collections/ObservableArray.html as a possibility.
The third-party library ReactFX has functionality for this. You can do
ObservableList<Point> points = FXCollections.observableArrayList();
ObservableList<PointRepresentation> representations = LiveList.map(points, PointRepresentation::new);
This will update representations automatically on add/remove etc changes to points.

Automatically read a file - easy

This should be a really easy question, but I just cant seem to get it done, I have a section of code calculating X Y points on a graph, then saving them to file.
If a certain condition is met I want to plot the values on a graph, I am using this code to plot the graph- http://www.kodejava.org/examples/805.html
But I don't want it to ask for the user to point to the file location, I just want it to open a file which has a directory hard coded in, and plot it automatically. So basically remove the buttons at the top and carry out the commands of the buttons automatically.
Would be fantastic if somebody could point me in the right direction, I'm a physicist not a coding expert so as much help as possible would be excellent.
Hope I can help one of you in return sometime.
1) Inside public static void main, just above frame.setVisible(true); insert openButton.setVisible(false);
2) Inside class GraphPanel, inside the method public void actionPerformed(ActionEvent e) insert datapanel.actionPerformed(e); as the first line.
3) Inside class DataPanel inside public void actionPerformed comment out from the beginning JFrame fileFrame = new JFrame(); to initialized = readFile(datafile);
4) Just after the comment, insert initialized = readFile(new File("path_to_data_file"));
Now if you open, and press plot, the hard coded file will be read and plot will be drawn.
Heck,, I don't care if this gets downvoted :). I've never touched Java. After reading your problem, specially I'm a physicist not a coding expert first i searched in google how to compile and run a java file. Then started reading the java program. I even made another version which does not need the button press also, Just open and your graph will be drawn. But that's only if needed, then provided. "Welcome to my java attempt" :)
Update:
For doing without pressing plot, in GraphPanel and DataPanel, and rename the actionPerformed methods to something else like GraphPanel::start_working and DataPanel::start_working Now inside GraphPanel::start_working call DataPanel::start_working instead of earlier datapanel.actionPerformed(e); . If compiler cribs, add some empty actionPerformed for compilation. (perhaps we can remove the implements ) Now your flow is ready without any user action. you just need to start it. So you set plotButton.setVisible(false); to hide the plot button and call graphpanel.start_work(); to start the flow in main.
Update:
Inside GraphPanel
public void start_working() {
datapanel.start_working()
if (!datapanel.isInitialized()) {
return;
}
datapanel.refreshData();
panel.setDisplayPlot(true);
panel.update(panel.getGraphics());
frame.setSize(700, 600);
frame.setVisible(true);
frame.pack();
}
And inside DataPanel
public void start_working(ActionEvent e) {
initialized = readFile(new File("PATH_TO_FILE");
panel.update(panel.getGraphics());
frame.pack();
frame.setVisible(true);
}
in main last 5 lines
openButton.setVisible(false);
plotButton.setVisible(false);
graphpanel.start_working();
frame.setVisible(true);
frame.pack();

Qt: update pixmap grid layout with 2d array values

I am undertaking a game using a combination of c++ in visual studios 2010 and Qt 4.7 (both windows). The game is a clone of battleship and is console input based. I have created my gui how I want it to look, and on the Qt side in Qt designer, my gui consists of a grid layout 10x10, using labels to hold pixmaps of game cells:
I have painstakingly named each label to represent its position in the 2d array (ie. fleet map => F_00 => F[0,0] => F[i],[j]). I can manually choose what pixmap I would like to display using the properties editor, but I would like something dynamic.
I use an update mapboard class to redraw the game board after a player fires, which keeps storing over a char array. I would like to update my pixmaps for each, using a generic getupdatearray type function. As we traverse the array it will update the pixmap currently associated with individual labels to match their cousins from the array. (say F[5][6] = 'X' for hit, then when the loops got to that position in the array it would update the grid of pixmaps at F_56 to equal hit.png, replacing the empty.png.
I have an idea how to make the loop that would accomplish this, but unsure how i would go about getting the pixmap for each label to be more along the lines of a runtime feature versus the now compile time (static) feature. I have read about QPainter and another Qt class that deals with images, but still having a hard go at it.
Question to any of you, how do I update these pixmaps based on a 2d array?
loop structure - i can figure out
condition statements - i can figure out
qt specific syntax dealing with labels- newbie so no idea atm.
Here's some pseudocode of the kind of thing I am trying to do with map.h:
#include <QtCore>
#include <QtGui>
// WARNING: PSEUDOCODE, DOES NOT COMPILE
// AT A LOSS ON HOW TO SELECT THE CORRECT LABEL
// MAYBE A CHILD CLASS FOR THAT?
class map {
public:
char updateboard(char mapname, char b[][10]){
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
char C = b[i][j];
if (C == 'M'){//miss
Qlabel mapname_[i][j](<img src='images/missspace.png'/>);
mapname_[i][j].show();
}
else if(C == 'X'){//hit
Qlabel mapname_[i][j](<img src='images/hitspace.png'/>);
mapname_[i][j].show();
}
else if(C == ' '){//undiscovered space
Qlabel mapname_[i][j](<img src='image/emptyspace.png'/>);
mapname_[i][j].show();
}
}
}
}
};
Then in my mainwindow.cpp, I include map.h and say:
// calls class function update board
// takes updated array values and replaces old pixmap with new
map.updateboard(T,b[][10]); // target map update
map.updateboard(F,v[][10]); // fleet map update
Thanks in Advance
UPDATE:
I've gotten to the point where I can swap pixmaps with buttons presses, but I would like to create something more dynamic. I wanted to use a Qstring in which I place the name of the label I want to change using by appending x y values using:
TR_position.append(QString::number(xvalue));
When I try to call it using:
ui->TR_position->setPixmap(QPixmap(":/images/missspace.png"));
...it obviously doesnt work. Is there a way to type case it, or use the contents of the string as the Qlabel name?
You manually entered and named 200 label widgets? Let no one call you lazy. :)
Per your update, you now know how to use QLabel::setPixmap(). What you think you need is getting a QLabel pointer from a name, which would be a combination of two things:
QWidget::findChild to get a QWidget* from a QString
qobject_cast to get a QLabel* from a QWidget
If you go down this path, what you'd wind up with is something like:
QWidget* cellWidget = ui->findChild(TR_position);
QLabel* cellLabel = qobject_cast<QLabel*>(cellWidget);
cellLabel->setPixmap(QPixmap(":/images/missspace.png"));
But BEWARE! There are many things wrong with this approach.
It's brittle: What if there doesn't happen to be any widget with that name (mysterious crash)? Or even worse, what if there are multiple widgets with that name and this code marches along blissfully ignorant of that odd condition that is likely a bug?
It's poor OOP: While there are some decent cases to use dynamic casting (or "downcasting"), it usually indicates a flaw in a design. You know that all QLabels are QWidgets, but not all QWidgets are QLabels...so that qobject_cast call might return NULL. It's just one more point of failure. Sometimes you can't avoid this, but really there is no reason your program needs to be structured in such a way.
It's terribly slow: Searching for a widget by its name is essentially a naive recursive search. If you've set aside a separate widget frame for each grid and only search that, Qt will have to do 100 string compares to find the last element (so 50 in the average case). Imagine clearing the grid with a loop...now you're talking about 100*50 string compares!
All these things are avoidable. Just as it's possible to use loops to set the images on the controls by name, it's possible to use loops to create the widgets in the first place. You basically would leave the area for the game board blank in the design tool, and then dynamically create the controls with code...attach them to the layout with code...and save pointers to them in 2D array. (You wouldn't access them by label name at that point, you'd index them just as you are indexing your board.)
You could create your own class derived from QLabel (such as a GameCell class) which contained the information for your board cell and methods related to it. Then you wouldn't need an array of label widgets in parallel to an array representing your board. You'd simply have one array of objects that took care of both aspects of the implementation.
UPDATE: Since you asked in the comments for specifics, here's a GameCell class:
class GameCell : public QLabel
{
Q_OBJECT
public:
enum State { Undiscovered, Hit, Miss };
GameCell (QWidget *parent = 0) : QLabel (parent),
currentState (Undiscovered)
{
syncBitmap();
}
State getState() const { return currentState; }
void setState(State newState) {
if (currentState != newState) {
currentState = newState;
syncBitmap();
}
}
private:
void syncBitmap() { // you'd use setPixmap instead of setText
switch (currentState) {
case Undiscovered: setText("U"); break;
case Hit: setText("H"); break;
case Miss: setText("M"); break;
}
}
State currentState;
};
This does double duty by behaving like a QWidget as well as maintaining a piece of internal state. Then a GameMap widget can use a QGridLayout of these GameCells:
class GameMap : public QWidget {
Q_OBJECT
public:
static const int Rows = 10;
static const int Columns = 10;
GameMap (QWidget* parent = 0) :
QWidget (parent)
{
layout = new QGridLayout (this);
for (int column = 0; column < Columns; column++) {
for (int row = 0; row < Rows; row++) {
GameCell* cell = new GameCell (this);
cells[column][row] = cell;
layout->addWidget(cell, row, column);
}
}
}
private:
GameCell* cells[Columns][Rows];
QGridLayout* layout;
};
If you wanted to, you could just leave spaces in your layout in the designer you wanted to fill in with the GameMap widget. Or you can push on and do the whole thing programmatically. For the sake of simplicity I'll just put two boards next to each other with a vertical separator on the surface of a dialog:
class Game : public QDialog
{
Q_OBJECT
public:
Game (QWidget *parent = 0)
: QDialog(parent)
{
targetMap = new GameMap (this);
fleetMap = new GameMap (this);
verticalSeparator = new QFrame (this);
verticalSeparator->setFrameShape(QFrame::VLine);
verticalSeparator->setFrameShadow(QFrame::Sunken);
layout = new QHBoxLayout (this);
layout->addWidget(targetMap);
layout->addWidget(verticalSeparator);
layout->addWidget(fleetMap);
setLayout(layout);
setWindowTitle(tr("Battleship"));
}
private:
GameMap* targetMap;
QFrame* verticalSeparator;
GameMap* fleetMap;
QHBoxLayout* layout;
};
I'm not going to write a whole game here or make it look fancy. That's just the gist, showing how to get 200 labels up in a programmatic fashion:
With my code, getting a GameCell from an (x,y) coordinate doesn't require an average of 50 string compares. Due to the formalized and predictable nature of 2D arrays, indexing into cells[x][y] only requires a single multiply operation and a single addition operation. There's no downcasting, and you can simply write:
cells[x][y].setState(GameCell::Miss);
ADDENDUM: Creating a QWidget for each grid cell isn't necessarily the way to go in the first place. Some might consider that "heavyweight". If your game were being played out on a large virtual space of tiles then it could be much too slow. You might find it useful to look into QGraphicsGridLayout, which could be a more appropriate approach in the long run:
http://doc.qt.io/qt-5/qtwidgets-graphicsview-basicgraphicslayouts-example.html
Using QWidgets won't be much of an issue with a 10x10 grid, however, so if you want to just stick with that then you can. If you're going to do it that way, then at least you shouldn't be placing them all by hand!

Am I writing AS3 the right way?

I'm very new to flash and actionscript 3. I've been reading a lot about it and this is also my first aprouch on object oriented programming.
So far, I created an application with a login button, that's all. However, I would like to know what kind of things I am doing wrong or should be doing different (or better). I am using Adobe Flex Builder 3.
The main actionscript file is Client2.as:
package
{
//import required libraries
import flash.display.Sprite;
//set project properties
[SWF(width="800", height="600", frameRate="31", backgroundColor="#C0C0C0")]
//launch main class
public class Client2 extends Sprite
{
public function Client2() { //the constructor
trace("Client launched.");
var loginGui:LoginInterface = new LoginInterface(); //load the login interface object
loginGui.init(); //initialize the login interface (load it)
addChild(loginGui); //add login gui to the display tree
}
}
}
It is loading the login interface object. Is that a good thing, and am I doing it the right way?
Then there's the LoginInterface.as class file:
package
{
//import required libraries
import flash.display.Sprite;
//the LoginInterface class
public class LoginInterface extends Sprite
{
public function LoginInterface() //the constructor
{
trace("LoginInterface object loaded.");
}
public function init():void //initialize the login interface (load it)
{
trace("LoginInterface init method was called.");
var loginButton:CustomButton = new CustomButton(300, 300, 100, 30, 3, 18, "Login!"); //create a new custom button
addChild(loginButton); //add the custom button to the display tree
}
}
}
What about that? Any comments? To make the creation of simple buttons a bit easier, I then created another class file called CustomButton.as -->
package
{
import flash.display.SimpleButton;
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
public class CustomButton extends Sprite
{
public function CustomButton(xLoc:int, yLoc:int, width:int, height:int, iLabelOffset:int, fontsize:uint, label:String)
{
//create new simple button instance
var myButton:SimpleButton = new SimpleButton();
//create the look of the states
var normal:Sprite = new Sprite();
normal.graphics.lineStyle(1, 0x000000);
normal.graphics.beginFill(0x6D7B8D);
normal.graphics.drawRect(xLoc, yLoc, width, height);
//the mouseover sprite
var over:Sprite = new Sprite();
over.graphics.lineStyle(1, 0x000000);
over.graphics.beginFill(0x616D7E);
over.graphics.drawRect(xLoc, yLoc, width, height);
// assign the sprites
myButton.upState = normal;
myButton.downState = normal;
myButton.hitTestState = normal;
myButton.overState = over;
//add the button to the display tree
addChild(myButton);
//create button label
var tText:TextField = new TextField();
tText.mouseEnabled = false,
tText.x = xLoc;
tText.y = yLoc + iLabelOffset;
tText.width = width;
tText.selectable = false
var Format:TextFormat = new TextFormat();
Format.font = "Arial";
Format.color = 0x000000;
Format.size = fontsize;
Format.bold = false;
Format.align = TextFormatAlign.CENTER;
tText.defaultTextFormat = Format;
tText.text = label;
addChild(tText)
}
}
}
Is there anything to comment on this? I am sure that I'm doing a lot of things wrong, maybe I didn't really get the whole object oriented thing? Also, I have a bad feeling about the way I am using the "extends ..." after a class declaration, mainly because I'm just using Sprite all the time and don't really understand why or what it does (having trouble finding out on the internet aswell). Another thing I am unsure about is the naming of variables in AS3. Should I really be using names such as xLoc, or iLabelOffset? I think I am not being very consistent in my variable naming atleast?
I hope someone can give me a push to a better track than the one I am on now, as I am sure that I should improve my AS3 coding before I continue working on this beast.
Thanks a lot.
My opinion:
A class called Client2 is probably a bad naming choice. Client2 isn't telling me much. How much will it tell you in a year's time?
In CustomButton, initialization is taken care of in the constructor. In LoginInterface, using an instance of the class requires an explicit call to init(). Easy to forget and unnecessary. Unless there's a good reason not to, call init from the constructor.
What does iLabelOffset mean? better to use a less confusing name in a parameter list.
The parameter list of the CustomButton constructor is pretty long. It's not necessary to pass in the x and y. Sprite has an x and y property already, so put everything back to a zero offset and manipulate the x and y properties of the CustomButton once it's constructed.
Of the remaining parameters to the CustomButton constructor, consider reordering them so that you can provide default parameters (which can only go at the end of the parameter list). labelOffset and fontSize seem like good candidates.
Keep function size small by removing repeated code. Create a function to create the button state Sprites that takes a color in its parameters (or better yet, move this functionality into a new type of Sprite derived class), and also add a createLabel function so that you can move that code out of the constructor. Your code will become easier to read and maintain if you try to keep function size small. It also means you have to write less comments ;-)
Spender hit the nail on the head. Those are definitely the issues that are raised when I looked over your code. The things he mentioned are not nessesarly Actionscript issues, (issue's not quite the right word, perhaps "areas to note"), these are issues general to all programing languages. Descriptive naming for example is extremely important.
There are few books that focus on this side of programming, and even fewer that do it well. I would highly recommend picking up the following two books if you want to grow more in this area, (I'll recommend it even if you don't want too :)
Code Complete
The pragmatic programmer
There both books that every programmer should read, so check them out. You're code from an Actionscript point of view is fine, but that's just syntax. It's important to note that these skill will never develop unless you actually write code, so by all means "continue working on this beast" and the rest will follow suit.
Just as a matter of style, I like to declare my variables outside of the constructor. It helps me to feel that I won't have any surprises with public vs private or scope. Also notice the added white space, which can improve readability.
public class CustomButton extends Sprite
{
private var myButton:SimpleButton;
private var normal:Sprite;
private var over:Sprite;
// etc ...
public function CustomButton(xLoc:int, yLoc:int, width:int, height:int, iLabelOffset:int, fontsize:uint, label:String)
{
//create new simple button instance
myButton = new SimpleButton();
//create the look of the states
normal = new Sprite();
normal.graphics.lineStyle(1, 0x000000);
normal.graphics.beginFill(0x6D7B8D);
normal.graphics.drawRect(xLoc, yLoc, width, height);
//the mouseover sprite
over = new Sprite();
over.graphics.lineStyle(1, 0x000000);
over.graphics.beginFill(0x616D7E);
over.graphics.drawRect(xLoc, yLoc, width, height);
// etc ...

Resources