Iterating over list of list of object - c++

I want to iterate over a list of list of Object,
list<list<Point>> gnuPoints;
this is a static list which accepts list from various classes like circle and polygon all of which classes pushes multiple objects i.e Point(x,y) to the list
while (angle != 360)
{
double x = m_radius*cos(angle);
double y = m_radius*sin(angle);
angle += 30;
circlePoint.push_back(Point(x, y));
}
similarly goes with Polygon and line shapes
polygonPoint.push_back(Point(x,y));
linePoint.Push_back(point(x,y));
then these lists are pushed in gnuPoint(list< list< Point> >).
gnuPoints.push_back(circlePoints);
gnuPoints.push_back(polygonPoints);
gnuPoints.push_back(linePoints);
now i want to write all these x,y values of different shapes in a file,
To iterate over it i cant find any particular solution after this code.
for (list<list<Point>>::iterator it = Point::gnuPoints.begin();
it != Point::gnuPoints.end();
it++)
{
//My assumption is that another For loop would come but could not apply
as I don't know what is available at the first index of gnuPoints list.
}

for (list<list<Point>>::iterator it = Point::gnuPoints.begin();
it != Point::gnuPoints.end();
it++)
{
for (list<Point>::iterator innerIt = it->begin(); innerIt != it->end(); ++innerIt)
}
If you are already on a compiler that supports c++11, this could be simply written as:
for (const auto& container : Point::gnuPoints)
{
for (const auto& item : container)
{
}
}

Related

C++ Sfml delete single Object from vector

i try to making a little game in SFML (C++) So i have a simple Problem with pick up an object by a player. The object is in a vector, i have to objects on the screen and when the player intersect(Collision) with them they have to erase. But still booth objects erase when the player intersect with a single object, how i can fix ?
so my question is: How can i erase (or delete) a single object from a vector who is collide with a player?
here is my code
RectangleShape object;
std::vector<RectangleShape> objects(3);
RectangleShape player;
...
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event));
...
for (int j = 0; j < objects.size(); j++){
objects[j].setFillColor(Color::Cyan);
objects[1].setSize(Vector2f(100, 100));
objects[1].setPosition(Vector2f(650, 1000));
objects[2].setSize(Vector2f(100, 100));
objects[2].setPosition(Vector2f(650, 700));
}
for (auto& object: objects){
FloatRect playerBounds = player.getGlobalBounds();
FloatRect objectBounds = object.getGlobalBounds();
for ( auto it = objects.begin(); it != objects.end();)
{
if(objectBounds. intersects(playerBounds)) {
it = objects.erase(it);
}
else
{
++it;
}
window.draw(objects[1]);
window.draw(objects[2]);
}
}
I tried to keep as much from your code as it was possible so you could see the difference, not the whole different code. The reason why your code wasn't deleting just one obj. and every single is that your loops weren't correctly written.
See this:
for (auto& object: objects){ //iterating through objects
FloatRect playerBounds = player.getGlobalBounds();
FloatRect objectBounds = object.getGlobalBounds(); //<- this *1*
for ( auto it = objects.begin(); it != objects.end();) //iterating through every single one AGAIN
{
if(objectBounds. intersects(playerBounds)) { //what this if does is that it check if this *1* obj. intersects with your player
it = objects.erase(it); //however it doesn't particularly erase that *1* obj., it just erases every obj. in the vector, because when that if is true it will iterate through the vector and delete one by one.
}
else
{
++it;
}
}
The main problem is that 2nd iteration for ( auto it = objects.begin(); it != objects.end();) and if in it are 2 separate things.
There are many solutions to make it work, but then it would be just adding more code to make more spaghetti, so just redo it to make it better.
Here is the working ver:
RectangleShape object;// not needed
std::vector<RectangleShape> objects(3);
for (int j = 0; j < objects.size(); j++) {
objects[j].setFillColor(Color::Cyan);
objects[j].setSize(Vector2f(100, 100));
objects[j].setPosition(Vector2f(650, 1000 - j * 300)); //just a quick way to set position of "every" to be 1000, 700, 400 etc.
//objects[1].setSize(Vector2f(100, 100));
//objects[1].setPosition(Vector2f(650, 1000)); // shouldn't set the obj[1] parameters withing loop since you are setting them the n times where n is number of objs. in the vector
//objects[2].setSize(Vector2f(100, 100));
//objects[2].setPosition(Vector2f(650, 700));//and you should just delete it from there
}
RectangleShape player;
player.setSize(Vector2f(100, 100));
player.setPosition(Vector2f(650, 1000)); //setting player parameters separately since it is not in the vector
// Also I moved making and setting of player and other obj in the vector out of the game loop so it won't be creating them every single frame
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event));
...
for (auto it = objects.begin(); it != objects.end();) {
FloatRect playerBounds = player.getGlobalBounds();
FloatRect objectBounds = it->getGlobalBounds(); //iterator is just similar to a pointer, so to access what it points to you need to use "->" or "*" instead of "."
if (objectBounds.intersects(playerBounds)) {
it = objects.erase(it);
}
else
it++;
}
for (auto& object : objects) { //drawing every single obj. in the vector
window.draw(object);
}
window.draw(player); //drawing player separately since it is not in the vector
}
For the tutorial part that you mentioned in the comments, I would recommend you checking ones from sfml site since they not only contain descriptions of methods, etc. but also demo code.

