How to compute center of an arbitrary shape in 3D? [closed] - c++

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I want to know the accurate method to find the center of an arbitrary shape in 3D.
In the figure, I have explained 3 cases.
In first case how can we compute the center of arbitrary points ? One idea is summation of all points divided by total number of points. Is it the only method and Is it accurate ?
2nd is how to compute the approximate center of irregular arbitrary shape in 3D? Is this the same case of 1 ?
How can we compute the center line of the bended/curved tube that composed of arbitrary vertices ? For this problem we have to solve first two cases I think so ?

The solution really depends on what you are actually looking for.
If you seek the average position of all points in a shape, then averaging them does indeed give you that. But it can be far off from the point which you'd intuitively say is "in the middle". For example, consider a box where one side has twice as many vertices as the opposite side. The average position would be on the half of that side, not in the middle of the box.
More likely, I'd say you are looking for the point defined by calculating the max and min bounds in each dimension and then averaging the two. Because you tagged this with C++, here's some example code:
// Define max and min
double max[DIMENSIONALITY];
double min[DIMENSIONALITY];
// Init max and min to max and min acceptable values here. (see numeric_limits)
// Find max and min bounds
for(size_t v_i = 0; v_i < num_vertices; ++v_i)
{
for(int dim = 0; dim < DIMENSIONALITY; ++dim)
{
if(shape[v_i][dim] < min[dim]) min[dim] = shape[v_i][dim];
if(shape[v_i][dim] > max[dim]) max[dim] = shape[v_i][dim];
}
}
// Calculate middle
double middle[DIMENSIONALITY];
for(int dim = 0; dim < DIMENSIONALITY; ++dim)
middle[dim] = 0.5 * (max[dim] + min[dim]);
For either solution, the dimensionality of the problem doesn't matter.
Edit:
As pointed out in the comment below, this may result in a middle point which lies outside of the shape itself. If you need a point which lies inside the shape, an alternative approach must be used. A simple solution could be to use ray-marching across each axis.

Related

Spline options for interpolating between control points on a population curve?

I'm looking to model population curves using an interpolative spline between 7 control points. My problem is that I can't find any grokkable/digestable coding/math resource that compares the pros and cons of various splines in layman's terms.
First, here's a simplified illustration of the population curve in my code:
struct CurvePoint {
public:
short height; // the point's height along a population curve, measured as age in years (can be negative, representing a building trend whose peak/valley will happen in the future)
double width; // the (nonnegative) width of the population curve at this point, measured as number of people **born within a single year**
// Each CurvePoint represents one "bar" of a population pyramid that's one year tall.
};
class PopulationCurve {
public:
std::array<CurvePoint, 7> control_points; // assumes that control_points[i].height < control_points[i + 1].height and that control_points[i].width >= 0
// control_points[0] is the young end of the curve (typically a nonpositive number; see above)
// control_points[6] is the old end of the curve (typically representing the longevity of the population; if so, control_points[6].width will be 0 since no one is left alive at that point)
std::vector<CurvePoint> constructCurve() {
std::vector<CurvePoint> curve;
short youngest_age = control_points[0].height;
short oldest_age = control_points[6].height;
for (auto a = youngest_age; a <= oldest_age; ++a) {
CurvePoint p;
p.height = a;
// p.width = ??? (the interpolated width at age a)
curve.push_back(p);
}
return curve;
}
void deconstructCurve(std::vector<CurvePoint> curve) {
std::array<CurvePoint, 7> sampled_control_points;
// ??? (turn point samples from the input curve into control points as appropriate)
control_points = sampled_control_points;
}
};
The hardcoding of 7 control points is intentional. I'm implementing a choice between two compression schemes: virtually lossless compression of 7 control points in 44 bytes, and lossy compression of 7 control points in 20 bytes (my application is currently more memory/disk-limited than CPU-limited). I don't believe those compression schemes are relevant to the question, but let me know if I need to show their code, especially if there's a good reason I should be considering <7 or >7 control points.
Here are the criteria I'm looking for in a spline, in descending order of importance:
Interpolation between all control points. This is by far the most important criterion; otherwise, I would've used a Bézier curve or b-spline.
Interpolation between the first and last control point only. If all points aren't interpolated between, then only the first and last can be (i.e. what a Bézier curve or b-spline would've got me).
Fast constructability + deconstructability. There's a near-1:1 correlation between constructCurve() and deconstructCurve(); almost every call to construct will eventually be followed up by a call to deconstruct, so I'm only interested in the combined performance and the not the performance of either one individually. That being said, while I'm very interested in memory/disk optimization right now, I am not going to prematurely optimize speed, so this is a consideration only.
Reasonably accurate deconstructability.
Lossless deconstructability if no changes to the curve are made. i.e. If deconstructCurve(constructCurve()); is called, control_points will remain the same.
Prettiness =) (since linear interpolation between control points is the best match for the rest of the criteria...)
I didn't post this question on math since it's not entirely language-agnostic and contains C++ code. I didn't post it on gamedev since it's a question of implementation and not design.

