How to Create asteroids on the x and y axes - c

I'm doing Asteroids (Atari) in C. I designed the ADT for asteroids, all the ADT is related to 1 asteroid.
I need to create an asteroid in a random position, but random within (0, y) or (x, 0)
I have my function asteroid_create():
asteroid_t *asteroid_create(float x, float y, float radio){
asteroid_t *ast = malloc(sizeof(asteroid_t));
ast->x_pos = x;
ast->y_pos = y;
ast->radio = radio;
ast->vx = rand_float((1000/ast->radio)-100,(1000/ast->radio)+100);
ast->vy = rand_float((1000/ast->radio)-100,(1000/ast->radio)+100);
ast->angle = rand_float(0,2*PI);
size_t rock_rand = rand() % ASTEROIDS_TYPES;
ast->name_rock = rocks_dictionary[rock_rand];
return ast;
}
That creates an asteroid with certain fixed variables. Then, in another file, I create a list of asteroids and I'm inserting as many asteroids I need.
bool asteroids_insert(list_t* l){
asteroid_t *ast = asteroid_create(rand_float(0,WINDOW_WIDTH),rand_float(0,WINDOW_HIGH),AST_INITIAL_RADIO);
if(!list_append(l,ast))
return false;
return true;
}
In the main:
for(size_t i=0; i< ASTEROIDS_INITIAL;i++){
asteroids_insert(list_asteroids);
}
In this way, I am creating asteroids anywhere on the screen. I only need them to be generated on the y axis or the x axis.
The way I am doing it, I can't think of how I can do what I need. How can I do it so that asteroid_create() receive as a parameter positions in (0, y) or (x, 0) randomly?

Imagine you bend the y axis down to the left, so that in effect it becomes the "negative part" of the x axis.
Generate a random number value between -MAX_Y and +MAX_X.
If the resulting number is 0 your point is (0, 0); if it's positive, your point is (value, 0), otherwise it's (0, -value).
Note: if your x axis is larger than y axis, this will make it more probable to generate points on the x axis.

Related

How do I zoom on cursor position in mandelbrot or julia set?

I am writing a fractal explorer at the moment and I got stuck at zooming on a certain point in the set. My drawing function for the Julia set for example looks like this:
void *julia_thread(void *param)
{
int x, y, temp;
long double re, aux, im;
int start = ((int *)param)[0];
int end = ((int *)param)[1];
int iterations;
for (x = start; x < end; x++)
for (y = 0; y < WIN_SIZE; y++)
{
re = range_change(zoom_factor, x, mv_x);
im = range_change(zoom_factor, y, mv_y);
iterations = 0;
while (!blowing_up(re, im) && iterations < max_iter)
{
aux = re;
re = re * re - im * im + re_c;
im = 2 * aux * im + im_c;
iterations++;
}
put_pixel(img, x, y, color_table[iterations]);
}
return NULL;
}
The function that calculates the initial values for the real and imaginary part of Z is this:
long double range_change(long double zoom_factor, int value, long double mv)
{
long double newmax = 2 / zoom_factor;
long double newmin = -2 / zoom_factor;
return ((long double)value * (newmax - newmin)) / WIN_SIZE + newmin + mv;
}
So I get a scaled down value that is part of the interval where the fractal exists and according to the number of iterations I assign a colour to that certain pixel. Zooming works fine by making the real interval (-2, 2) smaller by dividing both of the ends with a factor. This works but I can't seem to be figure out how to zoom on a certain spot other than the centre. I can move around and reach that spot eventually by adding to the real and imaginary part (x, y) a number but I can't zoom on a point determined by the screen (x, y) given to me by the cursor position.
It is a very bad idea to do indiscriminate integer divisions:
2 / zoom_factor
will return 0 if zoom_factor is larger than 2. Replace 2 by 2.0 to force floating point division, this should be sufficient to repair the code.
If I interpret this correctly, you want that the screen window represents a square in the coordinate or fractal plane with the width and height 4.0/zoom_factor around the point (mv_x, mv_y).
mv is situated at WIN_SIZE/2, so that
coord = mv + ( 4*value/WIN_SIZE - 2 )/zoom_factor
which can be implemented exactly as this
return mv + ( (4.0*value)/WIN_SIZE - 2.0 )/zoom_factor;
and with the factor 4.0 the denominator gets type double and division is carried out in double.
Slow derivation
What the function range_change wants to achieve is a linear change of coordinates
coord = A*screen + B
where screen is the input screen coordinate and coord is the coordinate in the Cartesian plane playing host for the Julia fractal. The endpoint mapping is
screen=0 --> coord = center - 2.0/zoom
screen=WIN_SIZE --> coord = center + 2.0/zoom
From the first we read B=center - 2.0/zoom and from the second formula
A*WIN_SIZE + center - 2.0/zoom = center + 2.0/zoom
A*WIN_SIZE = 4.0/zoom
A = 4.0/(zoom*WIN_SIZE)
which gives the transformation formula
coord = (4.0*value)/(zoom*WIN_SIZE) + center - 2.0/zoom
= ( (4.0*value)/WIN_SIZE - 2.0 )/zoom + center

