Efficient data structure for storing 3d points - c++

I'm looking for efficient data structures for storing 3d points (x,y,z). The effect of storing in at the points in a data structure should generate a more memory efficient structure and a faster search for a specific set of coordinates. The 3d points is mapping to a specific ID so it should be able to keep track of each set of coordinates I'm looking for any implementation which is available.
x, y, z gives the cartesian coordinates of each node.
id x y z
1 14.566132 34.873772 7.857000
2 16.022520 33.760513 7.047000
3 17.542000 32.604973 6.885001
4 19.163984 32.022469 5.913000
5 20.448090 30.822802 4.860000
6 21.897903 28.881084 3.402000
7 18.461960 30.289471 8.586000
8 19.420759 28.730757 9.558000
The number of coordinates will be huge maybe around 1 000 000.
Thanks in advance!

a more memory efficient structure
More memory efficient than what? A list? You'd need compression for that.
a faster search for a specific set of coordinates
If you want to find the k closest points from a set of coordinates, a ball tree is a good option.
If you want to search a volume, a quad tree (or octree) works better.

I'm hearing that the coords you're looking up will be exact matches for those in the structure already. Depending perhaps on your spatial distribution, you could create a hash function that takes the coord and attempts to produce something fairly unique, then just use a standard hash map. Most modern languages provide some kind of hash map implementation, so all you'd need to do is provide those appropriate hash values for your coords.
If you need to look up coords near the test coord, then a balltree or octree or something, but it doesn't sound like that's what you need.

You can use a struct:
struct coordinate
{
double x;
double y;
double z;
} points[1000000];

Related

Histogram Binning of Gradient Vectors

I am working on a project that has a small component requiring the comparison of distributions over image gradients. Assume I have computed the image gradients in the x and y directions using a Sobel filter and have for each pixel a 2-vector. Obviously getting the magnitude and direction is reasonably trivial and is as follows:
However, what is not clear to me is how to bin these two components in to a two dimensional histogram for an arbitrary number of bins.
I had considered something along these lines(written in browser):
//Assuming normalised magnitudes.
//Histogram dimensions are bins * bins.
int getHistIdx(float mag, float dir, int bins) {
const int magInt = reinterpret_cast<int>(mag);
const int dirInt = reinterpret_cast<int>(dir);
const int magMod = reinterpret_cast<int>(static_cast<float>(1.0));
const int dirMod = reinterpret_cast<int>(static_cast<float>(TWO_PI));
const int idxMag = (magInt % magMod) & bins
const int idxDir = (dirInt % dirMod) & bins;
return idxMag * bins + idxDir;
}
However, I suspect that the mod operation will introduce a lot of incorrect overlap, i.e. completely different gradients getting placed in to the same bin.
Any insight in to this problem would be very much appreciated.
I would like to avoid using any off the shelf libraries as I want to keep this project as dependency light as possible. Also I intend to implement this in CUDA.
This is more of a what is an histogram question? rather than one of your tags. Two things:
In a 2D plain two directions equal by modulation of 2pi are in fact the same - so it makes sense to modulate.
I see no practical or logical reason of modulating the norms.
Next, you say you want a "two dimensional histogram", but return a single number. A 2D histogram, and what would make sense in your context, is a 3D plot - the plane is theta/R, 2 indexed, while the 3D axis is the "count".
So first suggestion, return
return Pair<int,int>(idxMag,idxDir);
Then you can make a 2D histogram, or 2 2D histograms.
Regarding the "number of bins"
this is use case dependent. You need to define the number of bins you want (maybe different for theta and R). Maybe just some constant 10 bins? Maybe it should depend on the amount of vectors? In any case, you need a function that receives either the number of vectors, or the total set of vectors, and returns the number of bins for each axis. This could be a constant (10 bins) initially, and you can play with it. Once you decide on the number of bins:
Determine the bins
For a bounded case such as 0<theta<2 pi, this is easy. Divide the interval equally into the number of bins, assuming a flat distribution. Your modulation actually handles this well - if you would have actually modulated by 2*pi, which you didn't. You would still need to determine the bin bounds though.
For R this gets trickier, as this is unbounded. Two options here, but both rely on the same tactic - choose a maximal bin. Either arbitrarily (Say R=10), so any vector longer than that is placed in the "longer than max" bin. The rest is divided equally (for example, though you could choose other distributions). Another option is for the longest vector to determine the edge of the maximal bin.
Getting the index
Once you have the bins, you need to search the magnitude/direction of the current vector in your bins. If bins are pairs representing min/max of bin (and maybe an index), say in a linked list, then it would be something like (for mag for example):
bin = histogram.first;
while ( mag > bin.min ) bin = bin.next;
magIdx = bin.index;
If the bin does not hold the index you can just use a counter and increase it in the while. Also, for the magnitude the final bin should hold "infinity" or some large number as a limit. Note this has nothing to do with modulation, though that would work for your direction - as you have coded. I don't see how this makes sense for the norm.
Bottom line though, you have to think a bit about what you want. In any case all the "objects" here are trivial enough to write yourself, or even use small arrays.
I think you should arrange your bins in a square array, and then bin by vx and vy independently.
If your gradients are reasonably even you just need to scan the data first to accumulate the min and max in x and y, and then split the gradients evenly.
If the gradients are very unevenly distributed, you might want to sort the (eg) vx first and arrange that the boundaries between each bin exactly evenly divides the values.
An intermediate solution might be to obtain the min and max ignoring the (eg) 10% most extreme values.

