Find pointer of object in vector C++ - 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
;

Related

Overflowing the stack memory with my quadtree class and don't know why

I have been working on a quadtree class for possible collision detections, but the more items I add the faster I overflow the stack.
I also noticed the memory usage increases linearly as the program runs so I assume I am not deleting something properly and it is just stacking on each other?
I know most stack overflow errors are caused by recursion but it shouldn't be happening with just 100 objects.
#include "Quadtree.h"
Quadtree::Quadtree(Rectangle* bounds)
{
this->bIsSplit = false;
this->bounds = bounds;
this->maxObjects = 5;
}
void Quadtree::Split(std::vector<std::pair<SpaceObject*, SpaceObject*>> &collidingObjects)
{
float x = bounds->x;
float y = bounds->y;
float subWidth = bounds->width / 2;
float subHeight = bounds->height / 2;
// Top Left
nodes.push_back(new Quadtree(new Rectangle(x, y, subWidth, subHeight)));
// Top Right
nodes.push_back(new Quadtree(new Rectangle(x + subWidth, y, subWidth, subHeight)));
// Bottom Left
nodes.push_back(new Quadtree(new Rectangle(x, y + subHeight, subWidth, subHeight)));
// Bottom Right
nodes.push_back(new Quadtree(new Rectangle(x + subWidth, y + subHeight, subWidth, subHeight)));
// takes all the objects in the parent node and splits them into there corresponding subdivided quadtree
for (auto o : this->objects)
{
for (int i = 0; i < nodes.size(); i++)
{
if (nodes[i]->bounds->Contains(o->x, o->y, o->size))
{
nodes[i]->Insert(o, collidingObjects);
}
}
}
this->objects.clear();
this->bIsSplit = true;
}
void Quadtree::Insert(SpaceObject* spaceObject, std::vector<std::pair<SpaceObject*, SpaceObject*>> &collidingObjects)
{
// if the object does not fit inside this quadtree, this isn't the right quadtree
if (!bounds->Contains(spaceObject->x, spaceObject->y, spaceObject->size))
{
return;
}
if (!bIsSplit && this->objects.size() < maxObjects) // add the object to the quadtree if the max has not been hit
{
objects.push_back(spaceObject);
for (auto o : this->objects)
{
// if the objects are not the same and overlapping (pythag)
if (spaceObject != o &&
((spaceObject->x - o->x) * (spaceObject->x - o->x)) + ((spaceObject->y - o->y) * (spaceObject->y - o->y)) <= (spaceObject->size + o->size) * (spaceObject->size + o->size))
{
// Add colliding pair to the collidingObjects vector
collidingObjects.push_back(std::make_pair(spaceObject, o));
}
}
}
else
{
if (!this->bIsSplit) // splits the quadtree if this quadtree has not been split yet
{
this->Split(collidingObjects);
}
// adds the passed in object to one of the subnodes
for (auto n : nodes)
{
n->Insert(spaceObject, collidingObjects);
}
}
}
void Quadtree::Delete(SpaceObject* spaceObject)
{
if (!bounds->Contains(spaceObject->x, spaceObject->y, spaceObject->size))
{
return;
}
if (!bIsSplit)
{
for (int i = 0; i < objects.size(); i++)
{
if (objects[i] == spaceObject)
{
this->objects.erase(objects.begin() + i);
return;
}
}
}
else
{
for (auto n : nodes)
{
n->Delete(spaceObject);
}
}
}
void Quadtree::Clear()
{
if (bIsSplit)
{
for (auto n : nodes)
{
n->Clear();
}
this->bIsSplit = false;
}
nodes.clear();
objects.clear();
}
Well, I can't tell what nodes is or how Quadtree is defined because you are not showing the complete code. But it's suspicious that you are using new. Is nodes a collection of pointers? If so, you are probably dropping them on the floor since they are never deleted.
Don't write this-> all over the place. Members are in the scope of the member functions. Your Quadtree constructor should be using inline initializers for the constant members and an initializer list for the bounds. And, using a bare pointer here is a red flag. What is the ownership of this bounds? Why does it need to be a pointer rather than simply a value of type Rectangle?
I wonder if you are used to a different language, one that uses new for all construction, and has reference semantics and objects are really pointers. C++ is different.
I'd suggest writing it without using any pointers. For sure, the Rectangle should be a value. A vector of Quadtree can be efficient when inserting and deleting etc. if the elements can be efficiently moved. So, Quadtree should have a move constructor. That is probably an advanced concept if you don't know all about constructors and special members yet.
What you should definitely follow, even as (especially as) a beginner, is ⧺C.149 — no naked new or delete. So, if you need to make a vector of pointers to Quadtree, make it a vector of shared_ptr. Remember, you don't have garbage collection in C++ so anything that's using a pointer has to explicitly deal with responsibility of lifetime management. A shared_ptr will behave more like you're used to, and they are safe for use in containers like vector.

