I have a list of coordinates and i currently have a function that deals with said coordinates to find the slope, all in order and paired
public void foo(){
int[] xCoords = {//stuff}
int[] yCoords = {//stuff}
for(int i = 0; i < 100000; i++){
getSlope(x[i], y[i], xcoords, ycoords)
}
}
public int getSlope(int x, int y, int[] x1, int[] y1){
//calculate slope using m = (y - y1) / (x - x1);
double slope;
for(int i = 0; i < x1.length(); i++){
slope = (y - y1[i]) / (x - x1[i]);
return slope;
}
return -2;
}
This is all well and good but I am wondering how can I do this with a massive list of coordinates. getSlope gets called from another method that places a coordinate to be evaluated and this is running really slow O(n^2) i think (for loop in a for loop).
Is there a quicker way to do this?
Full disclosure: This is part of a larger assignment for school so I wouldn't like answers just thoughts related to time complexity and big-Oh.
Edit: for a bit more clarification.
Edit2: for a little more clarification.
Assuming you want to find the slope between two consecutive points in your coordinate arrays:
public void foo(){
int[] xCoords = {//stuff}
int[] yCoords = {//stuff}
double slope;
for(int i = 0; i < xCoords.length-1 && i < yCoords.length-1; i++){
slope = getSlope(xCoords[i], yCoords[i], xCoords[i+1], yCoords[i+1]);
System.out.println(slope);
}
}
public double getSlope(int x, int y, int x1, int y1){
//calculate slope using m = (y - y1) / (x - x1);
return (y - y1) / (x - x1);
}
EDIT:
If what you want is to have multiple slopes with respect to a fixed reference point your method should return more than one value as shown below, but if you want to return a single slope from your method then there is no need for looping and your method does not also need to take array as parameter; you may just pass the two pair coordinates for a single slope calculation.
public void foo(){
int[] xCoords;// = {//stuff}
int[] yCoords;// = {//stuff}
int referenceX = //set to your value
int referenceY = //set to your value
double[] slopes = getSlope(referenceX, referenceY, xCoords, yCoords)
}
public double[] getSlope(int x, int y, int[] x1, int[] y1){
//calculate slope using m = (y - y1) / (x - x1);
double[] slope = new double[(x1.length<y1.length)? x1.length:y1.length];
for(int i = 0; i < x1.length && i < y1.length; i++){
slope[i] = (y - y1[i]) / (x - x1[i]);
}
return slope;
}
Related
I'm trying to visualize Mandelbrot's set with processing, and it's the first time I do something like this. My approach is pretty simple.
I have a function Z, which is literally just the set's main function (f(z)=z^2+c) and i do a loop for each pixel of the screen, every time i repeat the process of using Z() and using the result as the new z parameter in the function Z()
For some reason what shows up on the screen is only a diagonal line, and i have no idea of why that is.
Here's the full code:
void draw() {
int max_iterations = 100, infinity_treshold = 16;
for (int y = 0; y < 360; y++) {
for (int x = 0; x < 480; x++) {
float z = 0; // the result of the function, (y)
float real = map(x,0,480,-2,2); // map "scales" the coordinate as if the pixel 0 was -2 and the pixel 480 was 2
float imaginary = map(y,0,360,-2,2); // same thing with the height
int func_iterations = 0; // how many times the process of the equation has been excecuted
while (func_iterations < max_iterations) {
z = Z(z, real+imaginary);
if (abs(z) > infinity_treshold) break;
func_iterations++;
}
if (func_iterations == max_iterations) rect(x,y,1,1);
}
}
noLoop();
}
private float Z(float z, float c) {
return pow(z,2)+c;
}
The formula z = z^2 +c is meant to operate with Complex numbers. I recommend to use PVector to represent a complex number. e.g.:
private PVector Z(PVector z, PVector c) {
return new PVector(z.x * z.x - z.y * z.y + c.x, 2.0 * z.x * z.y + c.y);
}
See the example:
void setup() {
size(400, 400);
}
void draw() {
background(255);
int max_iterations = 100;
float infinity_treshold = 16.0;
for (int y = 0; y < width; y++) {
for (int x = 0; x < height; x++) {
float real = map(x, 0, width, -2.5, 1.5);
float imaginary = map(y, 0, height, -2, 2);
PVector c = new PVector(real, imaginary);
PVector z = new PVector(0, 0);
int func_iterations = 0;
while (func_iterations < max_iterations) {
z = Z(z, c);
if (z.magSq() > infinity_treshold)
break;
func_iterations++;
}
if (func_iterations == max_iterations) {
point(x, y);
}
}
}
noLoop();
}
private PVector Z(PVector z, PVector c) {
return new PVector(z.x * z.x - z.y * z.y + c.x, 2.0 * z.x * z.y + c.y);
}
See also
wikipedia - Mandelbrot set
Mandelbrot.java
You've declared z as float so it's a real number, it should be complex. I'm not familiar with processing, does it even have a complex number data type?
Another problem is at Z(z, real+imaginary) Real and imaginary are both floats, so real numbers, so their sum is a real number. You need to construct a complex number from the real and imaginary parts.
I have a program to draw 20 circles w/ random rad x and y. After, I need to test which circles are overlapping and if they are, set them cyan, if not set them black. heres what I have so far, the problem, is it always sets it to cyan overlapping or not.
public class AppletP5 extends JApplet{
MyCircle[] circle = new MyCircle[20];
public AppletP5(){
for(int i = 0; i<20; i++){
int x0= (int) (Math.random()*500);
int y0= (int) (Math.random()*500);
int rad0= (int) (30 + Math.random()*70);
circle[i] = new MyCircle(x0,y0,rad0);
}
}
public void paint(Graphics g){
for(int i = 0; i<20; i++){
if(circle[i].isOverlapping(circle) == true){
g.setColor(Color.CYAN);
g.drawOval(circle[i].x,circle[i].y,circle[i].rad*2,circle[i].rad*2);
} else if(circle[i].isOverlapping(circle) == false){
g.setColor(Color.BLACK);
g.drawOval(circle[i].x,circle[i].y,circle[i].rad*2,circle[i].rad*2);
}
}
}
}
public class MyCircle {
protected int x, y, rad;
public MyCircle(int x, int y, int rad){
this.x = x;
this.y = y;
this.rad = rad;
}
public boolean isOverlapping(MyCircle[] circles){
for(MyCircle c : circles){
if(Math.pow(c.rad - rad , 2) >= Math.sqrt(Math.pow(x - c.x, 2) + Math.pow(y - c.y , 2))){
return true;
}
}
return false;
}
}
You need to exclude the current Circle from the comparison, since a circle trivially overlaps itself.
You could go with an easy check as long as you just have one instance of each Circle:
for (MyCirlce c : circles) {
if (c != this && ...)
In addition you are checking if the difference of radii between two circles squared by two is greater than the distance of the two centres? Shouldn't you check for the sum of the radii, eg:
r1 + r2 <= distance(c1, c2)
isOverLapping is incorrect implemented.
Two circles intersect, if the distance between their centers is smaller than the sum of their radii. So:
int radSum = c.rad + rad;
int radDif = c.rad - rad;
int distX = c.x - x + radDif;
int distY = c.y - y + radDif;
if(radSum * radSum < distX * distX + distY * distY)
return true;
Apart from that you'll have to ensure you don't compare a circle with itself. And finally: Math.pow is rather costly, so replace it with the simpler version, if you only want the square of a number.
I am trying to write a program like bouncingBall. but i generated N obstacles in the screen. Each time the ball touch the obstacle, the obstacle disappears and shows up at another random place. i am trying to use 2 dimension array to store the random-gernerated obstacles' point (x,y).
Right now if I input N>50, it gives me outofbound.
But what i want is to store point from (0,0) to (50,50)..what should I do achieve this with 2-dimentional array?
Thanks!
import java.util.ArrayList;
public class BouncingBall {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java BouncingBall N");
System.exit(0);
}
int N = Integer.parseInt(args[0]);
if (N > 2500) {
System.out.println("Usage: java BouncingBall N<=2500");
System.exit(0);
}
double[][] myArray = new double[50][50];
// set the scale of the coordinate system
StdDraw.setXscale(-1.0, 1.0);
StdDraw.setYscale(-1.0, 1.0);
// initial values
double rx = 0.480, ry = 0.860; // position
double vx = 0.015, vy = 0.023; // velocity
double radius = 0.02; // radius
double x;
double y;
double a[] = new double[2];
StdDraw.setPenColor(StdDraw.WHITE);
StdDraw.filledSquare(0, 0, 1.0);
StdDraw.setPenColor(StdDraw.BLACK);
for(int i=0; i <= N; i++){
x = 2.0*(double)Math.random()-1.0;
y = 2.0*(double)Math.random()-1.0;
for (int t=0;t <50;t++){
for (int j=0;j <50;j++){
myArray[t][j]= x;
myArray[j][t]= y;
}
}
StdDraw.filledSquare(x, y, 0.02);
}
// main animation loop
while (true) {
// bounce off wall according to law of elastic collision
if (Math.abs(rx + vx) > 1.0 - radius) vx = -vx;
if (Math.abs(ry + vy) > 1.0 - radius) vy = -vy;
// clear the background
StdDraw.setPenColor(StdDraw.WHITE);
StdDraw.filledSquare(0, 0, 1.0);
StdDraw.clear();
StdDraw.setPenColor(StdDraw.BLACK);
for(int t=0; t <= N; t++){
for (int j=0;j <50;j++){
x = myArray[t][j];
y = myArray[j][t];
}
if ((Math.abs(rx + vx) > x - radius)||(Math.abs(ry + vy) > y - radius))
{ //if the ball touch the square
vx = -vx;
vy = -vy;
if (args.length == 2 && args[1].equals("-d")){
x = 2.0*(double)Math.random()-1.0; //new random x
y = 2.0*(double)Math.random()-1.0; //new random y
}else{
;
}
StdDraw.filledSquare(x, y, 0.02);
}
else{
StdDraw.filledSquare(x, y, 0.02); //if not touched, keep it.
}
}
rx = rx + vx;
ry = ry + vy;
StdDraw.filledCircle(rx, ry, radius);
// display and pause for 20 ms
StdDraw.show(20);
}
}
}
Imagine that the user inputs -1 for N, then x and y won't get a value because the loops bodies won't run.
Simple workaround: assign a default value to x and y (0 for example)
double x = 0;
double y = 0;
You need to initialize both x and y:
double x = 0;
double y = 0;
Your ArrayIndexOutOfBoundsException is occurring because you only define the array to be 50x50
double[][] myArray = new double[50][50];
yet access an index greater than that using t:
x = myArray[t][j];
you have to initialize your local variables, local variables dont get default values
int double x=0.0;
int double y=0.0;
would solve the compiler error.
if N>50
for (int t=0;t <50;t++){
for (int j=0;j <50;j++){
myArray[t][j]= x; // ArrayIndexOutOfBound Exection occurs here
myArray[j][t]= y;
}
}
I am calculating Geometric median of some (x,y) points in java. To calculate Geometric median, first i am calculating centroid of all the points, then this centroid is used to calculate Geometric median. My code works fine, but sometimes it goes to an infinite loop (i think.). The problem is with my while condition. This while condition should be change according to input points, but i don't know how. Below I am putting the complete code.
import java.util.ArrayList;
public class GeometricMedian {
private static ArrayList<Point> points = new ArrayList<Point>();
private class Point {
private double x;
private double y;
Point(double a, double b) {
x = a;
y = b;
}
}
public static void main(String[] args) {
GeometricMedian gm = new GeometricMedian();
gm.addPoints();
Point centroid = gm.getCentroid();
Point geoMedian = gm.getGeoMedian(centroid);
System.out.println("GeometricMedian= {" + (float) geoMedian.x + ", "
+ (float) geoMedian.y + "}");
}
public void addPoints() {
points.add(new Point(0, 1));
points.add(new Point(2, 5));
points.add(new Point(3, 1));
points.add(new Point(4, 0));
}
public Point getCentroid() {
double cx = 0.0D;
double cy = 0.0D;
for (int i = 0; i < points.size(); i++) {
Point pt = points.get(i);
cx += pt.x;
cy += pt.y;
}
return new Point(cx / points.size(), cy / points.size());
}
public Point getGeoMedian(Point start) {
double cx = 0;
double cy = 0;
double centroidx = start.x;
double centroidy = start.y;
do {
double totalWeight = 0;
for (int i = 0; i < points.size(); i++) {
Point pt = points.get(i);
double weight = 1 / distance(pt.x, pt.y, centroidx, centroidy);
cx += pt.x * weight;
cy += pt.y * weight;
totalWeight += weight;
}
cx /= totalWeight;
cy /= totalWeight;
} while (Math.abs(cx - centroidx) > 0.5
|| Math.abs(cy - centroidy) > 0.5);// Probably this condition
// needs to change
return new Point(cx, cy);
}
private static double distance(double x1, double y1, double x2, double y2) {
x1 -= x2;
y1 -= y2;
return Math.sqrt(x1 * x1 + y1 * y1);
}
}
Please help me to fix the bug, also if there exitis any better way to calculate Geometric median of some 2D points, write here. Thank you.
I don't see why you need two loops. You only need the loop over all the points. What is the reason for the other one, in your view?
One way to solve this is to iterate certain number of times. This similar to K-Means method where it either converges to a specific threshold or stops after a predefined number of iterations.
I'm trying to maintain and then use a transformation matrix for a computer graphics program. It's a 3x3 matrix that stores scale, rotate, and translate information for (x,y) points.
My program can handle any individual case... i.e. if I only scale or only rotate it works fine. However, it does not seem to work when combining scale and rotate, and I think that has to do with how I combine rotation and scale in the code. The matrix is called transformation and is of type float. The following methods clear, rotate, scale, and translate (in that order) the matrix.
public void clearTransform()
{
transformation[0][0] = 1;transformation[0][1] = 0;transformation[0][2] = 0;
transformation[1][0] = 0;transformation[1][1] = 1;transformation[1][2] = 0;
transformation[2][0] = 0;transformation[2][1] = 0;transformation[2][2] = 1;
}
public void rotate (float degrees)
{
double r = degrees * (Math.PI/180);
float sin = (float)Math.sin(r);
float cos = (float)Math.cos(r);
transformation[0][0] *= cos;
transformation[1][1] *= cos;
if(transformation[0][1] == 0)
transformation[0][1] = -sin;
else
transformation[0][1] *= -sin;
if(transformation[1][0] == 0)
transformation[1][0] = sin;
else
transformation[1][0] *= sin;
}
public void scale (float x, float y)
{
transformation[0][0] *= x;
transformation[1][1] *= y;
}
public void translate (float x, float y)
{
transformation[0][2] += x;
transformation[1][2] += y;
}
For scale, the matrix hold info like this:
(Sx, 0, 0)
(0, Sy, 0)
(0, 0, 1)
for rotation, like this:
(cos(theta), -sin(theta), 0)
(sin(theta), cos(theta), 0)
(0, 0, 1)
for translation, this:
(1, 0, Tx)
(0, 1, Ty)
(0, 0, 1)
I don't think I'm correctly combining scale and rotate. Here is where I actually apply the transformation:
public float[] transformX(float[] x, float[] y, int n) {
float[] newX = new float[n];
for(int i = 0; i < n; i ++) {
newX[i] = (x[i] * transformation[0][0]) + (y[i] * transformation[0][1]) + transformation[0][2];
}
return newX;
}
public float[] transformY(float[] x, float[] y, int n) {
float[] newY = new float[n];
for(int i = 0; i < n; i ++) {
newY[i] = (x[i] * transformation[1][0]) + (y[i] * transformation[1][1]) + transformation[1][2];
}
return newY;
}
Where x and y are the pre-transformed point arrays, and n is the number of points
Thank you for any help!
I think the correct transformation should be: