优化/简化许多点靠近的路径?

时间:2011-08-12 03:51:12

标签: c++ algorithm graph-theory

我有一条表示多边形轮廓的点的路径。路径由像素构成。

这意味着所有点都非常接近,但我确保它们都是独一无二的。

现在我正在检查3点是否共线,如果是,我将删除中间点。

我使用点积检查它们是否共线。然而,我观察到我的许多点积都是0.0f。可能有什么不对?

void ImagePolygon::computeOptimized()
{
    m_optimized = m_hull;

    m_optimized.erase(
        std::unique(m_optimized.begin(),
        m_optimized.end()),
        m_optimized.end());

    int first = 0;
    int second = 1;

    std::vector<int> removeList;

     for(int i = 2; i < m_optimized.size(); ++i)
        {
            second = i - 1;
            first = i - 2;

            if(isColinear(m_optimized[i - 2],m_optimized[i - 1],m_optimized[i]))
            {
                m_optimized.erase(m_optimized.begin() + i - 1);
            removeList.push_back(i - 1);
            }
        }

     std::sort(removeList.rbegin(),removeList.rend());
     for(int i = 0; i < removeList.size(); ++i)
     {
        m_optimized.erase(m_optimized.begin() + removeList[i]);
     }

}

bool ImagePolygon::isColinear( const b2Vec2& a, const b2Vec2& b, const b2Vec2& c ) const
{
    b2Vec2 vec1 = b2Vec2(b.x - a.x, b.y - a.y);
    vec1.Normalize();
    b2Vec2 vec2 = b2Vec2(c.x - b.x, c.y - b.y);
    vec2.Normalize();

    float dotProduct = vec1.x * vec2.x + vec1.y * vec2.y;

    //test value
    return abs(dotProduct) > 0.00001f;
}

主要的问题是,当我不应该这样时,我会得到很多0点产品,因此无论我在何处设置阈值,路径都没有达到应有的优化程度。

由于

float32 Normalize()
{
    float32 length = Length();
    if (length < b2_epsilon)
    {
        return 0.0f;
    }
    float32 invLength = 1.0f / length;
    x *= invLength;
    y *= invLength;

    return length;
}

3 个答案:

答案 0 :(得分:3)

您需要2x2行列式vec1.x * vec2.y - vec1.y * vec2.x而不是点积。如果点是共线的,则行列式为零,而如果点形成直角,则点积为零。

答案 1 :(得分:0)

此:

return abs(dotProduct) > 0.00001f;

实际上是在告诉你你的矢量是否(不)是垂直的,而不是它们是否是平行的。检查它是否接近1而不是接近0并行。

答案 2 :(得分:0)

如果删除元素,则不应增加索引。你正在跳过一些值。请尝试以下方法:

for(int i = 2; i < m_optimized.size();) {
    second = i - 1;
    first = i - 2;
    if (isColinear(m_optimized[i - 2],m_optimized[i - 1],m_optimized[i])) {
        m_optimized.erase(m_optimized.begin() + i - 1);
        removeList.push_back(i - 1);
    } else i++;
}

我也无法理解removeList的目的。您擦除主循环内的一些点并尝试擦除辅助循环中的相同点。这似乎是一个错误。顺便说一下,由于它的构造方式,没有理由对removeList进行排序。