Circle to Circle Vector Transform - java

Hi
I have a program where you drag and drop circles on a scene using JavaFX. I don't want circles to collide to each other so I added a collision algorithm to check that, which now works. What puzzles me is what I want to do afterwards.
If two circles overlap I want to make a vector between the middle of the two and transform the moved circle in the direction of the vector until they no longer overlap.
for (Stone stn:getCurrentScenario().getStones()) {
if (stn.circle == circle) continue;
double x1 = stn.circle.getTranslateX();
double y1 = stn.circle.getTranslateY();
double r1 = stn.circle.getRadius()+stn.circle.getStrokeWidth();
double x2 = circle.getTranslateX();
double y2 = circle.getTranslateY();
double r2 = circle.getRadius();
double distSq = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
double radSumSq = (r1 + r2) * (r1 + r2);
if (!(distSq != radSumSq && distSq > radSumSq)) {
System.out.println("Collision.");
// Transform "circle".
}
}

I ended up skipping the vector idea and went by angle instead. Going to keep the title if someone else runs into a similar issue:
double newX = circle.getTranslateX();
double newY = circle.getTranslateY();
for (Stone stn:getCurrentScenario().getStones()) {
if (stn.circle == circle) continue;
double x1 = stn.circle.getTranslateX();
double y1 = stn.circle.getTranslateY();
double r1 = stn.circle.getRadius()+stn.circle.getStrokeWidth();
double x2 = newX;
double y2 = newY;
double r2 = circle.getRadius();
double distSq = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
double radSumSq = (r1 + r2) * (r1 + r2);
if (!(distSq != radSumSq && distSq > radSumSq)) {
double angle = Math.atan2(x1-x2,y1-y2);
newX = x1 - Math.sin(angle) * (circle.getRadius() + circle.getStrokeWidth() + stn.circle.getRadius() + .01);
newY = y1 - Math.cos(angle) * (circle.getRadius() + circle.getStrokeWidth() + stn.circle.getRadius() + .01);
}
}
for (Stone stn:getCurrentScenario().getStones()) {
if (stn.circle == circle) continue;
double x1 = stn.circle.getTranslateX();
double y1 = stn.circle.getTranslateY();
double r1 = stn.circle.getRadius()+stn.circle.getStrokeWidth();
double x2 = newX;
double y2 = newY;
double r2 = circle.getRadius();
double distSq = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
double radSumSq = (r1 + r2) * (r1 + r2);
if (!(distSq != radSumSq && distSq > radSumSq)) {
newX = oldX;
newY = oldY;
break;
}
}
circle.setTranslateX(newX);
circle.setTranslateY(newY);
I made that piece of code just to make sure that it works as intended. Going to improve it now.

Related

Drawing pie chart with PDFbox

I'm trying to draw Pie chart with PDFbox, but there are white lines between the slices, could anyone help me with this? is there an option for this?
Attached the code for drawing the arc that I'm using:
while (start < stop) {
List<Float> smallArc = PdfUtils.createSmallArc(a, b, radius, start, start +
2.0944 > stop ? stop : start + 2.0944);
contentStream.saveGraphicsState();
contentStream.setNonStrokingColor(components[0], components[1],
components[2]);
contentStream.moveTo(smallArc.get(0), smallArc.get(1));
contentStream.curveTo(smallArc.get(2), smallArc.get(3), smallArc.get(4),
smallArc.get(5), smallArc.get(6), smallArc.get(7));
contentStream.fill();
contentStream.restoreGraphicsState();
start += 2.0944;
}
public static List<Float> createSmallArc(float x, float y, double r, double a1, double a2) {
double a = (a2 - a1) / 2;
double x4 = r * Math.cos(a);
double y4 = r * Math.sin(a);
double x1 = x4;
double y1 = -y4;
double q1 = x1 * x1 + y1 * y1;
double q2 = q1 + x1 * x4 + y1 * y4;
double k2 = 4 / 3d * (Math.sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4);
double x2 = x1 - k2 * y1;
double y2 = y1 + k2 * x1;
double x3 = x2;
double y3 = -y2;
double ar = a + a1;
double cos_ar = Math.cos(ar);
double sin_ar = Math.sin(ar);
List<Float> list = new ArrayList<Float>();
list.add((float) (r * Math.cos(a1)) + x);
list.add((float) -(r * Math.sin(a1)) + y);
list.add((float) (x2 * cos_ar - y2 * sin_ar) + x);
list.add((float) -(x2 * sin_ar + y2 * cos_ar) + y);
list.add((float) (x3 * cos_ar - y3 * sin_ar) + x);
list.add((float) -(x3 * sin_ar + y3 * cos_ar) + y);
list.add((float) (r * Math.cos(a2)) + x);
list.add((float) -(r * Math.sin(a2)) + y);
return list;
}
Attached image of the result:
Thanks
Instead of using fill(), use the fillAndStroke() method and call setStrokingColor() with the same parameters that you used for setNonStrokingColor().

