射线裁剪算法



//
// Created by wang shuai on 2018/10/12.
//

#ifndef FACEMAKER2_TRIANGLATEUTILS_H
#define FACEMAKER2_TRIANGLATEUTILS_H
#include <opencv2/opencv.hpp>

class TrianglateUtils {

/**
int clipSegment(Point2& p1, Point2 &p2, RealRect W){
do{
if (平凡接受) return 1; // 部分可见
if (平凡拒绝) return 0; // 完全不可见
if (p1在窗口外面){
if (p1在窗口左边) 用左边界截断,更新p1;
else if (p1在窗口右边) 用右边界截断,更新p1;
else if (p1在窗口上面) 用上边界截断,更新p1;
else if (p1在窗口下面) 用下边界截断,更新p1;
}else{ // p2在窗口外面
if (p2在窗口左边) 用左边界截断,更新p2;
else if (p2在窗口右边) 用右边界截断,更新p2;
else if (p2在窗口上面) 用上边界截断,更新p2;
else if (p2在窗口下面) 用下边界截断,更新p2;
}
}
}**/

#define INVALID -1
#define LEFT 8
#define TOP 4
#define RIGHT 2
#define BOTTOM 1

#define ACCEPT 1
#define REJECT 2
#define CUTTED 3

unsigned char getCode(cv::Point2f& p, cv::Rect2f& window){
unsigned char code = 0;
if (p.x < window.x) code |= LEFT;
if (p.y > window.y) code |= TOP;
if (p.x >= window.x + window.width) code |= RIGHT;
if (p.y <= window.y + window.height) code |= BOTTOM;
return code;
}


/**
* if(在左边){
* if(方向向左){
* 与Right和left都无交点。
* }else if(方向向右边){
* 沿方向移动到左边界更新p1到此位置。
* }else {
* 无交点
* return 平行;
* }
* }
* if(在右边){
* if(方向向右){
* 与Right和left都无交点。
* }else if(方向向左边){
* 沿方向移动到右边界更新p1到此位置。
* }else {
* 无交点
* return 平行;
* }
* }
*
* if(在下面){
* if(方向向下){
* 与Bottom和Top都无交点。
* }else if(方向向上){
* 沿方向移动到下边界更新p1到此位置。
* }else {
* 无交点
* return 平行;
* }
* }
* if(在上面){
* if(方向向上){
* 与Bottom和Top都无交点。
* }else if(方向下){
* 沿方向移动到上边界更新p1到此位置。
* }else {
* 无交点
* return 平行;
* }
* }
* 重新计算
* if(在里面){
* if(方向向上){
* 与top有交点
* 计算交点
* if(没有超过top边界端点范围){
* 记录p2为这个交点。
* return p1,p2
* }
* }
*
* if(方向向下){
* 与bottom有交点
* 计算交点
* if(没有超过上边界端点范围){
* 记录p2为这个交点。
* return p1,p2
* }
* }
* if(方向向左){
* 与left有交点
* 计算交点
* if(没有超过left边界端点范围){
* 记录p2为这个交点。
* return p1,p2
* }
* }
* if(方向向右){
* 与Right有交点
* 计算交点
* if(没有超过Right边界端点范围){
* 记录p2为这个交点。
* return p1,p2
* }
* }
*
* }
* @param p1
* @param direction
* @param window
* @return -1: 平行
*/
int clipRay(cv::Point2f& p1, cv::Point2f& direction, cv::Rect2f& window,cv::Point2f& p2){
unsigned char code1 = getCode(p1, window);
int direct = getDirection(direction);
if(direct&(LEFT|RIGHT) == 0){
return REJECT;
}

if(direct&(TOP|BOTTOM) == 0){
return REJECT;
}

//在左边
if(code1&LEFT!= 0){
if(direct&RIGHT!= 0){
float new_x = 0;
float delta = (new_x - p1.x)/direction.x;
p1.y = (delta*direction.y) + p1.y;
p1.x = new_x;
} else {
return REJECT;
}
}

if(code1&RIGHT!= 0){
if(direct&LEFT!= 0){
float new_x = window.width - 1;
float delta = (new_x - p1.x)/direction.x;
p1.y = (delta*direction.y) + p1.y;
p1.x = new_x;
} else {
return REJECT;
}
}

if(code1&TOP!= 0){
if(direct&BOTTOM!= 0){
float new_y = 0;
float delta = (new_y - p1.y)/direction.y;
p1.x = (delta*direction.x) + p1.x;
p1.y = new_y;
} else {
return REJECT;
}
}

if(code1&BOTTOM!= 0){
if(direct&TOP!= 0){
float new_y = window.height - 1;
float delta = (new_y - p1.y)/direction.y;
p1.x = (delta*direction.x) + p1.x;
p1.y = new_y;
} else {
return REJECT;
}
}

//code1 = getCode(p1, window);
if(direct&TOP!= 0){
float new_y = 0;
float delta = (new_y - p1.y)/direction.y;
float x = (delta*direction.x) + p1.x;
float y = new_y;
if(x >=0 && x <= window.width -1){
p2.x = x;
p2.y = y;
return CUTTED;
}
}

if(direct&BOTTOM!= 0){
float new_y = window.height -1;
float delta = (new_y - p1.y)/direction.y;
float x = (delta*direction.x) + p1.x;
float y = new_y;
if(x >=0 && x <= window.width -1){
p2.x = x;
p2.y = y;
return CUTTED;
}
}

if (direct&LEFT!= 0){
float new_x = 0;
float delta = (new_x - p1.x)/direction.x;
float y = (delta*direction.y) + p1.y;
float x = new_x;
if(y >=0 && y<= window.height -1){
p2.x = x;
p2.y = y;
return CUTTED;
}
}

if (direct&RIGHT!= 0){
float new_x = window.width -1;
float delta = (new_x - p1.x)/direction.x;
float y = (delta*direction.y) + p1.y;
float x = new_x;
if(y >=0 && y<= window.height -1){
p2.x = x;
p2.y = y;
return CUTTED;
}
}

return REJECT;
}

int getDirection(cv::Point2f& direction){
int result = 0;
if(direction.x > 0) {
result |= RIGHT;
}else if(direction.x < 0){
result |= LEFT;
}
if(direction.y > 0){
result |= BOTTOM;
}else if(direction.y < 0){
result |= TOP;
}
return result;
}

int clipSegment(cv::Point2f& p1, int& p1_edge, cv::Point2f& p2, int& p2_edge, cv::Rect2f& window){
p1_edge = INVALID;
p2_edge = INVALID;
int retCode = INVALID;

unsigned char code1 = getCode(p1, window), code2 = getCode(p2, window);

// 如果平凡接受,都在里面, return 1
if ((code1|code2) == 0) return ACCEPT;

// 如果平凡拒绝,都在外面, return 0
if ((code1&code2) != 0) return REJECT;

// if p1在外面
if (code1 != 0) {
int delx = p2.x - p1.x, dely = p2.y - p1.y;
p1_edge = chopLine(p1, window, code1, delx, dely);
}
//如果p2 在外面
if (code2 != 0) {
int delx = p1.x - p2.x, dely = p1.y - p2.y;
p2_edge = chopLine(p2, window, code2, delx, dely);
}
return INVALID;
}

// 裁剪线段
int chopLine(cv::Point2f& p, cv::Rect2f& window, unsigned char code, int delx, int dely){
if (code & LEFT) { // 使用左边界裁剪
p.y += (window.x - p.x) * dely / delx;
p.x = window.x;
return LEFT;
}
else if (code & RIGHT) { // 使用右边界裁剪
p.y += (window.x + window.width -1 - p.x) * dely / delx;
p.x = window.x + window.width -1;
return RIGHT;
}
else if (code & BOTTOM) { // 使用下边界裁剪
p.x += (window.y + window.height -1 - p.y) * delx / dely;
p.y = window.y + window.height -1;
return BOTTOM;
}
else if (code & TOP) { // 使用上边界裁剪
p.x += (window.y - p.y) * delx / dely;
p.y = window.y;
return TOP;
}
return INVALID;
}
};


#endif //FACEMAKER2_TRIANGLATEUTILS_H

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值