I wrote a physical simulation about gravitational force between two planets.It worked perfectly fine so I decided to take it to a new level and rewrote it using arrays and five planets(circles).But my code gives strange and never the same error. I get either NullPointerException error or the VM error when intializing the sketch(No description just the "Vm error couldn't initialize skecth" and the "see help and troubleshoot" bullsh*t) The program uses a txt file to read in data(double-checked and it works fine).
My Array names and descriptions are
PVector - Pos stands for Position
PVector - Vel stands for Velocity
PVector - Acc stands for Acceleration
PVector - Dist stands for Distance
PVector - Dir stands for Direction
float - Mass stands for Mass
My code:
public PVector[] Pos = new PVector[5];
public PVector[] Acc = new PVector[5];
public PVector[] Vel = new PVector[5];
public PVector[] Dist = new PVector[5];
public PVector[] Dir = new PVector[5];
public float[] Mass = new float[5];
void setup(){
String Data[] = loadStrings("Data.txt");
size(800,800);
for(int g = 0;g < 5;g++){
Pos[g] = new PVector(float(Data[g+1]),float(Data[g+6]));
Vel[g] = new PVector(float(Data[g+12]),float(Data[g+17]));
Mass[g] = float(Data[g+23]);
}
}
void draw(){
for (int i = 0;i < 5;i++){
for (int f = 0;f < 5;f++){
if(i !=f){
if(Pos[i].x < Pos[f].x){Dir[f].x = 1;Dist[f].x = (Pos[f].x - Pos[i].x);}else{ // I get the error here
if(Pos[i].x > Pos[f].x){Dir[f].x = -1;Dist[f].x = (Pos[i].x - Pos[f].x);}else{
if(Pos[i].x == Pos[f].x){Dir[f].x = 0;Dist[f].x = 0;}}}
if(Pos[i].y < Pos[f].y){Dir[f].y = 1;Dist[f].y = (Pos[f].y - Pos[i].y);}else{
if(Pos[i].y > Pos[f].y){Dir[f].y = -1;Dist[f].y = (Pos[i].y - Pos[f].y);}else{
if(Pos[i].y == Pos[f].y){Dir[f].y = 0;Dist[f].y = 0;}}}
if ((Dist[f].x != 0)){
Acc[i].x+=((6*((Mass[i]*Mass[f])/Dist[f].magSq())/10000000)/Mass[i])*Dir[f].x;// *6/1000000 is MY G constant
}
if ((Dist[f].y != 0)){
Acc[i].y+=((6*((Mass[i]*Mass[f])/Dist[f].magSq())/10000000)/Mass[i])*Dir[f].y;
}
}
}
Vel[i].x = Vel[i].x + Acc[i].x;
Vel[i].y = Vel[i].y + Acc[i].y;
Pos[i].x = Pos[i].x + Vel[i].x;
Pos[i].y = Pos[i].y + Vel[i].y;
ellipse(Pos[i].x,Pos[i].y,10,10);
}
}
You create array of PVectors of size 5 here : public PVector[] Dir = new PVector[5]; . In this moment, it has null five times for indexes 0-4 in it.
Because you do not create new PVectors in this array, when you try to access variable x in here Dir[f].x, you got error, because Dir[f] is null and you cant access variable x of null -> NullPointerException.
In this part you are instantizing some arrays
for(int g = 0;g < 5;g++){
Pos[g] = new PVector(float(Data[g+1]),float(Data[g+6]));
Vel[g] = new PVector(float(Data[g+12]),float(Data[g+17]));
Mass[g] = float(Data[g+23]);
}
You should add instantizing also for Dir, Acc and Dist
Note also, that you are working with objects, not with primitive data types. null is not same as new PVector(0,0)
Also from "design" point of view, using arrays this way is NOT good approach. You should create your own class Planet, where each planet holds information about its properties and in your main class you handle interaction between them.
How to create "empty" or "zero" variables instead of nulls? Just create them :)
for(int g = 0;g < 5;g++){
Pos[g] = new PVector(float(Data[g+1]),float(Data[g+6]));
Vel[g] = new PVector(float(Data[g+12]),float(Data[g+17]));
Mass[g] = float(Data[g+23]);
Dir[g] = new PVector(0,0);
Acc[g] = new PVector(0,0);
Dist[g] = new PVector(0,0);
}
PS : I do not how exactly is this class implemented, using new PVector() or new PVector(0) instead of new PVector(0,0) may also work.
Related
Lets say I have a public class called GameBoard that will be a two dimensional array with 4 rows and 5 columns. The spaces in the array are filed with String values from 1 to 20. A card will be drawn that has a name (King of Spades for example) . If the user inputs 15 I will store it in a String variable called userLocation. What would be the most efficient way to create a method that takes the input location and updates the array with the name of the Card? Would a for loop be most efficient?
public GameBoard() {
square = new String[4][5];
square[0][0] = new String("1");
square[0][1] = new String("2");
square[0][2] = new String("3");
square[0][3] = new String("4");
square[0][4] = new String("5");
square[1][0] = new String("6");
square[1][1] = new String("7");
square[1][2] = new String("8");
square[1][3] = new String("9");
square[1][4] = new String("10");
square[2][1] = new String("11");
square[2][2] = new String("12");
square[2][3] = new String("13");
square[3][1] = new String("14");
square[3][2] = new String("15");
square[3][3] = new String("16");
square[2][0] = new String(17);
square[3][0] = new String(18);
square[2][4] = new String(19);
square[3][4] = new String(20);
}
My preferred method as of now would look something like this but it gives me the error code "type mismatch:cannot convert string to boolean" under userLocation = board[i][j]
public String[][] updateBoard(String userLocation, Card card, String[][] board) {
for (int i = 0; i <4; i++)
{
for (int j = 0; j < 5; j++)
{
if(userLocation = board[i][j]) {
board[i][j] = card.name;
}
}
}
return board;
}
So the reason it will not compile is your = does not return a boolean expression. == would, but it's still not what you want, since you want to check if the String contents are the same, not if they're the same object, so use .equals.
But, no, I think you don't want to depend on strings to identify locations. What if you want to replace a card? And why look through everything when you need not?
Rather if i is some number between 1 and 20, identify the corresponding spot in the array by square[(i-1)/5][(i-1)%5]
That should bypass the issue you are having with matching strings.
So for example, your constructor becomes:
public GameBoard() {
square = new String[4][5];
for (int i=1; i<=20;i++){
square[(i-1)/5][(i-1)%5]=""+i;//initialize with 1 to 20 if you like
}
and userLocation is an int.
I am currently working through Objects module over on Hyperskills.org. One of the coding challenges is to create five Units, three Knights, one General, one Doctor. We are given the class definition for each object and each object has a constructor that sets one String field.
I took the prompt and just instantiated x-number of X-class as asked.
public static void createArmy(){
Unit unit1 = new Unit("U1");
Unit unit2 = new Unit("U2");
Unit unit3 = new Unit("U3");
Unit unit4 = new Unit("U4");
Unit unit5 = new Unit("U5");
Knight knight1 = new Knight("K1");
Knight knight2 = new Knight("K2");
Knight knight3 = new Knight("K3");
General general1 = new General("G1");
Doctor doctor1 = new Doctor("D1");
}
The compiler accepts my answer but it says, "Correct, but can be improved."
Please and thank you: How else can this code be improved?
You can improve it by putting the units and stuff into an array and using for loops. Also adding some parameters would make calling this function easier later on. ex:
public static void createArmy(int units, int knights, int generals, int doctors){
Unit unit = new Unit[units];
Knight knight = new Knights[knights];
General general = new Generals[generals];
Doctor doctor = new Doctors[doctors];
for(int x = 0; x < units;x++){
unit[x] = new Unit("U"+(x+1));
}
for(int x = 0; x < knights;x++){
knight[x] = new Knight("K"+(x+1));
}
for(int x = 0; x < generals;x++){
general[x] = new General("G"+(x+1));
}
for(int x = 0; x < doctors;x++){
doctor[x] = new Doctor("D"+(x+1));
}
}
Long story I can't figure out how to load the jet data jetid and currentLocation into j. Any help is appreciated. I apologize before hand if I referred to things wrongly. Thank you.
public class Corporation {
public Jet[] jets = new Jet[14];
public Corporation()//RUN A CONSTRUCTOR TO CREATE 14 NEW JETS, IN DIFFERENT LOCATIONS
{
//create 14 new jets
for(int i =0; i < jets.length; i++)
{
//make a new jet here
Jet j = new Jet();
j.jetid =
}
}
}
The second class the one I'm trying to pull jetid and currentLocation from is:
public class Jet {
public int jetid;
public Delivery deliveryArray[];
public String currentLocation; //where it's currently sitting
public Jet()
{
int random = (int)(Math.random()*10000);
this.jetid = random;
this.currentLocation = setCurrentLocation();
System.out.println("NEW JET IS ONLINE WITH JET ID: " + this.jetid + " AT LOCATION " + this.currentLocation);
}
private String setCurrentLocation()
{
//set up a random # that determines which city the plane is based in
double random = (Math.random());
String location = " ";
if(random < .1 && random > 0)
location = "PHX";
else if(random > .1 && random < .2)
location = "SAN";
else if(random > .2 && random <.3)
location = "LAX";
else if(random > .3 && random < .4)
location = "POR";
else if(random > .4 && random < .5)
location = "SEA";
else if(random > .5 && random <.6)
location = "SAF";
else
location = "DAL";
return location;
}
}
Thanks everyone for the input. Other problems aside I settled on this code shortly after posting this question:
Jet j = new Jet();
jets[i]=j;
And from there I've been able to figure out all other issues. Thanks again everyone for your input
The code appears to create 14 jets, all of which initialise their own data (e.g. they already have jetId and current location). The data's already there, the Corporation doesn't need to set it.
If you're saying you want the corp to create it, then create a new constructor, Jet(int jetId, String currentLocation) and you can pass the data in.
The corporation object will have an array with 14 references to the Jet object.
public class Corporation {
private Jet[] jets = new Jet[14];
// Constructor
// RUN A CONSTRUCTOR TO CREATE 14 NEW JETS, IN DIFFERENT LOCATIONS
public Corporation() {
//create 14 new jets
for (int i =0; i < jets.length; i++)
{
//make a new jet here
Jet j = new Jet();
//save the reference to array
jets[i] = j;
// more Jet intialization
j.id = ...
}
}
// accessor
public Jet [] getJets() {
...
}
}
You probably want to pass things in through the constructor:
public Jet(int jetid, String currentLocation)
{
this.jetid = jetid;
this.currentLocation = currentLocation;
}
Now you can write the following in your corporation class:
for(int i =0; i < jets.length; i++)
{
//make a new jet here
int randomId = (int)(Math.random()*10000);
String randomLocation = randomLocation();
jets[i] = new Jet(randomId, randomLocation);
}
That randomLocation is just your old setCurrentLocation method, from your Jet class. You should rename it and move it into your Corporation class, since Corporation is now responsible for making up random locations. Or you could rename it and leave it in Jet, and make it public static, and you could implement it in just 2 lines:
public static String randomLocation() {
// "DAL" is twice as likely as the others:
String[] array = {"ABC", "DEF", "DAL", "DAL"};
return array[new Random().nextInt(array.length)];
}
and then invoke it as follows:
String randomLocation = Jet.randomLocation();
you need to pass the variables to the jet class constructor!
Jet jet = new Jet(string _jetID, string _currentLocation)
Not sure what error you are getting, I assume, your constructor:
public Corporation()//RUN A CONSTRUCTOR TO CREATE 14 NEW JETS, IN DIFFERENT LOCATIONS
{
//create 14 new jets
for(int i =0; i < jets.length; i++)
{
//make a new jet here
Jet j = new Jet();
j.jetid =
}
}
Should be the following, if you declared a local j[] in your Corporation class
public Corporation()//RUN A CONSTRUCTOR TO CREATE 14 NEW JETS, IN DIFFERENT LOCATIONS
{
//create 14 new jets
for(int i =0; i < jets.length; i++)
{
//make a new jet here
Jet j[i] = new Jet();
//j.jetid = no need to set this
}
}
The other thing wrong is the j.jetid =. But you do not need to set it, as it is already set in the Jet constructor to this.jetid = random;. Happens every time you instantiate a new Jet in Jet j[i] = new Jet();
If i have understood your question correctly, you want to set jetid and currentLocation, than you need to change your Jet constructor like the following:
public Jet(int jetid, String currentLocation)
{
this.jetid = jetid;
this.currentLocation = currentLocation;
}
I've been issued the task of using MATLAB Builder to convert a MATLAB function into a Java class, now I have gotten to a point where I have the results from one class being fed into another and since the MATLAB builder will only output an object, I'm having issues.
import java.util.*;
import com.mathworks.toolbox.javabuilder.*;
public class mainKrigTau {
public static void main(String[] args) {
Object[] resultT = null;
Object[] resultK = null;
Object[] resultB = null;
krigingTau Tau = null;
krigingTau Krig = null;
Branin branin = null;
try {
Tau = new krigingTau();
Krig = new krigingTau();
branin = new Branin();
resultT = Tau.LPtau(1, 100, 2, 1234);
List<Object> X = Arrays.asList(resultT[0]);
System.out.println(X);
System.out.println((X.size()));
} catch (MWException e)
{
e.printStackTrace();
} finally
{
}
So basically the output of the Tau class is a 2D array, so the array is embedded into the resultT[] object, how to I get access to this array? One method I have tried is as above, changing it into an array list, X outputs the array, but I can't access the components of the array. X.size = 1, not 100 which is the actual size of the array. edit - just to add, all the examples I can find just output the result object and display it, rather than do anything with it.
Okay a software engineer nearby came to the rescue. It's a bit of a roundabout way but it works.
try {
Tau = new krigingTau();
Krig = new krigingTau();
branin = new Branin();
resultT = Tau.LPtau(1, 100, 2, 1234);
List<Object> X = Arrays.asList(resultT[0]);
if (X.get(0) instanceof MWNumericArray) {
MWNumericArray mw= (MWNumericArray) X.get(0);
ArrayList<Point> lists = new ArrayList<Point>();
for(int i = 1; i <= mw.numberOfElements()/2; i++){
Object o = mw.get(i);
System.out.println(o);
Double x = (Double) mw.get(i);
Double y = (Double) mw.get((mw.numberOfElements()/2)+i);
Point p = new Point(x.doubleValue(),y.doubleValue());
lists.add(p);
}
for(int i = 1; i < mw.numberOfElements()/2; i++)
{
resultB = branin.branin(1, lists.get(i).array);
System.out.println(resultB[0]);
}
where point sets the values of x and y into an array, so set it to an new MWNumericArray and do Object.get(i) but this flattens the array which is not ideal.
I try to retreive information from catia usig com4j. Some methods require to pass an array in argument to retreive information but the array is never populated. In this example is to get coordinate from a point in catia.
The declaration of the method generated by com4j
public interface Point extends com4j.catia.HybridShape {
...
void getCoordinates(java.lang.Object[] oCoordinates);
...
}
my code to get the coordinate
public static void testGetPointCoordinates() {
String catiafile="E:\\test.CATPart";
Application app =null;
app = COM4J.createInstance(Application.class, "CATIA.Application");
Documents documents = app.documents();
Document oDocument = (Document) documents.open(new Holder<>(catiaFile.getAbsolutePath()));
PartDocument partDocument = oDocument.queryInterface(PartDocument.class);
Part part = partDocument.part();
Factory HSFactory = part.hybridShapeFactory();
HybridShapeFactory HSF = HSFactory.queryInterface(HybridShapeFactory.class);
HybridBodies hbodies = part.hybridBodies();
int n = hbodies.count();
for (int i = 1; i <= n; i++) {
HybridBody hbody = null;
hbody = hbodies.item(i);
int nbitems = hbody.hybridShapes().count();
for (int j = 1; j <= nbitems; j++) {
String name = hbody.hybridShapes().item(j).name();
System.out.println("name=" + name);
//Object tab[]=new Object[3];
if (name.startsWith("Point.12")) {//true point
HybridShape hs = hbody.hybridShapes().item(j);
Reference reference = part.createReferenceFromObject(hs);
HybridShapePointCoord p3 = hs.queryInterface(HybridShapePointCoord.class);
//works
System.out.println("point name = " + p3.name());
System.out.println(p3.y().value());//display 50.0
//doesn't work
Variant tab[] = new Variant[3];
for (int k = 0; k < 3; k++) {
Variant variant = new Variant();
variant.set(k);
tab[k] = variant;
}
p3.getCoordinates(tab);
System.out.println(tab[1].getParseableString()); //display 1 (value not modified)
//doesn't work
tab = new Variant[3];
for (int k = 0; k < 3; k++) {
Variant variant = new Variant(Variant.Type.VT_EMPTY);//tested with VT_R4 VT_R8,...
tab[k] = variant;
}
System.out.println(tab[1].getJavaCode()); //display null (Don't know how to print VT_EMPTY as an Java literal)
//doesn't work with this other solution but ok in VBA
tab = new Variant[3];
//Variant v = new Variant(Type.VT_EMPTY);
tab[0] = new Variant(Variant.Type.VT_EMPTY);
tab[1] = new Variant(Variant.Type.VT_EMPTY);
tab[2] = new Variant(Variant.Type.VT_EMPTY);
HybridShapePointExplicit point = HSF.addNewPointDatum(reference);
point.getCoordinates(tab);
System.out.println(tab[1].doubleValue() + " " + tab[2].toString()); //display 0
//doesn't work
//crash JVM
// tab = new Variant[3];
// p3.getCoordinates(tab);
break;
}
}
}
}
the code below works in VBA with CATIA
Dim P1
Dim coordonnees(2)
Dim coordonnees2(100, 3)
coordonnees(0) = 0
coordonnees(1) = 0
coordonnees(2) = 0
Set P1 = HSF.AddNewPointDatum(hbody.HybridShapes.Item(i))
'fonction to get coordinates
P1.GetCoordinates coordonnees
'set name and coordinates
coordonnees2(Y, 0) = hbody.HybridShapes.Item(i).name
coordonnees2(Y, 1) = Round(coordonnees(0), 3)
coordonnees2(Y, 2) = Round(coordonnees(1), 3)
coordonnees2(Y, 3) = Round(coordonnees(2), 3)
I'm not familiar with com4j, but Point.GetCoordinates is a restricted method:
.
The solution to this problem in VB is you need to create a new variant and set it equal to p3. Then, call GetCoordinates from the variant's context. Intellisense will not work well on the variant, but the call to GetCoordinates will work.
In VB the code would look something like this:
...
Dim p3 As Variant
Dim arrayOfCoord(2) As Variant
Set p3 = hybridShapePointCoord1 'set variant = strongly typed point object
p3.GetCoordinates arrayOfCoord
...
In your case, non-VB, your code might look like this
...
Object p3Obj; //used in vb:Variant p3Var;
p3Obj = p3;
p3Obj.GetCoordinates(tab);//Intellisense will not work, but the call to this method should
...
Let me know if this works.