Get Polygon Intersection Line with CGAL

How can I easily retrieve the intersection line (from the first to the last intersection point) of two intersecting polygons with CGAL. See the image for clarification, the green line is what I want.
Currently I use the following algorithm, where I get the intersection polygon and then find the points which are on both polygon boundaries, these should be the intersection points. Here it is in code:
Polygon_2 P,Q;
Pwh_list_2 intR;
Pwh_list_2::const_iterator it;
CGAL::intersection(P, Q, std::back_inserter(intR));
//Loop through intersection polygons
for (it = intR.begin(); it != intR.end(); ++it) {
boost::numeric::ublas::vector<double> firstIntersectPoint(3), lastIntersectPoint(3);
Polygon_2 Overlap = it->outer_boundary();
typename CGAL::Polygon_2<Kernel>::Vertex_iterator vit;
int pointNr = 1;
//Loop through points of intersection polygon to find first and last intersection point.
for (vit = Overlap.vertices_begin(); vit != Overlap.vertices_end(); ++vit) {
CGAL::Bounded_side bsideThis = P.bounded_side(*vit);
CGAL::Bounded_side bsideArg = Q.bounded_side(*vit);
if (bsideThis == CGAL::ON_BOUNDARY && bsideArg == CGAL::ON_BOUNDARY && pointNr == 1) {
firstIntersectPoint <<= 0, CGAL::to_double(vit->x()), CGAL::to_double(vit->y());
pointNr = 2;
}
else if (bsideThis == CGAL::ON_BOUNDARY && bsideArg == CGAL::ON_BOUNDARY && pointNr == 2) {
lastIntersectPoint <<= 0, CGAL::to_double(vit->x()), CGAL::to_double(vit->y());
pointNr = 2;
}
}
//RESULT
std::cout << firstIntersectPoint << std::endl;
std::cout << lastIntersectPoint << std::endl;
}
Although this works I don't think it is the correct way to go. Can somebody give me an indication whether this is the correct way to do this or give my pointers how to do it better.
Insert the segments of the two polygons into a 2D Arrangement. Then find the vertices with degree 4. Notice that in the general case there might be more than 2; there might be none, and there might be 1.
std::list<X_monotone_curve_2> segments;
for (const auto& pgn : polygons) {
for (auto it = pgn.curves_begin(); it != pgn.curves_end(); ++it)
segments.push_back(*it);
}
Arrangement_2 arr;
insert(arr, segments.begin(), segments.end());
for (auto it = arr.begin_vertices(); it != arr.end_vertices(); ++it) {
if (4 == it->degree())
...
}
You can avoid the construction of the 'segments' list and instead directly insert the segments of the polygons into the arrangement using an iterator adapter. (This is pure generic programming and nothing to do with CGAL.)

Logic for creating graph c++

