Segmentation fault raised from stl_list.h : 731 - c++

I've got a very weird segmentation fault with my code. Actually, when I run my executable, it aborts. When I run it with gdb, it also aborts. But when I run it with valgrind, it terminates successfully and gives me the correct result.
That's for the introduction. Now here's a description of my algorithm. What I want to do is extracting the subsurface of a mesh that looks similar to another one, given a certain threshold, r. The key idea of my algorithm is looping on each point of the mesh (let's say, p). If I find a point of the reference mesh included in the sphere of center p and radius r, I don't do anything and I go to the next point. Otherwise, I delete the point and every element of the mesh including it (which means, edges, and triangles of the mesh to which the point belongs).
Now I jump to a short description of my classes. I have four classes to represent elements of the mesh :
Vertex. This class includes two attributes (I don't mention the getters and setters) : a position and a list, belongsTo, which contains pointers to all of the edges to which the vertex belongs.
Edge. This class includes three attributes : the two vertices delimiting the edge, and a list, also called belongsTo, wichi contains pointers to all of the triangles to which an edge belongs.
Triangle. This class includes three attributes : the three edges delimiting the triangle, and a normal vector (I mentioned it, but it doesn't really matter here : I only use it to render the triangle using OpenGL).
And, finally :
Mesh. This class includes a vector v of Vertex objets, a vector e of Edge objects and finally a vector t of Triangles.
Now here is the prototype of my function :
class Mesh {
...
void extractIdenticalSubsurfaces(Mesh *a, double threshold);
}
As you may have already guessed, this function takes two parameters into account : the reference mesh and a threshold (actually the radius of the sphere I build to determine if I have to delete the point from the mesh). Is everything clear ?
Description of my algorithm : I loop on each point of the mesh (on each point of v, actually). For each point, I build a sphere of radius 'threshold' centered in this point and I verify it there is a point of a in this sphere. If I find a point, I don't do anything. Otherwise, I delete it from v.
But before doing that, I have some operations to do.
Indeed, I have to loop on each edge to which the point belongs (using the list 'belongsTo') and then on each triangle to which the point belongs (once again using the list 'belongsTo').
For each of these triangles, I loop on the three edges delimiting it and I delete the address of the triangle from the list of edges to which this triangle belongs (because I want to delete this triangle, so I have to anticipate).
Once it's done, I do the same with the current edge of the loop : I delete the adress of the edge from the 'belongsTo' list associated to the two vertices of the edge.
But I also have to delete both suppressed edges and triangles from the vectors e and t !
It may seem not so easy to understand (I think it's better if you have a sheet of paper just in front of you and if you draw a mesh and consider a point that you want to suppress) but I am quite sure of the exactitude of this algorithm : actually, when I run my program with valgrind, it displays the good sub-mesh on my screen.
But the problem is that if I don't use valgrind, it fails.
Here's the error message displayed by gdb :
Program received signal SIGSEGV, Segmentation fault.
0x0000000000406f3a in std::list<Triangle*, std::allocator<Triangle*> >::begin (this=0x39) at /usr/include/c++/4.6/bits/stl_list.h:731
731 { return iterator(this->_M_impl._M_node._M_next); }
The backtrace :
(gdb) bt
#0 0x0000000000406f3a in std::list<Triangle*, std::allocator<Triangle*> >::begin (this=0x39) at /usr/include/c++/4.6/bits/stl_list.h:731
#1 0x0000000000406e37 in std::list<Triangle*, std::allocator<Triangle*> >::remove (this=0x39, __value=#0x7fffffffc860) at /usr/include/c++/4.6/bits/list.tcc:242
#2 0x00000000004062a1 in Edge::deleteTriangle (this=0x21, t=0xcf4ed0) at elements.cpp:109
#3 0x0000000000408aa4 in Mesh::extractIdenticalSubsurfaces (this=0xc14b10, a=0xc0f900, threshold=0) at mesh.cpp:174
#4 0x0000000000404687 in Scene::extractIdenticalSurfaces (this=0xbad8c0, threshold=0) at scene.cpp:36
#5 0x00000000004051c6 in Viewer::keyPressEvent (this=0x7fffffffde80, e=0x7fffffffd020) at viewer.cpp:104
...
As you can see, getting an error is logical here, because the system seems to try to apply the 'deleteTriangle' method on an object whose 'this' address is 0x21. But what I am wondering is, how on earth can it be 0x21. I tried to dislay the adresses of the pointers to edges and vertices included in all of the Triangles and Edges objects, and they seems to be correct (after all I can display all of the elements of my mesh using OpenGL, so...). But at a moment this 0x21 comes in and I definitely don't know why.
This is my code :
void Mesh::extractIdenticalSubsurfaces (Mesh *a, double threshold) {
vector<Vertex *>::iterator it1 = v.begin() ;
while (it1 != v.end()) {
if (a->emptySphere((*it1), threshold)) {
list<Edge *> edgesToDelete = list<Edge *>();
list<Triangle *> trianglesToDelete = list<Triangle *>();
for (list<Edge *>::iterator it2 = (*it1)->getIteratorBegin() ; it2 != (*it1)->getIteratorEnd() ; it2++) {
for (list<Triangle *>::iterator it3 = (*it2)->getIteratorBegin() ; it3 != (*it2)->getIteratorEnd() ; it3++) {
Triangle *argT = (*it3);
(*it3)->getFirstEdge()->deleteTriangle(argT);
(*it3)->getSecondEdge()->deleteTriangle(argT);
(*it3)->getThirdEdge()->deleteTriangle(argT);
trianglesToDelete.push_back(argT);
}
Edge *argE = (*it2);
(*it2)->getFirstVertex()->deleteEdge(argE);
(*it2)->getSecondVertex()->deleteEdge(argE);
edgesToDelete.push_back(argE);
}
edgesToDelete.unique();
trianglesToDelete.unique();
vector<Edge *>::iterator it4 = e.begin();
while (it4 != e.end()) {
bool isEqual = false;
for (list<Edge *>::iterator it5 = edgesToDelete.begin() ; it5 != edgesToDelete.end() ; it5++) {
if ((*it4) == (*it5)) {
isEqual = true;
edgesToDelete.erase(it5);
break;
}
}
if (isEqual) {
e.erase(it4);
} else {
it4++;
}
}
vector<Triangle *>::iterator it6 = t.begin();
while (it6 != t.end()) {
bool isEqual = false;
for (list<Triangle *>::iterator it7 = trianglesToDelete.begin() ; it7 != trianglesToDelete.end() ; it7++) {
if ((*it6) == (*it7)) {
isEqual = true;
trianglesToDelete.erase(it7);
break;
}
}
if (isEqual) {
t.erase(it6);
} else {
it6++;
}
}
v.erase(it1);
} else {
it1++;
}
}
}
(Well, not very pretty sometimes, I agree but this isn't the subject of my question (on first sight))
So, do you have any idea of why I get this error ?

Related

Triangulating a point set using boost::polygon::voronoi results in overlapping triangles

I'm triangulating a set of 2d points using boost::polygon::voronoi and the code below (found under this question)
boost::polygon::voronoi_diagram<vert_value_typed> vd{};
boost::polygon::construct_voronoi(vertices.begin(), vertices.end(), &vd);
for (const auto& vertex : vd.vertices()) {
boost::container::static_vector<uint32_t, 40> big_face{};
const auto* start_edge = vertex.incident_edge();
auto* edge = start_edge;
do {
const auto cell = edge->cell();
ASSERT(cell && cell->contains_point());
big_face.push_back(util::checked_cast<uint32_t>(cell->source_index()));
if (big_face.size() == 3) {
// process output triangles
faces.push_back({
big_face[0],
big_face[1],
big_face[2]
});
big_face.erase(big_face.begin() + 1);
}
edge = edge->rot_next();
} while (edge != start_edge);
}
However, some of my triangles overlap as illustrated by the following image:
Note that the overlapping triangles always have a reversed culling compared to the rest, i.e they are pointing downwards.
How can I modify the algorithm so that the resulting mesh does not contain these overlapping images? I'm not fluent enough in voronoi diagrams to solve this manually.

find one same element among several object

Currently I am doing a work related to polygons. Polygon can be described as several vertices.
struct Polygon{
vector<Point2D> vertex;
Color color;
};
Now, I have some polygons already vector<Polygon> polygons
and a method can tell me that a point is inside which polygon
Polygon queryPolygon(Point2D point);
I need to set the color of the returned polygon.
My first question is how to know whether the returned polygon is inside vector<Polygon> polygons, the one I already have.
My first idea is to use unordered_set and compare (vertex.begin(), vertex.end()). I don't know whether there is any better idea.
Another question is some polygon might contain the same edge. How to design the data structure so that I can know the polygons that contains same edge like
vector<Polygon> queryPolygonWithSameEdge(Point2D edgeStart, Point2D edgeEnd);
of course brute-force is one way, but is there any better ideas?
Thanks.
First question
There are some unclear aspects about this first question (see my comments). I'll nevertheless answer, assuming that you want just to compare an arbitrary polygon returned by the query with known polygons stored in your vector, with something like:
auto f = find_if (v.begin(), v.end(), [&p](const auto &x) { return compare1(x.vertex, p.vertex); });
if (f!=v.end()) {
cout << "Found at "<< f-v.begin() <<endl;
}
else cout << "Not found";
Comparing polygons (level 1)
The first level would be to compare point by point. The problem, is that the ordering of points does matter, because with exactly the same points, you can draw a pentagon or a pentagram, just depending on the order chosen and whether or not you accept self-intersecting polygons.
For simply comparing if the vertexes in the two vectors are the same:
bool compare1(const vector<Point2D> &x, const vector<Point2D> &y ) {
return x==y;
}
Unfortunately, this will not work if you have two identical polygones, that are just represented using a different starting point.
Comparing polygons (level 2)
Here we take care of a potential different starting point. So the first thing is to find the offset of the first point of the fist polygon in the second polygon, and perform the comparison by taking care of the offset. If the point is not found in the seond polygon, they are not the same:
bool compare2(const vector<Point2D> &x, const vector<Point2D> &y ) {
if (x.size() != y.size()) // if different size it's not the same
return false;
auto offset = find (y.cbegin(), y.cend(), x[0]); // asumes at least 1 point
if (offset==y.cend())
return false;
return equal(offset, y.cend(), x.cbegin())
&& equal(y.cbegin(), offset, x.cbegin()+(y.cend()-offset));
}
Comparing polygons (level 3)
Now, it's also possible that the points are the same, but the first polygon goes clockwise and the second anticlockwise. So we need to check in both direction:
bool compare3(const vector<Point2D> &x, const vector<Point2D> &y ) {
if (x.size() != y.size())
return false;
auto offset = find (y.cbegin(), y.cend(), x[0]); // asumes at least 1 point
if (offset==y.cend()) // no point in commont
return false;
else if (equal(offset, y.cend(), x.cbegin())
&& equal(y.cbegin(), offset, x.cbegin()+(y.cend()-offset)))
return true;
// not equal. And in reverse order ?
auto roffset = make_reverse_iterator(offset+1);
return equal(roffset, y.crend(), x.cbegin())
&& equal(y.crbegin(), roffset, x.cbegin()+(y.crend()-roffset));
}
Here you have an online demo
Comparing polygons (level 4)
Now it is not excluded that two consecutive edges are perfectly aligned. So it is possible that a polygon has an additional point which is not relevant for the comparison.
I let you as exercise the handling for this case. But the most natural place to process this special case is when you populate your polygon.
Second question
To fin the common edges, the easiest way would IMHO be to add the edges to a map, being understood that you would normalize them to ensure that the points are always in the same order.
You could associate to the edge anything you want, for example: a count, a color, or a container with a pointer to the owning polygon.

OpenCV Kalman Filter, erasing from std::vector

I have this problem, see.
I'm using OpenCV to track a hand in a video. The hand in located with a CascadeDetector and then tracked using CamSHIFT. I'm also using a Kalman Filter, to correct the position of the hand, if the CamShift algorithm fails at some frames.
The problem arises, when I'm trying to erase an element from a std::vector, where I'm storing my Hands. The reason for erasing is that due to some issues, a face is misinterpreted as a hand, so I'm detecting faces, and if the hand region intersects with a face region, I delete that hand. I know, very naive, but I'm currently at the very start.
The code looks like this:
class Hand {
...
public:
struct
{
...
struct {
cv::Mat_<float> measurement;
cv::KalmanFilter KF;
cv::Mat state;
cv::Mat processNoise;
} KalmanTracker;
} Tracker;
};
...
std::vector<Hand> hands;
...
std::vector<cv::Rect> faces;
faceCascade.detectMultiScale(frame, faces, 1.1, 2, CV_HAAR_FIND_BIGGEST_OBJECT);
// iterate through hands
for (std::vector<Hand>::iterator it = hands.begin(); it != hands.end(); ++it) {
// iterate through faces:
for (std::vector<cv::Rect>::iterator fc = faces.begin(); fc != faces.end(); ++fc) {
cv::Rect intersection = (*it).handBox.boundingRect() & (*fc);
// check if they have at leasy 75% intersection
if (intersection.area() >= ((*it).handBox.boundingRect().area() * 0.75)) {
// delete that hand from list
hands.erase(it); // this gets me a a EXC_BAD_ACCESS
}
}
}
The hands.erase(it) line gets me an EXC_BAD_ACCESS while pointing at my KalmanFilterTracker struct, as well as this line in mat.hpp with a EXC_i386_GPFLT:
inline void Mat::release()
{
if( refcount && CV_XADD(refcount, -1) == 1 ) // EXC_BAD_ACCESS, code=EXC_i386_GPFLT
...
}
Neither hands nor faces are empty.
If I completely remove the Kalman filter from my project and any mention or use of it, the error disappears.
vector::erase(iterator) invalidates the iterator being erased. But it does return a new iterator to the next valid item in the vector. Thus the line should be:
it = hands.erase(it);
Edit after berak's comment:
Ah, I missed the inner loop. Since you're invalidating it inside the inner loop, things get a little complicated. You'll need to jump through some hoops to get it right.
for (std::vector<Hand>::iterator it = hands.begin(); it != hands.end(); ) {
bool found = false;
// iterate through faces:
for (std::vector<cv::Rect>::iterator fc = faces.begin(); fc != faces.end() && !found; ++fc) {
cv::Rect intersection = (*it).handBox.boundingRect() & (*fc);
// check if they have at leasy 75% intersection
if (intersection.area() >= ((*it).handBox.boundingRect().area() * 0.75)) {
found = true;
}
}
if (found) {
it = hands.erase(it);
}
else {
++it;
}
}
It's possible to fold some of the iterator manipulation into the inner loop, but keeping it outside makes the code a bit clearer and easier to reason about.
Ok, through some debugging I found out, that my vector of hands becomes empty at some point and the error appears while trying to erase from an empty vector.
Only thing left is to find out why does it become empty and at which point.
Thank you everyone.

Intermittent "Vector iterator not dereferencable"

I have the following code, but when I run it, I intermittently get a Debug Assertion Failed error, with the reason "vector iterator not dereferencable".
What I'm trying to do with the program is create a bunch of 2D shapes (squares and circles), then move them about one by one, checking for collisions as they go. When two shapes collide, I want them to be removed, until there is (at most) one shape remaining. About 1 in 3 attempts results in a successful outcome, where the program finds four collisions, then stops. Other times, it will find 1-3 collisions and then error.
I should also mention that I'm relatively new to C++ (and yes, this is a coursework assignment), so if there are any other rookie mistakes in my code, please do point them out!
My methods for moving and colliding seem fine on their own, so I've not included them here.
Square * s1 = new Square(seedCoord(limit), seedCoord(limit), 2.0);
... //There is 9 new shapes created here (squares and circles)
std::vector<Shape*> shape;
shape.push_back(s1);
... //All 9 shapes added to the vector
int m = shape.size();
bool collision = false;
while(m>1) //Keep running until only one shape hasn't collided
{
for (auto i=shape.begin(); i!=(shape.end());) //Perform move on each shape in sequence
{
collision = false; //Set collision boolean to false
(*i)->move(seedCoord(0.5), direction[(rand() % 4)], limit); //Perform move on shape
for (auto j=shape.begin(); j!=(shape.end()-1);) //Check for collision with each shape in sequence
{
if((*i) != (*j)) //Ignore self when checking for collision
{
if((*i)->collide(*j)) //Check for collision
{
std::cout << "Collision between " << (*i) << " and " << (*j) << "\n";
m=m-2; //Lower shapes count by two (ie remove two collided shapes)
delete *i; //Delete pointer to initial shape
i = shape.erase(i); //Erase shape object
delete *j; //Delete pointer to collided shape
j = shape.erase(j); //Erase shape object
collision = true; //Set collision boolean to true
break; //Break out of internal for-loop (shape has been deleted so no more checks are necessary)
}
else
{
j++; //If no collision, move onto next shape
}
}
else
{
j++; //If i=j, move onto next shape
}
}
if(!collision) //If no collision with any shape, move onto next shape
{
i++; //If no collision with any shape, move onto next shape
}
else
{
break; //If collision has occurred, break out of external for-loop (shape has been deleted so no more checks are necessary)
}
}
}
Quoting cpprefernce on erase:
Iterators and references to the erased elements and to the elements between them and the end of the container are invalidated. The past-the-end iterator is also invalidated.
My guess is that your problem occurs when in your second call to erase(j), j is an iterator referring to a location between i and shape.end() and got invalidated.
You are running with two iterators over the same vector. When you erase an element of that vector, all iterators past that element are invalidated. That means that on each collision either i or j is invalidated as erase is called for the other one.
You continue to use the iterators after the erase. This gives undefined behavior, meaning "anything can happen". That "aything" means it can work most of the times, but there are times when it won't. Consider this case:
The last two elements collide, i is end()-2, j is end()-1. First you erase(i), meaning all elements get shoved one to the left, including the one j pointed to. j is now conceptually invalid, but being not much more than a pointer, it points now one past the last element, i.e. j == end(). You now go on and call delete *j;, dereferencing the end() iterator wich will trigger the assertion.
Looking at the code more closely, it looks like your issue is due to the erasure of elements
Namely
i = shape.erase(i); //Erase shape object
...
j = shape.erase(j); //Erase shape object
Now you're correctly using the newly returned iterator from vector.erase() but the problem is that i and j are both iterators into the same vector. This means the following happens
'i' is erased from the shape vector
shape vector gets reallocated without the 'i' element
'i' is reassigned to the next element, within the vector's memory block (which has had the remaining elements after i shuffled down a position)
'j' is still pointing at the old memory location (not taking into account the shuffling)
'j' is erased from shape vector (which is potentially now after the last element)
out of bounds error
Instead of deleting the elements within the loop, you'd be better off flagging your elements as 'dead' within the body of the loop, then using std::remove_if right at the end of the while loop
shape.erase(std::remove_if(shape.begin(),
shape.end(),
isDead),
shape.end());
where isDead is a functor defined something like:
struct isDead
{
bool operator()(const Shape* pX) const
{
return pX->isDead();
}
};

How to draw a polygon in C++ such that the lines do not intersect?

I need to draw a polygon in C++. I set random points in vector and then connect them via lines. But sometimes those lines intersect and i get something like this.
Is there any formula or something like that, so that the lines wouldn't cross?
Here is part of the code:
void draw_picture(Canvas & canvas) {
PairXY a,b,c,d,e;
int k;
vector <PairXY> vertex;
vertex.push_back(PairXY(drandom(k),drandom(k)));
vertex.push_back(PairXY(drandom(k),drandom(k)));
vertex.push_back(PairXY(drandom(k),drandom(k)));
vertex.push_back(PairXY(drandom(k),drandom(k)));
vertex.push_back(PairXY(drandom(k),drandom(k)));
vector <PairXY>::const_iterator iter;
iter = vertex.begin();
a=*iter;
iter = vertex.begin()+1;
b=*iter;
iter = vertex.begin()+2;
c=*iter;
iter = vertex.begin()+3;
d=*iter;
iter = vertex.begin()+4;
e=*iter;
Line l1(a,b);
draw_line(l1,canvas);
Line l2(b,c);
draw_line(l2,canvas);
Line l3(c,d);
draw_line(l3,canvas);
Line l4(d,e);
draw_line(l4,canvas);
Line l5(e,a);
draw_line(l5,canvas);
}
Sounds like you want a convex hull.
As far as calculating them goes, you have several options.
I've had good luck with the monotone chain algorithm.
It sounds like what you are probably looking for is a "Simple" (as opposed to "Complex") Polygon:
http://en.wikipedia.org/wiki/Simple_polygon
There's not necessarily a unique solution to that:
Sort point list into polygon
This is why the ordering of points or path segments typically matters in polygon drawing engines. If you are so inclined--however--you can find at least one non-complex polygon for a set of points:
http://www.computational-geometry.org/mailing-lists/compgeom-announce/2003-March/000727.html
http://www.computational-geometry.org/mailing-lists/compgeom-announce/2003-March/000732.html
Others have pointed out your code is repetitive as written. You also don't define k in the excerpt you shared, and it's better to use a plural term for a vector of objects ("vertices") rather than one suggesting it is singular ("vertex"). Here's one fairly simple-to-understand set of changes that should generalize to any number of vertices:
void draw_picture(Canvas & canvas, int k, int numVertices = 5) {
vector<PairXY> vertices;
for (int index = 0; index < numVertices; index++) {
vertices.push_back(PairXY(drandom(k),drandom(k)));
}
vector<PairXY>::const_iterator iter = vertices.begin();
while (iter != vertices.end()) {
PairXY startPoint = *iter;
iter++;
if (iter == vertices.end()) {
Line edgeLine (startPoint, vertices[0]);
draw_line(edgeLine, canvas);
} else {
Line edgeLine (startPoint, *iter);
draw_line(edgeLine, canvas);
}
}
}
There are a lot of ways to manage iterations in C++, although many of them are more verbose than their counterparts in other languages. Recently a nice range-based for loop was added in C++11, but your build environment may not support it yet.
sort the array before drawing it
Find the left most point
than go CCW from there
ie
leftmost where point y < first point y until none found
rightmost point until none found