Animating a line between two Point objects - java

What's the simplest way to draw a line between two Point objects in a way
that will look like I am drawing that line in real time by hand?
For example:
Point a = new Point(5,20);
Point b = new Point(15,20);
How do I connect these points with a "moving" line?
In other words I want to make the user feel "motion" of some sort. Is there a simple way to do that?

Given two points, you can determine the equation of the line connecting them. The equation of a line is of the form y = mx + c, where m is the slope, and c is the y intercept.
So, given your two points (5,20) and (15,20), we first determine m.
m = (y2-y1)/(x2-x1)
= (20-20)/(15-5)
= (0)/10
= 0
Substituting into the equation for a straight line, we get y = 0x + c or y = c. Now that we know this, we simply need to know the points where y = c and 5<=x<=15. Simply draw each of these points in the normal way (look at this for the exact method) with a Thread.sleep() call in between drawing each point. In this case, you have only 11 points to draw, so it would make sense to draw 1 point every 100 ms. For details on Thread.sleep() see here.
EDIT: Since Thread.sleep() won't work on the EDT, look at javax.swing.Timer instead, as Uhlen suggested.

Following the answer by Chinmay Kanchi, you need to create a feeling of animation. As mentioned above in comments by Uhlen you should use Swing's Timer when working on EDT. To give you example of how to use Timer. Lets assume we have a panel and we want it to slide open on e.g. a button click, thus we need to animate it sliding open by increasing its size. Below is an example showing pretty much how you would use Timer to do the operations.
this.extendingTimer = new Timer(0, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//assume sliding is vertical
int value = maximumHeight;
//make sure the size will not be bigger then allowed maximum
if(currentExtensionSize + extensionRate >= value)
{
currentExtensionSize = value;
stopExtending();
}
else
currentExtensionSize += extensionRate;
setSize(new Dimension(maximumWidth, currentExtensionSize));
}
});
extendingTimer.setInitialDelay(0);
extendingTimer.setDelay(100);
extendingTimer.setRepeats(true);

int lineCount = 0; //global
// timer calls the below
xLocation = (*a)[a->size()-1] * timeSoFar / duration ;
if(xLocation > (*a)[lineCount+1]){
lineCount++;
}
double m = ((*b)[lineCount+1] - (*b)[lineCount])/((*a)[lineCount+1]-(*a)[lineCount]);
double yIntercept = (*b)[lineCount]-m*(*a)[lineCount];
yLocation = m * xLocation + yIntercept;
xLocation = (yLocation - yIntercept) / m;
this is in c++ and using vectors but its the theory we want. This allows for multiple lines not just one.

Related

Drawing lines between clicks draws from top left corner