2 dimension geometric layout of objects

so I have this class:
class Piece{
int width;
int height;
}
my problem is that I need to make a container type class that somehow can save the layout of multiple and different size "Piece" objects (note that Piece can only represent rectangles).
Example:
________
| t |
| t jj |
| t jj |
_________
My goal with this is to be able to "fill" a empty rectangle with multiple "Piece" objects but with the ability to know if the "Piece" can fit in.
I'm developing this in C++. I started with the most logic solution I think that was to use a "matrix" of vectors (vector< vector< Piece * > > mat) but that doesn't work because as I said "Piece" objects can have different sizes.
I hope you can give some hints on how to get a solution for this or if it exists some lib or open-sorce project links.
Thank you.
EDIT
I forgot this:I know beforehand the dimensions of the container and the insertion (after validation) is sequential (Piece after Piece) with no predefined orientation.
You can use Piece p[width][height] and use memset to make all zeros or use a std::vector if you don't know the size of the grid beforehand. Then you can check(while adding a new Piece at some position (x, y)) if on any of its subsquares there is some other Piece already.
Edit: You can use a matrix char mem[sqrt(width)][sqrt(height)]; and a one vector of Pieces. Then using the matrix if there will be a probable collision and if not, just add the Piece. Else you iterate through all the existing ones and check for a collision.
If you want to make the procedure faster( this one is reasonable only with small grids ), then you will need to use more "advanced" data structures. What I suggest you is to learn about 2D BIT(or fenwick) trees(there are a lot of resources on google). You can also use 2D segment trees. Then when adding a new Piece at position (x, y) check the sum of all squares in it(e.g from (x, y) to (x + width, y + height)). If that sum is zero then the new Piece won't collide with previous ones and you then update the grid as you add 1 to all squares in your Piece(I mean to the corresponding values in the 2D segment tree). Else if the sum is greater than zero it means that there will be some overlap and you must then discard the new Piece.

Find coordinates in a vector c++