How to avoid creating of empty object?

I am making my homework and I have 2 functions unionRect and intersectRect.I am creating a set of my first class Rectangle from a file. I have to return the union and intersect rectangle of that oColl.I am having a problem with returning the values because the object returns two 0 values.
I have tried to return different things but I couldn't do it.
This is from the first class Rectangle
Rectangle unionRect(const Rectangle& rec) const {
int ux1, ux2, uy1, uy2;
ux1 = min(ix1, rec.ix1);
uy1 = min(iy1, rec.iy1);
ux2 = max(ix2, rec.ix2);
uy2 = max(iy2, rec.iy2);
Rectangle a(ux1, ux2, uy1, uy2);
return a;
}
This is second class RectangleCollection function to read from file
RectangleCollection(const string& strFileName) {
ifstream ifile(strFileName.data());
copy(istream_iterator<Rectangle>(ifile), istream_iterator<Rectangle>(), inserter(oColl,oColl.begin()));
};
this is my RectangleCollection class function for union Rect
Rectangle calcUnionColl() {
set<Rectangle>::iterator it;
Rectangle a;
for (it = oColl.begin(); it != oColl.end(); ++it) {
a = unionRect(*it);
}
return a;
}
and the .txt file is
5 5 10 10
6 6 12 12
but when i call calcUnionColl it returns me
x1:0 x2:6 y1:0 y2:12
I expect the output to be x1:5 x2:6 y1:5 y2:12.
Thank you in advance!
You are not union'ing all of the Rectangles together that are in the collection. You are union'ing each individual Rectangle only with the one Rectangle that calcUnionColl() is called on, and then you return the result of just the last union that was performed.
Try something more like this instead:
class Rectangle {
public:
...
Rectangle unionRect(const Rectangle& rec) const;
...
}
Rectangle Rectangle::unionRect(const Rectangle& rec) const {
int ux1, ux2, uy1, uy2;
ux1 = std::min(ix1, rec.ix1);
uy1 = std::min(iy1, rec.iy1);
ux2 = std::max(ix2, rec.ix2);
uy2 = std::max(iy2, rec.iy2);
return Rectangle(ux1, ux2, uy1, uy2);
}
...
class RectangleCollection {
public:
...
Rectangle calcUnionColl() const;
...
}
Rectangle RectangleCollection::calcUnionColl() const {
Rectangle a;
if (!oColl.empty()) {
std::set<Rectangle>::iterator it = oColl.begin();
a = *it++;
while (it != oColl.end()) {
a = a.unionRect(*it++);
}
}
return a;
}
The answer from Remy Lebeau has a minor issue. If oColl is empty, calcUnionColl will return the the default-constructed value of a. So if the default-constructed value of a is x1:0, x2:0, y1:0, y2:0 then if calcUnionColl returns that value, it is impossible to know if that is the actual union of the values in oColl, or if
oColl was empty.
A common trick when finding the the maximum value of multiple ints is to initialize the running maximum with INT_MIN. And in the same way, when finding a minimum value, we initialize the the running minimum with INT_MAX.
Finding the union of rectagles is nothing more than finding the min/max value of the rectangles corner coordinates, so we can use the above trick.
For instance if a = {x1:INT_MAX, x2:INT_MIN, y1:INT_MAX, y2:INT_MIN}, then when calculating the union of a and any rectangle b, we will have:
b.x1 <= a.x1 // a.x1 == INT_MAX
b.y1 <= a.y1 // a.y1 == INT_MAX
b.x2 >= a.x1 // a.x1 == INT_MIN
b.y2 >= a.y2 // a.y2 == INT_MIN
So the union of a and b in this case will be b
Making use of this in calcUnionColl():
// I assume the data-type for your rectangle coordinates is `int`.
// If you use another datatype, change this accoringly.
Rectangle RectangleCollection::calcUnionColl() const {
int i_min = std::numeric_limit<int>::min(); // c++ way of getting INT_MIN
int i_max = std::numeric_limit<int>::max(); // c++ way of getting INT_MAX
set<Rectangle>::iterator it;
Rectangle a(i_max, i_min, i_max, i_min);
for (it = oColl.begin(); it != oColl.end(); ++it) {
a = a.unionRect(*it);
}
return a;
}
Now, if oColl is empty, calcUnionColl() will return x1:INT_MAX, x2:INT_MIN, y1:INT_MAX, y2:INT_MIN. This should be an invalid value for a rectangle since x1>x2 and y1>y2, and should be easy to test for.
Sometimes you don't even have to test for it, since it often is an invalid value "that makes sense" for further calculations.

