效果预览
代码
QPointF ClosestPointOnPath(const QPointF &point, const QPainterPath &path)
{
if (path.isEmpty()) return point;
auto vec = QVector2D(point);
auto poly = path.toFillPolygon();
float d, minDist = FLT_MAX;
QVector2D p, q, v, u, minVec;
for (int k = 0; k < poly.count() - 1; k++)
{
p = QVector2D(poly.at(k));
if (k == poly.count() - 1)
k = -1;
q = QVector2D(poly.at(k + 1));
v = q - p;
u = v.normalized();
d = QVector2D::dotProduct(u, vec - p);
if (d < 0.0f) {
d = (vec - p).lengthSquared();
if (d < minDist)
{
minDist = d;
minVec = p;
}
}
else if (d*d > v.lengthSquared())
{
d = (vec - q).lengthSquared();
if (d < minDist)
{
minDist = d;
minVec = q;
}
}
else {
u *= d;
u += p;
d = (vec - u).lengthSquared();
if (d < minDist)
{
minDist = d;
minVec = u;
}
}
}
if (minDist >= FLT_MAX) return point;
return minVec.toPointF();
}