I'm creating a game in Qt in c++, and I store every coordinate of specific size into a vector like :
std::vector<std::unique_ptr<Tile>> all_tiles = createWorld(bgTile);
for(auto & tile : all_tiles) {
tiles.push_back(std::move(tile));
}
Each level also has some healthpacks which are stored in a vector aswell.
std::vector<std::unique_ptr<Enemy>> all_enemies = getEnemies(nrOfEnemies);
for(auto &healthPackUniquePtr : all_healthpacks) {
std::shared_ptr<Tile> healthPackPtr{std::move(healthPackUniquePtr)};
int x = healthPackPtr->getXPos();
int y = healthPackPtr->getYPos();
int newYpos=checkOverlapPos(healthPackPtr->getXPos(),healthPackPtr->getYPos());
newYpos = checkOverlapEnemy(healthPackPtr->getXPos(),newYpos);
auto healthPack = std::make_shared<HealthPack>(healthPackPtr->getXPos(), newYpos, healthPackPtr->getValue());
healthPacks.push_back(healthPack);
}
But know I'm searching for the fastest way to check if my player position is at an healthpack position. So I have to search on 2 values in a vector : x and y position. Anyone a suggestion how to do this?
Your 'real' question:
I have to search on 2 values in a vector : x and y position. Anyone a
suggestion how to do this?"
Is a classic XY question, so I'm ignoring it!
I'm searching for the fastest way to check if my player position is at
an healthpack position.
Now we're talking. The approach you are using now won't scale well as the number of items increase, and you'll need to do something similar for every pair of objects you are interested in. Not good.
Thankfully this problem has been solved (and improved upon) for decades, you need to use a spacial partitioning scheme such as BSP, BVH, quadtree/octree, etc. The beauty of the these schemes is that a single data structure can hold the entire world in it, making arbitrary item intersection queries trivial (and fast).
You can implement a callback system. Then a player moves a tile, fire a callback to that tile which the player is on. Tiles should know its state and could add health to a player or do nothing if there is nothing on that tile. Using this technique, you don`t need searching at all.
If all_leathpacks has less than ~50 elements I wouldn't bother to improve. Simple loop is going to be sufficiently fast.
Otherwise you can split the vector into sectors and check only for the elements in the same sector as your player (and maybe a few around if it's close to the edge).
If you need something that's better for the memory you and use a KD-tree to index the healtpacks and search for them fast (O(logN) time).

parsing the wavefront obj file format

I'd like to import obj models into my opengl program. I have a class / data format that I use to pass attribute data into shaders:
class CustomVertex : public IVtxFmt
{
public:
float m_Position[3]; // x, y, z offset 0, size = 3*sizeof(float)
float m_Normal[3]; // nx, ny, nz; offset 3
float m_TexCoords[2]; // u, v offset 6
float m_Colour[4]; // r, g, b, a offset 8
float m_Tangent[3]; // r, g, b offset 12
float m_Bitangent[3]; // r, g, b offset 15
};
So I'm working with a model of a log cabin I downloaded from the Internet.
The log cabin has several vertices, normals, and texture coord definitions, followed by a list of face definitions.
So my first instinct was to parse the obj file and end up with
vector<vertex>
vector<Normal>
vector<TexCoord>
That's not straightforward to translate into my CustomVertex format, since there might be 210 vertices, 100 tex coords and 80 normals defined in the file.
After a list of ~390 faces in this format:
f 83/42/1 67/46/1 210/42/1
I encounter the following in the file:
#
# object tile00
#
followed by more vertex definitions.
So from this, I have inferred that a model might consist of several sub objects, each defined by a number of faces; each face defined by 3 x vertex / normal / texcoord index values.
So in order to arrive with a vector of CustomVertex, I'm thinking that I need to do the following:
create and populate:
vector <vertex>
vector <normal>
vector <texcoord>
vector <indices>
I need to create a CustomVertex for each unique v/vn/vt triple in the face definitions.
So I thought about creating a map:
std::vector<CustomVertex> and
std::map< nHashId, CustomVertex_index >
So my idea is that for each v/vn/vt I encounter, I create a hash of this string e.g. nHashId = hash("80/50/1")* and search the map for the hash. If none exists, I create a CustomVertex and add it to the vector, then I add the newly created hash and the CustomVertex_index into the map.
*: By creating a hash of the v/vn/vt string, I'm creating a unique numeric value that corresponds to that string, which I'm hoping is faster to search/compare in the map than the equivalent text.
If I come across a match to the hash, I consider that the customvertex already exists and instead of creating a new CustomVertex, I just add the CustomVertex_index entry to the indices vector and move on.
Since this seems like a computationally expensive exercise, I guess I'll be dumping my CustomVertex arrays (and corresponding indices arrays) to disk for later retrieval, rather than parse the obj file every time.
Before I ask my questions, may I point out that due to time constraints and not wanting to have to redesign my Vbo class (a non-trivial task), I'm stuck with the CustomVertex format - I know its possible to supply attributes in separate arrays to my shaders, but I had read that interleaving the data like I have with CustomVertex can enhance performance.
So to my questions:
1. Does my method seem sound or crazy? If crazy, please point out where I'm going wrong.
Can you spot any potential issues?
Has anyone done this before and can recommend a simpler way to achieve what I'm trying to?
Can you spot any potential issues?
You mean besides hash collisions? Because I don't see the part of your algorithm that handles that.
Has anyone done this before and can recommend a simpler way to achieve what I'm trying to?
There's a much simpler way: just compare the indices and not use hashes.
Instead of creating a string hash of "v/vn/vt", the idea is to only hash v as an integer. After that you get a bucket that contains all the "v/vn/vt" combinations that share the same v index.
If a hash collision happens(same v encountered), you would compare the collided combination with those in the bucket to see if it is really duplicated. If not, remember to add the collided combination to the bucket.

Physically-based fracture simulation with opengl/c++

I am trying to implement the ideas in this paper for modeling fracture:
http://graphics.berkeley.edu/papers/Obrien-GMA-1999-08/index.html
I am stuck at a point (essentially page 4...) and would really appreciate any help. The part I am stuck on involves the deformation of tetrahedron (using FEM).
I have a single tetrahedron defined by four nodes (each node has a x, y, z position) in which I calculate the following matrices from:
u: each column is a vector containing material coordinates (x, y, z,
1) for each node (so total 4 columns), a 4x4 matrix
B: inverse(u), he calls this the basis matrix, a 4x4 matrix
P: each column is a vector containing real world coordinates (x, y,
z) for each node, I set P is initially equal to u since the object is
not deformed at the rest state, a 3x4 matrix
V: give some initial velocities for (x, y, z) in each node, so a 3x4
matrix
delta: basically an identity matrix, {{1, 0, 0}, {0, 1, 0}, {0, 0,
1}, {0, 0, 0}}
I get x(u) = P*B*u and v(u) = V*B*u, but not sure where to use these...
Also, I get dx = P*B*delta and dv = V*B*delta
I then get strain by Green's strain tensor, epsilon = 1/2(dx+transpose(dx)) - Identity_3x3
And then stress, sigma = lambda*trace(epsilon)*Identity_3x3 + 2*mu*epsilon
I get the elastic force by equation (24) on page 4 of the paper. It's just a big summation.
I then using explicit integration to update real world coordinates P. The idea is that the velocity update involves the force on the node of the tetrahedron and therefore affects the real-world coordinate position, making the object deform.
The problem, however, is that the force is incredibly small...something x 10^-19, etc. So, c++ usually rounds to 0. I've stepped through the calculations and can't figure out why.
I know I'm missing something here, just can't figure out what. What update am I not doing correctly?
A common reason why the force is small is that your Young's modulus (lambda) is too small. If you are using a scale of meters, a macro scale object might have 10^5 young's modlus and a .3 to .4 Poisson's ratio.
It sounds like what might be happening is that your tet is still in the rest configuration. In the presence of no deformation, the strain will be zero and so in-turn the stress and force will also be about zero. You can perturb the vertices in various ways and make sure your strain (epsilon) is being computed correctly. One simple test is to scale by 2 about the centroid which should give you a positive strain. If you scale by .5 about the centroid you will get a negative strain. If you translate the vertices uniformly you will get no change in strain (a common FEM invariant). If you rotate them you probably will get a change, but a co-rotational constitutive model wouldn't.
Note you might think that gravity would cause deformation, but unless one of the vertices is constrained, the uniform force on all vertices will cause a uniform translation which will not change the strain from being zero.
You definitely should not need to use arbitrary precision arithmetic for the examples in the paper. In fact, floats typically are sufficient for these types of simulation.
I might be mistaken, but c++ doubles only go to 15 decimal places, (at least that's what my std::numeric_limits says). So you're way out of precision.
So you might end up needing a library for arbitrary precision arithmetics, e.g., http://gmplib.org/