Detect interception with line

How can I make a algorithm that detects if a point (x, y) intercepts with a line. (x1, y1, x2, y2)?
I have already tried :
boolean onLine(float a, float b, float c, float d, float x, float y){
boolean answer = false;
float[] p1 = new float[] {a, b};
float[] p2 = new float[] {c, d};
float x_spacing = (p2[0] - p1[0]) / ((a+c)/2 + (b+d));
float y_spacing = (p2[1] - p1[1]) / ((a+c)/2 + (b+d));
List<float[]> line = new ArrayList();
float currentX = 0;
float currentY = 0;
while(currentX+a<c&&currentY+b<d){
currentX += x_spacing;
currentY += y_spacing;
line.add(new float[]{a+currentX, b+currentY});
}
for(int j = 0; j < line.size(); j++){
if(x > line.get(j)[0]-x_spacing && x < line.get(j)[0]+x_spacing && y > line.get(j)[1]-
y_spacing && y < line.get(j)[1]+y_spacing){
answer = true;
println("Hit line!");
break;
}
}
return answer;
}
This works sometimes, but is not always consistent.
I am putting this with a physics game, and I need this so the ball can roll down a line.
What are some ways I can improve it so that it works?.
EDIT: Thanks to Felix Castor I got it working. Here is the final Code:
boolean onLine(float x1, float y1, float x2, float y2, float xt, float yt,
float wid, float hit){
float Y = (y2 - y1)/(x2 - x1)* xt + y1 -(y2 - y1)/(x2 - x1) * x1;
boolean answer = false;
if(abs(Y - yt) < 5) answer = true;
if(abs(Y - yt-hit) < 5) answer = true;
if(abs(Y - yt-(hit/2)) < 5) answer = true;
if(abs(Y - yt+hit) < 5) answer = true;
if(abs(Y - yt+(hit/2)) < 5) answer = true;
return answer;
}
Using slope intercept form you can plug in your x and see if the y's are equal.
y = m*x + b
m = (y2 - y1)/(x2 - x1)
b = y1 - (y2 - y1)/(x2 - x1) * x1
So the equation becomes
Y = (y2 - y1)/(x2 - x1)* X + y1 -(y2 - y1)/(x2 - x1) * x1
given a point (xt, yt) you can plug in the xt into X and evaluate then compare the result to yt. If they are equal then the point is on the line.
if Y == yt given xt then the point is on the line.
You will need to handle the case where you have strictly horizontal lines as edge cases. Those will blow up the equation.
Edit: Conditions Changed
Since you are wanting to determine how far from the line a point is I would say the formula for the distance between a point and a line in cartesian space would be the way to go. See Distance from a point to a line section Line Defined By Two Points. The formula looks ugly but it's straight forward.
double numerator = Math.abs((y2 - y1) * xt - (x2 - x1) * yt + x2 * y1 - y2 * x1);
double denominator = Math.sqrt(Math.pow(y2 - y1, 2) + Math.pow(x2 - x1, 2));
double distance = numerator / denominator;
As before your test point is (xt, yt) and your line is defined by two points (x1, y1) and (x2, y2). Because distance is always >= 0 your test would be:
if( distance <= tolerance) return true
I think this is a better approach if you are interested in a tolerance.

3D Graphics, Cube seems illogical

