判断当前鼠标位置是否落在直线上面

在开发图片编辑功能时,作者遇到一个问题,即如何判断鼠标坐标是否在图形上。传统的边缘矩形判断方法不理想。通过数学方法,利用线段的两个端点、长度、与X轴的夹角以及虚线与图形的距离,可以计算出平行于线段的虚线边界的点,从而更精确地识别鼠标是否在图形内。代码示例展示了如何使用QLineF和QPointF进行计算。
摘要由CSDN通过智能技术生成

最近在搞图片编辑功能,发现有意思地方,也花费不少时间精力,今天mark下

图片编辑功能,很重要一个细节,就是要判断当前鼠标坐标是否落在某个图形上

最简单的做法,就是求得图像的边缘矩形框,然后判断是否包含该点,如:

红色框就是直线的边缘,

很显然这不是我们想要的

  1. 首先范围太大了,会遮挡其他“元件”的范围,实际使用体验效果非常差
  2. 第二对于水平方向或接近水平向的直线,范围又太小了,垂直方向也是同样问题。实际结果是判断不到范围

 实际上,我们想要效果应该是这样的:

 如图,虚线所示,这个才是我们想要的边缘效果。

那么问题来了,回归到数学知识了,如何生成这个虚线呢?(如何获取这些点)

首先,看下已知条件:

1. 线段的两个点,start、end点,的坐标是已知的

2. 那么,线段长度L也是已知的

3. 线段与X轴夹角a也是已知(与Y轴夹角b也是已知,且存在a+b=90°关系)

4. 虚线与直线是平行关系,且与线段的距离 s 也是已知的

 

那么存在如下关系:

\Delta x =\frac{ \left | start.y - end.y \right |}{L} \times s 

\Delta y =\frac{ \left | start.x - end.x \right |}{L} \times s

那么,平行线的起点、终点的坐标都知道了

 这个方法比较简单,效果也很好

利用相似三角形原理

 翠花上code

    QLineF line(start,end);
    qreal distance = abs(line.length());
    QPointF p1,p2,p3,p4,p5,p6;

// 
        qreal dy = abs(start.y() - end.y()) * len / distance;
        qreal dx = abs(start.x() - end.x()) * len / distance;

        QPointF newStart = start;
        QPointF newEnd = end;

        if(start.x() > end.x())
        {
            newStart = end;
            newEnd = start;
        }

        if(newStart.y() >= newEnd.y())
        {
            p1.setX(newStart.x() - dy);
            p1.setY(newStart.y() - dx);

            p2.setX(newStart.x() - dx);
            p2.setY(newStart.y() + dy);

            p3.setX(newStart.x() + dy);
            p3.setY(newStart.y() + dx);

            p4.setX(newEnd.x() + dy);
            p4.setY(newEnd.y() + dx);

            p5.setX(newEnd.x() + dx);
            p5.setY(newEnd.y() - dy);

            p6.setX(newEnd.x() - dy);
            p6.setY(newEnd.y() - dx);
        }
        else
        {
            p1.setX(newStart.x() + dy);
            p1.setY(newStart.y() - dx);

            p2.setX(newStart.x() - dx);
            p2.setY(newStart.y() - dy);

            p3.setX(newStart.x() - dy);
            p3.setY(newStart.y() + dx);

            p4.setX(newEnd.x() - dy);
            p4.setY(newEnd.y() + dx);

            p5.setX(newEnd.x() + dx);
            p5.setY(newEnd.y() + dy);

            p6.setX(newEnd.x() + dy);
            p6.setY(newEnd.y() - dx);
        }

        points << p1 << p2 << p3 << p4 << p5 << p6;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值