I am working on a project where I am given a list of edges with a weight of either A or B. I need eventually determine if it is possible to create a spanning tree with 'x' number of A edges.
Right now I am trying to make a list of all the edges that are used in creating the minimally spanning tree and am doing that by making a list of the vertices that I have used. If two of the vertices have been used then that edges is discarded. The problem I am having is that once I get to the end my graph, I am often left with two halves of graphs that are not connected because the edge that would connect the two halves have already been used. Any thoughts on how I can fix this problem, or is the overall approach wrong?
struct Edge{
int start;
int end;
char letter;
bool used;
};
void PrimWhite(...)
{
vector<int> usedVertices;
int count,maxNum,begin,end;
int totalVertexs = 0;
maxNum = whiteEdge.size();
Edge temp;
Edge *point = &temp;
Edge *usedorNah;
for (count = 0;count < maxNum; count++)
{
temp = whiteEdge[count];
usedorNah = &whiteEdge[count];
begin = point->start;
end = point->end;
if ( (find(usedVertices.begin(), usedVertices.end(), begin) == usedVertices.end()) && (find(usedVertices.begin(), usedVertices.end(), end) == usedVertices.end()))
{
usedVertices.push_back(begin);
usedVertices.push_back(end);
totalVertexs = totalVertexs + 2;
usedorNah->used = true;
}
else if ((find(usedVertices.begin(), usedVertices.end(), begin) == usedVertices.end()) && (find(usedVertices.begin(), usedVertices.end(), end) != usedVertices.end()))
{
usedVertices.push_back(begin);
totalVertexs++;
usedorNah->used = true;
}
else if ((find(usedVertices.begin(), usedVertices.end(), begin) != usedVertices.end()) && (find(usedVertices.begin(), usedVertices.end(), end) == usedVertices.end()) )
{
usedVertices.push_back(end);
totalVertexs++;
usedorNah->used = true;
}
Just use the criterion that Kruskal's algorithm uses: Add an edge to the graph if it does not form a loop. To check this, you have to check if the two incident nodes are connected to the same connected component. This can be done efficiently with the Union-Find data structure. I.e. whenever you add an edge, unite the components of both vertices. Before adding an edge, check if the two components are the same.

Removing elements from an unordered_multimap

I have an unordered_multimap that represents an adjacency list, and several edges that have self loops. For example:
edges_ might be:
edges_.insert(Edges::value_type(1, std::make_pair(1, 0.0)));
edges_.insert(Edges::value_type(1, std::make_pair(1, 0.0)));
edges_.insert(Edges::value_type(1, std::make_pair(1, 0.0)));
edges_.insert(Edges::value_type(1, std::make_pair(2, 0.0)));
I would like to remove the 3 duplicate (1, (1, 0.0)) values. If I break after the edges_.erase(it) line only one of the three duplicates is removed.
If I advance through the iteration, regardless of whether I increment the iterator or not, it seems to crash after that. How can I remove all three?
template <typename T_NodeLabel, typename T_EdgeWeight>
class Graph
{
public:
using NodeId = unsigned int;
using Nodes = std::unordered_map<NodeId, T_NodeLabel>;
using AdjacencyList = std::pair<NodeId, T_EdgeWeight>;
using Edges = std::unordered_multimap<NodeId, AdjacencyList>;
void RemoveSelfLoops(NodeId node)
{
auto edges = edges_.equal_range(node);
for (auto it = edges.first; it != edges.second;)
{
if (it->second.first == node)
{
edges_.erase(it);
}
else
{
++it;
}
}
}
private:
Nodes nodes_;
Edges edges_;
};
After call to erase, your iterator is invalidated. And then you try to use it on the next iteration.
You need to use a return value of erase as the new iterator.

Find pointer of object in vector C++

I have a class which is called Position:
class Position
{
public:
... //Constructor, Destructor, ...
private:
signed int x_;
signed int y_;
}
Then I have a vector which stores pointers of Positions:
std::vector<Position*> positions
How can I check if a Position is contained in the vector? For example, I have an object of a Position:
Position* p_ = new Position(0, 0);
And I want to check if the vector contains a Position with the same coordinates?
Which operator do I have to overload?
Thanks,
Barbara
auto it = find_if(positions.begin(), positions.end(),
[=](position* p)
{
return p->x() == p_->x() && p->y() == p_->y();
});
if(it != positions.end())
{
//object found
}
However, unless you have a real reason to store pointers in the vector (e.g. you're going to use polymorphism), storing objects directly is much simpler.
vector<position> v;
v.push_back(Position(1, 2));
...
Position p_(1, 4);
auto it = find_if(v.begin(), v.end(),
[=](position p)
{
return p.x() == p_.x() && p.y() == p_.y();
});
if(it != v.end())
{
//position found
}
In the latter case it is possible to further simplify the code by overloading operator == for position.
bool operator == (position p1, position p2)
{
return p1.x == p2.x && p1.y == p2.y; //assuming operator == is declared friend
}
Then you can
auto it = find(v.begin(), v.end(), p_);
And I want to check if the vector contains a Position with the same coordinates? Which operator do I have to overload?
If you had a vector of positions (instead of vector of pointers to positions) the operator you'd have to overload would be:
bool Position::operator==(const Position& p);
With this code, you could write (assuming you are using std::vector<Position> positions;, and not std::vector<Position*> positions;):
using std::find; using std::begin; using std::end;
const Position p{}; // element that is sought after
bool exists = (end(positions) != find(begin(positions), end(positions), p));
[comment:] Yeah I am also quite unsure about this. I asked one of my teammates why he does this [i.e. store by pointers] and he said it would be more efficient and faster and it should not be changed - EVER.
It is probably not more efficient, nor faster than storing by values. If you are not in a position to change the vector though, you will have to add the operator declared above, and also a predicate that compares a Position instance to the values in a Position pointer, and using that with std::find:
const Position p{}; // element that is sought after
auto matches_position = [&p](Position const* const x)
{
return x != nullptr // can positions in the vector be null?
&& p == *x;
};
bool exists = (end(positions) != find(begin(positions), end(positions),
matches_position));
== Coping strategy ==
I would go for the first version (no pointers in the vector), by doing the following:
create a new (minimalistic) project, that fills two separate vectors, with a bunch of randomized positions (fixed number of positions, between 2000 and 10000 instances or so); the vectors should contain positions by pointer and by value respectively, with the same values in each position (a position should be in both vectors, at the same index)
perform the search for the same values in both vectors.
repeat the searches multiple times (to average and minimize timing errors)
take results to your colleague(s).
There are two outcomes from this: either your colleague is right (which seems pretty unlikely, but hey! who knows?) or he is wrong, and his code that "should never be changed" - well ... it should be changed.
Add this to class Position
Public:
bool isSamePosition(position * p){
return p->x == this->x && p->y ==this->y;
}
Then compare with all in the vector
bool unique = true;
for (int i = 0; i < positions.length(); ++i){
if (new_position->isSamePosition(positions[i])
unique = false;
}
if (unique==true)
//do something like push_back vector
;