How do I use ArrayList.get()? - java

I am writing a program in Processing to make a 3-D scatterplot that one can rotate around in space using PeasyCam. Data is read in from a text file to an ArrayList of PVectors. The entire code is shown below. What I don't understand is that importTextfile() needs to be called (repeatedly) within draw() and this significantly slows things down. Why can't I get away with calling it once within setup()? With "println(pointsList)" within draw() I can see that pointList changes if it's not preceded by importTextFile(). Can anyone explain why?
(Update: From trying to construct a minimum working example I see now that the problem is when I make a PVector V and then write over it to map it to the display window. I would still appreciate feedback on a good work around that involves calling importTextFile() just during setup(). What do I use instead of .get() so I get a copy of what's in the Arraylist and not a pointer to the actually value in the ArrayList?)
Here is the code:
import peasy.*;
PeasyCam cam;
ArrayList <PVector>pointList;
int maxX = 0;
int maxY = 0;
int maxZ = 0;
int minX = 10000;
int minY = 10000;
int minZ = 10000;
int range = 0;
void setup() {
size(500, 500, P3D);
cam = new PeasyCam(this, width/2, width/2, width/2, 800);
cam.setMinimumDistance(100);
cam.setMaximumDistance(2000);
pointList = new ArrayList();
importTextFile();
println(pointList);
//Determine min and max along each axis
for (int i=0; i < pointList.size(); i++) {
PVector R = pointList.get(i);
if (R.x > maxX) {
maxX = (int)R.x;
}
if (R.x < minX) {
minX = (int)R.x;
}
if (R.y > maxY) {
maxY = (int)R.y;
}
if (R.y < minY) {
minY = (int)R.y;
}
if (R.z > maxZ) {
maxZ = (int)R.z;
}
if (R.z < minZ) {
minZ = (int)R.z;
}
}
if (maxX - minX > range) {
range = maxX - minX;
}
if (maxY - minY > range) {
range = maxY - minY;
}
if (maxZ - minZ > range) {
range = maxZ - minZ;
}
println(pointList);
}
void draw() {
//importTextFile(); Uncomment to make run properly
println(pointList);
background(255);
stroke(0);
strokeWeight(2);
line(0, 0, 0, width, 0, 0);
line(0, 0, 0, 0, width, 0);
line(0, 0, 0, 0, 0, width);
stroke(150);
strokeWeight(1);
for (int i=1; i<6; i++) {
line(i*width/5, 0, 0, i*width/5, width, 0);
line(0, i*width/5, 0, width, i*width/5, 0);
}
lights();
noStroke();
fill(255, 0, 0);
sphereDetail(10);
//**The problem is here**
for (int i=0; i < pointList.size(); i++) {
PVector V = pointList.get(i);
V.x = map(V.x, minX-50, minX+range+50, 0, width);
V.y = map(V.y, minY-50, minY+range+50, 0, width);
V.z = map(V.z, minZ-50, minZ+range+50, 0, width);
pushMatrix();
translate(V.x, V.y, V.z);
sphere(4);
popMatrix();
}
}
void importTextFile() {
String[] strLines = loadStrings("positions.txt");
for (int i = 0; i < strLines.length; ++i) {
String[] arrTokens = split(strLines[i], ',');
float xx = float(arrTokens[2]);
float yy = float(arrTokens[1]);
float zz = float(arrTokens[0]);
pointList.add( new PVector(xx,zz,yy) );
}
}

You could continue to refactor, I don't know why they show this way of iterating through ArrayLists in the Processing documentation but here is a go at refactoring it:
float calcV (float n) {
return map (n, minX-50, minX+range+50, 0, width);
}
for (PVector V: pointList) {
pushMatrix();
translate(calcV(V.x), calcV(V.y), calcV(V.z));
sphere(4);
popMatrix();
}
You might consider creating a new Class with a PVector as a field or extending PVector. Daniel Shiffman uses this pattern a lot. Create a Class with a PVector for position, another for velocity, a method to calc the new position per frame and another to draw it out to screen. That gives you a lot of flexibility without having to write a ton of loops, other than one to calc and display the objects in your ArrayList.

As PVector is an object, when you do PVector V = pointList.get(i) you pass the reference for that specific element in pointList, to V. It's address in memory. So now V and pointList.get(number) share the same memory address. Any change in either one will change both, as they are two different pointers to same place.
But, if you do:
PVector V = new PVector(pointList.get(i).x, pointList.get(i).y, pointList.get(i).z);
V will be a new object and things will work as you want, cause now V has it's own memory address. And poinList will remain untouched. Same thing goes for other objects, arrays for instance, try this to see:
int[] one = new int[3];
int[] two = new int[3];
void setup(){
one[0] = 0;
one[1] = 1;
one[2] = 2;
print("one firstPrint -> \n");
println(one);
two = one;
print("two firstPrint -> \n");
println(two);
two[2] = 4;
// we didn't mean to change one, but...
print("one secondPrint -> \n");
println(one);
}

I fixed things with the code below but am still interested in other ways.
for (int i=0; i < pointList.size(); i++) {
PVector V = pointList.get(i);
PVector W = new PVector(0.0, 0.0, 0.0);
W.x = map(V.x, minX-50, minX+range+50, 0, width);
W.y = map(V.y, minY-50, minY+range+50, 0, width);
W.z = map(V.z, minZ-50, minZ+range+50, 0, width);
pushMatrix();
translate(W.x, W.y, W.z);
sphere(4);
popMatrix();
}

Related

node's are not intersection while using loops inside of an array?

My problem is wherever i click a node appears and for the second click another node appears with connected edge...so i want that When i click at any location, the node should be generated at the closest grid intersection point. I tried using loops.
and i'm trying to do that without "class"
int n_partition=10;
int length = 101;
PVector[] position = new PVector[length];
int BallNum;
void setup() {
size(600, 360);
background(255);
}
void draw() {
fill(255);
grid();
fill(0);
}
void mousePressed(){
stroke(0);
BallNum++;
position[BallNum]= new PVector(mouseX, mouseY);
circle(position[BallNum].x, position[BallNum].y, 10);
if (BallNum > 1) {
line(position[BallNum].x,position[BallNum].y,position[BallNum-
1].x,position[BallNum-1].y);
line(position[1].x,position[1].y,position[BallNum].x,position[BallNum] .y);
}
for (int i = 0; i < position[BallNum].length; ++ i) {
position[BallNum] = position[BallNum].get(i);
position[BallNum] = position[BallNum].get((i+1) % position[BallNum].length);
line(position[BallNum].x, position[BallNum].y,
position[BallNum].x, position[BallNum].y);
}
}
I EXPECT THE NODE SHOULD GO TO THE CLOSEST INTERSECTION.
You've to calculate the nearest position of the mouse to a point on the grid. For that you've to know the width (tile_width) and the height (tile_height) of cell.
The index of the cell can be calculated by the dividing the mouse position to the size of a tile and round() the result to an integral value (e.g. round(mouseX / (float)tile_width)).
Don't draw anything in int the mousePressed callback. The only thing you've to do there is to add a pint to the list:
void mousePressed(){
int tile_width = width / n_partition; // adapt this for your needs
int tile_height = height / n_partition;
int x = round(mouseX / (float)tile_width) * tile_width;
int y = round(mouseY / (float)tile_height) * tile_height;
position[BallNum]= new PVector(x, y);
BallNum++;
}
All the drawing has to be done in draw(). Draw the lines and points in separate loops:
void draw() {
background(255);
grid();
// draw the lines in a loop
strokeWeight(3);
stroke(0, 0, 255);
for (int i = 0; i < BallNum; ++ i) {
int i2 = (i+1) % BallNum;
line(position[i].x, position[i].y, position[i2].x, position[i2].y);
}
// draw balls in a loop
strokeWeight(1);
stroke(0, 0, 0);
fill (255, 0, 0);
for (int i = 0; i < BallNum; ++i) {
circle(position[i].x, position[i].y, 10);
}
}
Note, the scene is consecutively redrawn in every frame. Before the scene is drawn, the entire window has to be "cleared" by background().
See the result:

curveVertex() not drawling in Processing?

I'm trying to create a script that drawls a curve through 'n' vertexes equally spaced around the center of an ellipse.
The reason I'm not just drawling an ellipse around the center ellipse is because I eventually want to connect a micro-controller to Processing where the data points acquired from the 'n' amount of sensors will vary the height ('y') of each vertex, creating constantly changing, irregular curves around the center ellipse such as this possible curve:
Essentially, this is supposed to be a data visualizer, but I cannot figure out why this is not working or how to achieve this effect after going through examples and the documentation on https://processing.org/reference/.
Here is my code:
color WHITE = color(255);
color BLACK = color(0);
void setup() {
size(500, 500);
}
void draw() {
background(WHITE);
translate(width/2, height/2); // move origin to center of window
// center ellipse
noStroke();
fill(color(255, 0, 0));
ellipse(0, 0, 10, 10); // center point, red
fill(BLACK);
int n = 10;
int y = 100;
float angle = TWO_PI / n;
beginShape();
for (int i = 0; i < n; i++) {
rotate(angle);
curveVertex(0, y);
}
endShape();
}
The matrix operations like rotate do not transform the single vertices in a shape. The current matrix is applied to the entire shape when it is draw (at endShape). You've to calculate all the vertex coordinates:
Create a ArrayList of PVector, fill it with points and draw it in a loop:
color WHITE = color(255);
color BLACK = color(0);
ArrayList<PVector> points = new ArrayList<PVector>();
void setup() {
size(500, 500);
int n = 10;
int radius = 100;
for (int i = 0; i <= n; i++) {
float angle = TWO_PI * (float)i/n;
points.add(new PVector(cos(angle)*radius, sin(angle)*radius));
}
}
void draw() {
background(WHITE);
translate(width/2, height/2);
noFill();
stroke(255, 0, 0);
beginShape();
PVector last = points.get(points.size()-1);
curveVertex(last.x, last.y);
for (int i = 0; i < points.size(); i++) {
PVector p = points.get(i);
curveVertex(p.x, p.y);
}
PVector first = points.get(0);
curveVertex(first.x, first.y);
endShape();
}

Processing 2,2,1 java. Reset position if inside 3d shape

i have made this code,with a 3d model,the model starts dismorph after 100 frames.I have a box shape that is moved with mouse,i want when ever the vertices be inside the box,to reset their position to the original position,and reconstruct the model,while the others dismorph. Always resetting the position when they are in the box,and move when they are not.Can anyone help me.Until now what it happens,is that when the vertices are inside the box they stop moving.
Thanks in Advance
import peasy.*;
import saito.objloader.*;
OBJModel model ;
OBJModel tmpmodel ;
PeasyCam cam;
float easing = 0.005;
float r;
float k =0.00001;
int VertCount;
PVector[] Verts;
PVector Mouse;
void setup()
{
size(800, 800, P3D);
frameRate(30);
noStroke();
model = new OBJModel(this, "Model2.obj", "absolute", TRIANGLES);
model.enableDebug();
model.scale(100);
model.translateToCenter();
tmpmodel = new OBJModel(this, "Model2.obj", "absolute", TRIANGLES);
tmpmodel.enableDebug();
tmpmodel.scale(100);
tmpmodel.translateToCenter();
cam = new PeasyCam(this, width/2, height/2, 0, 994);
}
void draw()
{
background(129);
lights();
int VertCount = model.getVertexCount ();
PVector[] Verts = new PVector[VertCount];
PVector[] locas = new PVector[VertCount];
float r =80;
PVector Mouse = new PVector(mouseX-width/2, mouseY-height/2, 0);
cam.setMouseControlled(true);
//println(frameCount);
pushMatrix();
translate(width/2, height/2, 0);
for (int i = 0; i < VertCount; i++) {
//PVector orgv = model.getVertex(i);
Verts[i]= model.getVertex(i);
arrayCopy(Verts, locas);
//PVector tmpv = new PVector();
if (frameCount> 100) {
float randX = random(-5, 5);
float randY = random(-5, 5);
float randZ = random(-5, 5);
PVector Ran = new PVector(randX, randY, randZ);
//float norX = abs(cos(k)) * randX;
//float norY = abs(cos(k)) * randY;
//float norZ = abs(cos(k)) * randZ;
if (Verts[i].x > Mouse.x - r/2 && Verts[i].x < Mouse.x + r/2) {
if (Verts[i].x > Mouse.y - r/2 && Verts[i].x < Mouse.y + r/2) {
if (Verts[i].x > Mouse.z - r/2 && Verts[i].x < Mouse.z + r/2) {
arrayCopy(locas, Verts);
}
}
} else {
Verts[i].x+=Ran.x;
Verts[i].y+=Ran.y;
Verts[i].z+=Ran.z;
if (Verts[i].x > width/2 || Verts[i].x < -width/2) {
Verts[i].x+=-Ran.x;
}
if (Verts[i].y > height/2 || Verts[i].y < -height/2) {
Verts[i].y+=-Ran.y;
}
if (Verts[i].z < -800/2 || Verts[i].z > 800/2) {
Verts[i].z+=-Ran.z;
}
}
tmpmodel.setVertex(i, Verts[i].x, Verts[i].y, Verts[i].z);
}
k+=0.0001;
}
pushMatrix();
translate(Mouse.x, Mouse.y, Mouse.z);
noFill();
stroke(255);
box(r);
popMatrix();
noStroke();
tmpmodel.draw();
popMatrix();
pushMatrix();
translate(width/2, height/2, 0);
noFill();
stroke(255);
box(width, height, 600);
popMatrix();
}
if you want to run it use the model from the saito obj example or the PshapeObj example.
There are a few things about your code that don't make a ton of sense (some comments might have helped with that). Why are you copying the array like that?
In any case, I would start simpler if I were you. I would adopt an object oriented approach, where you create a class that encapsulates a point's original position as well as its current position.
Here's an example that does this in two dimensions, but this approach generalizes to three dimensions:
ArrayList<MovingPoint> points = new ArrayList<MovingPoint>();
float circleDiameter = 200;
void setup(){
size(500, 500);
for(int i = 0; i < 100; i++){
points.add(new MovingPoint());
}
}
void draw(){
background(0);
noFill();
stroke(255, 0, 0);
ellipse(mouseX, mouseY, circleDiameter, circleDiameter);
fill(255);
stroke(255);
MovingPoint previousPoint = null;
for(MovingPoint mp : points){
mp.draw();
if(previousPoint != null){
line(previousPoint.current.x, previousPoint.current.y, mp.current.x, mp.current.y);
}
previousPoint = mp;
}
}
class MovingPoint{
PVector original;
PVector current;
public MovingPoint(){
original = new PVector(random(width), random(height));
current = original.copy();
}
void draw(){
if(dist(current.x, current.y, mouseX, mouseY) < circleDiameter/2){
//inside circle, reset position
current = original.copy();
}
else{
//outside circle, move randomly
current.x += random(-5, 5);
current.y += random(-5, 5);
}
ellipse(current.x, current.y, 10, 10);
}
}
You shouldn't have to go through the rigmarole of copying arrays. Just use a class that remembers each point's original and current positions, and then switch between them depending on the mouse position.
If you still can't get it working, please post another question that works from this example instead of your entire sketch. It's hard to help if we don't have access to the libraries you're using, so you're better off getting rid of them and narrowing the problem down to as few lines as possible. Good luck.

Connecting Pvector points into a Mesh in Processing from an L-System?

I've built this L-System in Processing using toxiclib and I want to connect each point which is specified to each intersection in the branching of the tree. I've written a separate sketch in which I'm trying to create a triangle mesh by connecting the three closest points, I've been able to connect three points but I want it to be able to go through all the Vertices in an arraylist and then connect three closest points until I have a mesh out of all the vertices in the array. I also need to be able to convert this whole sketch into a function where by I can feed it into my L-System and then it will return the whole system with all the points connected in order to create a mesh. Essentially this is so I can then texture and maybe possibly apply Shaders to it if possible. I think that I might be attempting a harder way of approaching this for I believe toxiclibs or HEMESH libraries could do all of this for me, but I've been unable to figure it out. Any help would be much appreciated.
Here's the code for the sketch I wrote to try and connect all the points into a mesh.
import peasy.*;
float min = 1000;
ArrayList <PVector> loc = new ArrayList <PVector> ();
ArrayList <PVector> locSort = new ArrayList <PVector> ();
float [] minDists;
int [] minIdxs;
PeasyCam cam;
void setup() {
size(600, 600, OPENGL);
cam = new PeasyCam(this, 100);
for (int i=0; i<50; i++) {
loc.add(new PVector(random(-50, 50), random(-50, 50), random(-50, 50)));
}
minDists = new float[3];
minIdxs = new int[3];
for (int i = 0; i < 3; i ++)minDists[i] = 1000;
for (int i=0; i<loc.size(); i++) {
for (int j=0; j<loc.size (); j++) {
PVector vi= loc.get(i);
// loc.remove(i);
PVector vj= loc.get(j);
// loc.remove(j);
float c = vi.dist(vj);
for (int k = 0; k < 3; k++) {
if (c < minDists[k] && c > 0) {
if (k == 0) {
minDists[2] = minDists[1];
minDists[1] = minDists[0];
} else if (k == 1) {
minDists[2] = minDists[1];
}
println(k, c);
minDists[k] = c;
minIdxs[k] = j;
break;
}
}
}
}
}
void draw() {
background(255);
for (PVector v : loc) {
pushMatrix();
translate(v.x, v.y, v.z);
fill(0);
noStroke();
sphere(1);
popMatrix();
}
for (int i = 0; i < 3; i ++) {
PVector p1 = loc.get(minIdxs[i]);
PVector p2 = loc.get(minIdxs[(i+1)%3]);
stroke(255, 0, 0);
line(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);
}
}
Also the L-System was created by following this tutorial: https://www.youtube.com/watch?v=qF8LGLVrwfo

Centering map or camera 2D game

I've tried so many solutions that it's possible that my code is a bit mixed up, but whatever I try, it just won't work.
Basically I made a map with Tiled, where my player can run around and bump into stuff. I want the whole map to be visible for the whole time (it's 20 by 15, 64 pixels a tile). The camera doesn't need to move around or follow the player, it has to stay still at the center of the map.
The problem is that the map only shows in the upper right corner of the screen. When I centered the camera to the map itself it messed up the collission detection, (bumping into trees while they were not visible & walking through visible trees). So what I want to do is center the map to 0,0 where my camera also is (at least I think..).
Another thing I'd like to accomplish is that the size of the map gets resized to match different mobile phones. Tried to accomplish this with the stretchviewport, but haven't been able to test this.
public class PlayScreen implements Screen {
TiledMap map;
OrthogonalTiledMapRenderer mapRenderer;
OrthographicCamera cam;
float unitScale = 1 / 64f;
OrthogonalTiledMapRenderer renderer = new OrthogonalTiledMapRenderer(map, unitScale);
Viewport viewport;
public void show() {
map = new TmxMapLoader().load("maps/map.tmx");
mapRenderer = new OrthogonalTiledMapRenderer(map);
cam = new OrthographicCamera(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);
cam.setToOrtho(false);
viewport = new StretchViewport(1280, 960, cam);
bounds = new ArrayList<Rectangle>();
for(int i = 0; i < 20; i++){
for(int j = 0; j < 15; j++){
TiledMapTileLayer cur = (TiledMapTileLayer) map.getLayers().get(1);
Cell cell = new Cell();
Vector3 center = new Vector3(cur.getWidth() * cur.getTileWidth() / 2, cur.getHeight() * cur.getTileHeight() / 2, 0);
cam.position.set(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, 0);
cam.update();
if(cur.getCell(i,j) != null){ //null = first layer != --> if its not
cell = cur.getCell(i, j);
System.out.println(i + ", " + j + ", " + cell.getTile().getId());
bounds.add(new Rectangle(i * 64, j * 64, 64 , 64));
}
}
}
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
mapRenderer.setView(cam);
mapRenderer.render();
cam.position.set(0, 0, 0);
cam.update();
batch.setProjectionMatrix(cam.combined);
batch.begin();
batch.draw(player.getCurrentFrame(), player.getPosition().x , player.getPosition().y);
player.update();
for(int i = 0; i < bounds.size(); i++){
if(bounds.get(i).overlaps(player.getBounds())){
int x = (int)bounds.get(i).x / 64;
int y = (int)bounds.get(i).y / 64;
TiledMapTileLayer cur = (TiledMapTileLayer)map.getLayers().get(1);
Cell cell = cur.getCell(x, y);
if(cell.getTile().getProperties().containsKey("blocked")){
System.out.println("bush");
}
player.reAdjust();
}
}
batch.end();
}
public void resize(int width, int height) {
viewport.update(width, height);
}
Nevermind, I deleted: cam.position.set(0, 0, 0); and everything seems to work just fine. Guess I already made some changes what caused it to work, just didn't see it cause this was still around.

Categories