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

Optimizing / simplifying a path where many points are close together?

本文关键字:多点 靠近 路径 许多点 优化      更新时间:2023-10-16

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

这意味着所有点彼此非常非常接近,但我确保它们都是唯一的。

现在我要检查3个点是否共线,如果是,我就去掉中间的那个。

我用点积检查它们是否共线。但是我发现很多点积都是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;
}

你想要2x2行列式vec1.x * vec2.y - vec1.y * vec2.x而不是点积。当点共线时行列式为零,当点成直角时点积为零。

This:

return abs(dotProduct) > 0.00001f;

实际上是告诉你向量是否垂直,而不是它们是否平行。检查parallel是否接近1而不是接近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的构造方式,没有理由对其进行排序。