I designed a simple java program viewing 3D Cube, but i do not why i guess there is something illogically in that.
the length of rib = 350
the front square depth (z axis) is 0
the back square depth (z axis) is equal to the length of rib,
but the result was very tall cube !!:
I designed a simple java program viewing 3D Cube, but i do not why i guess there is something illogically in that.
the length of rib = 350
the front square depth (z axis) is 0
the back square depth (z axis) is equal to the length of rib,
but the result was very tall cube !!:
The code:
public void paint(Graphics g){
super.paint(g);
int squareLengthRib = 350; // Ribs length
int frontSquareDepth = 0; // Z value (Depth of front square)
int backSquareDepth = frontSquareDepth + squareLengthRib; // Z value (Depth of back square)
x1 = 300;
y1 = 300;
z1 = frontSquareDepth;
x2 = x1 + squareLengthRib;
y2 = y1 ;
z2 = z1;
x3 = x2;
y3 = y2 + squareLengthRib;
z3 = z2;
x4 = x1;
y4 = y3;
z4 = z3;
/**********************************************/
x5 = x1;
y5 = y1;
z5 = backSquareDepth;
x6 = x2;
y6 = y2;
z6 = z5;
x7 = x3;
y7 = y3;
z7 = z6;
x8 = x4;
y8 = y4;
z8 = z7;
PerspectiveProjection();
g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
g.drawLine((int)x2, (int)y2, (int)x3, (int)y3);
g.drawLine((int)x3, (int)y3, (int)x4, (int)y4);
g.drawLine((int)x4, (int)y4, (int)x1, (int)y1);
g.drawLine((int)x5, (int)y5, (int)x6, (int)y6);
g.drawLine((int)x6, (int)y6, (int)x7, (int)y7);
g.drawLine((int)x7, (int)y7, (int)x8, (int)y8);
g.drawLine((int)x8, (int)y8, (int)x5, (int)y5);
g.drawLine((int)x1, (int)y1, (int)x5, (int)y5);
g.drawLine((int)x2, (int)y2, (int)x6, (int)y6);
g.drawLine((int)x3, (int)y3, (int)x7, (int)y7);
g.drawLine((int)x4, (int)y4, (int)x8, (int)y8);
}
private void PerspectiveProjection() {
double d = 100;
double xd, yd;
xd = (x1 * d) / (z1 + d);
yd = (y1 * d) / (z1 + d);
x1 = xd;
y1 = yd;
xd = (x2 * d) / (z2 + d);
yd = (y2 * d) / (z2 + d);
x2 = xd;
y2 = yd;
xd = (x3 * d) / (z3 + d);
yd = (y3 * d) / (z3 + d);
x3 = xd;
y3 = yd;
xd = (x4 * d) / (z4 + d);
yd = (y4 * d) / (z4 + d);
x4 = xd;
y4 = yd;
xd = (x5 * d) / (z5 + d);
yd = (y5 * d) / (z5 + d);
x5 = xd;
y5 = yd;
xd = (x6 * d) / (z6 + d);
yd = (y6 * d) / (z6 + d);
x6 = xd;
y6 = yd;
xd = (x7 * d) / (z7 + d);
yd = (y7 * d) / (z7 + d);
x7 = xd;
y7 = yd;
xd = (x8 * d) / (z8 + d);
yd = (y8 * d) / (z8 + d);
x8 = xd;
y8 = yd;
}

Debugging Java/Processing output of an object patrolling screen

