我有一条表示多边形轮廓的点的路径。路径由像素构成。
这意味着所有点都非常接近,但我确保它们都是独一无二的。
现在我正在检查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;
}
答案 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
进行排序。