using C++ priority_queue comparator correctly

This question was asked in an interview recently
public interface PointsOnAPlane {
/**
* Stores a given point in an internal data structure
*/
void addPoint(Point point);
/**
* For given 'center' point returns a subset of 'm' stored points that are
* closer to the center than others.
*
* E.g. Stored: (0, 1) (0, 2) (0, 3) (0, 4) (0, 5)
*
* findNearest(new Point(0, 0), 3) -> (0, 1), (0, 2), (0, 3)
*/
vector<Point> findNearest(vector<Point> points, Point center, int m);
}
This is following approach I used
1) Create a max heap priority_queue to store the closest points
priority_queue<Point,vector<Point>,comp> pq;
2) Iterate the points vector and push a point if priority queue size < m
3) If size == m then compare the queue top with current point and pop if necessary
for(int i=0;i<points.size();i++)
{
if(pq.size() < m)
{
pq.push(points[i]);
}
else
{
if(compareDistance(points[i],pq.top(),center))
{
pq.pop();
pq.push(points[i]);
}
}
}
4) Finally put the contents of priority queue in a vector and return.
How should I write the comp and the compareDistance comparator which will allow me to store m points initially and then compare the current point with the one on top?
I think your approach can be changed so that it uses the priority_queue in a different way. The code becomes a bit complex since there's an if-statement in the for loop, and this if-statement controls when to add to the priority_queue. Why not add all the points to the priority_queue first, and then pop out m points? Let the priority_queue do all the work.
The key to implementing the findNearest function using a priority_queue is to realize that the comparator can be a lambda that captures the center parameter. So you can do something like so:
#include <queue>
#include <vector>
using namespace std;
struct Point { int x, y; };
constexpr int distance(const Point& l, const Point& r)
{
return (l.x - r.x)*(l.x - r.x) + (l.y - r.y)*(l.y - r.y);
}
vector<Point> findNearest(const vector<Point>& points, Point center, int m)
{
auto comparator = [center](const Point& l, const Point& r) {
return distance(l, center) > distance(r, center);
};
priority_queue<Point, vector<Point>, decltype(comparator)> pq(comparator);
for (auto&& p : points) {
pq.emplace(p);
}
vector<Point> result;
for (int i = 0; i < m; ++i) {
result.push_back(pq.top());
pq.pop();
}
return result;
}
In an interview setting it's also good to talk about the flaws in the algorithm.
This implementation runs in O(nlogn). There's going to be a clever algorithm that will beat this run time, especially since you only need the closest m points.
It uses O(n) more space because of the queue, and we should be able to do better. What's really happening in this function is a sort, and sorts can be implemented in-place.
Prone to integer overflow. A good idea would be use a template on the Point struct. You can also use a template to make the points container generic in the findNearest function. The container just has to support iteration.

Iterating over list of list of object

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)
{
}
}

How do I delete the closest "Point" object in a STD::List to some x,y?