Array Best Match [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
You have been called upon to write a Match-Making program for a marriage beaureau. The beaureau’s questionnaire has 8 statements, and the applicant indicates her or his degree of agreement on a scale of 1 to 5. The response of the applicant is entered through the keyboard. Each response contains the applicant’s code number, sex (F or M), & response to the questionnaire (8 integers).
You may assume that there are no more than 50 applicants. Your program should match each person with 3 most compatible person of opposite sex and should print the code no. of applicant along with code no. of prospective applicants.
i want to implement this through c++. Is there any matching algorithm for this ?. or there is some simple approach. It would be nice for me, if you write the whole function.
and sorry, if the question is very simple bcs i'm a learner.
Based on our comments above I'll post some comments to get you started. But remember the best thing is to try something on your own and then get help afterwards...
int questionnaire_answers[50][8]; // 2D array holding answers
int sex[50]; // 1D array holding sex of those who answered
int i, j;
int index = 0;
int best = 999999;
int distance;
// We look for the best match for the first person
for (i = 1; i < 50; i++)
{
if (sex[0] != sex[i])
{
// Calculate the distance from index 0 to index i
// See note below
distance = 0;
for (j=0 ; j < 8; j++)
{
distance = distance + abs(questionnaire_answers[0][j]-questionnaire_answers[i][j]);
}
}
else
{
distance = 999999;
}
if (distance < best)
{
best = distance;
index = i;
}
}
// Now index holds the index of the best match
I'll leave it to you to figure out how to find the second and third best match :)
IMPORTANT:
I have used a simple linear distance calculation. In the real world you will probably do better with something more complicated. The world of math has several good option, e.g. least/minimum-mean-square
Have fun!
You can use Cosine Correlation. First normalize the 50X8 matrix such that each column has mean=0 and standard deviation=1. Now for each record(row), calculate the cosine correlation with every other record. The record giving maximum cosine correlation will be a match for this record.

Programming task: sum of submatrices

I have a problem with resolving my programming task. In fact, I resolved it, but my code don't pass some of test (time overseed).
The text of task is following:
We have a matrix that have N*N size. The first line of input contain two int: N and K. K is a number of lines that define submatrices.
Next N lines contains elements of main matrix (whitespace as delimeter of elements, \n as delimeter of lines). After that we have K lines that defines submatrices.
Definition is following:
y_l x_l y_r x_r where (x_l, y_l) is column and line of left top corner of submatrix in main matrix and (x_r, y_r) is column and line of right bottom corner of submatrix. We have to calculate sum of all submatrices and divide it into equivalence classes (submatrices are belong to one class if that sums are equal).
Output of program should be following:
three int (divided by whitespace) where first one is number of equivalence classes, second one is number of equivalence classes that have maximum elements and third one is average of sum of all submatrices.
From tests I pick up fact that problem is in calculation of sum:
while(true){
for(int i = x_l; i <= x_r; i++)
sum += *diff++;
if(diff == d_end) break;
d_start = d_start + size;
diff = d_start;
}
But I have no idea how to optimize it. May be someone can give me algorithm or some ideas how to calculate those sums faster.
Thanks.
UPDATE: Answer
After few days of searching I finally got working version of my program. Thanks to Yakk, which gave some very usefull advices.
There's final code.
Very usefull link that I strangely couldn't find before unless I ask a very specific question (bases on information that Yakk gave me) link.
I hope that my code might be helpfull for somebody in future.
Build a sum matrix.
At location (a,b) in the sum matrix, the sum of all elements left&above (including at (a,b)) of (a,b) in the original matrix is summed.
Now calculating the sum of a submatrix is 4 lookups, one add and two subtracts. Draw a 4x4 matrix and express the bottom right 2x2 using such sums to see how.
If you double stored data you can halve lookups. But I would not bother.
Building the sum matrix requires only a modest amoumt of work if you do it carefully.

Efficient data structure for sparse data lookup

Situation:
Given some points with coordinate (x, y)
Range 0 < x < 100,000,000 and 0 < y <100,000,000
I have to find smallest square which contains at least N no of points on its edge and inside it.
I used vector to store coordinates and searched all squares with side length minLength upto side length maxLength (Appling Brute Force in relevant space)
struct Point
{
int x;
int y;
};
vector<Point> P;
int minLength = sqrt(N) - 1;
int maxLength = 0;
// bigx= largest x coordinate of any point
// bigy= largest y coordinate of any point
// smallx= smallest x coordinate of any point
// smally= smallest y coordinate of any point
(bigx - smallx) < (bigy - smally) ? maxLength = (bigx - smallx) : maxLength = (bigy - smally);
For each square I looked up, traversed through complete vector to see if at least N points are on its edge and inside it.
This was quite time inefficient.
Q1. What data structure should I use to improve time efficiency without changing Algorithm I used?
Q2. Efficient Algorithm for this problem?
There are points on 2 opposite edges - if not, you could shrink the square by 1 and still contain the same number of points. That means the possible coordinates of the edges are limited to those of the input points. The input points are probably not on the corners, though. (For a minimum rectangle, there would be points on all 4 edges as you can shrink one dimension without altering the other)
The next thing to realize is that each point divides the plane in 4 quadrants, and each quadrant contains a number of points. (These can add up to more than the total number of points as the quadrants have one pixel overlap). Lets say that NW(p) is the number of points to the northwest of point p, i.e. those that have x>=px and y>=py. Then the number of points in a square is NW(bottomleft) + NW(topright) - NW(bottomright) - NW(topleft).
It's fairly easy to calculate NW(p) for all input points. Sort them by x and for equal x by y. The most northwestern point has NW(p)==0. The next point can have NW(p)==1 if it's to the southeast of the first point, else it has NW(p)==0. It's also useful to keep track of SW(p) in this stage, as you're working through the points from west to east and they're therefore not sorted north to south. Having calculated NW(p), you can determine the number of points in a square S in O(1)
Recall that the square size is restricted by by the need to have points on opposite edges. Assume the points are on the left (western) and right edge - you still have the points sorted by x order. Start by assuming the left edge is at your leftmost x coordinate, and see what the right edge must be to contain N points. Now shift the left edge to the next x coordinate and find a new right edge (and thus a new square). Do this until the right edge of the square is the rightmost point.
Its also possible that the square is constrained in y direction. Just sort the points in y direction and repeat, then choose the smallest square between the two outcomes.
Since you're running linearly through the points in x and y direction, that part is just O(N) and the dominant factor is the O(N log N) sort.
Look at http://en.wikipedia.org/wiki/Space_partitioning for algorithms that use the Divide-and-Conquer technique to solve this. This is definitely solvable in Polynomial time.
Another variant algorithms can be on the following lines.
Generate a vornoi-diagram on the points to get neighbour information. [ O(nlog(n)) ]
Now use Dynamic Programming, the DP will be similar to the problem of finding the maximum subarray in a 2D array. Here instead of the sum of numbers, you will keep count of points before it.
2.a Essentially a recursion similar to this will hold. [ O(n) ]
Number of elements in square from (0,0) to (x,y ) = (Number of elems
from square (0,0 to ((x-1),y))+ (Number of elems in square 0,0 - ( x, y-1))
- (Number of elems in (0,0)-((x-1),(y-1)))
Your recurrence will have to change for all the points on its neighbourhood and to the left and above, instead of just the points above and left as above.
Once the DP is ready, you can query the points in a sqare in O(1).
Another O(n^2) loop to find from all possible combinations and find the least square.
You can even greedily start from the smallest squares first, that way you can end your search as soon as you find a suitable square..
The rtree allows spatial searching, but doesn't have stl implementation, although sqlite would allow binding. This can answer "get all points within range", "k nearest neighbours"
Finding a region which has the most dense data, is a problem similar to clustering.
Iterating over the points and finding the N nearest entries to each point. Then generate the smallest circle - centre would be the Max(x) - min(x), Max(y) - min(y). A square can be formed which contains all the neighbours, and would be somewhere between 2r length and 2sqrt(r) length sides compared to circle.
Time taken O(x) to build structure
O(X N log(X)) to search for smallest cluster
Note: There are a bunch of answers for your second question (which will probably reap bigger benefits), but I'm only referring to your first one, i.e. what data to use without changing the algorithm.
There, I think that your choice using a vector is already pretty good, because in general vectors offer the best payload/overhead ratio and also the fastest iteration. In order to find out specific bottlenecks, use a profiler, otherwise you are only guessing. With large vectors, there are a few things to avoid though:
Overallocation, this wastes space.
Underallocation, this causes copying when the vector is grown to the necessary size.
Copying.

Algorithms for 3D Mazes [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
Are there algorithms to produce 3 dimensional mazes? Essentially the same as a 2D maze but the Z depth axis can be traversed? The idea is still the same though, to get from Start to End. Could backtracking still be used?
Which algorithm should I use to generate a 3D maze?
See here. I mean that you can go into the cube too, not just iterate the faces of it.
I made 2d mazes a few years ago using Kruskal's Algorithm here. There should be no reason this couldn't work with the 3d case you described. Basically you'd consider a cell a cube, and have a large array that has (for every cells), 6 walls in the +/- x, y, and z directions. The algorithm initially starts with all walls everywhere and randomly makes walls disappear until every cell in the maze is connected.
I have the code for generating a 2D maze in, of all things, RPGLE (something I did as a self-exercise while learning the language). Because of the way I wrote it, about the only changes necessary for the general alogrithm would be to add the Z dimension as an additional dimension...
The entire thing is 20 pages long (although this includes input/output), so here's some code. You should be able to translate this into whatever language you need: I translated it from spaghetti-code BASIC (gotos were way overused here, yeah. But it was a fun exercise).
//set out maximum maze size
maximumMazeSquareCounter = mazeHorizontalSize * mazeVerticalSize + 1;
// generate a starting horizontal positiongetRandomNumber(seed : randomNumber);
currentHorizontalPosition = %inth(randomNumber * (mazeHorizontalSize - 1)) + 1;
currentVerticalPosition = 1;
mazeSquareCounter = 1;
// generate the top row of the maze (with entrance)
mazeTopRow = generateEntrance(currentHorizontalPosition);
//write to the printer file
writeMazeDataLine(mazeTopRow);
mazeSquareCounter += 1;
//set the first position in the maze(the entry square
setPathPoint(currentHorizontalPosition : currentVerticalPosition);
//do until we've reached every square in the maze
dou mazeSquareCounter >= maximumMazeSquareCounter;
//get the next available random direction
mazeDirection = getNextRandomDirection(getNextAvailableDirection(currentHorizontalPosition : currentVerticalPosition));
//select what to do by the returned results
select;
//when FALSE is returned - when the maze is trapped
when mazeDirection = FALSE;
//if not at the horizontal end of the maze
if currentHorizontalPosition <> mazeHorizontalSize;
//add one to the position
currentHorizontalPosition += 1;
//else if not at the vertical end of the maze
elseif currentVerticalPosition <> mazeVerticalSize;
//reset the horizontal position
currentHorizontalPosition = 1;
//increment the vertical position
currentVerticalPosition += 1;
//otherwise
else;
//reset both positions
currentHorizontalPosition = 1;
currentVerticalPosition = 1;
endif;
//when 'N' is returned - going up (other directions removed)
when mazeDirection = GOING_NORTH;
//set the point above current as visited
setPathPoint(currentHorizontalPosition : currentVerticalPosition - 1);
//set the wall point to allow passage
setWallDirection(currentHorizontalPosition : currentVerticalPosition : GOING_NORTH);
//change the position variable to reflect change
currentVerticalPosition -= 1;
//increment square counter
mazeSquareCounter += 1;
endsl;
enddo;
//generate a random exit
// get a random number
getRandomNumber(seed : randomNumber);
// set to the horzontal position
currentHorizontalPosition = %inth(randomNumber * (mazeHorizontalSize - 1)) + 1;
//set the vertical position
currentVerticalPosition = mazeVerticalSize;
//set wall to allow for exit
setWallDirection(currentHorizontalPosition : currentVerticalPosition : GOING_SOUTH);
The entire thing is backed by two two-dimensional arrays (well, the RPG equivalent): One for the walls that occupy the 'square', and the other for whether or not that square has been visited. The maze is created after every square has been visited. Garuanteed one-path only, worm-turns maze.
To make this three-dimensional, make it use three-dimensional arrays, and add the necessary dimension index.
I designed an algorithm some time ago for 2D mazes on a square grid, there is no reason why this shouldn't also work for a 3D maze on a cubic grid.
Start with a 3D grid initially fully populated with wall cells.
...
Start an agent at an edge of the grid, the agent travels in a straight line in the X, Y, Z, -X, -Y or -Z direction clearing wall as she travels.
Action 'N' has a small chance of occurring each step.
Action 'M' occurs when the cell directly in front of the agent is wall and the cell in front of that is empty.
'N' is a random choice of:
removing that agent
turning left or right 90 degrees
and creating an agent on the same square turned 90 degrees left, right or both (two agents).
'M' is a random choice of:
removing that agent
removing the wall in front of that agent and then removing that agent
and doing nothing, carrying on
turning left or right 90 degrees.
and creating an agent on the same square turned 90 degrees left, right or both (two agents).
The mazes are distinctive, and their character is highly flexible by adjusting the trigger for 'M' (to do with valid junctions) and by also adjusting the chances of 1 to 8 occurring. You may want to remove an action or two, or introduce your own actions, for example one to make a small clearing or sidestep one step.
The trigger for 'N' can also be another sort of randomness, for example the example below can be used to create fairly branchy mazes that still have some long straight parts.
float n = 1;
while (random_0_to_1 > 0.15)
{
n *= 1.2;
}
return (int)n;
Some small adjustments will be needed from my simple description, for example trigger for action 'M' will need to check the cells adjacent to the cells it checks as well depending on what sort of junctions are desirable.
Either 5 or 6 are needed for the maze to contain cycles and at least one alternative 'M' action to 5 and 6 is required for the maze to contain dead ends.
Some choices of chances/actions and 'M' triggers will tend to make mazes that don't work, for example are unsolvable or full of empty or wall cells, but many will produce consistently nice results.