How do we find the intersection of the interiors of n squares that have sides parallel to the x and y axes given their centers and side lengths?
The input is the number of squares followed by that many descriptions of squares. The description of each square is the x and y coordinates of its center and its side length. For example:
3
5 11 10
7 9 10
10 6 8
describes three squares, starting with one centered at (5, 11) with side length 10.
An algorithm to find the intersection of the interiors of squares (with sides parallel to the x and y axes) given by their centers and lengths is:
Convert the center (the point (x, y)) and length (l) of the first square to the x coordinates of the left edge (x−l/2) and the right edge (x+l/2) and the y coordinates of the bottom edge (y−l/2), and the top edge (y+l/2). Keep those as the left, right, bottom, and top.
For each following square:
Convert its center and length to coordinates as above.
Figure out which x coordinate is greater, the old left or the new left edge, and keep that as the new left.
Figure out which x coordinate is lesser, the old right or the new right edge, and keep that as the new right.
Figure out which y coordinate is greater, the old bottom or the new bottom edge, and keep that as the new bottom.
Figure out which y coordinate is lesser, the old top or the new top edge, and keep that as the new top.
After processing all squares, left, right, bottom, and top are the coordinates of the rectangle bounding the area that is inside all of the squares. (If right < left or top < bottom, the intersection is empty. Otherwise, if right = left or top = bottom, the intersection is a line [if only one is true] or a point [if both are true].)
Here is a simple function to calculate the intersection between two rectangles. A square is a rectangle, so it can be used for squares. I assume that the rectangles height and width are parallel to the y and x axis.
struct point { double x, y; };
struct rectangle { struct point a, b; };
double max(double a, double b) { return a>b ? a : b; }
double min(double a, double b) { return a<b ? a : b; }
// Calculate the intersection of r1 and r2 and store the result in output
// Assumes that a.x < b.x and a.y < b.y for r1 and r2
// Returns NULL if there is no intersection
// Will always modify output. Do do NOT read output if this function returns NULL
struct rectangle *intersection(
struct rectangle *output,
const struct rectangle *r1,
const struct rectangle *r2)
{
output->a.x = max(r1->a.x, r2->a.x);
output->b.x = min(r1->b.x, r2->b.x);
if(output->a.x > output->b.x) return NULL;
output->a.y = max(r1->a.y, r2->a.y);
output->b.y = min(r1->b.y, r2->b.y);
if(output->a.y > output->b.y) return NULL;
return output;
}
Related
I am having trouble to make the camera rotate around my object. I am going to try to express myself as good as i can.
The objective is that when i load a new object and select it, (selecting it means that _selected_object points to the new object), the active camera points only to the center of the object(when analisis mode is activated), so the rotations and translation( translations just in the Z axis) are made around this object.
This is what i am trying right now:
_selected_camera->at.x=_selected_object->mtptr->M[3];
_selected_camera->at.y=_selected_object->mtptr->M[7];
_selected_camera->at.z=_selected_object->mtptr->M[11];
This code happens when the analisis mode (camera pointing and moving towards object) is activated. But when i move the object, the camera points nowhere or where it was initially pointing.
at.x from selected camera is the point towards the camera is looking. mtptr is the 4x4 matrix position of the object (in which object transformations are made), where last column has the center of the object.
If you're using legacy OpenGL, use gluLookAt.
Otherwise (pseudo code):
mat4 lookAt(vec3 eye, vec3 target, vec3 up)
{
//calculate axes based on the provided parameters
//cross product gives us the perpendicular vector
vec3 z = eye - target;
vec3 x = cross(up, z);
vec3 y = cross(z, x);
//normalize to make unit vectors
normalize(x);
normalize(y);
normalize(z);
//translation vector
//based on the angle between the eye vector (camera position) and the axes
//hint: angle = dot(a, b) -> see: https://en.wikipedia.org/wiki/Dot_product
vec3 t = {
-dot(eye, x),
-dot(eye, y),
-dot(eye, z)
};
return { //a combined scale, skew, rotation and translation matrix
x[0], x[1], x[2], t[0],
y[0], y[1], y[2], t[1],
z[0], z[1], z[2], t[2],
0, 0, 0, 1
};
}
Multiply the resulting (view) matrix with a projection matrix (ortho, perspective).
Rectangles are located in a doubly-linked list. In this context, a rectangle is a figure, formed using a data of the rectangle's structure (no matter how).
struct rect {
int l; /* left */
int t; /* top */
int r; /* right */
int b; /* bottom */
};
Its fields has the strict positions (I guarantee it for any rectangle).
[l; t] [r; t]
+------+
| |
| |
+------+
[l; b] [r; b]
Rectangles are stored in objects.
struct object {
struct rect *rect;
bool selected;
};
And objects are stored in the list's nodes.
struct node {
struct object *obj;
struct node *next;
struct node *prev;
};
Rectangles draws consistently, beginning from the list's head -- first draws a rectangle, closer to the beginning of the list. Thereby, an each next figure overlaps previous figures.
I select rectangles, with a selection rectangle, that forms by mouse cursor. The selection check is done, during iterating over the list from the end.
struct node *node = getend(list);
struct object *obj;
do {
obj = node->obj;
/* Check, if a selection rectangle somehow
* intersects with a rectangle of the current
* object. */
if (rcheck(sel_rect, obj->rect))
obj->selected = true;
}
while ((node = node->prev));
Take a look to the demonstration of my problem, a little below.
As you can see, the selection rectangle selects two rectangles: yellow and green. In this case, only the yellow figure should be selected; in general -- if behind a forward rectangle another figure is located (a backward rectangle), and a selection rectangle does not cover a "visible" part of this figure (on the animation it's the green polygon, formed by overlapping the yellow figure), but covers its "hidden" part, then a backward rectangle should not be selected.
A forward rectangle means, that it's located closer to the end of the list; a backward rectangle - that it's located closer to its beginning.
This alrogithm is used in game's two-dimensional map editor, for rectangular textures selection.
Five different approaches:
Screen Space Selection
Render the rectangles from back to front order onto a temporary array/grid of "pixels", but using "rectangle ID" instead of colors. Use the selection rectangle to select "pixels" and examine them to determine the "rectangle IDs" for selected rectangles. This is likely to be the simplest option (and likely to have the worst performance).
Selection Rectangle Subdivision
Search from front to back (like you are); but when you find a rectangle that overlaps the selection rectangle use its edges to split the selection rectangle up into sub-rectangles and discard sub-rectangles that overlap the found rectangle. This will leave you with zero to 8 sub-rectangles that don't overlap the found rectangle. Repeat this process using each of the resulting sub-rectangles (instead of the original selection rectangle) to find more rectangles that were selected. Note that (for "worst case") the number of sub-rectangles can increase by 7 for each rectangle selected.
Rectangle List Subdivision
Pre-process the list of rectangles using the edges of front rectangles to sub-divide any back-polygons, and discard any overlapping sub-rectangles; so that the resulting list of rectangles no longer contains anything that overlaps. After this; find all (sub)rectangles that overlap with the selection rectangle. Note that this is nicer if the list of rectangles doesn't change often and the same "pre-processed list of rectangles" can be re-used many times.
Selection Polygon Subtraction
Assume the selection area is an arbitrary shape with N vertices and N sides, which just happens to be 4 vertices and 4 sides in the beginning. Search from front to back (like you are); but when you find a rectangle that overlaps the selection polygon subtract the overlapping areas from the selection polygon. This is incredibly complicated; partly because the selection polygon can be split into "separated/non-touching" pieces and/or can become "donut like". This can be combined with the previous approach - e.g. use the edges of the overlapping rectangle to split the selection polygon into sub-polygons, then discard overlapping sub-polygons, then merge sub-polygons that share a common edge to reduce the number of sub-polygons.
Rectangle List Subtraction
Pre-process the list of rectangles (and convert them all into arbitrary shaped polygons) using a similar approach to "Selection Polygon Subtraction". After this; find all (sub)polygons that overlap with the selection rectangle. Note that this is nicer if the list of rectangles doesn't change often and the same "pre-processed list of polygons" can be re-used many times.
Notes
There's more advanced techniques for polygon subtraction than the "split then merge if you can" approach I described, which are much more complicated and give better performance. For one research paper, see https://www.pnnl.gov/main/publications/external/technical_reports/PNNL-SA-97135.pdf
Myself, I'd probably use the "Selection Rectangle Subdivision" approach if the highest possible performance isn't a necessity (and if the list of rectangles changes more often than the selection rectangle).
I though of the solution myself, and it turned out to be a little more difficult, than I expected. And it took me a while.
The method of the list traversing wasn't changed -- I do the selection check for each node from front to back.
First, I select root rectangle (first rectangle, intersecting with the selection). Next, if other rectangles intersecting, they are checked on intersecting with root to make sure they aren't just aside.
I memorize rectangles between r (the current rectangle) and root (including root) -- it will be needed for the further checks. Rectangles are stored in rect_list (in another list).
Traversing this list starts. On this moment, I firstly check r and sr (a node's rectangle) aren't intersecting together, and store their intersection in ir. Also, the selection rectangle should intersect ir.
if (!rintersect(r, sr, ir))
continue;
if (!rcheck(sel_rect, ir))
continue;
Now, I scan the area around ir -- points of each side of rectangle with coordinates:
struct rect scan_area {
ir.l - 1,
ir.t - 1,
ir.r + 1,
ir.b + 1
};
to check for a point in current rectangle and in the selection, but not in all memorized rectangles (list_check does this).
bool l = false;
bool t = false;
bool r = false;
bool b = false;
struct point p;
int i;
for (i = ir.l; i <= ir.r; i++) {
p.x = i;
p.y = ir.t - 1;
if ((t = list_check(rect_list, p))
break;
p.y = ir.b + 1;
if ((b = list_check(rect_list, p))
break;
}
for (i = ir.t; i <= ir.b; i++) {
if (t || b)
break;
p.y = i;
p.x = ir.l - 1;
if ((l = list_check(rect_list, crd))
break;
p.x = ir.r + 1;
if ((r = list_check(rect_list, crd))
break;
}
if ((obj->selected = l || t || r || b))
break;
I wouldn't say this alrogithm highly inefficient, comparing it with the first Brendan's proposed way: screen space selection, because I need to check all rectangles, firstly; check all pixels of these rectangles, including each pixel of the selection, secondly.
Objectively, this alrogithm isn't fast (O(n^3)). However, it isn't noticeable within my task.
I am trying to render ellipse on plotter powered by an MCU so there is low memory to work with and integer arithmetics is preffered.
I've got this equation
and I tried to implement it in C in the following way:
y = sqrt( (b*b) * ( 1 - ( (x*x) / (a*a) )));
where y, b, x and a are integer values but the results where wrong .
Q1 Is this correct implementation of ellipse equation?
Q2 Are there any other ways to do this?
for plotting the ellipse (outline by lines) is the parametric equation the best.
Here axis aligned ellipse:
x=x0+a*cos(t);
y=y0+b*sin(t);
where:
(x0,y0) is the ellipse center
a,b are the semi-axises
t is angular parameter t=<0,2*M_PI>
So form a loop where t goes the full circle with some small enough step
compute (x,y) per each step of t
interpolate/render line per each step (from last to new point)
as your x,y,x0,y0,a,b are integers either convert them to float/double or create integer table for cos[],sin[] for example:
int tcos[360],tsin[360];
where tcos[i]=float(1000.0*cos(float(i)*M_PI/180.0)); now on use just integers like:
for (i=0;i<360;i++)
{
x=x0+(a*tcos(i))/1000;
y=y0+(b*tsin(i))/1000;
//...
}
If you need pixel perfect rendering or render filled ellipse
Then you need use different approach (the same as your equation)
loop one axis with pixel step
compute the other axis coordinate
render both pixels/or fill the line
for example axis aligned (0,0) centered ellipse:
for (x=-a;x<=a;x++)
{
y = sqrt( (b*b) - ( (x*x*b*b) / (a*a) )));
// render pixels: (x,+y) and (x,-y) or join them by line
}
if you need integer sqrt then implement one (instead of using math.h) for example:
int bits(DWORD p)
{
DWORD m=0x80000000; int b=32;
for (;m;m>>=1,b--)
if (p>=m) break;
return b;
}
DWORD sqrt(const DWORD &x)
{
DWORD m,a;
m=(bits(x)>>1); // bits(x) just return position of MSB nonzero bit can use m=16; instead
if (m) m=1<<m; else m=1;
for (a=0;m;m>>=1) { a|=m; if (a*a>x) a^=m; }
return a;
}
where DWORD is unsigned 32 bit int data type.
for filling you do not need the sqrt
You can instead loop through the area and decide if the pixel is inside or not:
for (y=-b;y<=b;y++)
for (x=-a;x<=a;x++)
if ( (y*y) <= ( (b*b) - ( (x*x*b*b) / (a*a) ) ) )
// render pixel: (x,y)
The implementation is correct. I set y,b,x and a as double values this fixed the wrong output.
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
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.