我怎么删除最近的"点"的对象在一STD::列出一些x、y?
题
我有一点类似的:
class Point {
public:
int x, y;
Point(int x1, int y1)
{
x = x1;
y = y1;
}
};
和一个列表中的点:
std::list <Point> pointList;
std::list <Point>::iterator iter;
我快点,我pointList(虽然名单可能没有包含点,但如果没有被推迟)。
我有两个问题:
我怎么可以删除的最近点到一些任意的(x,y)从名单?
可以说我有x,y(第5、12)和我想找点列表中的最接近于这一点,并将其从STD::名单。
我知道我会有用的距离公式我有迭代使用的一个迭代,但我有一些麻烦构思如何,我会跟踪这点是最近作为我迭代过该列表。
我怎么能回返的一系列或列表内的点x半径定(x,y)?
类似于后一个问题,除了我需要一个列表指针指向的"点"的对象在说半径5个给定(x,y)。此外,我应该返回的一系列或一个清单?
如果有人能帮助我出去,我仍然挣扎我的方式通过C++和我欣赏它。
解决方案
使用一个std ::目录::迭代变量来跟踪最近的点,你遍历列表。当你到了列表的末尾它将包含最近的点,可以用来删除该项目。
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);
}
}
给定的点的半径内构建点的列表是类似的。需要注意的是一个空的半径列表是通过引用传递给函数。添加点到列表通过引用将消除对由值返回向量当复制所有点的需要。
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);
}
}
}
再次使用副本,如果:
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));
}
注意的开方可以,如果你需要额外的性能,因为幅度的平方的作品一样好这些比较中移除。另外,如果你真的想提高性能不是考虑的数据结构,允许现场分区像四叉树一>。第一个问题是密切相关的碰撞检测并有一吨的关于该主题的有价值的信息可用。
其他提示
您是对的,应该如何进行。刚刚经历列表中的所有项目进行迭代,并跟踪最小距离已经发现了,你在两个变量中找到的最近点,确保你不点与本身如果问题状态,以便匹配。然后,只需删除您找到的点。
这是如何精确地制成保持作为练习。
如果你想获得点的列表,从另外一个角度给定半径,迭代列表,并构建包含指定范围内只点一个第二列表。
再次它是如何在代码所做留给您作为一个练习。
你可以做到这一组合使用了STL和 提升。迭代 和 提升。绑定的 -我粘贴的整个来源解决你的问题在这里为了您的方便:
#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;
}
肉的解决方案是改变每个元素的列表中使用的变换迭代使用 point_distance
功能,并随后得到的最小距离,从所有距离。你可以这样做的同时,穿过该列表,并在结束时达到入 transform_iterator
获得基迭代(使用 base()
部件的功能)。
现在你有了这些迭代,你可以替代的 assert(closest == points.begin())
与 points.erase(closest)
.
我同意以前的解决方案,而只是想补充另一个想法。虽然贵点类不是非常大,所以副本是不是真的有问题,你可以考虑使用点*为您的列表。这样,当您创建第二个列表,则可以将存储指向同一类。这样做的下侧是,如果你是从多个列表没有管理所有创建点“主”删除,你既可以创建一个内存泄漏,如果你没有删除底层类或意外删除一类仍然是在另一个列表中使用。要考虑的事情,不过,这取决于你的系统是如何演变。
您必须不断迭代事后删除它。
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);