Partitioning of an AABB - c++

I have a problem where I need to divide an AABB into a number of small AABBs. I need to find the minimum and maximum points in each of the smaller AABB.
If we take this cuboid as an example, we can see that is divided into 64 smaller cuboids. I need to calculate the minimum and maximum points of all of these smaller cuboids, where the number of cuboids (64) can be specified by the end user.
I have made a basic attempt with the following code:
// Half the length of each side of the AABB.
float h = side * 0.5f;
// The length of each side of the inner AABBs.
float l = side / NUMBER_OF_PARTITIONS;
// Calculate the minimum point on the parent AABB.
Vector3 minPointAABB(
origin.getX() - h,
origin.getY() - h,
origin.getZ() - h
);
// Calculate all inner AABBs which completely fill the parent AABB.
for (int i = 0; i < NUMBER_OF_PARTITIONS; i++)
{
// This is not correct! Given a parent AABB of min (-10, 0, 0) and max (0, 10, 10) I need to
// calculate the following positions as minimum points of InnerAABB (with 8 inner AABBs).
// (-10, 0, 0), (-5, 0, 0), (-10, 5, 0), (-5, 5, 0), (-10, 0, 5), (-5, 0, 5),
// (-10, 5, 5), (-5, 5, 5)
Vector3 minInnerAABB(
minPointAABB.getX() + i * l,
minPointAABB.getY() + i * l,
minPointAABB.getZ() + i * l
);
// We can calculate the maximum point of the AABB from the minimum point
// by the summuation of each coordinate in the minimum point with the length of each side.
Vector3 maxInnerAABB(
minInnerAABB.getX() + l,
minInnerAABB.getY() + l,
minInnerAABB.getZ() + l
);
// Add the inner AABB points to a container for later use.
}
Many thanks!

I assume that your problem is that you don't get enough sub-boxes. The number of partitions refers to partitions per dimension, right? So 2 partitions yield 8 sub-boxes, 3 partitions yield 27 sub-boxes and so on.
Then you must have three nested loops, one for each dimension:
for (int k = 0; k < NUMBER_OF_PARTITIONS; k++)
for (int j = 0; j < NUMBER_OF_PARTITIONS; j++)
for (int i = 0; i < NUMBER_OF_PARTITIONS; i++)
{
Vector3 minInnerAABB(
minPointAABB.getX() + i * l,
minPointAABB.getY() + j * l,
minPointAABB.getZ() + k * l
);
Vector3 maxInnerAABB(
minInnerAABB.getX() + l,
minInnerAABB.getY() + l,
minInnerAABB.getZ() + l
);
// Add the inner AABB points to a container for later use.
}
}
}
Alternatively, you can have one huge loop over the cube of your partitios and sort out the indices by division and remainder operations inside the loop, which is a bit messy for three dimensions.
It might also be a good idea to make the code more general by calculating three independent sub-box lengths for each dimension based on the side lengths of the original box.

Related

If I have a 3d grid of cubes, how can I efficiently find all the cubes that intersect a sphere of radius r and position p?