Value error in drawing the contourf plot

I want to draw the contourf of a certain function and my code was as follows:
xlist = linspace(0, 100, 100)
ylist = linspace(0, 100, 200)
X, Y = meshgrid(xlist, ylist)
#print "X = " + str(X)
#print "Y = " + str(Y)
Z = power_at_each_point(X, Y)
#print "Z = " + str(Z)
figure()
CP2 = contourf(X, Y, Z)
colorbar(CP2)
title('Contour Plot')
xlabel('Room-x (m)')
ylabel('Room-y (m)')
show()
The function power_at_each_point(X,Y) when I test it alone I write:
print power_at_each_point(50, 50)
and the output is -80.9187477018
which basically represents the power reached to this point in the room and it outputs a number normally but when I call it after the meshgrid command it returns an error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
I want to take each coordinate of points in the room x-coord and y-coord and calculate the power reached at this point using the power_at_each_point method
which is supposed to return a number and I'd represent it in the contourf plot.
My guess is that the arguments (X,Y) of Z = power_at_each_point changed from being just numbers to being arrays which I don't want and that's what is causing the error.
How can I let the function Z = power_at_each_point(X,Y) take as arguments X as a number ex :1 and Y ex :2 and return a value for the power at this point so that I can represent it in my contourf plot.
Any help would be appreciated.
I've found that the function meshgrid wants a Matrix pretty much as an argument so I went ahead and created a Matrix called Z and I filled by myself the values in it and then I went ahead and entered Z as an argument to the meshgrid function:
x_list = linspace(0, 100, 100)
y_list = linspace(0, 100, 100)
X, Y = meshgrid(x_list, y_list)
Z = [[0 for x in range(len(x_list))] for x in range(len(y_list))]
for each_axes in range(len(Z)):
for each_point in range(len(Z[each_axes])):
Z[each_axes][each_point] = power_at_each_point(each_axes, each_point)
figure()
CP2 = contourf(X, Y, Z)
and that got me the result I wanted as far as I was asking here.
The points is reversed in the Z Matrix or as you can say mirrored along the horizontal but that's something i'm gonna play with so that I can get those elements in Z to match how the meshgrid actually sets it's grid points.

Count the number of lattice paths from (0,0) to (x,y) in recursion

Does anyone know how can i write a recursive function that gets unsigned integers x, y and returns how many paths are to the point x,y from 0,0 in C??
there is only one step every time: up or right.
The limit of the steps are in the rectangle:
(0,0), (0, x), (0,y), (x,y)
Sorry, this isn't C, but you should understand it very well.. Whatever starts with dollar is a variable, the rest is similar.
function path($x, $y){
if($x==0 && $y==0){ /* && is logical AND operator */
return 1;
// here's first (and only) edge case. If X and Y is 0, that means were are already where we want to be. We assume there's one path from the position you are on to the same position you are on.
}
$count=0;
if($x>0){
$count+=path($x-1, $y); // Here, we ask how many paths go from position (x-1, y) to zero, if the X is not zero already..
}
if($y>0){
$count+=path($x, $y-1); // here same stuff for Y, if Y is not zero, let's recurse into (x, y-1)
}
return $count; // in those conditions above, the result is added into COUNT variable
}
$x=6;
$y=4; // some input
print path($x, $y); // here it all starts, with the original input numbers
There's no math behind it, it's a recursion. In each run of the path() function, the path function runs another instance of the path function, and that runs another and that runs another.... Always with the position one less than current, in one dimension and then one less in the other dimension. Only if the recursion already reached the (0,0) position, it will return 1, which will be added to the count variable in previous instance, that will be added to count variable in yet previous instance, and so on and so on, until it returns that to the print function.
Note: the function doesn't go from (0,0) to (x,y) but from (x,y) to (0,0). But the result is the same.
A Java solution :
/**
* Compute the number of ways you can get from 0,0 to x,y
*
* #param x grid width
* #param y grid height
* #return number of lattice paths
*/
public long compute(int x, int y) {
// there's only 1 way you can reach a point which is on some edge
if (x == 0 || y == 0) {
return 1;
}
/* Otherwise apply back recursion, i.e. take the last step (when you reach x,y) :
you can get there only by moving from x-1,y (right) or from x,y-1 (up).
So the result would be the number of ways you can get to x-1,y plus the number
of ways you can get to x,y-1 */
return compute(x - 1, y) + compute(x, y - 1);
}
As the area of the grid grows (x and y) the algorithm become very slow, because you compute the same value a lot of times due to the recursion, so you might want to cache :
Map<Pair, Long> cache = new HashMap<>();
public long compute(int x, int y) {
Pair pair = new Pair(x, y);
if (cache.containsKey(pair)) {
return cache.get(pair);
}
if (x == 0 || y == 0) {
return 1;
}
long result = compute(x - 1, y) + compute(x, y - 1);
cache.put(pair, result);
return result;
}
Pair is a simple POJO following the equals() and hashCode() Contract.

