I've got an array of strings that I'd like to draw as a giant spiral. I only have a very, very rough idea of where to begin. First, I will probably need to break the strings into an array of individual characters? Next, I will probably need to apply the following geometry in order to generate the spiral shape?
float r = 0;
float theta = 0;
void setup() {
size(200,200);
background(255);
}
void draw() {
float x = r * cos(theta);
float y = r * sin(theta);
noStroke();
fill(0);
ellipse(x+width/2, y+height/2, 6, 6);
theta += 0.01;
r += 0.05;
}
However, I don't know how to step through my array of characters in order to draw them in a spiral-like format. I apologize for the lack of clarity. Any suggestions would be awesome! I'm very new to all of this (clearly).
Your code for creating the spiral is a good idea. One way to create rotated text would be using rotate(), combined with text(). You would have a for loop, iterate through your character array, increment the radius, and draw your text that way. Note that rotate() has a cumulative effect. Something like:
String str = "asdflkkjsahfdlkadshflkahdslkfajsdf";
float radius = 0;
//so we are rotating around the center, rather than (0,0):
translate(width/2, height/2);
for (int i = 0; i < str.length(); i++) {
radius += 2;
// taken out because of non-constant spacing at large radius:
//rotate(0.5);
// this should give constant spacing, no matter the radius
// change 10 to some other number for a different spacing.
rotate(10/radius);
// drawing at (0,radius) because we're drawing onto a rotated canvas
text(str.charAt(i), 0, radius);
}
You may want to have the angle change be a function of radius, because at large radii, the letters are spaced very far apart. One way to do this would be using the equation s = rθ, where s is the arclength (in this case, distance between letters), r is radius, and θ is the angle change. If you want a constant distance between letters, regardless of radius, then θ would have to be proportional to 1/r. And of course, you can tweak the hard-coded values to your liking.
Also: the rotate() and translate() methods are undone at the end of draw(), so if you aren't doing anything after this code, then it's okay to leave it as is. If you do want to draw more stuff after, then you'll have to undo the rotation and translation manually before you draw anything else.
Edit: I just realized that I assumed you wanted the letters to be rotated as well, and not just positioned in a spiral but still oriented normally. In that case, you could use your existing code and replace the ellipse(...) with text(str.charAt(...)...), with appropriate parameters of course.
Related
Given a list of spheres described by (xi, yi, ri), meaning the center of sphere i is at the point (xi, yi, 0) in three-dimensional space and its radius is ri, I want to compute all zi where zi = max { z | (xi, yi, z) is a point on any sphere }. In other words, zi is the highest point over the center of sphere i that is in any of the spheres.
I have two arrays
int **vs = (int **)malloc(num * sizeof(int *));
double **vh = (double **)malloc(num * sizeof(double *));
for (int i = 0; i < num; i++){
vs[i] = (int *)malloc(2 * sizeof(int)); // x,y
vh[i] = (double *)malloc(2 * sizeof(double)); r,z
}
The objective is to calculate the maximum z for each point. Thus, we should check if there are larger spheres over each x,y point.
Initially we see vh[i][1]=vh[i][0] for all points, which means that z is the r of each sphere. Then, we check if these z values are inside larger spheres to maximize the z value.
for (int i = 0; i < v; i++) {
double a = vh[i][0] * vh[i][0]; // power of the radius of sphere #1
for (int j = 0; j < v; j++) {
if (vh[i][0] > vh[j][1]) { // check only if r of sphere #1 is larger than the current z of #2
double b = a - (vs[j][0] - vs[i][0]) * (vs[j][0] - vs[i][0])
- (vs[j][1] - vs[i][1]) * (vs[j][1] - vs[i][1]);
// calculating the maximum z value of sphere #2 crossing sphere #1
// (r of sphere #1)**2 = (z of x_j,y_j)**2 + (distance of two centers)**2
if (b > vh[j][1] * vh[j][1]) {
vh[j][1] = sqrt(b);// update the z value if it is larger than the current value
}
}
}
}
it works perfectly, but the nested loop is very slow when the number of points increases. I look for a way to speed up the process.
An illustration for the clarification of the task
When you say
The objective is to calculate the maximum z for each point.
I take you to mean, for the center C of each sphere, the maximum z coordinate among all the points lying directly above C (along the z axis) on any of the spheres. This is fundamentally an O(n2) problem -- there is nothing you can do to prevent the computational expense scaling with the square of the number of spheres.
But there may be some things you can do to reduce the scaling coeffcient. Here are some possibilities:
Use bona fide 2D arrays (== arrays of arrays) instead arrays of pointers. It's easier to implement, more memory-efficient, and better for locality of reference:
int (*vs)[2] = malloc(num * sizeof(*vs));
double (*vh)[2] = malloc(num * sizeof(*h));
// no other allocations needed
Alternatively, it may help to use an array of structures, one per sphere, instead of two 2D arrays of numbers. It would certainly make your code clearer, but it might also help give a slight speed boost by improving locality of reference:
struct sphere {
int x, y;
double r, z;
};
struct sphere *spheres = malloc(num * sizeof(*spheres));
Store z2 instead of z, at least for the duration of the computation. This will reduce the number of somewhat-expensive sqrt calls from O(v2) to O(v), supposing you make a single pass at the end to convert all the results to zs, and it will save you O(v2) multiplications, too. (More if you could get away without ever converting from z2 to z.)
Pre-initialize each vh[i][1] value to the radius of sphere i (or the square of the radius if you are exercising the previous option, too), and add j != i to the condition around the inner-loop body.
Sorting the spheres in decreasing order by radius may help you find larger provisional z values earlier, and therefore to make the radius test in the inner loop more effective at culling unnecessary computations.
You might get some improvement by checking each distinct pair only once. That is, for each unordered pair i, j, you can compute the inter-center distance once only, determine from the relative radii which height to check for a possible update, and go from there. The extra logic involved might or might not pay off through a reduction in other computations.
Additionally, if you are doing this for large enough inputs, then you might be able to reduce the wall time consumed by parallelizing the computation.
Note, by the way, that this comment is incorrect:
// (r of sphere #1)**2 = (r of sphere #2)**2 + (distance of two centers)**2
. However, it also not what you are relying upon. What you are relying upon is that if sphere 1 covers the center of sphere 2 at all, then its height, z, above the center of sphere 2 satisfies the relationship
r12 = z2 + d1,22
. That is, where you wrote r of sphere #2 in the comment, you appear to have meant z.
Very complicated for me to explain the problem, but I will try my best.
I am making a game. There is an area of game objects and a canvas that draws every object in that area using some "draw_from" function - void draw_from(const char *obj, int x, int y, double scale) so that it looks as if a copy of that area is made on-screen.
This gives the advantage of scaling that area using the scale parameter of the draw_from() function.
However, a problem occurs when doing so. For simplicity imagine there are just two actors in that area - one that is right above the other one.
When they are scaled-down, they will appear in different vertical positions, further from each other.
I need to calculate the new correct positions for each of the objects and pass them to draw_from, but I just seem to be unable to figure out how. What is the correct way to recalculate the new positions if each of those objects is scaled down with the same value?
Here is a decent illustration of the problem more or less:
As you can tell the draw_from function will draw the object centered on the x/y coordinates. To draw an object at 0:0 (top-left corner) you must do draw_from(obj, obj->width/2, obj->height/2, 1.0); Not sure if the scaling is implemented that way exactly, but I created a function to obtain the new width and height of the scaled object:
void character_draw_get_scaled_dimensions (Actor* srcActor, double scale, double* sWidth, double* sHeight)
{
double sCharacterWidth = 0;
double sCharacterHeight = 0;
if(srcActor->width >= srcActor->height)
{
sCharacterWidth = (double)srcActor->width * scale / 1.0;
sCharacterHeight = sCharacterWidth * (double)srcActor->height / (double)srcActor->width;
}
else
{
sCharacterHeight = (double)srcActor->height * scale / 1.0;
sCharacterWidth = sCharacterHeight * (double)srcActor->width / (double)srcActor->height;
}
if(sWidth)
(*sWidth) = sCharacterWidth;
if(sHeight)
(*sHeight) = sCharacterHeight;
}
In other words, I need to maintain the distances between those objects across down-scales and I explained how draw_from and /somehow/ how its scaling works.
I need the correct parameters to pass to the draw_from's x and y arguments.
From that point, I think it will get just too broad if I continue elaborating further.
Not the solution I hoped for, but it is still a solution.
The more hacky and less practical (including performance-wise) solution is to draw every object on an offscreen canvas with a scale of 1.0 then draw from that canvas to the main canvas at any scale desired.
That way only the canvas should be repositioned and not every object. It gets really easy from there. I still would prefer the conventional purposed mathematical solution.
I'm trying to rotate a 2D pixel matrix, but nothing actually happens.
my origin is a stored bitmap[w x h x 3].
why isn't the shown image being rotated?
Here's the display function:
void display()
{
uint32_t i = 0,j = 0,k = 0;
unsigned char pixels[WINDOW_WIDTH * WINDOW_HEIGHT * 3];
memset(pixels, 0, sizeof(pixels));
for(j = bitmap_h -1; j > 0; j--) {
for(i = 0; i < bitmap_w; i++) {
pixels[k++]=bitmap[j][i].r;
pixels[k++]=bitmap[j][i].g;
pixels[k++]=bitmap[j][i].b;
}
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(90,0,0,1);
glDrawPixels(g_img.descriptor.size_w, g_img.descriptor.size_h, GL_RGB, GL_UNSIGNED_BYTE, &pixels);
glutSwapBuffers();
}
First and foremost glDrawPixels should not be used. The problem you have is one of the reasons. The convoluted rules by which glDrawPixels operate are too vast to outline here, let's just say, that there's a so called "raster position" in your window, at which glDrawPixels will place the lower left corner of the image it draws. No transformation whatsoever will be applied to the image.
However when setting the raster position, that's when transformations get applied. And should, for whatever reason, the raster position lie outside the visible window nothing will get drawn at all.
Solution: Don't use glDrawPixels. Don't use glDrawPixels. DON'T USE glDrawPixels. I repeat DON'T USE glDrawPixels. It's best you completely forget that this function actually exists in legacy OpenGL.
Use a textured quad instead. That will also transform properly.
I did something similar. I'm creating a 3D space shooter game using OpenGL/C++. For one of my levels, I have a bunch of asteroids/rocks in the background each rotating and moving at a random speed.
I did this by taking the asteroid bitmap image and creating a texture. Then I applied the texture to a square (glBegin(GL_QUADS)). Each time I draw the square, I multiply each of the vertex coordinates (glVertex3f(x, y, z)) with a rotation matrix.
|cos0 -sin0|
|sin0 cos0 |
0 is the theta angle. I store this angle as part of my Asteroid class. each iteration I increment it by a value, depending on how fast I want the asteroid to spin. It works great.
I have a set of data points, which I want to test if they lie on a logarithmic spiral arm for given parameters. The following program seems to work, but does not return any points close to the center of my plane, which contains all the data points. The image attached shows that my program does not seem to find any points which overlap with the spiral near the center. Here is the link :
http://imgur.com/QbNPg5S. Moreover, it seems to show two spirals in the overlapped points, which is another issue.
int main(){
float radial[10000]={0}, angle[10000]={0}; // my points of interest
float theta, r_sp; // radius and the angle theta for the spiral
Construct a spiral which lies in the same plane as my sources (green in the image)
for (j=0;j<=PI*10; j++){
theta=j*3./10;
r_sp=a_sp*exp(b_sp*theta);
Calculating the radial and angular components from x and y given coordinates (read from a file)
for (m=0;m<=30;m++){
radial[m]=pow((x_comp*x_comp+y_comp*y_comp),0.5);
angle[m]= atan2f(y_comp, x_comp);
Change the range from [ -pi, pi] to [0, 2*pi] consistent with "theta" of spiral
if (angle[m] < 0.){
angle[m]=angle[m]+PI;
}
Check if the point (radial and angle) lies on/around the spiral. For the realistic effect, I am considering the points at a radial distance "dr=0.5" (jitter) away from the "r_sp" value of the spiral.
if (fabs(r_sp-radial[m]) <=0.5 && fabs(theta-angle[m]) <= 1.0e-2){
printf("%f\t%f\t%f\t%f\n",l[k],b[k],ns[k],radial[m]);
}
}
}
return 0;
}
You check the conditions only for the first turn of spiral that lies in angle range 0..2*Pi.
At first you have to estimate potential turn number from r = radial[m]
r=a*exp(b*t)
r/a=exp(b*t)
ln(r/a)=b*t
t = ln(r/a) / b
turnnumber = Floor(ln(r/a) / b)
Now you can use
angle[m] = YourAngleFromArctan + 2 * Pi * turnnumber
to compare
In order to infer, how can we get 1D arrays for some degrees that we define of a 2D matrix, like image shows with always have the starting point at the center of the 2D matrix. The 2D matrix will always have equal height with length.
If you know the center, say x_c, y_c then you loop through all the pixels (current pixel is x_p, y_p) and calculate the angle with angle = atan2(y_p-y_c, x_p-x_c). This will give you a precise angle so you will want to round it with something like floor(angle). You can then check if the modulus of your desired sub angle (say 30 deg) is 0 to see if the angle is good. If it is you can do what you want with the data.
x_c = picture_center_x;
y_c = picture_center_x;
angleMod = 30;
for x_p = 1:pixels
for y_p = 1:pixels
angle = floor(atan2(y_p-y_c, x_p-x_c))*180/pi;
if (mod(angle, angleMod) == 0)
%push back pixel data
end
end
end
Pretty simple algorithm, hope it can work for you.
Here is a solution for your problem:
center = [26,26]; %position of your center
size= 51; %size of the matrix
matrix=bsxfun(#plus, ([(center(1)-size):1:0, 1:1:(size-center(1))].^2)',[(center(2)-size):1:0, 1:1:(size-center(2))].^2); %my generated matrix to test the solution
angle= [0,30,60,90,120,150,180,210,240,270,300,330]; %array of angles
angle=angle*pi/180; % changing angles into rad (from degree)
sine_angle=sin(angle); %computing sine of those angles
cos_angle=cos(angle); %computing cosine of those angles
cos_max = abs(size-center(2))*cos_angle.^(-1); %computing the maximum distance in left right direction of each angle
sine_max = abs(size-center(1))*sine_angle.^(-1); %computing the max. distance in up/down direction of each angle
sine_cos_max = min(abs(cos_max), abs(sine_max)); %checking which boarder is reached first
angle_array = cell(1,numel(angle));
k=0;
while k<=max(sine_cos_max)
for m=1:1:numel(angle)
if k <= sine_cos_max(m)
helper = angle_array{1,m};
helper2 = [helper, matrix(center(1)+floor(sine_angle(m)*k),center(2)+floor(cos_angle(m)*k))];
angle_array(1,m) = {helper2};
end
end
k=k+1;
end
You must use floor, because in the used example you would otherwise try to adress an element outside of the matrix for 30, and 60 degree. Alternatively you can use another argument in the if case to check if its still possible.