您的位置:首页 > 其它

直线线段的点击判断

2016-03-05 10:06 162 查看

前言

要做直线线段的点击判断, 如果击中画直线线段的控制点为选中状态.
一点在直线上应符合2个条件:
* 该点在直线线段的延长线上
* 该点在线段的起点和终点围起的正矩形内

demo

BOOL CShapeLine::IsPtOnShape(CPoint pt) {
    // y = kx + b ///< 直线通项公式
    /*
        y1 = kx1 + b
        y2 = kx2 + b
        b = y2 - kx2
        y1 = kx1 + (y2 - kx2)
        y1 = kx1 + y2 - kx2
        y1 = k(x1 - x2) + y2
        k = (y1 - y2) / (x1 - x2); ///< 已知2点求斜率的公式(公式1)
        b = y2 - kx2; ///< 已知2点求截距的公式(公式2)
    */

    /// 如果一点是线段延长线上一点, 且在线段起点和终点圈定的正矩形内
    /// 该点就是该线段上的一点, 即可判定为击中线段

    const int nOffsetMax = 10; ///< 在判断条件的 nOffsetMax ppx内, 就算击中线段
    int nOffsetX = 0; ///< 目标点距离直线延长线的y距离
    int nOffsetY = 0; ///< 目标点距离直线延长线的x距离
    double k = 0; ///< 直线斜率
    double b = 0; ///< 直线截距
    double x1 = 0; ///< 线段上的起点和终点
    double y1 = 0;
    double x2 = 0;
    double y2 = 0;
    double yOk = 0; ///< 直线延长线上的一点(xOk, yOk)
    double xOk = 0;
    BOOL bPtOnLineExt = FALSE; ///< 是否为直线线段延长线上的一点.
    BOOL bPtOnRect = FALSE; ///< 是否入参点在线段起点和终点圈出的正矩形内.

    if (!(m_bValidPtBegin && m_bValidPtEnd)) {
        return FALSE;
    }

    x1 = m_ptBegin.x;
    y1 = m_ptBegin.y;
    x2 = m_ptEnd.x;
    y2 = m_ptEnd.y;

    k = (y1 - y2) / (x1 - x2);
    b = y2 - k*x2;

    // y = kx + b
    yOk = k*pt.x + b;

    // x = (y - b) / k
    xOk = (pt.y - b) / k;

    nOffsetY = abs(pt.y - (int)yOk);
    nOffsetX = abs(pt.x - (int)xOk);
    bPtOnLineExt = (min(nOffsetX, nOffsetY) <= nOffsetMax);
    bPtOnRect = (pt.x >= ((min(m_ptBegin.x, m_ptEnd.x) - nOffsetMax))
        && (pt.x <= (max(m_ptBegin.x, m_ptEnd.x) + nOffsetMax))
        && (pt.y >= (min(m_ptBegin.y, m_ptEnd.y) - nOffsetMax))
        && (pt.y <= (max(m_ptBegin.y, m_ptEnd.y) + nOffsetMax)));

    return (bPtOnLineExt && bPtOnRect);
}


void CShapeLine::OnDrawWasSelect(CDC* pDC) {
    CPen* pPenOrg = NULL;
    CBrush* pBrushOrg = NULL;
    const int nOffset = 6; ///< 控制点选择块的r/2
    
    if (NULL == pDC) {
        return;
    }
    
    if (m_bValidPtBegin) {
        CPen pen(PS_DOT,
            1,
            GetShapeParam()->m_crColorPen);

        CBrush brush(GetShapeParam()->m_crColorPen);
        
        pPenOrg = pDC->SelectObject(&pen);
        pBrushOrg = pDC->SelectObject(&brush);
        
        CPoint pt1 = CPoint(m_ptBegin.x, m_ptBegin.y);
        CPoint pt3 = CPoint(m_ptEnd.x, m_ptEnd.y);
        
        /// 增强的控制点总是能比原来的控制点大一些
        pDC->MoveTo(pt1.x - nOffset , pt1.y - nOffset);
        pDC->LineTo(pt1.x + nOffset , pt1.y - nOffset);
        pDC->LineTo(pt1.x + nOffset , pt1.y + nOffset);
        pDC->LineTo(pt1.x - nOffset , pt1.y + nOffset);
        pDC->LineTo(pt1.x - nOffset , pt1.y - nOffset);

        /// Rectangle填充的小矩形好难看啊(锯齿特别严重, 矩形越小看的越明显), 丑哭了
        // pDC->Rectangle(pt1.x - nOffset , pt1.y - nOffset, pt1.x + nOffset, pt1.y + nOffset);

        pDC->MoveTo(pt3.x - nOffset , pt3.y - nOffset);
        pDC->LineTo(pt3.x + nOffset , pt3.y - nOffset);
        pDC->LineTo(pt3.x + nOffset , pt3.y + nOffset);
        pDC->LineTo(pt3.x - nOffset , pt3.y + nOffset);
        pDC->LineTo(pt3.x - nOffset , pt3.y - nOffset);

        // pDC->Rectangle(pt3.x - nOffset , pt3.y - nOffset, pt3.x + nOffset , pt3.y + nOffset);
        
        pDC->SelectObject(pBrushOrg);
        pDC->SelectObject(pPenOrg);
    }
}


显示效果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: