I develop a java application to generate a 3D object as a .obj file. I would like to visualize this object in a viewer3D of my application before exporting it but I only have a java object containing a list of faces and vertices of my 3D object. From my list of faces and vertices I would like to create a javafx type Shape or MeshView.
In fact, I'm trying to convert my java object into a javafx 3D object.
I have implement a Face Object :
public class Face {
private int id, idVertice1, idVertice2, idVertice3;
public Face(int idVertice1, int idVertice2, int idVertice3) {
this.idVertice1 = idVertice1;
this.idVertice2 = idVertice2;
this.idVertice3 = idVertice3;
}
public int getIdVertice1() {
return idVertice1;
}
public int getIdVertice2() {
return idVertice2;
}
public int getIdVertice3() {
return idVertice3;
}
}
I have too an Vertices class :
public class Vertices {
private double x, y, z;
public Vertices(double line, double height, double column) {
x = column;
y = height;
z = line;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
And her is my Mesh class :
public class Mesh {
private TreeMap<Double, TreeMap<Double, Vertices>> setOfVertices;
private LinkedList<Face> setOfFaces;
public Mesh() {
setOfFaces = new LinkedList();
setOfVertices = new TreeMap<Double, TreeMap<Double, Vertices>>();
}
public TreeMap getSetOfVertices() {
return setOfVertices;
}
public LinkedList<Face> getSetOfFaces() {
return setOfFaces;
}
How convert this Mesh object to a JavaFX mesh object into my viewer 3D (my viewer 3D is a subScene) :
Is this possible?
Related
I'm writing a Rectangle class and it has 2 instance variables which are 2 points that are called _pointSW and _pointNE. I have to define the width and the height of the rectangle, but I can't use any other variables besides the 2 points.
I want to ask how I could write the getWidth() method, for example using just the _pointNE, or maybe better write a private method (because I can't use any new public methods) to define the width and the height, and then use it in other methods and if that's an option, then how do I actually write it? thanks!
If your SW means South-West and NE means North-East:
public class Tuple<X, Y> {
public final X x;
public final Y y;
public Tuple(X x, Y y) {
this.x = x;
this.y = y;
}
}
public class Rectangle {
private Tuple<double,double> pointSW;
private Tuple<double,double> pointNE;
public Rectangle(final Tuple<double,double> sw, final Tuple<double,double> ne) {
this.pointSW = sw;
this.pointNE = ne;
}
public double getWidth() {
return Math.abs(this.pointNE.x - this.pointSW.x);
}
public double getHeight() {
return Math.abs(this.pointSW.y - this.pointNE.y);
}
public void setWidth(final double width) {
this.pointNE.x = this.point.SW.x + width;
}
public void setHeight(final double eight) {
this.pointNE.y = this.point.SW.y + eight;
}
}
Here's the code
class TwoD {
int x, y;
public TwoD(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
class ThreeD extends TwoD {
int z;
public ThreeD(int x, int y, int z) {
super(x, y);
this.z = z;
}
}
class FourD extends ThreeD {
int t;
public FourD(int x, int y, int z, int t) {
super(x, y, z);
this.t = t;
}
}
class coords<T extends TwoD> {
T cordinates;
public coords(T cordinates) {
super();
this.cordinates = cordinates;
}
static void show(coords<? super ThreeD> c) {}
}
public class mainX {
public static void main(String a[]) {
FourD fourD = new FourD(1, 2,3,4);
coords check = new coords(fourD);
coords.show(check);
TwoD twoD = new TwoD(1, 2);
coords check1 = new coords(twoD);
coords.show(check1);
// How this program runs fine with the child and parent subclass objects in show method?
}
}
The method
static void show(coords c)
should only allow Parent class objects ? Why is it allowing child class objects also?
How this program runs fine with the child and parent subhclass objects in show method?
I am confused!
As mentioned by #Thomas in the comments, you're using raw types for your coords. (I could go into detail, but the linked answer explains everything very clearly. Your use case is mainly mentioned in the sections How's a raw type different from using <?> as a type parameter? and A raw type is the erasure of that type.)
If you'd change:
coords check = new coords(fourD);
...
coords check1 = new coords(twoD);
To:
coords<FourD> check = new coords<>(fourD);
...
coords<TwoD> check1 = new coords<>(twoD);
You would get the error you'd expect:
error: incompatible types: coords<TwoD> cannot be converted to coords<? extends ThreeD>
coords.show(check1);
^
PS/off-topic: Class coords should be with a capital C (thus Coords) when following Java's code standards.
This is using Processing 3.5, not every java thing works the same here.
The Bird class is giving me the error saying it needs to implement call(). Isn't it already under the main? I'm not experienced with interfaces so I don't know what exactly is going on here.
public interface FuncCall<A> {
A call();
}
class Bird implements FuncCall{
//Error here ^
//The type FuncCallTest.Bird must implement the inherited abstract method FuncCallTest.FuncCall.call()
//Is this not implemented already under main?
float x, y, size;
ArrayList<FuncCall<Float>> inputs = new ArrayList<FuncCall<Float>>();
public Bird(float x, float y, float size){
this.x = x;
this.y = y;
this.size = size;
}
public void main(String[] args){
FuncCall<Float> getX = new FuncCall<Float>(){
#Override
public Float call(){
return x;
}
};
FuncCall<Float> getY = new FuncCall<Float>(){
#Override
public Float call(){
return y;
}
};
FuncCall<Float> getSize = new FuncCall<Float>(){
#Override
public Float call(){
return size;
}
};
inputs.add(getX);
inputs.add(getY);
inputs.add(getSize);
}
}
class Pol {
ArrayList<FuncCall<Float>> inputs = new ArrayList<FuncCall<Float>>();
public Pol(ArrayList<FuncCall<Float>> inputs){
this.inputs = inputs;
}
//public float call(ArrayList<FuncCall<Float>> arr, int index){
//return arr.get(index).call();
//}
//How do I do this? Do I need to implement the interface here as well? Because if so same error as on Bird
}
I'll also stick this extra bit on the end here.
System.out.println(pol.call(pol.inputs, 1));
Does will that work? It doesn't error before compiling.
I appreciate any help. Please ask if something doesn't make sense as I'm still new to stack and not the best with java. :)
main file :
void setup(){
Bird bird = new Bird(1.2, 3.2, 7.5);
Pol pol = new Pol(bird.inputs);
System.out.println(pol.call(pol.inputs, 1););
}
First of all you could skip your FuncCall interface and use Java's Supplier functional interface and just add these Suppliers respectively method references of your class objects getters to the list.
Another approach is to provide an interface or abstract class that has getters and/or member variables for x, y and size and use this interface or abstract class as type parameter for the list.
With Suppliers:
This is closer to your example and requires less changes in
your code.
The second option with an interface changes your Pol class
completely and I am not sure if this is acceptable for you.
´
public class Bird {
private float x;
private float y;
private float size;
public Bird(float x, float y, float size) {
//set your members here
}
public Float getX() {
return this.x;
}
public Float getY() {
return this.y;
}
public Float getSize() {
return this.size;
}
}
´
Then the Pol class
´
public class Pol {
private final List<Supplier<Float>> inputs;
public Pol(List<Supplier<Float>> inputs) {
this.inputs = inputs;
}
public Float call(int index) {
return this.inputs.get(index).get();
}
}
´
And your main should look like
´
public static int main(String[] args) {
Bird bird = new Bird(1.0f, 1.0f, 2.5f);
Pol pol = new Pol(Arrays.asList(bird::getX,
bird::getY, bird::getSize));
Float birdsSize = pol.call(2);
return 0;
}
´
The Cube class have two constructors, one which accepts three parameters that are converted into the tree attributes of the cube, and another one that doesn't require any parameter and therefore creates an "empty" cube. My question is how can a boolean method check if the cubes are valid or empty? Is there a way to do that without the need of checking each one of the attributes?
class Application {
public static void main(String[] args) {
Cube c1 = new Cube(4, 3, 6);
Cube c2 = new Cube();
System.out.println(isNotEmpty(c1));
System.out.println(isNotEmpty(c2));
}
public static boolean isNotEmpty(Cube cube) {
if (/*cube attributes are NOT empty*/) {
return true;
} else {
return false;
}
}
public static class Cube {
private int height;
private int width;
private int depth;
public Cube() {}
public Cube(int height, int width, int depth) {
this.height = height;
this.width = width;
this.depth = depth;
}
public int getHeight() { return height; }
public int getWidth() { return width; }
public int getDepth() { return depth; }
}
}
Since it appears that the only state which a Cube has are the height, width, and depth, then you could actually just use null to represent an empty Cube.
It doesn't make much sense to call a cube with no dimensions a cube in the first place. Using null as a marker might make the most sense.
Either change one (or more) of your int fields to be an Integer Object, or introduce a new Boolean field isSet or get rid of your empty constructor
1) If you use an Integer Object you can test to see if it is null where -as int primitives have a default value of 0
2) If you have a Boolean field you can default it to false and set it to true in your proper constructor
Use a bool flag isEmptyCube in the constructor. At the time of object creation, it will be automatically marked correctly whether it is blank or not.
public static class Cube {
//...
private boolean isEmptyCube;
public Cube() {isEmptyCube = true;}
public Cube(int hight, int width, int depth) {
//...
isEmptyCube = false;
}
public isCubeEmpty() { return isEmptyCube;}
It seems a so tricky question. At first, we have to have any criteria: What is an empty object?. When we have some criteria, even single, we must check it.
From the reason when we are considering the Cube c3 = new Cube(0, 0, 0) like is not empty, so, here is one of ways:
public class CubeApplication {
public static void main(String[] args) {
Cube c1 = new Cube(4, 3, 6);
Cube c2 = new Cube();
Cube c3 = new Cube(0, 0, 0);
System.out.println(c1.isEmpty());
System.out.println(c2.isEmpty());
System.out.println(c3.isEmpty());
}
static class Cube {
private int hight;
private int width;
private int depth;
private boolean isEmpty;
public Cube() {
this.isEmpty = false;
}
public Cube(int hight, int width, int depth) {
this.hight = hight;
this.width = width;
this.depth = depth;
this.isEmpty = true;
}
public boolean isEmpty() {
return this.isEmpty;
}
public int getHight() {
return this.hight;
}
public int getWidth() {
return this.width;
}
public int getDepth() {
return this.depth;
}
}
}
OUTPUT:
true
false
true
This is how I add a line to my chart at the moment. This is the abstract class for an arbitrry funciton I want to display:
public abstract class ArbitraryFunction implements
ValueProvider<ArbitraryFunctionData, Double> {
private String field;
public abstract Double f(Double x);
/**
* Constructor
*/
public ArbitraryFunction(String field) {
this.field = field;
}
#Override
public Double getValue(ArbitraryFunctionData object) {
return object.get(field);
}
#Override
public void setValue(ArbitraryFunctionData object, Double value) {
object.put(field, value);
}
#Override
public String getPath() {
return field;
}
}
This is how the chart is created:
ArbitraryFunction f1 = new ArbitraryFunction("f1") {
#Override
public Double f(Double x) {
return Math.sin(x);
}
};
functionMap.put(f1.getPath(), f1);
// collects the data of the functions and adds them to the store
for (Double x = 0.0; x <= 2 * Math.PI; x = x + 0.1) {
ArbitraryFunctionData d = new ArbitraryFunctionData();
d.setName("" + x);
for (Map.Entry<String, ArbitraryFunction> entry : functionMap.entrySet()) {
ArbitraryFunction tmp = entry.getValue();
d.put(tmp.getPath(), tmp.f(x));
}
store.add(d);
}
chart.setStore(store);
verticalAxis.setPosition(Position.LEFT);
verticalAxis.addField(f1);
verticalAxis.setSteps(2);
verticalAxis.setMinorTickSteps(5);
chart.addAxis(verticalAxis);
This works so far as intended. The graph shows my lines as it should do it and the vertical axis is correct too. But I have problems drawing the horizontal axis since I don't know what I need to give horizontalAxis.addField( ??? ). I've tried a few things, but nothing worked.
Does anyone know how I need to set up the horizontal axis?
What do you want the horizontal axis value to be? Is it another NumericAxis - does each data point have a x value that it should be drawn on? Each d in your loop has a String name and some value - perhaps you want a CategoryAxis<ArbitraryFunctionData, String> that just draws those name values?
Looks like I misunderstood earlier - your Function objects are just used in setup, not in changing how you plot data
I'm still not sure what you are after, but it sounds like you mostly want to plot some lines. Each data point (ArbitraryFunctionData?) seems to have Y values for each function being used, and a title, but no X values, so there is no way to plot each point as (X,Y) with two numeric axes, just as (name, Y) using a CategoryAxis and a NumericAxis. This would end up more or less like this sample: http://www.sencha.com/examples/#ExamplePlace:linechart - strings along the bottom, and numbers along the side.
Here's take one, build mostly off of the idea/structure you already have:
public class FunctionPlotter implements EntryPoint {
public static class ArbitraryFunctionData {
private double xValue;
private Map<String, Double> yValues = new HashMap<String, Double>();
public double get(String key) {
return yValues.get(key);
}
public void put(String key, double yValue) {
yValues.put(key, yValue);
}
public double getXValue() {
return xValue;
}
public void setxValue(double xValue) {
this.xValue = xValue;
}
}
public interface AFDProperties extends PropertyAccess<ArbitraryFunctionData> {
//xvalue is unique, key off of that
#Path("xValue")
ModelKeyProvider<ArbitraryFunctionData> key();
//automatic ValueProvider generation for the get/setXValue methods
ValueProvider<ArbitraryFunctionData, Double> xValue();
}
/**
* This is really doing two different jobs at once - wasn't quite was I was trying to suggest in
* that other question. See the second version of this for clarification...
*/
public static abstract class ArbitraryFunction implements ValueProvider<ArbitraryFunctionData, Double> {
private final String field;
public ArbitraryFunction(String field) {
this.field = field;
}
public abstract Double f(Double x);
#Override
public Double getValue(ArbitraryFunctionData object) {
return object.get(field);
}
#Override
public void setValue(ArbitraryFunctionData object, Double value) {
object.put(field, value);
}
#Override
public String getPath() {
return field;
}
}
#Override
public void onModuleLoad() {
Viewport vp = new Viewport();
Set<ArbitraryFunction> functions = new HashSet<ArbitraryFunction>();
ArbitraryFunction f1 = new ArbitraryFunction("f1") {
#Override
public Double f(Double x) {
return Math.sin(x);
}
};
functions.add(f1);
AFDProperties props = GWT.create(AFDProperties.class);
ListStore<ArbitraryFunctionData> store = new ListStore<ArbitraryFunctionData>(props.key());
// collects the data of the functions and adds them to the store
for (Double x = 0.0; x <= 2 * Math.PI; x = x + 0.1) {
// Create one data object, and set the X value, since that is the same for all Y values
ArbitraryFunctionData d = new ArbitraryFunctionData();
d.setxValue(x);
// For each function, set the corresponding Y value
for (ArbitraryFunction func : functions) {
d.put(func.getPath(), func.f(x));
}
store.add(d);
}
Chart<ArbitraryFunctionData> chart = new Chart<ArbitraryFunctionData>();
chart.setStore(store);
//Y-axis
NumericAxis<ArbitraryFunctionData> verticalAxis = new NumericAxis<ArbitraryFunctionData>();
verticalAxis.setPosition(Position.LEFT);
verticalAxis.addField(f1);//needs to know this field to properly set the range of values
//f2, f3, etc
verticalAxis.setSteps(2);
verticalAxis.setMinorTickSteps(5);
chart.addAxis(verticalAxis);
// X-Axis, this time reading from the xValue, not the series of ValueProviders
NumericAxis<ArbitraryFunctionData> horizAxis = new NumericAxis<ArbitraryFunctionData>();
horizAxis.setPosition(Position.BOTTOM);
horizAxis.addField(props.xValue());//same value for all
horizAxis.setSteps(2);
horizAxis.setMinorTickSteps(5);
chart.addAxis(horizAxis);
for (ArbitraryFunction func : functions) {
LineSeries<ArbitraryFunctionData> line = new LineSeries<ArbitraryFunctionData>();
// configure x axis
line.setXAxisPosition(Position.BOTTOM);//where is it
line.setXField(props.xValue());//what value do i use
// configure y axis
line.setYAxisPosition(Position.LEFT);//where is it
line.setYField(func);//what value do i use
//probably want to customized per func
line.setStroke(RGB.GRAY);
line.setStrokeWidth(2);
chart.addSeries(line);
}
vp.setWidget(chart);
RootPanel.get().add(vp);
}
}
And here's take two, this time with much simpler data and actually making the Function its own ValueProvider, and keeping the data dirt simple - just a double! Note that the ValueProvider is the function, and we never call getValue ourselves, we let the axis/series do it for us! Added a second function here to demonstrate that it does actually work.
public class FunctionPlotter implements EntryPoint {
/**
* Where did everything go? We're just making a ValueProvider now that can handle
* each number as a value, and working out the details from there
*
* For fun, added per-function coloring too
*/
public abstract static class Function implements ValueProvider<Double, Double> {
private final String name;
private final Color color;
public Function(String name, Color color) {
this.name = name;
this.color = color;
}
#Override
public abstract Double getValue(Double object);
#Override
public String getPath() {
return name;
}
#Override
public void setValue(Double object, Double value) {
//no-op
}
public Color getColor() {
return color;
}
}
#Override
public void onModuleLoad() {
Viewport vp = new Viewport();
Set<Function> functions = new HashSet<Function>();
Function f1 = new Function("f1", RGB.RED) {
#Override
public Double getValue(Double x) {
return Math.sin(x);
}
};
functions.add(f1);
Function f2 = new Function("f2", RGB.BLACK) {
#Override
public Double getValue(Double x) {
return Math.cos(x);
}
};
functions.add(f2);
//Turns out Stores can hold any objects - should probably factor out this key provider for reuse...
ListStore<Double> store = new ListStore<Double>(new ModelKeyProvider<Double>() {
#Override
public String getKey(Double item) {
return item.toString();
}
});
// collects the data of the functions and adds them to the store
for (Double x = 0.0; x <= 2 * Math.PI; x = x + 0.1) {
store.add(x);
}
Chart<Double> chart = new Chart<Double>();
chart.setStore(store);
//Y-axis
NumericAxis<Double> verticalAxis = new NumericAxis<Double>();
verticalAxis.setPosition(Position.LEFT);
for (Function func : functions) {
verticalAxis.addField(func);//needs to know this field to properly set the range of values
}
verticalAxis.setSteps(2);
verticalAxis.setMinorTickSteps(5);
chart.addAxis(verticalAxis);
// X-Axis, this time reading from the xValue, not the series of ValueProviders
NumericAxis<Double> horizAxis = new NumericAxis<Double>();
horizAxis.setPosition(Position.BOTTOM);
horizAxis.addField(new IdentityValueProvider<Double>());//magic value provider that returns the same string
horizAxis.setSteps(2);
horizAxis.setMinorTickSteps(5);
chart.addAxis(horizAxis);
for (Function func : functions) {
LineSeries<Double> line = new LineSeries<Double>();
// configure x axis
line.setXAxisPosition(Position.BOTTOM);//where is it
line.setXField(new IdentityValueProvider<Double>());//what value do i use
// configure y axis
line.setYAxisPosition(Position.LEFT);//where is it
line.setYField(func);//what value do i use
//probably want to customized per func
line.setStroke(func.getColor());
line.setStrokeWidth(2);
chart.addSeries(line);
}
vp.setWidget(chart);
RootPanel.get().add(vp);
}
}