OpenGL glcolor for loop

i am trying to draw a lorenz attractor where the color changes throughout the attractor. i have written the following for loop which calculates the attractor points.
float x = 1, y = 1, z = 1;
glBegin(GL_LINE_STRIP);
int i;
for (i=0; i < initialIterations; i++) {
glColor3d(0,i/50000,1);
// compute a new point using the lorenz attractor equations
float dx = sigma*(y-x);
float dy = x*(r-z) - y;
float dz = x*y - b*z;
// save the new point
x = x + dx*dt;
y = y + dy*dt;
z = z + dz*dt;
glVertex3f(x/50,y/50,z/50);
}
glEnd();
i am using the glcolor at the top of the code to change the color as a function of i. However i do not see the result i want, all i get is one solid color. i know the color works like a state machine but i need to find a way to change the color throughout.
You're doing integer division : i/50000, so it's always 0.
Try i/50000.0

Finding the squares in a plane given n points

Given n points in a plane , how many squares can be formed ...??
I tried this by calculating the distances between each 2 points , then sort them , and look for the squares in the points with four or more equal distances after verifying the points and slopes.
But this looks like an approach with very high complexity . Any other ideas ...??
I thought dynamic programming for checking for line segments of equal distances might work ... but could not get the idea quite right ....
Any better ideas???
P.S : The squares can be in any manner . They can overlap , have a common side, one square inside another ...
If possible please give a sample code to perform the above...
Let d[i][j] = distances between points i and j. We are interested in a function count(i, j) that returns, as fast as possible, the number of squares that we can draw by using points i and j.
Basically, count(i, j) will have to find two points x and y such that d[i][j] = d[x][y] and check if these 4 points really define a square.
You can use a hash table to solve the problem in O(n^2) on average. Let H[x] = list of all points (p, q) that have d[p][q] = x.
Now, for each pair of points (i, j), count(i, j) will have to iterate H[ d[i][j] ] and count the points in that list that form a square with points i and j.
This should run very fast in practice, and I don't think it can ever get worse than O(n^3) (I'm not even sure it can ever get that bad).
This problem can be solved in O(n^1.5) time with O(n) space.
The basic idea is to group the points by X or Y coordinate, being careful to avoid making groups that are too large. The details are in the paper Finding squares and rectangles in sets of points. The paper also covers lots of other cases (allowing rotated squares, allowing rectangles, and working in higher dimensions).
I've paraphrased their 2d axis-aligned square finding algorithm below. Note that I changed their tree set to a hash set, which is why the time bound I gave is not O(n^1.5 log(n)):
Make a hash set of all the points. Something you can use to quickly check if a point is present.
Group the points by their X coordinate. Break any groups with more than sqrt(n) points apart, and re-group those now-free points by their Y coordinate. This guarantees the groups have at most sqrt(n) points and guarantees that for each square there's a group that has two of the square's corner points.
For every group g, for every pair of points p,q in g, check whether the other two points of the two possible squares containing p and q are present. Keep track of how many you find. Watch out for duplicates (are the two opposite points also in a group?).
Why does it work? Well, the only tricky thing is the regrouping. If either the left or right columns of a square are in groups that are not too large, the square will get found when that column group gets iterated. Otherwise both its top-left and top-right corners get regrouped, placed into the same row group, and the square will be found when that row group gets iterated.
I have a O(N^2) time, O(N) space solution:
Assume given points is an array of object Point, each Point has x,y.
First iterate through the array and add each item into an HashSet: This action de-duplicate and give us an O(1) access time. The whole process takes O(N) time
Using Math, Say vertices A, B, C, D can form a square, AC is known and it's a diagonal line, then the corresponding B, D is unique. We could write a function to calculate that. This process is O(1) time
Now Let's get back to our thing. write a for-i-loop and a for-j-inner-loop. Say input[i] and input[j] form a diagonal line, find its anti-diagonal line in the set or not: If exist, counter ++; This process take O(N^2) time.
My code in C#:
public int SquareCount(Point[] input)
{
int count = 0;
HashSet<Point> set = new HashSet<Point>();
foreach (var point in input)
set.Add(point);
for (int i = 0; i < input.Length; i++)
{
for (int j = 0; j < input.Length; j++)
{
if (i == j)
continue;
//For each Point i, Point j, check if b&d exist in set.
Point[] DiagVertex = GetRestPints(input[i], input[j]);
if (set.Contains(DiagVertex[0]) && set.Contains(DiagVertex[1]))
{
count++;
}
}
}
return count;
}
public Point[] GetRestPints(Point a, Point c)
{
Point[] res = new Point[2];
int midX = (a.x + c.y) / 2;
int midY = (a.y + c.y) / 2;
int Ax = a.x - midX;
int Ay = a.y - midY;
int bX = midX - Ay;
int bY = midY + Ax;
Point b = new Point(bX,bY);
int cX = (c.x - midX);
int cY = (c.y - midY);
int dX = midX - cY;
int dY = midY + cX;
Point d = new Point(dX,dY);
res[0] = b;
res[1] = d;
return res;
}
It looks like O(n^3) to me. A simple algo might be something like:
for each pair of points
for each of 3 possible squares which might be formed from these two points
test remaining points to see if they coincide with the other two vertices
Runtime: O(nlog(n)^2), Space: θ(n), where n is the number of points.
For each point p
Add it to the existing arrays sorted in the x and y-axis respectively.
For every pair of points that collide with p in the x and y-axis respectively
If there exists another point on the opposite side of p, increment square count by one.
The intuition is counting how many squares a new point creates. All squares are created on the creation of its fourth point. A new point creates a new square if it has any colliding points on concerned axes and there exists the "fourth" point on the opposite side that completes the square. This exhausts all the possible distinct squares.
The insertion into the arrays can be done binary, and checking for the opposite point can be done by accessing a hashtable hashing the points' coordinates.
This algorithm is optimal for sparse points since there will be very little collision points to check. It is pessimal for dense-squares points for the opposite of the reason for that of optimal.
This algorithm can be further optimized by tracking if points in the axis array have a collision in the complementary axis.
Just a thought: if a vertex A is one corner of a square, then there must be vertices B, C, D at the other corners with AB = AD and AC = sqrt(2)AB and AC must bisect BD. Assuming every vertex has unique coordinates, I think you can solve this in O(n^2) with a hash table keying on (distance, angle).
This is just an example implementation in Java - any comments welcome.
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
public class SweepingLine {
public static void main(String[] args) {
Point[] points = {
new Point(1,1),
new Point(1,4),
new Point(4,1),
new Point(4,4),
new Point(7,1),
new Point(7,4)
};
int max = Arrays.stream(points).mapToInt(p -> p.x).max().orElseThrow(NoSuchElementException::new);
int count = countSquares(points, max);
System.out.println(String.format("Found %d squares in %d x %d plane", count, max, max));
}
private static int countSquares(Point[] points, int max) {
int count = 0;
Map<Integer, List<Integer>> map = new HashMap<>();
for (int x=0; x<max; x++) {
for (int y=0; y<max; y++) {
for(Point p: points) {
if (p.x == x && p.y == y) {
List<Integer> ys = map.computeIfAbsent(x, _u -> new ArrayList<Integer>());
ys.add(y);
Integer ley = null;
for (Integer ey: ys) {
if (ley != null) {
int d = ey - ley;
for (Point p2: points) {
if (x + d == p2.x && p2.y == ey){
count++;
}
}
}
ley = ey;
}
}
}
}
}
return count;
}
private static class Point {
public final int x;
public final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
}
Here is a complete implemention of finding the diagonal points in C++!
Given points a and c, return b and d, which lie on the opposite diagonal
If b or d are not integer points, dicard them (optional)
To find all squares generated by n points, can check out this C++ implementation
Idea credited to Kevman. Hope it can help!
vector<vector<int>> createDiag(vector<int>& a, vector<int>& c){
double midX = (a[0] + c[0])/2.0;
double midY = (a[1] + c[1])/2.0;
double bx = midX - (a[1] - midY);
double by = midY + (a[0] - midX);
double dx = midX - (c[1] - midY);
double dy = midY + (c[0] - midX);
// discard the non-integer points
double intpart;
if(modf(bx, &intpart) != 0 or modf(by, &intpart) != 0 or modf(dx, &intpart) != 0 or modf(dy, &intpart) != 0){
return {{}};
}
return {{(int)bx, (int)by}, {(int)dx, (int)dy}};
}

Resources