I am a first year computer programming student working on a project of Robots and Robot testing environment.
Although I'm new to Stackoverflow, I'm pretty aware that we are not supposed to help with assignments or homework.
I'm struggling to understand why such behavior is happening, so it would be really helpful just to understand why it's happening.
We are using Processing libraries to program in Java.
Our task is to create a robot testing environment and create three robots performing different movements.
The movement I'm trying to program is Patrol, which means just go around the edges of the screen.
The expected behavior is to go forward until it reaches a wall, turn left (90 degrees counter-clock wise), and go forward again.
This project is in conjunction with our Math class. That being said, we can't use methods like rotate(), translate(), pushMatrix() and popMatrix() to help rotating the forms (each robot is a triangle).
So, the steps I followed to rotate the triangles were:
1) translate its center point to the origin (0,0) and the vertices using the same translation;
2) rotate all points, where (x, y) become (y, -x);
3) translate back to correct position (inverse of the step 1 translation).
I set some boundaries if statements to put the triangle back to screen if, after rotation, anything went off screen.
My problem
After turning, the triangle is appearing in strange position, like teleporting.
I added a few lines so we can get each vertex's coordinates, the direction it's going and detect when direction is changed.
Code
There are two files: TestRobots, Robot.
Robot:
import processing.core.PApplet;
public class Robot{
int colour;
String name;
float width;
float height;
float x1;
float y1;
float x2;
float y2;
float x3;
float y3;
int direction;
int speed;
float centralPointX = width/2;
float centralPointY = height/2;
PApplet parent;
public Robot(PApplet parent, String name, int colour, float x1, float y1, float x2, float y2, float x3, float y3, int speed){
this.parent = parent;
this.name = name;
this.colour = colour;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
this.speed = speed;
direction=4;
width = x2-x3;
if (width < 0){
width *= -1;
}
if (y2 > y3){
height = y2-y1;
}else{
height = y3-y1;
}
if (height < 0){
height *= -1;
}
if (y1<y2 && y1<y3){
direction=4;
}
}
public void drawRobot(){
parent.fill(colour);
parent.triangle(x1, y1, x2, y2, x3, y3);
parent.ellipseMode(parent.CENTER);
parent.ellipse(x1, y1, 3, 3);
}
public void moveForward(){
if(x1<parent.width || y1 <parent.height || x1 > 0 || y1 > 0){
switch (direction){
case 1:
x1 += speed;
x2 += speed;
x3 += speed;
break;
case 2:
y1 += speed;
y2 += speed;
y3 += speed;
break;
case 3:
x1 -= speed;
x2 -= speed;
x3 -= speed;
break;
case 4:
y1 -= speed;
y2 -= speed;
y3 -= speed;
break;
}
}
}
public void turnLeft(){
//Store original coordinates.
float tempX1 = x1;
float tempY1 = y1;
float tempX2 = x2;
float tempY2 = y2;
float tempX3 = x3;
float tempY3 = y3;
//Calculate translation of the central point of triangle to the origin.
float xTranslation = 0 - centralPointX;
float yTranslation = 0 - centralPointY;
//Translate all points by the translation calculated.
float translatedX1 = tempX1 + xTranslation;
float translatedY1 = tempY1 + yTranslation;
float translatedX2 = tempX2 + xTranslation;
float translatedY2 = tempY2 + yTranslation;
float translatedX3 = tempX3 + xTranslation;
float translatedY3 = tempY3 + yTranslation;
//Rotate all points 90 degrees counterclockwise, (x, y) --> (y, -x).
float rotatedX1 = translatedY1;
float rotatedY1 = -translatedX1;
float rotatedX2 = translatedY2;
float rotatedY2 = -translatedX2;
float rotatedX3 = translatedY3;
float rotatedY3 = -translatedX3;
//Translate all points back.
x1 = rotatedX1 - xTranslation;
y1 = rotatedY1 - yTranslation;
x2 = rotatedX2 - xTranslation;
y2 = rotatedY2 - yTranslation;
x3 = rotatedX3 - xTranslation;
y3 = rotatedY3 - yTranslation;
//Check which y and which x are the smallest, in order to correct any negative numbers.
float minX;
float minY;
if (y1<y2 && y1<y3){
minY = y1;
} else if (y2<y1 && y2<y3){
minY = y2;
} else {
minY = y3;
}
if (x1<x2 && x1<x3){
minX = x1;
} else if (x2<x1 && x2<x3){
minX = x2;
} else {
minX = x3;
}
//Check which y and which x are the biggest, in order to correct any out-of-screen draws.
float maxX;
float maxY;
if (y1>y2 && y1>y3){
maxY = y1;
} else if (y2>y1 && y2>y3){
maxY = y2;
} else {
maxY = y3;
}
if (x1>x2 && x1>x3){
maxX = x1;
} else if (x2>x1 && x2>x3){
maxX = x2;
} else {
maxX = x3;
}
//Correct position if any coordinate is negative.
if((minY-speed)<=minY){
float differenceY = -minY + 10;
y1 += differenceY;
y2 += differenceY;
y3 += differenceY;
}
if(x1<=(x1-speed)){
float differenceX = -minX + 10;
x1 += differenceX;
x2 += differenceX;
x3 += differenceX;
}
//Correct position if any coordinate is bigger than the screen size.
if((parent.height<=(maxY+speed))){
float differenceY = (-maxY+parent.height) + 10;
y1 -= differenceY;
y2 -= differenceY;
y3 -= differenceY;
}
if((x1+speed)>=parent.width){
float differenceX = (-maxX+parent.width) + 10;
x1 -= differenceX;
x2 -= differenceX;
x3 -= differenceX;
}
//Change direction variable and adjust it between 0 and 4.
direction -=1;
if (direction == 0){
direction = 4;
}
}
public void patrol(){
System.out.println("Direction is: "+ direction);
if(((y1-speed)<= 0)||((y1+speed)>= parent.height) || ((x1+speed)>=parent.width)||((x1-speed)<=0)){
turnLeft();
System.out.println("The NEW direction is: "+ direction);
}
moveForward();
}
}
TestRobots:
import processing.core.PApplet;
public class TestRobots extends PApplet{
Robot alice = new Robot(this, "Alice", 255, 257f, 389f, 309f, 450f, 209f, 450f, 3);
public static void main(String[] args){
PApplet.main("TestRobots");
}
public void settings(){
size(1000, 500);
}
public void setup(){
frameRate(30);
}
public void draw(){
background(255);
alice.patrol();
System.out.println("x1 = "+ alice.x1);
System.out.println("y1 = "+ alice.y1);
System.out.println("x2 = "+ alice.x2);
System.out.println("y2 = "+ alice.y2);
System.out.println("x3 = "+ alice.x3);
System.out.println("y3 = "+ alice.y3);
alice.drawRobot();
}
}
Here is a print of the generated output. I snipped the part where it changes direction:
Direction is: 2
x1 = 62.0
y1 = 497.0
x2 = 10.0
y2 = 436.0
x3 = 110.0
y3 = 436.0
The NEW direction is: 1
x1 = 500.0
y1 = 58.0
x2 = 439.0
y2 = 110.0
x3 = 439.0
y3 = 10.0
Same strange behavior here:
Direction is: 4
x1 = 257.0
y1 = 2.0
x2 = 309.0
y2 = 63.0
x3 = 209.0
y3 = 63.0
The NEW direction is: 3
x1 = -1.0
y1 = 62.0
x2 = 60.0
y2 = 10.0
x3 = 60.0
y3 = 110.0
The NEW direction is: 2
x1 = 62.0
y1 = 74.0
x2 = 10.0
y2 = 13.0
x3 = 110.0
y3 = 13.0
Thank you very much for reading until here and sorry in advance if I wasn't clear enough. It's my first question!
Gustavo
I think your problem relates to the variables centralPointX and centralPointY. Look at this code you wrote:
//Calculate translation of the central point of triangle to the origin.
float xTranslation = 0 - centralPointX;
float yTranslation = 0 - centralPointY;
//Translate all points by the translation calculated.
float translatedX1 = tempX1 + xTranslation;
float translatedY1 = tempY1 + yTranslation;
float translatedX2 = tempX2 + xTranslation;
float translatedY2 = tempY2 + yTranslation;
float translatedX3 = tempX3 + xTranslation;
float translatedY3 = tempY3 + yTranslation;
It seems from this that you think centralPointX and centralPointY indicate the center of the triangle... However, look at where they are defined:
float centralPointX = width/2;
float centralPointY = height/2;
So they don't actually represent the center xy co-ordinates. What you need to do is fix this part:
//Calculate translation of the central point of triangle to the origin.
float xTranslation = 0 - centralPointX;
float yTranslation = 0 - centralPointY;
So that it actually does what the comment says it should do, i.e., calculates the x and y co-ordinates of the center of your triangle.
I won't implement this for you, because as you said, it is homework. However, I think this should definitely point you in the right direction. Also, keep up the good work. I wish every first question was as well thought out as this.

