IOU的C语言快速实现

typedef enum {
    REF_FRONTLEFT = 0,
    REF_FRONTRIGHT,
    REF_REARRIGHT,
    REF_REARLEFT,
    REF_FRONTCENTER,
    REF_RIGHTCENTER,
    REF_REARCENTER,
    REF_LEFTCENTER,
    REF_CENTER,

    REF_POINT_CNT
}EReferencePoint;

typedef struct {
    float x;       
    float y;   
} Point2F;

typedef struct {
    EReferencePoint en_ref_point;
    Point2F xy_point;
}RefPoint_st;

typedef struct {
    u_char_t size;
    Point2F  point_coordinate[10];
}Overlap_Points;

/*!
此部分函数主要是计算矩形相交的面积   备注:将4个点按照时钟序排列(必须是顺时针或者逆时针排序好的)
box1_refpoint  : box1的参考点结构体包含为哪个参考点和其坐标(必须是按照时钟序排列)
\box2_refpoint  : box1的参考点结构体包含为哪个参考点和其坐标(必须是按照时钟序排列)
 box1_points    : box1的四个顶点的坐标(必须是按照时钟序排列)
box2_points    : box2的四个顶点的坐标(必须是按照时钟序排列)
overlap_points : 两个矩形相交的点以及某个矩形的顶点落在另一个矩形内的点集合S和个数的结构体
\return   overlap_area   : 相交的面积
*/
float calcuate_boxes_overlap(RefPoint_st *box1_refpoint, RefPoint_st *box2_refpoint,float *box1_points, float *box2_points, Overlap_Points *overlap_points)
{
    if (box1_refpoint == NULL || box2_refpoint == NULL || box1_points == NULL || box2_points == NULL || overlap_points == NULL)
    {
        return 0.0f;
    }
    float overlap_area = 0.0f;
    whether_rectangles_intersect(box1_refpoint, box2_refpoint, box1_points, box2_points, overlap_points);
    sort_vertex_in_convex_polygon(overlap_points);
    overlap_area = cal_overlap_area(overlap_points);
    return overlap_area;
}

/*!
计算出两个矩形相交的点以及某个矩形的顶点落在另一个矩形内的点集合Soverlap_points : 两个矩形相交的点以及某个矩形的顶点落在另一个矩形内的点集合S和个数的结构体
*/
void whether_rectangles_intersect(RefPoint_st* box1_refpoint, RefPoint_st* box2_refpoint, float* box1_points, float* box2_points, Overlap_Points* overlap_points)
{   
    if (box1_refpoint == NULL || box2_refpoint == NULL || box1_points == NULL || box2_points == NULL || overlap_points == NULL)
    {
        return;
    }
    bool whether_point_in_box = false;
    for (int i = 0; i < 4; i++)
    {
        whether_point_in_box = false;
        whether_point_in_box = point_in_box(box1_refpoint[i].xy_point, box2_points);
        if (whether_point_in_box)
        {
            overlap_points->point_coordinate[overlap_points->size] = box1_refpoint[i].xy_point;
            overlap_points->size++;
        }
    }
    for (int i = 0; i < 4; i++)
    {
        whether_point_in_box = false;
        whether_point_in_box = point_in_box(box2_refpoint[i].xy_point, box1_points);
        if (whether_point_in_box)
        {
            overlap_points->point_coordinate[overlap_points->size] = box2_refpoint[i].xy_point;
            overlap_points->size++;
        }
    }
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            line_segment_intersection(box1_points, box2_points, i, j, overlap_points);
        }
    }
}
 

/*!
对两个矩形相交的点以及某个矩形的顶点落在另一个矩形内的点集合S进行时钟序排序overlap_points : 两个矩形相交的点以及某个矩形的顶点落在另一个矩形内的点集合S和个数的结构体
*/

void sort_vertex_in_convex_polygon(Overlap_Points* overlap_points) 
{
    if (overlap_points == NULL || overlap_points->size > 9)
    {
        return;
    }
    Point2F polygon_center = { 0 };
    if (overlap_points->size > 0)
    {
        for (u_char_t i = 0; i < overlap_points->size; i++)
        {
            polygon_center.x += overlap_points->point_coordinate[i].x;
            polygon_center.y += overlap_points->point_coordinate[i].y;
        }
        polygon_center.x = polygon_center.x/overlap_points->size;
        polygon_center.y = polygon_center.y/overlap_points->size;
        //选择排序
        for (u_char_t i = 0; i < overlap_points->size; i++)
        {
            for (u_char_t j = i + 1; j < overlap_points->size; j++)
            {
                Point2F tmp = { 0 };
                float vx_i = overlap_points->point_coordinate[i].x - polygon_center.x;
                float vy_i = overlap_points->point_coordinate[i].y - polygon_center.y;
                float d_i = sqrtf(vx_i * vx_i + vy_i * vy_i);
                //单位向量
                vx_i = vx_i / d_i;
                vy_i = vy_i / d_i;
                if (vy_i < 0)
                {
                    vx_i = -2 - vx_i;
                }
                float vx_j = overlap_points->point_coordinate[j].x - polygon_center.x;
                float vy_j = overlap_points->point_coordinate[j].y - polygon_center.y;
                float d_j = sqrtf(vx_j * vx_j + vy_j * vy_j);
                vx_j = vx_j / d_j;
                vy_j = vy_j / d_j;
                if (vy_j < 0)
                {
                    vx_j = -2 - vx_j;
                }
                if (vx_i > vx_j)
                {
                    tmp = overlap_points->point_coordinate[i];
                    overlap_points->point_coordinate[i] = overlap_points->point_coordinate[j];
                    overlap_points->point_coordinate[j] = tmp;
                }
            }
        }
    }
}
 

/*!
根据向量的叉积求解面积即可(如找到一个点p,将每一条边都和这个点相连的三角形通过叉积求面积进行加和)
box1_refpoint  : box1的参考点结构体包含为哪个参考点和其坐标(必须是按照时钟序排列)
box2_refpoint  : box1的参考点结构体包含为哪个参考点和其坐标(必须是按照时钟序排列)
box1_points    : box1的四个顶点的坐标(必须是按照时钟序排列)
box2_points    : box2的四个顶点的坐标(必须是按照时钟序排列)
overlap_points : 两个矩形相交的点以及某个矩形的顶点落在另一个矩形内的点集合S和个数的结构体
return    overlap_area   : 相交的面积
*/

float cal_overlap_area(Overlap_Points* overlap_points)
{
    if (overlap_points == NULL || overlap_points->size > 9)
    {
        return 0.0f;
    }
    float area_val = 0.0f;
    if (overlap_points->size > 2)
    {
        Point2F point_a = overlap_points->point_coordinate[0];
        for (u_char_t i = 0; i < (overlap_points->size - 2); i++)
        {
            Point2F point_b = overlap_points->point_coordinate[i + 1];
            Point2F point_c = overlap_points->point_coordinate[i + 2];
            //S= (1/2)*(x1y2+x2y3+x3y1-x1y3-x2y1-x3y2)
            area_val += fabsf(((point_a.x - point_c.x) * (point_b.y - point_c.y) - (point_a.y - point_c.y) *
                (point_b.x - point_c.x)) / 2.0f);
        }
    }
    return area_val;
}

  • 16
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值