【问题标题】:find one same element among several object在多个对象中找到一个相同的元素
【发布时间】:2019-08-13 03:21:05
【问题描述】:

目前我正在做与多边形相关的工作。多边形可以描述为几个顶点。

struct Polygon{
   vector<Point2D> vertex;
   Color color;
};

现在,我已经有了一些多边形vector polygons

一个方法可以告诉我一个点在哪个多边形内

Polygon queryPolygon(Point2D point);

我需要设置返回多边形的颜色。

我的第一个问题是如何知道返回的多边形是否在我已经拥有的vector polygons内。

我的第一个想法是使用 unordered_set 并比较 (vertex.begin(), vertex.end())。不知道有没有更好的办法。

另一个问题是某些多边形可能包含相同的边。如何设计数据结构,以便我可以知道包含相同边的多边形

vector<Polygon> queryPolygonWithSameEdge(Point2D edgeStart, Point2D edgeEnd);

当然蛮力是一种方法,但有没有更好的想法?

谢谢。

【问题讨论】:

  • 如果你给你的多边形唯一的ID(地址也可以用作ID),第一个问题就变得微不足道了。对于第二个问题,您可以考虑std::multimap&lt;Edge, Polygon*&gt;,其中Edge 是一对点。要么确保 Edge 始终根据某种方法排序,要么插入两个 Point2D 排列以形成优势。
  • 你需要澄清你的第一个问题:1)你认为多边形是一个表面(点在由顶点设置的边界内的任何地方)还是一组边(只有边上的点) ? 2)如果查询点在任何已知多边形之外会发生什么? 3) 查询是否返回现有多边形之一,或者它是否会创建一个由最近顶点定义的新多边形?还是通过现有多边形的交集?

标签: c++ algorithm data-structures geometry


【解决方案1】:

第一个问题

关于第一个问题有一些不清楚的方面(请参阅我的 cmets)。尽管如此,我还是会回答,假设您只想将查询返回的任意多边形与存储在向量中的已知多边形进行比较,例如:

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";

比较多边形(第 1 级)

第一级是逐点比较。问题在于点的顺序确实很重要,因为对于完全相同的点,您可以绘制pentagonpentagram,这取决于选择的顺序以及您是否接受self-intersecting polygons

用于简单比较两个向量中的顶点是否相同:

bool compare1(const vector<Point2D> &x, const vector<Point2D> &y ) {
    return x==y;  
}

不幸的是,如果您有两个相同的多边形,这将不起作用,它们只是使用不同的起点表示。

比较多边形(第 2 级)

在这里,我们处理一个潜在的不同起点。所以第一件事是找到第一个多边形的第一个点在第二个多边形中的偏移量,并通过照顾偏移量进行比较。如果在第二个多边形中没有找到该点,则它们不一样:

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

比较多边形(第 3 级)

现在,点也可能相同,但第一个多边形顺时针方向,第二个逆时针方向。所以我们需要双向检查:

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

这里有一个online demo

比较多边形(第 4 级)

现在不排除两个连续的边缘完全对齐。因此,多边形可能有一个与比较无关的附加点。

我让你作为这个案子的处理工作。但是处理这种特殊情况的最自然的地方是填充多边形时。

第二个问题

要找出公共边,恕我直言,最简单的方法是将边添加到map,理解为您将对它们进行归一化以确保点始终处于相同的顺序。

您可以将任何您想要的东西关联到边缘,例如:计数、颜色或带有指向所属多边形的指针的容器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    • 2022-01-18
    • 1970-01-01
    • 2012-03-07
    • 2018-09-15
    • 2019-09-08
    • 1970-01-01
    相关资源
    最近更新 更多