Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2563679
  • 博文数量: 315
  • 博客积分: 3901
  • 博客等级: 少校
  • 技术积分: 3640
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-08 15:32
个人简介

知乎:https://www.zhihu.com/people/monkey.d.luffy Android高级开发交流群2: 752871516

文章分类

全部博文(315)

文章存档

2019年(2)

2018年(1)

2016年(7)

2015年(32)

2014年(39)

2013年(109)

2012年(81)

2011年(44)

分类: C/C++

2013-06-14 21:53:22

    前段时间因为项目需要进行优化,此时需要用到裁剪算法,因此网上找了下,也看了一些文献啥的,找了一些还可以,不是特别复杂,但是有bug的代码,自己也是根据需要进行了修改,实在不想花时间在实现上了,且任务也是紧迫。其实逻辑和数学挺重要的,至少现在用到了很多数学知识。逻辑,业务还需要不断学习和加强。感谢网友分享...
cut.hpp

点击(此处)折叠或打开

  1. #ifndef CUT_HPP_INCLUDED
  2. #define CUT_HPP_INCLUDED

  3. #include <stdint.h> //typedef short int int16_t;
  4.                     //typedef unsigned short int uint16_t;

  5. ///< 多边形剪切
  6. #define Rectangle_Right 1
  7. #define Rectangle_Bottom 2
  8. #define Rectangle_Left 3
  9. #define Rectangle_Top 4
  10. #define CutCount_N 50

  11. typedef struct _Point
  12. {
  13.     int16_t x;
  14.     int16_t y;
  15. } Point;

  16. ///< 直线起始点
  17. typedef struct _RtVector
  18. {
  19.     Point sp;
  20.     Point ep;
  21. }RtVector;

  22. ///< 矩形框
  23. typedef struct _Rectangle
  24. {
  25.         int16_t x;
  26.         int16_t y;
  27.         uint16_t width;
  28.         uint16_t height;
  29. } Rectangle;

  30. /**
  31.   * @brief 矩形裁剪直线
  32.   * @param[in/out] vector - 直线的起始点坐标
  33.   * @param[in] rect - 矩形框范围
  34.   * @return 成功裁剪true,裁剪结果保存在vector中,如果不再裁剪区域范围则返回false.
  35.   * @note 此接口如果裁剪结果为一个点相交,则算作不再裁剪区域范围内.
  36.   */
  37. bool _rtPruneLB(RtVector * vector, Rectangle rect);

  38. /**
  39.   * @brief 矩形裁剪多边形
  40.   * @param[in] Xwmax - 矩形框x轴最大值
  41.   * @param[in] Xwmin - 矩形框x轴最小值
  42.   * @param[in] Ywmax - 矩形框y轴最大值
  43.   * @param[in] Ywmin - 矩形框y轴最小值
  44.   * @param[in] n - 多边形顶点个数
  45.   * @param[in] x - 多边形x坐标点
  46.   * @param[in] y - 多边形y坐标
  47.   * @param[out] xout - 裁剪得到的多边形具有一定顺序的x坐标点序
  48.   * @param[out] yout - 裁剪得到的多边形具有一定顺序的y坐标点序
  49.   * @return 返回裁剪后的多边形的顶点个数,如果不再裁剪区域范围则返回0.
  50.   * @note 调用约定:
  51.   * 1> 多边形顶点序列要么都是顺时针【裁剪得到的多边形是顺时针点序】,要么都是逆时针【裁剪得到的多边形是逆时针点序】;
  52.   * 2> xout和yout的数组大小至少为20;
  53.   * 注意:
  54.   * 1> xout和yout具有一一对应关系;
  55.   */
  56. int clip_polygon(int Xwmax, int Xwmin,
  57.                  int Ywmax, int Ywmin,
  58.                  int n, float * x, float * y,
  59.                  float * xout, float * yout);

  60. #endif // CUT_HPP_INCLUDED
cut.cpp