Imagine you have a 3D space between 0 and d meters in the x,y and z directions (it's a cube of length d). now let's assume I want to break this up into a 3D array of smaller cubes. We want n cubes in each direction. This means each cube has a length, width and height of d/n (you can assume that d/n divides perfectly).
This can be held in the following array:
Cube* cubes[n][n][n];
Now let us assume we can have a sphere of radius r and position p, where p can be anywhere inside the 3d space, and r has no constraints. What is the most efficient way of finding and returning all the cubes that intersect with this sphere?
Currently, I am looping through all the cubes in the array and using the Pythagorean theorem to check the distance between each cube and p, which I wrote the pseudo code for below.
Cube* getIntersectingCubes(r,p) {
Cube* cubes[n][n][n];
Cube* result[];
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
for(int k=0;k<n;k++) {
if(distanceBetween(cubes[i][j][k],p) < r) {
result.add(cubes[i][j][k]);
}
}
}
}
return result;
}
However, there is definitely a better way to do this. How could I return the same output but check as few cubes as possible?
If you are still having trouble working out a coordinate system and your algorithm, start with a diagram:
Essentially what you have is a 3D grid of cubes and your points p can be chosen any way you like so long as they describe a cube completely. What you want to determine is for which cubes does the radius r intersect any part of the cube. You can handle that with three vectors. You simply treat the cube origin as a vector. You know the lengths of the sides of each cube (d / n) you can use to form a second vector (call it the extent of p or p_extent) which you can add to the origin vector to determine the farthest point in the cube. So p_extent would equal d/ni + d/nj + d/nk.
You can create a struct to help in handling the coordinates as a vector, e.g.:
typedef struct {
double x, y, z;
} vect_pos;
With your two vectors, you can simply add them together (e.g. p + p_extent) to form a vector describing the farthest point in the cube from the origin. (you want the direction of the vector inside your cube to have the same sign direction as your origin vector (so you can simply multiply it with a unit vector in that direction). For example is your point is -3i -1j and 2k, you can multiple by the p_extent vector by -1i -1j 1k. (picture the cube origin vector in each of the 8-quadrants and the values that x, y, z would have in each.
To add two vector_pos together, you can simply use vector addition, e.g.
/* vector addition */
vect_pos vect_add (const vect_pos *a, const vect_pos *b)
{
vect_pos c = { .x = 0. };
c.x = a->x + b->x;
c.y = a->y + b->y;
c.z = a->z + b->z;
return c;
}
The last wrinkle that choosing the coordinate at a corner of the cube will require you solve is that the origin vector will not always point to the corner closest to the origin (picture in the diagram above where p would point if you rotated the origin counter-clockwise by 90 deg about the axis. (your alternative is to choose the center of the cube as its origin, but then you have twice the number of calculations).
You can handle the closest corner issue by a simple check and shifting the corner for the origin by a cube side length for purposes of the calculation of whether r is between the closest and farthest corners (the cube is still the same cube) With your cube origin and the farthest corner described, you can simply use the vector-distance formula to calculate the distance each is from the origin and if r is between the two, the sphere intersects that cube.
To choose the closest point to the origin before calculating the distances you can use:
/* point in cube closest to origin */
vect_pos closest_pt (const vect_pos *p, const int len)
{
vect_pos c = { p->x >= 0 ? p->x : p->x + len,
p->y >= 0 ? p->y : p->y + len,
p->z >= 0 ? p->z : p->z + len };
return c;
}
(choosing your cube at origin 0, 0, 0 with positive sides allows you to simply add a cube side length in the case that coordinate is negative to choose the closest point on the cube as the origin)
and for the distance calculations, a simple square-root of the sum of the squares:
/* vector distance */
double vect_dist (const vect_pos *p)
{
return sqrt (p->x * p->x + p->y * p->y + p->z * p->z);
}
To check if r falls between the closest and farthest distance within each cube you can put it altogether with a short function that handles choosing the extent vector in the same direction as the origin, adds the vectors and then compares the distances of each to r, e.g.
/* does r intersect cube at postition p */
int intersect (vect_pos *p, const double r, const int len)
{
vect_pos c = closest_pt (p, len), /* closest pt to origin */
p_extent = { .x = c.x >= 0 ? len : -len, /* length, unit vector */
.y = c.y >= 0 ? len : -len, /* pointing outward */
.z = c.z >= 0 ? len : -len },
p_farthest = vect_add (&c, &p_extent); /* farthest point in cube */
double nearest = vect_dist (&c), /* distance to nearest */
farthest = vect_dist (&p_farthest); /* distance to farthest */
return nearest <= r && r <= farthest; /* return radius in between */
}
That's basically it. You can add a short function to output the points to as a convenience, e.g.
void prn_pos (const vect_pos *p)
{
printf ("(% d, % d, % d)\n",
(int)p->x, (int)p->y, (int)p->z);
}
and then add a main() that allows entry of r, d and n and outputs the results:
int main (int argc, char **argv) {
double r = argc > 1 ? strtod (argv[1], NULL) : .9; /* r */
int d = argc > 2 ? strtol (argv[2], NULL, 0) : 1, /* d */
n = argc > 3 ? strtol (argv[3], NULL, 0) : d, /* n */
dn = 0, /* d/n */
nc = 0, /* number of cubes in each direction */
total = 0, /* total cubes in search grid */
intersecting = 0; /* number of cubes that intersect sphere */
if (r < 0 || d < 0) { /* validate length inputs */
fputs ("error: negtive length in input of r or d.\n", stderr);
return 1;
}
if (!n || n < 0) { /* validate n not zero or negative */
fputs ("error: n - divide by zero or negative.\n", stderr);
return 1;
}
if (d < r) { /* ensure d >= r */
int min_d = ceil (r);
n *= min_d / d;
d = min_d;
}
if (d % n) { /* validate d equally divisible by n */
fputs ("error: d not equally divisible by n.\n", stderr);
return 1;
}
dn = d / n; /* cube side length */
nc = ceil (r / dn) + 1; /* limit of cubes needed per-direction */
total = nc * nc * nc * 8; /* total number of cubes in search grid */
printf ("\nOut of %d cubes, the following intersect sphere of radius %.2f\n\n",
total, r);
for (int i = -d; i <= d; i += dn) /* loop -d to d */
for (int j = -d; j <= d; j += dn)
for (int k = -d; k <= d; k += dn) {
vect_pos p = { i, j, k }; /* vector to cube origin */
if (intersect (&p, r, dn)) { /* does it intersect sphere? */
prn_pos (&p); /* output cube origin */
intersecting++; /* increment count */
}
}
printf ("\nintersecting cubes: %d\n", intersecting);
}
Add the headers:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
and then compile linking against the math library -lm and you have a working program to test. If no arguments for r, d or n are provided, the code uses .90, 1, and 1 as defaults. Note the loop limits are at minimum from -(next int above r) to (next int above r) in each dimension or as given by d whichever is greater and not shorter than r.
Example Use/Output
Default case with r = .9 and d = 1 and n = 1:
$ ./bin/cube-sphere-intersect
Out of 64 cubes, the following intersect sphere of radius 0.90
(-1, -1, -1)
(-1, -1, 0)
(-1, 0, -1)
(-1, 0, 0)
( 0, -1, -1)
( 0, -1, 0)
( 0, 0, -1)
( 0, 0, 0)
intersecting cubes: 8
If you draw the cubes out on a grid, those are the 8 cubes surrounding the origin.
Choosing r = 5.5, d = 6 and n = 1 would give the same result other than the sides of the cubes being of different length:
$ ./bin/cube-sphere-intersect 5.5 6 1
Out of 64 cubes, the following intersect sphere of radius 5.50
(-6, -6, -6)
(-6, -6, 0)
(-6, 0, -6)
(-6, 0, 0)
( 0, -6, -6)
( 0, -6, 0)
( 0, 0, -6)
( 0, 0, 0)
intersecting cubes: 8
If you enter an r length of exacly 1, then this is where your choice of whether to consider r equal to the min or max length will come into play. There are arguments for saying "touching" a cube doesn't really mean it intersects as the point will technically lie on a tangent that distance out, but there are equally good arguments that say that intersects (the choice of whether you want to use <= or < in the comparison is left to you)
For example if you enter anything between 1.0 < sqrt(2) (1.414...) you will find 32 cube intersect, e.g.
$ ./bin/cube-sphere-intersect 1.1
Out of 216 cubes, the following intersect sphere of radius 1.10
(-2, -1, -1)
(-2, -1, 0)
(-2, 0, -1)
(-2, 0, 0)
(-1, -2, -1)
(-1, -2, 0)
(-1, -1, -2)
(-1, -1, -1)
(-1, -1, 0)
(-1, -1, 1)
(-1, 0, -2)
(-1, 0, -1)
(-1, 0, 0)
(-1, 0, 1)
(-1, 1, -1)
(-1, 1, 0)
( 0, -2, -1)
( 0, -2, 0)
( 0, -1, -2)
( 0, -1, -1)
( 0, -1, 0)
( 0, -1, 1)
( 0, 0, -2)
( 0, 0, -1)
( 0, 0, 0)
( 0, 0, 1)
( 0, 1, -1)
( 0, 1, 0)
( 1, -1, -1)
( 1, -1, 0)
( 1, 0, -1)
( 1, 0, 0)
intersecting cubes: 32
Then for radius between sqrt(2) <= sqrt(3) you would find 56 cube intersect and so on.
This is just one way to implement it. If you are curious, go rewrite it to use the center of each cube as the origin of the cube. You don't have to use a struct, you can just operate on each x, y, z directly, but the struct helps keep the logic clear. Look things over and let me know if you have further questions.
Divide and conquer:
Assume the entire domain as a single cube:
Figure out if there is an intersection
If so, divide into octants and repeat (1)
Because you only need to search the octants where an intersection is present, you won't have to preallocate a massive array of cells.
The intersection algorithm can be simplified to any cube where at least one of the nodes is less than the radius from p and at least one is greater. It should be possible to write this algorithm in a way that is easy to vectorise.
Note: Probably don't want to store your 3d array on the stack, even if you pick a relatively small number for n, say 50, that's already 125000 doubles, enough to cause a stack overflow on some systems.
I would start with the cube containing point p and go into any one direction while given cube still intersects the sphere. That would give you a distance +-1 to all "edge" cubes.
This provides early termination of the search through cubes you know won't intersect and gives you an approximation of end points in all directions.
Let's say a cube is in the outer shell if it intersects the sphere but isn't fully contained in the sphere. Say the initial point p = (x, y, z). We'll proceed by finding the cubes in the outer shell. Given these, it's easy to find interior cubes.
1. Find the cube containing p in O(1).
2. Find the most distant cube intersecting the sphere that can be reached by decreasing x.
3. Add this to a set: unexplored
4. repeatedly do the following (each iteration is O(1):
a. Pull a cube from unexplored.
b. Add any neighbors that intersect the outer shell and aren't explored to unexplored.
c. Mark the current cube as explored.
How long does this take? It's linear with the surface area of the sphere measured in cubes, so O(4pi(r/d)^2) = O((r/d)^2). I.e. the formula for the surface area of a sphere, but with the radius measured in cubes.
If it suffices to return the outer shell then you're done. If you need to return the contents then this grows to be linear with the output, which is O((r/d)^3)
First of all you need a function that will map any point in 3D into three integers:
(x,y,z) -> (floor(x/dx), floor(y/dy), floor(z/dz))
where, in your case, dx = dy = dz = d/n is the size (along axes x, y, z) of small cubes (which I shall rather call "cells") you divide the whole space into. This function maps any point in 3D into a discrete cell.
Now, you should find the minimum cuboid, which is made of cells, and which contains the sphere centered at P and of radius r. In a general case this is a cuboid, though often it will be just a cube. After all, it kinda circumscribes a sphere. Let your cube be denoted A, and let this cuboid be denoted B. The answer to your problem lies inside both A and B. For this reason find the intersection C of A and B. Focus entirely on C. This trick alone should result in a huge reduction of the problem complexity, with practically zero cost.
Now I assume you have a well written, well tested function distance(cube, point). Remember that the point on the cube that minimize the distance to point may lie on one of cube's corners, edges, sides or its interior volume and so such a function will need several if-else branches.
Check if distance returns a value less or equal than r. If not, the answer is an empty set, you're done.
If the distance is <= r, then you can apply a modified method reported here by M.A., but applied to C. This C is not a cube, so octants are no solution here. However, C is a cuboid, for an intersection of 2 cuboids is a cuboid. Denote its side lengths as Lx, Ly, Lz. Thee numbers are integers, becassue now you measure the lengths in units of dx, dy and dz along axes x, y, z, repectively. Find the largest of them. Suppose, for clarity, that it is Lx. If Lx > 1 you divide C along the x axis into two equal-sized (when Lx is even) or almost equal (Lx is odd) sub-cuboids. You check the distance to each of them. If it is larger than r then you reject this whole sub-cuboid. Otherwise you repeat the division along the largest side of the current cuboid. This is very similar to, for example, implementation of the BVH tree.
Once you reached the "sub-cuboid" of size 1x1x1, you verify if it intersects with the sphere. If yes, add it to the solution set.
* * *
This algorithm is very general because your question contains no details as to where the answer to this problem is to be used. For example, how large can n be? Will the solution be used for fixed radius and varying sphere centers? Knowing such details could help develop a better solution.
For example, the sphere can contain O(N^3) cells, so one might expect that he solution cannot be found in time smaller than O(N^3). But perhaps you do nod a list of the cells? Perhaps a different format would do?
The set of cells forming the solution can be regarded as a union of disjoint columns of cells, oriented along the z axis. With this representation, the solution can be written as a set of pairs (cell, height). Here cell denote the lowest cell in a column, and height - its height. If a solution in this format is OK. the problem can be solved in O(N^2) or at mot O(N^2 log N) time.

Suggestions to Compute the Intersetions of Multiple Convex 2D Polygons

I am writing this question fishing for any state-of-the-art software or methods that can quickly compute the intersection of N 2D polygons (the convex hulls of projected convex polyhedrons), and M 2D polygons where typically N >> M. N may be in the order or at least 1M polygons and N in the order 50k. I've searched for some time now, but I keep coming up with the same answer shown below.
Use boost and a loop to
compute the projection of the polyhedron (not the bottleneck)
compute the convex hull of said polyhedron (bottleneck)
compute the intersection of the projected polyhedron and existing 2D polygon (major bottleneck).
This loop is repeated NK times where typically K << M, and K is the average number of 2D polygons intersecting a single projected polyhedron. This is done to reduce the number of computations.
The problem with this is that if I have N=262144 and M=19456 it takes about 129 seconds (when multithreaded by polyhedron), and this must be done about 300 times. Ideally, I would like to reduce the computation time to about 1 second for the above sizes, so I was wondering if someone could help point to some software or literature that could improve efficiency.
[EDIT]
#sehe's request I'm posting the most relevant parts of the code. I haven't compiled it, so this is just to get the gist... this code assumes, there are voxels and pixels, but the shapes can be anything. The order of the points in the grid can be any, but the indices of where the points reside in the grid are the same.
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/ring.hpp>
const std::size_t Dimension = 2;
typedef boost::geometry::model::point<float, Dimension, boost::geometry::cs::cartesian> point_2d;
typedef boost::geometry::model::polygon<point_2d, false /* is cw */, true /* closed */> polygon_2d;
typedef boost::geometry::model::box<point_2d> box_2d;
std::vector<float> getOverlaps(std::vector<float> & projected_grid_vx, // projected voxels
std::vector<float> & pixel_grid_vx, // pixels
std::vector<int> & projected_grid_m, // number of voxels in each dimension
std::vector<int> & pixel_grid_m, // number of pixels in each dimension
std::vector<float> & pixel_grid_omega, // size of the pixel grid in cm
int projected_grid_size, // total number of voxels
int pixel_grid_size) { // total number of pixels
std::vector<float> overlaps(projected_grid_size * pixel_grid_size);
std::vector<float> h(pixel_grid_m.size());
for(int d=0; d < pixel_grid_m.size(); d++) {
h[d] = (pixel_grid_omega[2*d+1] - pixel_grid_omega[2*d]) / pixel_grid_m[d];
}
for(int i=0; i < projected_grid_size; i++){
std::vector<float> point_indices(8);
point_indices[0] = i;
point_indices[1] = i + 1;
point_indices[2] = i + projected_grid_m[0];
point_indices[3] = i + projected_grid_m[0] + 1;
point_indices[4] = i + projected_grid_m[0] * projected_grid_m[1];
point_indices[5] = i + projected_grid_m[0] * projected_grid_m[1] + 1;
point_indices[6] = i + (projected_grid_m[1] + 1) * projected_grid_m[0];
point_indices[7] = i + (projected_grid_m[1] + 1) * projected_grid_m[0] + 1;
std::vector<float> vx_corners(8 * projected_grid_m.size());
for(int vn = 0; vn < 8; vn++) {
for(int d = 0; d < projected_grid_m.size(); d++) {
vx_corners[vn + d * 8] = projected_grid_vx[point_indices[vn] + d * projeted_grid_size];
}
}
polygon_2d proj_voxel;
for(int vn = 0; vn < 8; vn++) {
point_2d poly_pt(vx_corners[2 * vn], vx_corners[2 * vn + 1]);
boost::geometry::append(proj_voxel, poly_pt);
}
boost::geometry::correct(proj_voxel);
polygon_2d proj_voxel_hull;
boost::geometry::convex_hull(proj_voxel, proj_voxel_hull);
box_2d bb_proj_vox;
boost::geometry::envelope(proj_voxel_hull, bb_proj_vox);
point_2d min_pt = bb_proj_vox.min_corner();
point_2d max_pt = bb_proj_vox.max_corner();
// then get min and max indices of intersecting bins
std::vector<float> min_idx(projected_grid_m.size() - 1),
max_idx(projected_grid_m.size() - 1);
// compute min and max indices of incidence on the pixel grid
// this is easy assuming you have a regular grid of pixels
min_idx[0] = std::min( (float) std::max( std::floor((min_pt.get<0>() - pixel_grid_omega[0]) / h[0] - 0.5 ), 0.), pixel_grid_m[0]-1);
min_idx[1] = std::min( (float) std::max( std::floor((min_pt.get<1>() - pixel_grid_omega[2]) / h[1] - 0.5 ), 0.), pixel_grid_m[1]-1);
max_idx[0] = std::min( (float) std::max( std::floor((max_pt.get<0>() - pixel_grid_omega[0]) / h[0] + 0.5 ), 0.), pixel_grid__m[0]-1);
max_idx[1] = std::min( (float) std::max( std::floor((max_pt.get<1>() - pixel_grid_omega[2]) / h[1] + 0.5 ), 0.), pixel_grid_m[1]-1);
// iterate only over pixels which intersect the projected voxel
for(int iy = min_idx[1]; iy <= max_idx[1]; iy++) {
for(int ix = min_idx[0]; ix <= max_idx[0]; ix++) {
int idx = ix + iy * pixel_grid_size[0]; // `first' index of pixel corner point
polygon_2d pix_poly;
for(int pn = 0; pn < 4; pn++) {
point_2d pix_corner_pt(
pixel_grid_vx[idx + pn % 2 + (pn / 2) * pixel_grid_m[0]],
pixel_grid_vx[idx + pn % 2 + (pn / 2) * pixel_grid_m[0] + pixel_grid_size]
);
boost::geometry::append(pix_poly, pix_corner_pt);
}
boost::geometry::correct( pix_poly );
//make this into a convex hull since the order of the point may be any
polygon_2d pix_hull;
boost::geometry::convex_hull(pix_poly, pix_hull);
// on to perform intersection
std::vector<polygon_2d> vox_pix_ints;
polygon_2d vox_pix_int;
try {
boost::geometry::intersection(proj_voxel_hull, pix_hull, vox_pix_ints);
} catch ( std::exception e ) {
// skip since these may coincide at a point or line
continue;
}
// both are convex so only one intersection expected
vox_pix_int = vox_pix_ints[0];
overlaps[i + idx * projected_grid_size] = boost::geometry::area(vox_pix_int);
}
} // end intersection for
} //end projected_voxel for
return overlaps;
}
You could create the ratio of polygon to bounding box:
This could be done computationally once to arrive at an avgerage poly area to BB ratio R constant.
Or you could do it with geometry using a circle bounded by its BB Since your using only projected polyhedron:
R = 0.0;
count = 0;
for (each poly) {
count++;
R += polyArea / itsBoundingBoxArea;
}
R = R/count;
Then calculate the summation of intersection of bounding boxes.
Sbb = 0.0;
for (box1, box2 where box1.isIntersecting(box2)) {
Sbb += box1.intersect(box2);
}
Then:
Approximation = R * Sbb
All of this would not work if concave polys were allowed. Because a concave poly can occupy less than 1% of it's bounding box. You will still have to find the convex hull.
Alternatively, If you can find the polygons area quicker than its hull, you could use the actual computed average poly area. This would give you a decent approximation as well while avoiding both poly intersection and wrapping.
Hm, the problem seems similar to doing "collision-detection" i game-engines. Or "potentially visible sets".
While I don't know much about the current state-of-the-art, i remember an optimization was to enclose objects in spheres, since checking overlaps between spheres (or circles in 2D) is really cheap.
In order to speed-up checks for collisions, objects were often put into search-structures (e.g. a sphere-tree (circle-tree in 2D case)). Basically organizing the space into a hierarchical structure, to make queries for overlaps fast.
So basically my suggestion boils down to: Try looking at algorithms for collision-detection i game-engines.
Assumption
I'm assuming that you mean "intersections" and not intersection. Moreover, It is not the expected use case that most of the individual polys from M and N will overlap at the same time. If this assumption is true then:
Answer
The way this is done with 2D game engines is by having a scene graph where every object has a bounding box. Then place all the the polygons into a node in an quadtree according to their location determined by bounding box. Then the task becomes parallel because each node can be processed separately for intersection.
Here is the wiki for quadtree:
Quadtree Wiki
An octree could be used when in 3D.
It actually doesn't even have to be a octree. You could get the same results with any space partition. You could find the maximum separation of polys (lets call it S). And create say S/10 space partitions. Then you would have 10 separate spaces to execute in parallel. Not only would it be concurrent, but It would no longer be M * N time since not every poly must be compared against every other poly.

Finding the number of integer points inside a sphere of radius R and dimension D centered at the Origin [duplicate]

This question already has answers here:
Counting integer points inside a sphere of radius R and dimension D
(3 answers)
Closed 6 years ago.
I am writing a computer program/algorithm to count the number of integer points inside a sphere of radius R and Dimension D centered at the origin. In essence, if we have a sphere of dimension 2 (circle) and radius 5, I am determining all integer solutions to the inequality X^2+Y^2 ≤ 25. Instead of counting every possible integer point, is there an efficient way to count the points ? Using symmetry ?
Suppose the dimension is 3, and R is the radius. For z = 0, the possible x,y coordinates are the points inside a circle of radius R, and for any z, the x,y's are the points inside a circle of radius sqrt( R * R - z * z); the possible values of z are -r, .. 0, 1, .. r where r is the smallest integer less than R. Note the count for z and -z will be the same.
When we get down to dimension 1, we are asking how many integers i satisfy |i| < R, and this is 1 + 2 * r
So:
int ncip( int dim, double R)
{
int i;
int r = (int)floor( R);
if ( dim == 1)
{ return 1 + 2*r;
}
int n = ncip( dim-1, R); // last coord 0
for( i=1; i<=r; ++i)
{ n += 2*ncip( dim-1, sqrt( R*R - i*i)); // last coord +- i
}
return n;
}
Well, using symmetry, you can always just count all the integer solutions on the positive side, and then invert the components. So, in case of your Circle (D=2, R=5), you'd just have to find
{ X,Y ∈ N: X²+Y² ≤ R }. Then create the combinations (X,Y), (X,-Y), (-X,Y), (-X,-Y)
This leaves you with just (1/2)D solutions to find.
Also, you can approximate a circle of radius R as a Square with radius R/√2, so all combinations of integers smaller than or equal to that can automatically be added.

Finding a square in a group of coordinates

Ok, I'm having a bit of trouble finding a solution for this that seems to be a simple geometry problem.
I have a list of triple coordinates that form a square angle.
Between all these triple-coordinates I want to find a pair that forms up a square.
I believe the best I can do to exemplify is show an image:
and 2. are irrelevant. 3. and 4. are what I'm looking for.
For each triple coordinate I have the midle point, where the angle is, and two other points that describe the two segments that form the angle.
Summing it up, given six points, 2 for the diagonal + 4 other points, how can I find if these make a square?
obs: the two lines that make the angle are consistent but don't have the same size.
obs2:the lines from different triples may not intersect
Thank you for time and any help and insight provided.
If any term I used is incorrect or just plain hard to understand let me know, I'm not a native english speaker.
Edit: The code as it stands.
//for all triples
for (size_t i = 0; i < toTry.size() - 1; i++) {
Vec2i center_i = toTry[i].avg;
//NormalizedDiagonal = ((Side1 - Center) + (Side2 - Center));
Vec2i a = toTry[i].p, b = toTry[i].q;
Vec2f normalized_i = normalizedDiagonal(center_i, toTry[i].p, toTry[i].q);
for (size_t j = i + 1; j < toTry.size(); j++) {
Vec2i center_j = toTry[j].avg;
//Se os pontos sao proximos, nao importam
if (areClose(center_i, center_j, 25))
continue;
Vec2f normalized_j = normalizedDiagonal(center_j, toTry[j].p, toTry[j].q);
line(src, Point(center_i[0], center_i[1]), Point(center_i[0] + 1 * normalized_i[0], center_i[1] + 1 * normalized_i[1]), Scalar(255, 255, 255), 1);
//test if antiparallel
if (abs(normalized_i[0] - normalized_j[0]) > 0.1 || abs(normalized_i[1] - normalized_j[1] > 0.1))
continue;
Vec2f delta;
delta[0] = center_j[0] - center_i[0]; delta[1] = center_j[1] - center_i[1];
double dd = sqrt(pow((center_i[0] - center_j[0]), 2) + pow((center_i[1] - center_j[1]), 2));
//delta[0] = delta[0] / dd;
//delta[1] = delta[1] / dd;
float dotProduct = normalized_i[0] * delta[0] + normalized_i[1] * delta[1];
//test if do product < 0
if (dotProduct < 0)
continue;
float deltaDotDiagonal = delta[0] * normalized_i[0] + delta[1] * normalized_i[1];
menor_d[0] = delta[0] - deltaDotDiagonal * normalized_i[0];
menor_d[1] = delta[1] - deltaDotDiagonal * normalized_i[1];
dd = sqrt(pow((center_j[0] - menor_d[0]), 2) + pow((center_j[1] - menor_d[1]), 2));
if(dd < 25)
[...]
Just to be clear, the actual lengths of the side segments is irrelevant, right? All you care about is whether the semi-infinite lines formed by the side segments of two triples form a square? Or do the actual segments need to intersect?
Assuming the former, a method to check whether two triples form a square is as follows. Let's use the Point3D and Vector3D from the System.Windows.Media.Media3D namespace to define some terminology, since these are decent general-purpose 3d double precision points and vectors that support basic linear algebra methods. These are c# so you can't use them directly but I'd like to be able to refer to some of the basic methods mentioned there.
Here is the basic method to check if two triples intersect:
Define a triple as follows: Center, Side1 and Side2 as three Point3D structures.
For each triple, define the normalized diagonal vector as
NormalizedDiagonal = ((Side1 - Center) + (Side2 - Center));
NormalizedDiagonal.Normalize()
(You might want to cache this for performance.)
Check if the two centers are equal within some linear tolerance you define. If equal, return false -- it's a degenerate case.
Check if the two diagonal vectors are antiparallel within some angular tolerance you define. (I.e. NormalizedDiagonal1 == -NormalizedDiagonal2 with some tolerance.) If not, return false, not a square.
Compute the vector from triple2.Center to triple2.Center: delta = triple2.Center - triple1.Center.
If double deltaDotDiagonal = DotProduct(delta, triple1.NormalizedDiagonal) < 0, return false - the two triples point away from each other.
Finally, compute the distance from the center of triple2 to the (infinite) diagonal line passing through the center triple1. If zero (within your linear tolerance) they form a square.
To compute that distance: distance = (delta - deltaDotDiagonal*triple1.NormalizedDiagonal).Length
Note: deltaDotDiagonal*triple1.NormalizedDiagonal is the projection of the delta vector onto triple1.NormalizedDiagonal, and thus delta - deltaDotDiagonal*triple1.NormalizedDiagonal is the component of delta that is perpendicular to that diagonal. Its length is the distance we seek.
Finally, If your definition of a square requires that the actual side segments intersect, you can add an extra check that the lengths of all the side segments are less than sqrt(2) * delta.Length.
This method checks if two triples form a square. Finding all triples that form squares is, of course, O(N-squared). If this is a problem, you can put them in an array and sort then by angle = Atan2(NormalizedDiagonal.Y, NormalizedDiagonal.X). Having done that, you can find triples that potentially form squares with a given triple by binary-searching the array for triples with angles = +/- π from the angle of the current triple, within your angular tolerance. (When the angle is near π you will need to check both the beginning and end of the array.)
Update
OK, let's see if I can do this with your classes. I don't have definitions for Vec2i and Vec2f so I could get this wrong...
double getLength(Vec2f vector)
{
return sqrt(pow(vector[0], 2) + pow(vector[1], 2));
}
Vec2f scaleVector(Vec2f vec, float scale)
{
Vec2f scaled;
scaled[0] = vec[0] * scale;
scaled[1] = vec[1] * scale;
return scaled;
}
Vec2f subtractVectorsAsFloat(Vec2i first, Vec2i second)
{
// return first - second as float.
Vec2f diff;
diff[0] = first[0] - second[0];
diff[1] = first[1] - second[1];
return diff;
}
Vec2f subtractVectorsAsFloat(Vec2f first, Vec2f second)
{
// return first - second as float.
Vec2f diff;
diff[0] = first[0] - second[0];
diff[1] = first[1] - second[1];
return diff;
}
double dot(Vec2f first, Vec2f second)
{
return first[0] * second[0] + first[1] * second[1];
}
//for all triples
for (size_t i = 0; i < toTry.size() - 1; i++) {
Vec2i center_i = toTry[i].avg;
//NormalizedDiagonal = ((Side1 - Center) + (Side2 - Center));
Vec2i a = toTry[i].p, b = toTry[i].q;
Vec2f normalized_i = normalizedDiagonal(center_i, toTry[i].p, toTry[i].q);
for (size_t j = i + 1; j < toTry.size(); j++) {
Vec2i center_j = toTry[j].avg;
//Se os pontos sao proximos, nao importam
if (areClose(center_i, center_j, 25))
continue;
Vec2f normalized_j = normalizedDiagonal(center_j, toTry[j].p, toTry[j].q);
//test if antiparallel
if (abs(normalized_i[0] - normalized_j[0]) > 0.1 || abs(normalized_i[1] - normalized_j[1] > 0.1))
continue;
// get a vector pointing from center_i to center_j.
Vec2f delta = subtractVectorsAsFloat(center_j, center_i);
//test if do product < 0
float deltaDotDiagonal = dot(delta, normalized_i);
if (deltaDotDiagonal < 0)
continue;
Vec2f deltaProjectedOntoDiagonal = scaleVector(normalized_i, deltaDotDiagonal);
// Subtracting the dot product of delta projected onto normalized_i will leave the component
// of delta which is perpendicular to normalized_i...
Vec2f distanceVec = subtractVectorsAsFloat(deltaProjectedOntoDiagonal, center_j);
// ... the length of which is the distance from center_j
// to the diagonal through center_i.
double distance = getLength(distanceVec);
if(distance < 25) {
}
}
There are two approaches to solving this. One is a very direct approach that involves finding the intersection of two line segments.
You just use the triple coordinates to figure out the midpoint, and the two line segments that protrude from it (trivial). Do this for both triple-sets.
Now calculate the intersection points, if they exist, for all four possible permutations of the extending line segments. From the original answer to a similar question:
You might look at the code I wrote for Computational Geometry in C,
which discusses this question in detail (Chapter 1, Section 5). The
code is available as SegSegInt from the links at that web site.
In a nutshell, I recommend a different approach, using signed area of
triangles. Then comparing appropriate triples of points, one can
distinguish proper from improper intersections, and all degenerate
cases. Once they are distinguished, finding the point of intersection
is easy.
An alternate, image processing approach, would be to render the lines, define one unique color for the lines, and then apply an seed/flood fill algorithm to the first white zone found, applying a new unique color to future zones, until you flood fill an enclosed area that doesn't touch the border of the image.
Good luck!
References
finding the intersection of two line segments in 2d (with potential degeneracies), Accessed 2014-08-18, <https://math.stackexchange.com/questions/276735/finding-the-intersection-of-two-line-segments-in-2d-with-potential-degeneracies>
In a pair of segments, call one "the base segment" and one that is obtained by rotating the base segment by π/2 counterclockwise is "the other segment".
For each triple, compute the angle between the base segment and the X axis. Call this its principal angle.
Sort triples by the principal angle.
Now for each triple with the principal angle of α any potential square-forming mate has the principal angle of α+π (mod 2π). This is easy to find by binary search.
Furthermore, for two candidate triples with vertices a and a' and principal angles α and α+π, the angle of vector aa' should be α+π/4.
Finally, if each of the four segments is at least |aa'|/√2 long, we have a square.

check if four points are on the same plane, only by using distances (verify colinearity)

There is a method called Cayley-Menger determinant in order to find if 3 points are collinear, 4 points are coplanar etc. provided that all the pairwise distances are given.
However, in 2-D, there is a much simple way to determine if 3 points, {A,B,C} are collinear: Triangle inequality!
!(|AB| + |AC| = |BC|) AND !(|AB| + |BC| = |AC|) AND !(|AC| + |BC| = |AB|) IFF A, B, C are not collinear
Is there a similar approach in 3-D?
Yes, there is similar formula for three dimensions.
Solution 1
The four points are in the same plane if and only if one of the areas of the four triangles you can make has an area equal to the sum (or sum/difference, e.g. P1=P2+P3-P4) of the
other three areas.
Heron formula states that the area A of the triangle with vertices a, b, c is
where s = 0.5( a + b + c). Thus you can compute each area from your distances and test if condition holds.
Solution 2
The four points are in the same plane if and only if the volume of the tetrahedron comprised from these four points is 0.
A Heron formula gives a volume of the tetrahedron in terms of its edges, so you can test this based only on distances. Here is a brief derivation of the formula.
A triangular equality can be seen just a special case of Heron formula for computing a content of a n - dimensional simplex from it's n + 1 vertices. The content of a n-dimensional simplex is 1/n! times the “heights” of the vertices (taken in any linear sequence) above the sub-space containing the previous vertices. Imagine how you multiply a basis of a triangle by it's height ( and with 1/2) to get an area of triangle, then multiply this area by height (and 1/3) of a tetrahedron to get it's volume, and so on.
Note that any vertex of a simplex in k-dimensional space can be regarded as the apex of a “pyramid” on a (k-1)-dimensional base defined by the other vertices. Letting Vk-1 denote the content of the base, and h the perpendicular distance of the apex from the sub-space containing the base, the content Vk of the pyramid is given by
Therefore, applying this formula to the vertices (in any order) recursively, beginning with k = n, we have
where h1 is simply the distance between the first two vertices, h2 is the height of the third vertex above the line containing those two vertices, h3 is the height of the fourth vertex above the plane containing the first three vertices, and so on. Thus the content of a n-dimensional simplex is 1/n! times the “heights” of the vertices (taken in any linear sequence) above the sub-space containing the previous vertices.
In general we can apply an n-dimensional rotation that places n-1 of the vertices into a sub-space orthogonal to one of the axes.
This leads us to Cayley-Menger determinant, for the area of a triangle in terms of the edge lengths
which gives a Heron formula for the area of a triangle in terms of the edge lengths
A Heron formula for the volume of a tetrahedron
If U, V, W, u, v, w are lengths of edges of the tetrahedron (first three form a triangle; u opposite to U and so on), then
where:
If one of the points is located on a plane defined by three other points, Volume is 0, so one of the factors in numerator is 0 and this is condition you can test.
Heron's Formula and Brahmagupta's Generalization
Tetrahedron
I have written the function heron_3d in C++. This function returns boolean value indicating if 4 points belong to the same plane or not, using the approach described in Solution 1: comparing each face of the tetrahedron against the sum of 3 other faces using the Heron formula to calculate each area.
#include <cmath>
/**
* #return area of triangle based on Heron formula
*/
double areaOfTriangle( double edge1, double edge2, double edge3) {
double s = 0.5 * ( edge1 + edge2 + edge3);
return std::sqrt( s * ( s - edge1) * ( s - edge2) * ( s - edge3));
}
/**
* U, V, W, u, v, w are lengths of edges of the tetrahedron, as in
* http://en.wikipedia.org/wiki/Tetrahedron
* #param U basis edge 1
* #param V basis edge 2
* #param W basis edge 3
* #param u opposite to U
* #param v opposite to V
* #param w opposite to W
* #return
*/
bool heron_3d( double U, double V, double W,
double u, double v, double w) {
double areas[] = { areaOfTriangle( U, V, W),
areaOfTriangle( U, v, w),
areaOfTriangle( V, u, w),
areaOfTriangle( W, u, v)};
for ( int i = 0; i < 4; ++i) {
double area = areas[ i];
double sum = 0;
for ( int j = 1; j < 4; ++j) {
sum += areas[ (i + j) % 4];
}
if ( area == sum) return true;
}
return false;
}
usage:
int main(int argc, char** argv) {
bool b0 = heron_3d( 3, 3, 0, 5, 5, 4); // true
bool b1 = heron_3d( 3, 3.1, 0.1, 5.1, 5, 4); // false
bool b2 = heron_3d( 3, 5, 2, std::sqrt( 16 + 25), 5, 4); // true
return 0;
}