I'm currently trying to create a program using processing that draws lines from all mouseclicks to new mouseclicks.
As a side it also should save the clicks in a two-dimensional array.
public void setup() {
size(500,500);
}
int clickcount = 0;
int storedclicks = 10000;
int[] mouseclickX = new int [storedclicks];
int[] mouseclickY = new int [storedclicks];
public void draw() {
background(80);
drawing();
}
public void mousePressed() {
if(clickcount >= storedclicks) {
clickcount = 0;
}
mouseclickX[clickcount] = mouseX;
mouseclickY[clickcount] = mouseY;
clickcount++;
}
public void drawing() {
beginShape(LINES);
for (int i = 0; i < storedclicks; i++) {
vertex(mouseclickX[i], mouseclickY[i]);
}
endShape();
}
}
Something works with the code I have now, but something doesn't add up for me. As it is now, on first click I get a line from the upper left corner, next click that line disappears and I get a new line from the ending point of that line and the first line disappears.
Next click a new line from the corner to clicking point comes (line nr. 2 still present). And then it just continues.
I figured if I changed the storeclicks to a number like 5, it doesn't do the from corner thing, just a new line from every previous click position.
It sounds a little confusing, so here's a picture to help (after 3 clicks):
A few notes:
I'd use a lifo ring buffer (you could simulate it with a linked list) or similar to store the clicks, that way you don't have to check storedclicks separately and it should make drawing easier since the head of the buffer moves when you remove elements from the front.
Additionally I'd only draw lines if there are at least two points in the list/buffer.
Third, to prevent synchronization issues (updating only x or y) I'd use a list/buffer/array of Point objects (make your own or use java.awt.Point) rather than two separate x and y arrays.
As for your drawing code you should loop over the stored points rather than all elements (most of which might be empty), i.e. like this:
When using your code:
if( clickcount > 1 ) {
for (int i = 0; i < clickcount ; i++) {
vertex(mouseclickX[i], mouseclickY[i]);
}
}
When using a list/ring buffer as well as Point objects:
if( list.size() > 1 ) {
for (Point clickpos : list ) {
vertex(clickpos.x, clickpos.y);
}
}
Finally, if processing is similar to OpenGL (I don't know processing) the shape type LINES would draw a line between two vertices, i.e. every uneven vertex is a line start and every even vertex is a line end. What you probably want is something like LINE_STRIP (don't know the name or whether it exists in processing) which makes the renderer draw lines between all vertices (i.e. from 0 to 1, from 1 to 2 etc.)
Edit:
As an explanation for the situation in the image you posted, I assume the clicks are ordered from right to left (indices 0, 1, 2). If that's the case then I'd explain it like this (see above for more info):
The first line is drawn between points 0 and 1, which is ok.
The second line is drawn between points 2 and 3 (see paragraph about the loop as well as LINES resp. line strips), which is not what you want.
The third line (if storedclicks > 5) will be drawn between points 4 and 5, which is a point since both vertices have the coordinates 0/0.
The above bulletpoint is repeated for all following lines (again see the paragraph about the loop).
As you can see there are two problems:
You'd want to draw lines between 0 and 1 and between 1 and 2 which is why I suggested a line strip (if that exists in processing, otherwise you'd have to reuse the last point).
You'd want to stop at index 2, i.e. ignore all indices starting from 3, which is why I mentioned not using storedclicks in the loop condition).
Just to add to the existing great answers, here's a hacky approach that simply takes advantage of not clearing the background:
int lastClickX = -1;
int lastClickY = -1;
void setup(){
size(500,500);
background(80);
}
void draw(){}
void mouseReleased(){
if(lastClickX >= 0 && lastClickY >= 0) line(mouseX,mouseY,lastClickX,lastClickY);
lastClickX = mouseX;
lastClickY = mouseY;
}
You can run this as demo bellow:
var lastClickX = -1;
var lastClickY = -1;
function setup(){
createCanvas(500,500);
background(80);
}
function draw(){}
function mouseReleased(){
if(lastClickX >= 0 && lastClickY >= 0) line(mouseX,mouseY,lastClickX,lastClickY);
lastClickX = mouseX;
lastClickY = mouseY;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.17/p5.min.js"></script>
Bare in mind, although this method doesn't store position, it simply takes advantage of not clearing the screen, which isn't the most flexible of options.
To understand what's happening in your sketch, look to the reference.
This code:
beginShape(LINES);
vertex(30, 20);
vertex(85, 20);
vertex(85, 75);
vertex(30, 75);
endShape();
Generates this image:
(source: processing.org)
So, that's why you're getting gaps where your line segments aren't drawn. Instead of using LINES, you probably want to use the no-args beginShape() function along with the endShape(CLOSE) function:
(source: processing.org)
noFill();
beginShape();
vertex(30, 20);
vertex(85, 20);
vertex(85, 75);
vertex(30, 75);
endShape(CLOSE);
As for why you're getting a point at 0,0: keep in mind that int arrays are initialized to contain all zeroes by default. So when you loop through your entire array, you end up drawing a bunch of points at 0,0. Instead, you probably want a separate variable that keeps track of the total number of clicks (which you stop updating when you reach the maximum number of clicks you want to hold).
As a side it also should save the clicks in a two-dimensional array.
Note that you aren't storing the clicks in a two-dimensional array. You're storing them in two one-dimensional arrays, also known as parallel arrays. This is generally a bad design. Instead, consider using Processing's PVector class along with an ArrayList instead of an array. That way you can keep track of how many valid clicks you have without needing the separate variable I mentioned above.
Putting it all together, it might look something like this:
ArrayList<PVector> clicks = new ArrayList<PVector>();
public void setup() {
size(500, 500);
}
public void draw() {
background(80);
drawing();
}
public void mousePressed() {
clicks.add(new PVector(mouseX, mouseY));
if(clicks.size() > 5){
clicks.remove(0);
}
}
public void drawing() {
noFill();
beginShape();
for(PVector v : clicks){
vertex(v.x, v.y);
}
endShape(CLOSE);
}
draws lines from all mouseclicks to new mouseclicks.
If instead of a closed polygon, you want something like a spider web that connects every point to every other point, then you just have to loop through each click and draw the connecting lines:
public void drawing() {
for (PVector v1 : clicks) {
for (PVector v2 : clicks) {
line(v1.x, v1.y, v2.x, v2.y);
}
}
}

How to get a number from a changing variable?

I'm currently trying to make something like a trail that follows an object. Well, basically I just create a "trail object" every second at X,Y of the main object. However, I can't make it work.
This the movement code for the main object.
dx = ((Math.sin(speed)*20);
speed = speed + 0.09;
x = x + dx;
My idea was that for making a trail I just need to subtract dx from x, so it would look like that
tick = tick + gameTimer.getDelay();
for(int i = 0; i < 100; i++)
{
if (tick > 1000*i)
{
g2d.drawOval(x-dx, y, 50, 50);
}
}
but apparently my theory is wrong and therefore I ask for your help people.
P.S. There is no code for "y" because I don't need it yet.
P.S.S I know that I'm missing a lot of details, so if you need some more info let me know and I'll paste some more code

How to move an entire GPen object?

In Java using the acm.graphics GPen is there any way to move the entire drawn sequence of lines? I've read the manual thoroughly and I'm beginning to think it's not possible which brings me to my second question. Are there any other graphics objects in Java that work very similar to a pen that can also be moved. The reason I'm asking is because I've been working on a graphing program that allows mouse gestures to be used to pan around and zoom in and out. After building functionality for implicit functions I realized simply clearing the drawing board and redrawing everything is not going to cut it anymore so I really need to work on more efficient ways to handle intermediate changes of the graph without having to recalculate everything. For example with this or similar code:
GPen p = new GPen();
p.setLocation(100,100); //places the pen on the canvas at 100, 100
p.drawLine(-50,0); //draw a line left 50 pixels
p.drawLine(50,-50); //draw a line right and up 50 pixels each
p.drawLine(0,50); //draw a line down 50 pixels
This would result in a simple right triangle who's bottom right most point is at 100, 100 on a particular canvas. What I need to do is be able to move this same drawn sequence of lines relative to one another to another origin. What I hoping for is a class that has separate methods for setLocation() and move() where setLocation() controls pen position and move() would move the entire object around.
Ok so having received almost no attention on here I've came to the conclusion that such a method just needs to be written from scratch and went ahead and did that. I'm not entirely sure how helpful posting my proprietary code would be but in the event that anybody could use it I'll post the basic idea of it. Since Pen utilities are essentially a bunch of lines and lines are a bunch of from and to's I created an object that I called FPen (for FunctionPen) that accepts the instructions for from and to. While defining FPen you pass it where to start and how far to go however many times you need and that's it. Once you've passed these instructions I created another method called returnGPen(Color c) which will on call use the instructions it has on hand and generate the desired GPen object. When you want to move the entire GPen you can then create a method called adjustOrigin(double oX, double oY); which will calculate a change from a previously recorded origin and this new one and go through the list of instructions and adjust them appropriately.
My needs for this Class are strictly for my Graphing program and are not entirely finished either but it does work for most purposes.
import acm.graphics.GPen;
import java.awt.Color;
import java.util.ArrayList;
public class FPen{
private double relativeCenterX;
private double relativeCenterY;
private ArrayList<Double> fromX = new ArrayList<Double>();
private ArrayList<Double> fromY = new ArrayList<Double>();
private ArrayList<Double> distX = new ArrayList<Double>();
private ArrayList<Double> distY = new ArrayList<Double>();
public FPen(double rX, double rY, double z){
relativeCenterX = rX;
relativeCenterY = rY;
}
public void adjustOrigin(double cX, double cY){
double changeX = relativeCenterX-cX;
double changeY = relativeCenterY-cY;
for(int i = 0; i < fromX.size(); i++){
fromX.set(i,fromX.get(i)+changeX*zoom);
fromY.set(i,fromY.get(i)-changeY*zoom);
}
relativeCenterX = cX;
relativeCenterY = cY;
}
public void clear(){
fromX.clear();
fromY.clear();
distX.clear();
distY.clear();
}
public void drawLine(double fX, double fY, double tX, double tY){
fromX.add(fX);
fromY.add(fY);
distX.add(tX);
distY.add(tY);
}
public GPen returnGPen(Color c){
GPen pen = new GPen();
pen.setColor(c);
for(int i = 0; i < fromX.size(); i++){
pen.setLocation(fromX.get(i),fromY.get(i));
pen.drawLine(distX.get(i),distY.get(i));
}
return pen;
}
}
Of course a unexpected nice thing that came out of this was the idea that I can now quickly benchmark different drawing routines by creating different methods for each and calling what I'm interested in.

Drawing lots of particles efficiently

I have written a particle system applet; currently I am creating, and drawing each particle separately.
(Here is the code)
BufferedImage backbuffer;
Graphics2D g2d;
public void init(){
backbuffer = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
g2d = backbuffer.createGraphics();
setSize(WIDTH, HEIGHT);
//creates the particles
for (int i = 0; i < AMOUNTPARTICLES; i++) {
prtl[i] = new particleO();
prtl[i].setX(rand.nextInt(STARTX));
prtl[i].setY(rand.nextInt(STARTY));
prtl[i].setVel(rand.nextInt(MAXSPEED)+1);
prtl[i].setFAngle(Math.toRadians(rand.nextInt(ANGLESPREAD)));
}
//other code
}
public void update(Graphics g) {
g2d.setTransform(identity);
//set background
g2d.setPaint(BGCOLOUR);
g2d.fillRect(0,0,getSize().width,getSize().height);
drawp();
paint(g);
}
public void drawp() {
for (int n = 0; n < AMOUNTPARTICLES; n++) {
if (prtl[n].getAlive()==true){
g2d.setTransform(identity);
g2d.translate(prtl[n].getX(), prtl[n].getY());
g2d.setColor(prtl[n].getColor());
g2d.fill(prtl[n].getShape());
}
}
}
It's performance was alright, I could get ~40FPS with 20,000 particles (although, I have a decent laptop). But after I added collision detection (see below), that number plummeted to less than 2000,
public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)
for (int j = 0; j < AMOUNTPARTICLES; j++) {
if (i!=j && prtl[j].getAlive()==true){
if(hasCollided(i, j)){
prtl[i].setcolor(Color.BLACK);
prtl[j].setcolor(Color.BLACK);
}
}
}
public boolean hasCollided(int prt1, int prt2){
double dx = prtl[prt1].getX() - prtl[prt2].getX();
double dy = prtl[prt1].getY() - prtl[prt2].getY();
int edges = prtl[prt1].getRadius() + prtl[prt2].getRadius();
double distance = Math.sqrt( (dx*dx) + (dy*dy) );
return (distance <= edges);
}
I have searched quite a bit for a better way of drawing the particles to the screen, but the examples either confused me, or were not applicable.
I am doing a boat load of calculations (too many). But I couldn’t think of another way of doing it, suggestions are welcome.
First of all, adding in something like collision detection always takes a lot of memory. However, let's look at your collision detection algorithm
public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)
for (int j = 0; j < AMOUNTPARTICLES; j++) {
if (i!=j && prtl[j].getAlive()==true){
if(hasCollided(i, j)){
prtl[i].setcolor(Color.BLACK);
prtl[j].setcolor(Color.BLACK);
}
}
}
Let's pretend there was only 2 particles, 1 and 2. You will check, in order
1,1
1,2
2,1
2,2
The truth is, you only really needed to check 1 vs 2 in this case. If 1 hits 2, 2 will also hit 1. So change your for loop skip previously tested, and the same number for that matter.
public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)
for (int j = i+1; j < AMOUNTPARTICLES; j++) {
Another thing I notice is that you do a sqrt operation, but only to compare to what looks like a static number. If you remove that, and compare it to the number squared, you'll get a large improvement, especially with something you do so much.
double distance_squared = ( (dx*dx) + (dy*dy) );
return (distance <= edges*edges);
Keep looking for improvements like this. Then you might carefully look at other options, like using a different class, threading, etc, which all might improve the system. But make sure you optimize the code where you can first. Here is a list of other things that I would try, roughly in order.
Check to see if particle i is alive before you even calculate anything else after i comes into view.
Do a quick pass over the pairs, only even bothering to check in detail if they are close. A simple way would be to detect if they are within the x and y dimensions first, before taking a sqrt operation. Always do the cheapest test first, before doing complex ones.
Look at your code, to see if you really use all of the values calculated, or if you might be able to reduce the number of operations somehow.
Perhaps you could cluster the images on a regular basis with a broad stroke, then refine only objects which passed the initial cluster for a period of time, then do a broad cluster algorithm.
You could thread the collision detection. However, if you are going to do this, you should only thread the checking to see if something has collided, and after all of those threads are done, update the objects on the view.
Look into alternative architectures, which might speed things up some.
Painting is a complex process and paint requests can be triggered for any number of reasons, the OS might want the window to update, the repaint manager might want to repaint, the programer might want to repaint.
Updating the particles within the paint process is bad idea. What you want to do is update the particles in a separate thread on a separate buffer. When you're ready, request that the component responsible for painting the buffer perform a repaint, passing a new copy of the buffer to repainted (you don't want to be painting on the buffer that is begin updated to the screen, you'll end up with dirty paints).
It's hard to tell from you code, but it would appear you're using java.awt.Applet, personally, I'd upgrade to javax.swing.JApplet.
I'd move the painting to a java.swing.JPanel. Swing components provide double buffering (as well as other buffering strategies). The only job this panel has is to paint a buffer to the screen when the particles engine has a new frame.
The particles engine is responsible for updating all the particles and painting these results to a backing buffer (BufferedImage), this would then be handed to the panel and the panel would make a copy and schedule an update.
Swing is NOT THREAD SAFE. That is, you shouldn't make changes to the UI from any thread other then the Event Dispatching Thread. To this end, you might like to have a read through Concurrency in Swing for solutions to resync the off screen buffer to the client.
You are checking all particless colliding with all particlesand this is quite a requeriment, of the order of n^2 (2,000 particles means 4,000,000 combinations, for each frame).
The issue is not java but the algorithm. There must be better options, but to begin with you could reduce the comparations; if you have a maximum speed S and the time in your world increments by T, with T*S you get the maximum distance D of a particle that can collide with the particle you are considering. Reduce the search to those particle which are at a distance equal or less than that. Maybe it will be easier to restrict the search to those in an square centered in your particle an with height/widht D (this will include some particles that are too far, but will make the checks easier).
Additionally, in your code you are checking collisions of P1 vs P2 and P2 vs P1 which is the same, that is a redundance that you can avoid easily.

How to dynamically construct 3d object by adding paths? (Java; OpenGL)

So I have some path generator which now works like this
http://www.openprocessing.org/visuals/?visualID=2615 (There is source; WQRNING - JAVA APPLET)
I want to create some 3D object using paths I generated so it locked in one of perspectives similar to what I get now in 2D.
So how do I dynamically construct 3D object by adding paths?
BTW: actually I ment algorithm like this http://www.derschmale.com/2009/07/20/slice-based-volume-rendering-using-pixel-bender/
So I want to create from such PATH (I do not want to use images and I do not want to use flash I want to use Java + OpenGl)
such 3d image (But note I want openGL Java and Path's))
I'm not sure I understand what you're after.
The example you supplied draws 2d paths, but merely uses z. scaling would have worked
in a similar way.
So How to dinamicly construct 3d
object by adding path's ?
Do you mean extruding/lathing an object, or replicating the scrunch sketch ?
Drawing a path is easy in processing, you just place vertex objects, in a for loop
between beginShape() and endShape() calls.
Here is the bit of code that does that in the example you've sent:
beginShape();
for (int p=0; p<pcount; p++){
vertex(Ring[p].position().x(),Ring[p].position().y());
}
endShape(CLOSE);
you can also call vertex(x,y,z)
I wanted to extrude a path a while back, here is my question in case it helps.
Basic sketch is uploaded here.
EDIT:
If you have an array of 2 polygons, you can just loop through them, and draw
using something similar to beginShape() and endShape(), GL_POLYGON might be handy.
e.g.
import processing.opengl.*;
import javax.media.opengl.*;
int zSpacing = 10;
PVector[][] slices;
void setup() {
size(600, 500, OPENGL);
slices = new PVector[3][3];
//dummy slice 1
slices[0][0] = new PVector(400, 200,-200);
slices[0][1] = new PVector(300, 400,-200);
slices[0][2] = new PVector(500, 400,-200);
//dummy slice 2
slices[1][0] = new PVector(410, 210,-200);
slices[1][1] = new PVector(310, 410,-200);
slices[1][2] = new PVector(510, 410,-200);
//dummy slice 3
slices[2][0] = new PVector(420, 220,-200);
slices[2][1] = new PVector(320, 420,-200);
slices[2][2] = new PVector(520, 420,-200);
}
void draw() {
background(255);
PGraphicsOpenGL pgl = (PGraphicsOpenGL) g; // g may change
GL gl = pgl.beginGL(); // always use the GL object returned by beginGL
for(int i = 0 ; i < slices.length; i ++){
gl.glColor3f(0, .15 * i, 0);
gl.glBegin(GL.GL_POLYGON);
for(int j = 0; j < slices[i].length; j++){
gl.glVertex3f(slices[i][j].x, slices[i][j].y,slices[i][j].z + (zSpacing * i));
}
gl.glEnd();
}
pgl.endGL();
}
The idea is you loop through each slice, and for each slice your loop through all its points. Obviously slices and the number of 3d vectors inside each slice is up to your data. Speaking of which, where does your data come from ?
If slices is not what your after volTron could come in handy:
volTron http://dm.ncl.ac.uk/joescully/voltronlib/images/s2.jpg
HTH,
George

Categories