点击(此处)折叠或打开

  1. #include "cut.hpp"
  2. #include <iostream>
  3. #include "cut.hpp"

  4. using namespace std;

  5. static void clip_single_edge(int edge, int type,
  6.                              int nin, float * xin,
  7.                              float * yin, int * nout,
  8.                              float * xout, float * yout);

  9. static void test_intersect(int edge, int type,
  10.                            float x1, float y1,
  11.                            float x2, float y2,
  12.                            float * xout, float * yout,
  13.                            int * yes, int * is_in);

  14. bool _rtPruneLB(RtVector * vector, Rectangle rect)
  15. {
  16.     RtVector dest;
  17.     bool flag = false;
  18.     float u1 = 0, u2 =1;
  19.     int p[4], q[4], i;
  20.     float r;

  21.     p[0] = vector->sp.x - vector->ep.x;
  22.     p[1] = vector->ep.x - vector->sp.x;
  23.     p[2] = vector->sp.y - vector->ep.y;
  24.     p[3] = -vector->sp.y + vector->ep.y;
  25.     q[0] = vector->sp.x - rect.x;
  26.     q[1] = rect.x + rect.width - vector->sp.x;
  27.     q[2] = vector->sp.y - rect.y;
  28.     q[3] = rect.y + rect.height - vector->sp.y;

  29.     ///< 排除在矩形边框之外,并且平行于矩形边线的直线
  30.     if (0 == p[0] && (vector->sp.x < rect.x || vector->sp.x > (rect.x + rect.width)))
  31.     {
  32.         return false;
  33.     }
  34.     if (0 == p[2] && (vector->sp.y < rect.y || vector->sp.y > (rect.y + rect.height)))
  35.     {
  36.         return false;
  37.     }

  38.     for(i = 0; i < 4; ++i)
  39.     {
  40.         r = (float)q[i] / (float)p[i];
  41.         if (p[i] < 0)
  42.         {
  43.             u1 = max(u1,r);
  44.             if(u1 > u2)
  45.             {
  46.                 flag = true;
  47.             }
  48.         }
  49.         if (p[i] > 0)
  50.         {
  51.             u2 = min(u2, r);
  52.             if (u1 > u2)
  53.             {
  54.                 flag = true;
  55.             }
  56.         }
  57.         if (0 == p[i] && p[i] < 0)
  58.         {
  59.             flag = true;
  60.         }
  61.     }

  62.     if (flag)
  63.     {
  64.         return false;
  65.     }

  66.     dest.sp.x = vector->sp.x - u1 *(vector->sp.x - vector->ep.x);
  67.     dest.sp.y = vector->sp.y - u1 *(vector->sp.y - vector->ep.y);
  68.     dest.ep.x = vector->sp.x - u2 *(vector->sp.x - vector->ep.x);
  69.     dest.ep.y = vector->sp.y - u2 *(vector->sp.y - vector->ep.y);

  70.      ///< 裁剪结果为一个点,返回false
  71.     if ((dest.sp.x == dest.ep.x) && (dest.sp.y == dest.ep.y))
  72.     {
  73.         return false;
  74.     }

  75.     vector->sp.x = dest.sp.x;
  76.     vector->sp.y = dest.sp.y;
  77.     vector->ep.x = dest.ep.x;
  78.     vector->ep.y = dest.ep.y;

  79.     return true;
  80. }

  81. int clip_polygon(int Xwmax, int Xwmin,
  82.                  int Ywmax, int Ywmin,
  83.                  int n, float * x, float * y,
  84.                  float * xout, float * yout)
  85. {
  86.     float x1[CutCount_N] = {0}, y1[CutCount_N] = {0};
  87.     int n1 = 0;

  88.     clip_single_edge(Xwmax, Rectangle_Right, n, x, y, &n1, x1, y1);
  89.     clip_single_edge(Ywmax, Rectangle_Bottom, n1, x1, y1, &n1, xout, yout);
  90.     clip_single_edge(Xwmin, Rectangle_Left, n1, xout, yout, &n1, x1, y1);
  91.     clip_single_edge(Ywmin, Rectangle_Top, n1, x1, y1, &n1, xout, yout);
  92.     
  93.     if (n1 > 1) ///< 排除某些剪切情况下,最后一个点重复的情况
  94.     {
  95.         if (xout[n1 - 1] == xout[n1 - 2] && yout[n1 - 1] == yout[n1 - 2])
  96.         {
  97.             return n1 - 1;
  98.         }
  99.     }

  100.     return n1;
  101. }

  102. void clip_single_edge(int edge, int type,
  103.                       int nin, float * xin,
  104.                       float * yin, int * nout,
  105.                       float * xout, float * yout)
  106. {
  107.     int j = 0, k = 0, yes, is_in;
  108.     float x, y, x_intersect, y_intersect;

  109.     if (0 == nin)
  110.     {
  111.         return;
  112.     }    

  113.     x = xin[nin - 1];
  114.     y = yin[nin - 1];
  115.     for (j = 0; j < nin; ++j)
  116.     {
  117.         test_intersect(edge, type, x, y, xin[j], yin[j], &x_intersect, &y_intersect, &yes, &is_in);
  118.         if (yes)
  119.         {
  120.             xout[k] = x_intersect;
  121.             yout[k] = y_intersect;
  122.             ++k;
  123.         }
  124.         if (is_in)
  125.         {
  126.             xout[k] = xin[j];
  127.             yout[k] = yin[j];
  128.             ++k;
  129.         }
  130.         x = xin[j];
  131.         y = yin[j];
  132.     }
  133.     (*nout) = k;

  134.     return;
  135. }

  136. void test_intersect(int edge, int type,
  137.                     float x1, float y1,
  138.                     float x2, float y2,
  139.                     float * xout, float * yout,
  140.                     int * yes, int * is_in)
  141. {
  142.     float m;
  143.     (*is_in) = (*yes) = 0;

  144.     if (x1 != x2)
  145.     {
  146.         m = (float)((float)y2-(float)y1)/((float)x2-(float)x1);
  147.     }

  148.     switch(type)
  149.     {
  150.     case Rectangle_Right :
  151.     {
  152.         if (x2 <= edge)
  153.         {
  154.             (*is_in) = 1;
  155.             if (x1 > edge)
  156.             {
  157.                 (*yes) = 1;
  158.             }
  159.         }
  160.         else
  161.         {
  162.             if (x1 <= edge)
  163.             {
  164.                 (*yes) = 1;
  165.             }
  166.         }
  167.     }
  168.         break;
  169.     case Rectangle_Bottom:
  170.     {
  171.         if (y2 <= edge)
  172.         {
  173.             (*is_in) = 1;
  174.             if (y1 > edge)
  175.             {
  176.                 (*yes) = 1;
  177.             }

  178.         }
  179.         else
  180.         {
  181.             if (y1 <= edge)
  182.             {
  183.                 (*yes) = 1;
  184.             }

  185.         }
  186.     }
  187.         break;
  188.     case Rectangle_Left:
  189.     {
  190.         if (x2 >= edge)
  191.         {
  192.             (*is_in) = 1;
  193.             if (x1 < edge)
  194.             {
  195.                 (*yes) = 1;
  196.             }

  197.         }
  198.         else
  199.         {
  200.             if (x1 >= edge)
  201.             {
  202.                 (*yes) = 1;
  203.             }
  204.         }
  205.     }
  206.         break;
  207.     case Rectangle_Top:
  208.     {
  209.         if (y2 >= edge)
  210.         {
  211.             (*is_in) = 1;
  212.             if (y1 < edge)
  213.             {
  214.                 (*yes) = 1;
  215.             }
  216.         }
  217.         else
  218.         {
  219.             if (y1 >= edge)
  220.             {
  221.                 (*yes) = 1;
  222.             }
  223.         }
  224.     }
  225.         break;
  226.     default:
  227.         break;
  228.     }

  229.     if ((*yes))
  230.     {
  231.         if ((type == Rectangle_Right) || (type == Rectangle_Left))
  232.         {
  233.             (*xout) = edge;
  234.             (*yout) = y1 + m * ((*xout) - x1);
  235.         }
  236.         else
  237.         {
  238.             if (x1 == x2)
  239.             {
  240.                 if (Rectangle_Bottom == type && (y1 <= edge || y2 <= edge))
  241.                 {
  242.                     (*xout) = x1;
  243.                     (*yout) = edge;
  244.                 }
  245.                 if (Rectangle_Top == type && (y1 >= edge || y2 >= edge))
  246.                 {
  247.                     (*xout) = x1;
  248.                     (*yout) = edge;
  249.                 }
  250.             }
  251.             else
  252.             {
  253.                 (*yout) = edge;
  254.                 (*xout) = x1 + ((*yout) - y1)/m;
  255.             }
  256.         }
  257.     }
  258.     return;
  259. }
测试:main.cpp

点击(此处)折叠或打开

  1. #include <iostream>
  2. #include "cut.hpp"

  3. using namespace std;

  4. int main()
  5. {
  6.    int i;
  7.    int xwmax=300, xwmin=50, ywmax=250, ywmin=150;

  8.    float x[]={10,300,300};     ///< 直角三角形在右边
  9.    float y[]={200,230,200};
  10.    int n = 3;

  11.    float xout[CutCount_N]={0};
  12.    float yout[CutCount_N]={0};
  13.    int cutCount = 0;

  14.    cutCount = clip_polygon(xwmax, xwmin, ywmax, ywmin, n, x, y, xout, yout);

  15.    cout << cutCount << endl;
  16.    for (i = 0; i < cutCount; ++i)
  17.    {
  18.         cout << "x: " << xout[i] << " y: " << yout[i] << endl;
  19.    }

  20.    return 0;
  21. }

阅读(4190) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~