I have a point class like:
class Point {
public:
int x, y;
Point(int x1, int y1)
{
x = x1;
y = y1;
}
};
and a list of points:
std::list <Point> pointList;
std::list <Point>::iterator iter;
I'm pushing points on to my pointList (although the list might contain no Points yet if none have been pushed yet).
I have two questions:
How can I delete the closest point to some arbitrary (x, y) from the list?
Lets say I have the x,y (5,12) and I want to find the Point in the list closest to that point and remove it from the STD::List.
I know I'll have to use the distance formula and I'll have to iterate through the list using an iterator but I'm having some trouble conceptualizing how I'll keep track of which point is the closest as I iterate through the list.
How can I return an array or list of points within x radius of a given (x,y)?
Similar to the last question except I need a list of pointers to the "Point" objects within say 5 radius of a given (x,y). Also, should I return an array or a List?
If anyone can help me out, I'm still struggling my way through C++ and I appreciate it.
Use a std::list::iterator variable to keep track of the closest point as you loop through the list. When you get to the end of the list it will contain the closest point and can be used to erase the item.
void erase_closest_point(const list<Point>& pointList, const Point& point)
{
if (!pointList.empty())
{
list<Point>::iterator closestPoint = pointList.begin();
float closestDistance = sqrt(pow(point.x - closestPoint->x, 2) +
pow(point.y - closestPoint->y, 2));
// for each point in the list
for (list<Point>::iterator it = closestPoint + 1;
it != pointList.end(); ++it)
{
const float distance = sqrt(pow(point.x - it->x, 2) +
pow(point.y - it->y, 2));
// is the point closer than the previous best?
if (distance < closestDistance)
{
// replace it as the new best
closestPoint = it;
closestDistance = distance
}
}
pointList.erase(closestPoint);
}
}
Building a list of points within a radius of a given point is similar. Note that an empty radius list is passed into the function by reference. Adding the points to the list by reference will eliminate the need for copying all of the points when returning the vector by value.
void find_points_within_radius(vector<Point>& radiusListOutput,
const list<Point>& pointList,
const Point& center, float radius)
{
// for each point in the list
for (list<Point>::iterator it = pointList.begin();
it != pointList.end(); ++it)
{
const float distance = sqrt(pow(center.x - it->x, 2) +
pow(center.y - it->y, 2));
// if the distance from the point is within the radius
if (distance > radius)
{
// add the point to the new list
radiusListOutput.push_back(*it);
}
}
}
Again using copy if:
struct RadiusChecker {
RadiusChecker(const Point& center, float radius)
: center_(center), radius_(radius) {}
bool operator()(const Point& p)
{
const float distance = sqrt(pow(center_.x - p.x, 2) +
pow(center_.y - p.y, 2));
return distance < radius_;
}
private:
const Point& center_;
float radius_;
};
void find_points_within_radius(vector<Point>& radiusListOutput,
const list<Point>& pointList,
const Point& center, float radius)
{
radiusListOutput.reserve(pointList.size());
remove_copy_if(pointList.begin(), pointList.end(),
radiusListOutput.begin(),
RadiusChecker(center, radius));
}
Note that the sqrt can be removed if you need extra performance since the square of the magnitude works just as well for these comparisons. Also, if you really want to increase performance than consider a data structure that allows for scene partitioning like a quadtree. The first problem is closely related to collision detection and there is a ton of valuable information about that topic available.
You are right on how it should be made. Just iterate through all items in the list and keep track of the smallest distance already found, and the nearest point you found in two variables, making sure you don't match the point with itself if the problem states so. Then just delete the point you found.
How this is exactly made is kept as an exercise.
If you want to get a list of points in a given radius from another point, iterate the list and build a second list containing only the points within the specified range.
Again, how it's made in code is left to you as an exercise.
You can do this using a combination of the STL and Boost.Iterators and Boost.Bind -- I'm pasting the whole source of the solution to your problem here for your convenience:
#include <list>
#include <cmath>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/bind.hpp>
#include <cassert>
using namespace std;
using namespace boost;
struct Point {
int x, y;
Point() : x(0), y(0) {}
Point(int x1, int y1) : x(x1), y(y1) {}
Point(Point const & other) : x(other.x), y(other.y) {}
Point & operator=(Point rhs) { rhs.swap(*this); return *this; }
void swap(Point & other) { std::swap(other.x, x); std::swap(other.y, y); }
};
double point_distance(Point const & first, Point const & second) {
double x1 = first.x;
double x2 = second.x;
double y1 = first.y;
double y2 = second.y;
return sqrt( ((x2 - x1) * (x2 -x1)) + ((y2 - y1) * (y2 - y1)) );
}
int main(int argc, char * argv[]) {
list<Point> points;
points.push_back(Point(1, 1));
points.push_back(Point(2, 2));
points.push_back(Point(3, 3));
Point source(0, 0);
list<Point>::const_iterator closest =
min_element(
make_transform_iterator(
points.begin(),
bind(point_distance, source, _1)
),
make_transform_iterator(
points.end(),
bind(point_distance, source, _1)
)
).base();
assert(closest == points.begin());
return 0;
}
The meat of the solution is to transform each element in the list using the transform iterator using the point_distance function and then get the minimum distance from all the distances. You can do this while traversing the list, and in the end reach into the transform_iterator to get the base iterator (using the base() member function).
Now that you have that iterator, you can replace the assert(closest == points.begin()) with points.erase(closest).
I agree with the previous solution, and just wanted to add another thought. Although your Point class isn't very large and so a copy isn't really a problem, you might consider using Point* for your list. This way, when you create your second list, you would store the pointer to the same class. The down-side of this would be if you were deleting from multiple lists without a "master" that manages all created points, you could either create a memory leak if you didn't delete the underlying class or accidentally delete a class that was still being used in another list. Something to consider, though, depending on how your system evolves.
You have to keep the iterator to delete it afterwards.
std::list<Point>::iterator closest;
std::list<Point>::iterator it = pointList.begin();
double min_dist=dist(your_point, *it);
++it;
for (; it != pointList.end(); ++it)
{
double actual_dist = dist(your_point, *it);
if (actual_dist < min_dist)
{
min_dist = actual_dist;
closest = it;
}
}
pointList.erase(closest);