Processing sketch glitchs when using values depending upon values of x

My program contains main shapes i.e square, rect, circle they work good ( for x2,y2 in those shapes I used absolute values e.g square( x, y, 5, 5) ), but when working with triangle shape,
Triangles in my program glitches.
below is the code of my program modules,
if (vehicleStyle.getVehicleShape().equals(VehicleShape.TRIANGLE)) {
processingVisualizer
.fill(vehicleStyle.getColor().red,
vehicleStyle.getColor().green,
vehicleStyle.getColor().blue);
processingVisualizer.strokeWeight(1 * vehicleSize);
//System.out.println(x + "-" + y);
//## to place face toward movement direction
/*
* -----<|----
* | |
* \/ /\
* | |
* -----|>----
*/
float x2, y2, x3, y3;
if (x == 100) {
System.out.println( "x==100");
x2 = x - 5;
y2 = y + 5;
x3 = x + 5;
y3 = y + 5;
processingVisualizer.triangle(x, y, x2, y2, x3, y3);
} else if (x == 20) {
System.out.println( "x==20");
x2 = x - 2;
y2 = y - 2;
x3 = x + 2;
y3 = y - 2;
processingVisualizer.triangle(x, y, x2, y2, x3, y3);
} else if (y == 100) {
System.out.println( "y ==100");
x2 = x - 2;
y2 = y - 2;
x3 = x - 2;
y3 = y + 2;
processingVisualizer.triangle(x, y, x2, y2, x3, y3);
} else if (y == 20) {
System.out.println( "y ==20");
x2 = x+5;//x - 2;
y2 = y-5;
x3 = x+5 ;//- 2;
y3 = y+5;
processingVisualizer.triangle(x, y, x2, y2, x3, y3);
}
}
processingVisualizer.strokeWeight(1);
}
Can't test your code, but my assumption is the "glitch" happens because you are rendering a triangle only when your 4 conditions are met. You should update the triangle's corner positions based on your conditions if you like, but render the triangle all time, even when the positions are out of date:
if (vehicleStyle.getVehicleShape().equals(VehicleShape.TRIANGLE)) {
processingVisualizer
.fill(vehicleStyle.getColor().red,
vehicleStyle.getColor().green,
vehicleStyle.getColor().blue);
processingVisualizer.strokeWeight(1 * vehicleSize);
//System.out.println(x + "-" + y);
//## to place face toward movement direction
/*
* -----<|----
* | |
* \/ /\
* | |
* -----|>----
*/
float x2, y2, x3, y3;
if (x == 100) {
System.out.println( "x==100");
x2 = x - 5;
y2 = y + 5;
x3 = x + 5;
y3 = y + 5;
} else if (x == 20) {
System.out.println( "x==20");
x2 = x - 2;
y2 = y - 2;
x3 = x + 2;
y3 = y - 2;
} else if (y == 100) {
System.out.println( "y ==100");
x2 = x - 2;
y2 = y - 2;
x3 = x - 2;
y3 = y + 2;
} else if (y == 20) {
System.out.println( "y ==20");
x2 = x+5;//x - 2;
y2 = y-5;
x3 = x+5 ;//- 2;
y3 = y+5;
}
processingVisualizer.triangle(x, y, x2, y2, x3, y3);
}
processingVisualizer.strokeWeight(1);
}
Also, you can easily compute the direction of motion, if you store the previous position, using the arc tangent function (atan2()):
float angle = atan2(currentY-previousY,currentX-previousX);
Here's a quick example:
float cx,cy,px,py;//current x,y, previous x,y
float len = 15;
void setup(){
size(200,200);
background(255);
}
void draw(){
//update position - chase mouse with a bit of easing
cx -= (cx - mouseX) * .035;
cy -= (cy - mouseY) * .035;
//find direction of movement based on the current position
float angle = atan2(cy-py,cx-px);
//store previous position
px = cx;
py = cy;
//render
fill(255,10);noStroke();
rect(0,0,width,height);
fill(127,32);stroke(0);
pushMatrix();
translate(cx,cy);
pushMatrix();
rotate(angle);
triangle(len,0,-len,-len,-len,len);
line(0,0,len,0);
popMatrix();
popMatrix();
}

Categories