I want to generate random discrete valued vectors in a space. The simple instance was a follows; a cube. In this instance each coefficient of the vector had to be in between two values, so that it is inside the multi-dimensional cube. This cube can be described by it's two corner points (stored in points[0] and points[1]). I programmed this in C++(11) as follows:
random_device rd;
mt19937 eng(rd());
vector<uniform_int_distribution<>> distr;
for(int i = 0; i< points[0].size();i++){
distr.push_back(uniform_int_distribution<>(point[0].at(i),points[1].at(i)));
}
for(int i = 0;i<trials;i++){
vector<unsigned> draw;
for(int j = 0; j< points[0].size();j++){
draw.push_back(distr.at(j)(eng));
}
// Do stuff with vector
}
This code runs fine. Now however instead of a cube, I have to generate a vector inside the difference of two cubes. So we have the two corner points of the large cube, and a point inside the large cube that combined with EITHER the top OR bottom corner of the large cube induces a cube in which I don't want the vector to lie.
My first instinct was to generate vectors as before and then filtering out those that are in the small cube. If however the small cube is rather large, then it will take too much time to generate the amount of trials I want. Does someone here have an idea?
I think that first you need to define what that third point is, i.e.: say that your initial cube is (point[0],point[1]) and that the third point is point[2]. Do you want to sample in the difference between (point[0],point[1]) and (point[0],point[2]) or in the difference between (point[0],point[1]) and (point[2],point[1])?
Accordingly, I would change the call to the ctor uniform_int_distribution<>(point[0].at(i),points[1].at(i))) to uniform_int_distribution<>(point[2].at(i),points[1].at(i))) or to uniform_int_distribution<>(point[0].at(i),points[2].at(i))).
Related
I want to use ceres to calculate triangle coordinates.
For the problem I need to solve for mesh coordinates in a mesh. Each triangle has its own vertices, but structure like triangles (3 vertices) and edges (4 vertices) is available.
Example data (pseudo code):
triangles = [[v1, v2, v3], [v4, v5, v6]]
inner_edges = [[[v1, v4], [v2, v5]]]
The edges [v1, v2] and [v4, v5] are initially the same, which may change during solving.
Now I have two cost functions, one on triangles and one on inner edges
f([v1, v2, v3]) = res_t1
g([v1, v4, v2, v5]) = res_2
There are two simple block structures
Two blocks, one with all triangle residuums, one with all edge residdums.
One block per triangle and one block per edges.
The first one solves for a vector x with all coordinates (2*|V| as each vertex has two coordinates), as the blocks depend on all vertices. In the second one, the triangle blocks should only depend on three vertices and the edge blocks on four vertices.
I want now to use the second one, as I expect better performance and better convergence.
How do I setup ceres to solve for the same coordinates, but only considering a subset of the vertices as relevant for the current residuum?
I tried setting up the problem with size 6 and 8 and a pointer at the right place in x, but ceres does not allow to use the same result pointer with different offset.
Next I tried to use SubsetParameterization for example like this
vector<double> x(mesh.n_faces()*6);
for(int i=0; i < mesh.n_faces(); i++){
vector<int> const_params;
for(int j = 0; j < mesh.n_faces(); j++) {
if(i != j) {
const_params.push_back(6*j);
const_params.push_back(6*j+1);
const_params.push_back(6*j+2);
const_params.push_back(6*j+3);
const_params.push_back(6*j+4);
const_params.push_back(6*j+5);
}
}
//auto *ssp = new ceres::SubsetParameterization(6, const_params); // (1)
auto *ssp = new ceres::SubsetParameterization(mesh.n_faces() * 6, const_params); // (2)
problem.AddParameterBlock(x.data(), mesh.n_faces() * 6, ssp);
problem.AddResidualBlock(face_cost_function, NULL, x.data());
}
But the ceres checks tell me that both variants are wrong.
for (1) I get
local_parameterization.cc:98 Check failed: constant.back() < size Indices indicating constant parameter must be less than the size of the parameter block.
and for (2) I get
problem_impl.cc:135 Check failed: size == existing_size Tried adding a parameter block with the same double pointer, 000002D736397260, twice, but with different block sizes. Original size was 1152 but new size is 6
How do I set ceres up, such that I can split the same problem in overlapping blocks, which only affect a few of the result variables?
I got it. You are allowed to use multiple pointers into the same array, you are just not allowed to have different block sizes for the same pointer.
This means your blocks inside the array may not overlap inside the array, but different cost functions are allowed to use the same blocks.
The solution is to use one block per coordinate pair:
for(int i = 0; i < mesh.n_faces(); i++) {
face_cost_functors.push_back(new FaceFunctor());
ceres::DynamicAutoDiffCostFunctionFaceFunctor> *face_cost_function = new ceres::DynamicAutoDiffCostFunction<FaceFunctor>(face_cost_functors.back());
face_cost_function->SetNumResiduals(1);
face_cost_function->AddParameterBlock(2);
face_cost_function->AddParameterBlock(2);
face_cost_function->AddParameterBlock(2);
problem.AddResidualBlock(face_cost_function, NULL, &x.data()[6*i], &x.data()[6*i+2], &x.data()[6*i+4]);
}
Then you can add more cost functions, as long as they use the same blocks (i.e. starting address and block size are the same). I do not use any SubsetParametrization at all here.
It did not work for before, because I tried to use a block of size 6 for the triangles and 4 blocks of size 2 for the edge pairs, which overlap the blocks of size 6.
Now it runs a lot faster than before and converges without problems.
I have a dataset of 500 cv::Point.
For each point, I need to determine if this point is contained in a ROI modelized by a concave polygon.
This polygon can be quite large (most of the time, it can be contained in a bounding box of 100x400, but it can be larger)
For that number of points and that size of polygon, what is the most efficient way to determine if a point is in a polygon?
using the pointPolygonTest openCV function?
building a mask with drawContours and finding if the point is white or black in the mask?
other solution? (I really want to be accurate, so convex polygons and bounding boxes are excluded).
In general, to be both accurate and efficient, I'd go with a two-step process.
First, a bounding box on the polygon. It's a quick and simple matter to see which points are not inside the box. With that, you can discard several points right off the bat.
Secondly, pointPolygonTest. It's a relatively costly operation, but the first step guarantees that you will only perform it for those points that need better accuracy.
This way, you mantain accuracy but speed up the process. The only exception is when most points will fall inside the bounding box. In that case, the first step will almost always fail and thus won't optimise the algorithm, will actually make it slightly slower.
Quite some time ago I had exactly the same problem and used the masking approach (second point of your statement). I was testing this way datasets containing millions of points and found this solution very effective.
This is faster than pointPolygonTest with and without a bounding box!
Scalar color(0,255,0);
drawContours(image, contours, k, color, CV_FILLED, 1); //k is the index of the contour in the array of arrays 'contours'
for(int y = 0; y < image.rows, y++){
const uchar *ptr = image.ptr(y);
for(int x = 0; x < image.cols, x++){
const uchar * pixel = ptr;
if((int) pixel[1] = 255){
//point is inside contour
}
ptr += 3;
}
}
It uses the color to check if the point is inside the contour.
For faster matrix access than Mat::at() we're using pointer access.
In my case this was up to 20 times faster than the pointPolygonTest.
Im very new to c++ and only know the very basics. array, if while for dynamic and pointer..
I am working on a code and here is what i want to do.
For example on a 2D square plane(10x10) I have randomly scattered 1000 points(an array of size 100).
The 2D square plane is divided into 10 smaller rectangles. Now I want to sort the 1000 points into these smaller rectangles. Basically, I want to make 10 dynamic arrays(one for each "small rectangle") and each of these array will contain the scattered points that are inside the corresponding region.
The most basic iteration i thought of was just use if, if, if...
But with this, I have to repeat the iteration 1000times for each region. And I think it is very inefficient.
Write a function to classify a single point, i.e. determine into which region it belongs. As a simple example that you can expand:
std::size_t classify(double px, double py, double split) {
if (px < split) {
return 0; // left plane
} else {
return 1; // right plane
}
}
Then, iterate over the points and put them into respective containers:
std::vector<std::vector<point_t>> region{2};
for (auto const & point : points) {
region[classify(point.x, point.y, split)].push_back(point);
}
This way you iterate once over all points, doing a classification (that should be possible to do in constant time in your case) for every point, which is the minimum work required.
I have a particle simulation program I'm currently working on that generate random particle positions in a rectangular shape. This works for now but it's not the best solution, often particles overlap and there are small holes in the rectangle. How would I initialize the particles in the shape of a rectangle?
My current loop:
for(auto i=0; i<MAXPARTICLES; i++){
int particleIndex = FindUnusedParticle(); //grab the index to give a particle life
ParticlesContainer[particleIndex].life = 100.0f; //Long particle life
//generate random positions for particles in the shape of a box with random patterns
ParticlesContainer[particleIndex].pos = glm::vec3((rand()%50)/5.0,(rand()%50)/5.0,-50.0);
// Very bad way to generate a random color
ParticlesContainer[particleIndex].r = 255;
ParticlesContainer[particleIndex].g = 0;
ParticlesContainer[particleIndex].b = 0;
ParticlesContainer[particleIndex].a = 255;
ParticlesContainer[particleIndex].size = .2f;
}
It's a more complicated problem than just using uniform distribution over two dimensions separately. If your "evenliness" is the distance between two closest particles, then there are exactly two ways to achieve that: equilateral triangles and squares (well, three if you count hexagons). The only random thing there is the position of one seed and the "direction" in which that will go.
Refer to the image:
That will give you a very regular, grid-like look, though. You could try applying random, minuscule changes to particles distributed that way, and see how that would work.
I'm trying to write a program that handles detection of various objects. The objects have an origin, width, height, and velocity. Is there a way to set up a data structure/algorithm so that every object isn't checking with every other object?
Some sample code of the problem I'm trying to avoid:
for (int i = 0; i < ballCount; i++)
{
for (int j = i + 1; j < ballCount; j++)
{
if (balls[i].colliding(balls[j]))
{
balls[i].resolveCollision(balls[j]);
}
}
}
You can use a quadtree to quickly find all rectangles that intersect with another rectangle. If you need to handle non-rectangular shapes, you can first find objects whose bounding boxes intersect.
Some common uses of quadtrees
...
Efficient collision detection in two dimensions
...
As mentioned by other answer(s), you can use a quadtree structure to make your collision detection faster.
I would recommend the GEOS open-source C++ library, which has a good quadtree implementation. Here are the docs for their quadtree class.
So your pseudo code would look like this:
Quadtree quadtree;
// Create and populate the quadtree.
// Change it whenever the balls move.
// Here's the intersection loop:
for (int i=0; i<ballCount; ++i) {
Envelope envelope = ...; // Get the bounds (envelope) of ball i
std::vector<void*> possiblyIntersectingBalls;
quadtree.query(envelope, possiblyIntersectingBalls);
// Now loop over the members of possiblyIntersectingBalls to check
// if they really intersect, since quadtree only checks bounding
// box intersection.
}