zoukankan      html  css  js  c++  java
  • Segment

    #pragma once
    #include <vector>
    
    #define PI   3.1415926535897932384626433832795
    #define DB_MAX         1.7976931348623158e+308 /* max value */
    
    typedef struct _MyPoint
    {
        double x;
        double y;
    
        _MyPoint(double x, double y)
        {
            this->x = x;
            this->y = y;
        }
    
    }MyPoint;
    
    typedef struct _MyRect
    {
        double x;
        double y;
        double width;
        double height;
    
        _MyRect(double x, double y, double width, double height)
        {
            this->x = x;
            this->y = y;
            this->width = width;
            this->height = height;
        }
    
    }MyRect;
    
    //一条线段,有起点和终点
    class CSegment
    {
    public:
        CSegment();
        CSegment(MyPoint p1, MyPoint p2);
        CSegment(const double& x1, const double& y1, const double& x2, const double& y2);
        ~CSegment();
    
    public:
        double x1, y1, x2, y2;        //线段的断点坐标
    
    public:
        //判断两直线是否平行,定义最大误差角度
        bool AngleDiffAbs(CSegment& os, const double& dDiff = 1.0);
        //两直线的交点
        bool IntersectionLine(CSegment& os, MyPoint& pInter);
        //两线段的交点
        bool IntersectionSeg(CSegment& os, MyPoint& pInter);
        //判断是否与某个矩形区域相交
        bool IsPartInRect(const MyRect& rect);
        //点是否在直线上
        bool IsPointInLine(const MyPoint& pt, const double& dDiff = 0.01);
        //点是否在线段上
        bool IsPointInSeg(const MyPoint& pt, const double& dDiff = 1.0);
        //判断两直线是否垂直,定义最大误差角度
        bool VerAngleDiffAbs(CSegment& os, const double& dDiff = 1.0);
    
        //获取线段的中点
        MyPoint GetCenter();
        //获取点到直线的垂线段与直线的交点
        MyPoint GetVerticalPoint(const MyPoint& pt);
        //获取线段在某张图片中的正方形区域
        MyRect GetSquare(const int& nImgWidth, const int& nImgHeight, const int nSideLength);
        //获取线段所在的最小矩形区域,定义最小宽度
        MyRect GetRect(const int& nMinGap = 8);
        //获取线段在图像内部的最小矩形区域,定义最小宽度
        MyRect GetRect(const int& nImgWidth, const int& nImgHeight, const int& nMinGap = 8);
    
        //与x轴正向的夹角,-90到+90度
        double Angle();
        //两条线段中点的距离
        double CenterGap(CSegment& os);
        //长度
        double Length();
    
        double GapFromPoint(const MyPoint& pt);
        //斜率
        double Slope();
    
        int Offset(const int& x, const int& y);
    
    private:
        double TwoPointsGap(const MyPoint& p1, const MyPoint& p2);
        double TwoPointsGap(const double& x1, const double& y1, const double& x2, const double& y2);
    };
    #include "Segment.h"
    
    CSegment::CSegment()
    {
    }
    
    
    CSegment::CSegment(MyPoint p1, MyPoint p2)
    {
        x1 = p1.x;
        y1 = p1.y;
        x2 = p2.x;
        y2 = p2.y;
    }
    
    CSegment::CSegment(const double& x1, const double& y1, const double& x2, const double& y2)
    {
        this->x1 = x1;
        this->y1 = y1;
        this->x2 = x2;
        this->y2 = y2;
    }
    
    CSegment::~CSegment()
    {
    
    }
    
    bool CSegment::AngleDiffAbs(CSegment& os, const double& dDiff /*= 1.0*/)
    {
        return fabs(Angle() - os.Angle()) <= dDiff;
    }
    
    bool CSegment::IntersectionLine(CSegment& os, MyPoint& pInter)
    {
        //第一条直线的参数
        double a0 = y1 - y2;
        double b0 = x2 - x1;
        double c0 = x1 * y2 - x2 * y1;
    
        double x3 = os.x1;
        double y3 = os.y1;
        double x4 = os.x2;
        double y4 = os.y2;
    
        //第二条直线的参数
        double a1 = y3 - y4;
        double b1 = x4 - x3;
        double c1 = x3 * y4 - x4 * y3;
    
        //求交点
        double D = a0 * b1 - a1 * b0;
    
        if (fabs(D) < 0.00001)
        {
            //无交点
            return false;
        }
    
        pInter.x = (b0 * c1 - b1 * c0) / D;
        pInter.y = (c0 * a1 - c1 * a0) / D;
    
        return true;
    }
    
    bool CSegment::IntersectionSeg( CSegment& os, MyPoint& pInter )
    {
        bool bRes = IntersectionLine(os, pInter);
        return bRes && IsPointInSeg(pInter) && os.IsPointInSeg(pInter);
    }
    
    bool CSegment::IsPartInRect(const MyRect& rect)
    {
        return x1 >= rect.x && x1 <= rect.x + rect.width && y1 >= rect.y && y1 <= rect.y + rect.height ||
            x2 >= rect.x && x2 <= rect.x + rect.width && y2 >= rect.y && y2 <= rect.y + rect.height;
    }
    
    bool CSegment::IsPointInLine(const MyPoint& pt, const double& dDiff/* = 0.01*/)
    {
        return GapFromPoint(pt) <= dDiff;
    }
    
    bool CSegment::IsPointInSeg(const MyPoint& pt, const double& dDiff/* = 1.0*/)
    {
        //考虑到图像的特殊性,不需要斜率相同,只需要用距离判断即可
        return TwoPointsGap(pt, MyPoint(x1, y1)) + TwoPointsGap(pt, MyPoint(x2, y2)) - Length() <= dDiff;
    }
    
    bool CSegment::VerAngleDiffAbs(CSegment& os, const double& dDiff /*= 1.0*/)
    {
        return fabs(Angle() - os.Angle()) >= 90.0 - dDiff && fabs(Angle() - os.Angle()) <= 90 + dDiff;
    }
    
    MyPoint CSegment::GetCenter()
    {
        return MyPoint((x1 + x2) / 2, (y1 + y2) / 2);
    }
    
    MyPoint CSegment::GetVerticalPoint(const MyPoint& pt)
    {
        if (Slope() == DBL_MAX)
        {
            //如果是垂直的直线
            double x = x1;
            double y = pt.y;
            return MyPoint(x, y);
        }
    
        if (fabs(Slope()) <= 0.00001)
        {
            //如果是水平的直线
            double x = pt.x;
            double y = y1;
            return MyPoint(x, y);
        }
    
        //四舍五入
        double x = (Slope()* x1 + pt.y + 1 / Slope() * pt.x - y1) /(Slope() + 1 / Slope());
        double y = Slope() * x + y1 - Slope() * x1;
    
        return MyPoint(x, y);
    }
    
    MyRect CSegment::GetSquare(const int& nImgWidth, const int& nImgHeight, const int nSideLength)
    {
        MyPoint center = GetCenter();
    
        int x = center.x - nSideLength / 2;
        int y = center.y - nSideLength / 2;
        int width = nSideLength;
        int height = nSideLength;
    
        if (x < 0)
        {
            x = 0;
            width = center.x + nSideLength / 2;
        }
    
        if (y < 0)
        {
            y = 0;
            height = center.y + nSideLength / 2;
        }
    
        if (x + width > nImgWidth)
        {
            width = nImgWidth - x;
        }
    
        if (y + height > nImgHeight)
        {
            height = nImgHeight - y;
        }
    
        return MyRect(x, y, width, height);
    }
    
    double CSegment::Angle()
    {
        return atan(Slope()) / PI * 180;
    }
    
    double CSegment::Slope()
    {
        if (fabs(x1 - x2) <= 0.0001)
        {
            return DB_MAX;
        }
    
        return (y1 - y2) / (x1 - x2);
    }
    
    double CSegment::Length()
    {
        return sqrt((y1 - y2) * (y1 - y2) + (x1 - x2) * (x1 - x2));
    }
    
    MyRect CSegment::GetRect(const int& nMinGap /*= 8*/)
    {
        //只是得到矩形区域,可能为负
        int x = x1 < x2 ? x1 : x2;
        if (abs(y2 - y1) <= nMinGap)
        {
            int y = (y1 + y2) / 2 - nMinGap / 2;
            int width = abs(x1 - x2);
            if (width <= nMinGap)
            {
                x = (x1 + x2) / 2 - nMinGap / 2;
                width = nMinGap;
            }
    
            int height = nMinGap;
            return MyRect(x, y, width, height);
        }
        else
        {
            int y = y1 < y2 ? y1 : y2;
            int width = abs(x1 - x2);
            if (width <= nMinGap)
            {
                x = (x1 + x2) / 2 - nMinGap / 2;
                width = nMinGap;
            }
            int height = abs(y1 - y2);
            return MyRect(x, y, width, height);
        }
    }
    
    MyRect CSegment::GetRect(const int& nImgWidth, const int& nImgHeight, const int& nMinGap /*= 8*/)
    {
        MyRect roi = GetRect(nMinGap);
    
        if (roi.x < 0)
        {
            roi.x = 0;
        }
    
        if (roi.x + roi.width > nImgWidth)
        {
            roi.width = nImgWidth - roi.x;
        }
    
        if (roi.y < 0)
        {
            roi.y = 0;
        }
    
        if (roi.y + roi.height > nImgHeight)
        {
            roi.height = nImgHeight - roi.y;
        }
        
        return roi;
    }
    
    double CSegment::CenterGap(CSegment& os)
    {
        MyPoint p1 = GetCenter();
        MyPoint p2 = os.GetCenter();
    
        return TwoPointsGap(p1, p2);
    }
    
    double CSegment::GapFromPoint(const MyPoint& pt)
    {
        double k = Slope();
    
        if (k == DBL_MAX)
        {
            //垂直的时候直接返回差值
            return fabs(x1 - pt.x);
        }
    
        double b = y1 - k * x1;
    
        return fabs(k * pt.x - pt.y + b) / sqrt( 1 + k * k);
    }
    
    int CSegment::Offset(const int& x, const int& y)
    {
        x1 += x;
        y1 += y;
        x2 += x;
        y2 += y;
    
        return 0;
    }
    
    double CSegment::TwoPointsGap(const MyPoint& p1, const MyPoint& p2)
    {
        return TwoPointsGap(p1.x, p1.y, p2.x, p2.y);
    }
    
    double CSegment::TwoPointsGap(const double& x1, const double& y1, const double& x2, const double& y2)
    {
        return sqrt((y1 - y2) * (y1 - y2) + (x1 - x2) * (x1 - x2));
    }
  • 相关阅读:
    【转】Android-Input input&按键布局文件
    【转】Android-Input 触摸设备
    【转】IE沙箱拖拽安全策略解析
    FireFox 插件xpi文件签名2
    如何给Firefox附加组件签名
    【转】用opencv使摄像头在30fps下捕获1080p的数据
    Displaylink安卓驱动
    无主之地2 不费子弹手枪
    jsoncpp
    [APIO2010] 算法竞赛竞赛经典 巡逻
  • 原文地址:https://www.cnblogs.com/autumoonchina/p/7243063.html
Copyright © 2011-2022 走看看