#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/opencv.hpp>
#include<stdio.h>
#include <string>
#define For(i,a,b) for(int i=a;i<=b;++i)
using namespace cv;
Mat src;
Mat dst;
Point old_pt;
Point new_pt;
double xmin,xmax,ymin,ymax;
int flag;
void liang(Point pre_pt, Point cur_pt){
flag=0;
double l,r,L,R;
double x1=pre_pt.x,x2=cur_pt.x;
double y1=pre_pt.y,y2=cur_pt.y;
double p[6],q[6];
p[1] = -(x2 - x1);
p[2] = -p[1];
p[3] = -(y2 - y1);
p[4] = -p[3];
q[1] = x1 - xmin;
q[2] = xmax - x1;
q[3] = y1 - ymin;
q[4] = ymax - y1;
if(p[1]<0){
l=q[1]/p[1];
r=q[2]/p[2];
}
if(p[1]>0){
r=q[1]/p[1];
l=q[2]/p[2];
}
if(p[1]==0){
l=0;
r=1;
}
if(p[3]<0){
L=q[3]/p[3];
R=q[4]/p[4];
}
if(p[3]>0){
R=q[3]/p[3];
L=q[4]/p[4];
}
if(p[3]==0){
L=0;
R=1;
}
l=max((double)0,l);
r=min((double)1,r);
L=max((double)0,L);
R=min((double)1,R);
l=max(l,L);
r=min(r,R);
if(l<r){
old_pt.x=x1+l*p[2];
old_pt.y=y1+l*p[4];
new_pt.x=x1+r*p[2];
new_pt.y=y1+r*p[4];
flag=1;
}
}
void on_mouse(int event, int x, int y, int flags, void* ustc){
static Point pre_pt ;
static Point cur_pt ;
char temp_1[20];
char temp_2[20];
if (event == EVENT_LBUTTONDOWN){
dst.copyTo(src);
pre_pt = Point(x, y);
circle(src, pre_pt, 0.5, Scalar(255, 0, 0), FILLED, 0);
imshow("liang-barsky", src);
}
else if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON)){
dst.copyTo(src);
cur_pt = Point(x, y);
sprintf(temp_2,"x:%d,y:%d",pre_pt.x,pre_pt.y);
sprintf(temp_1,"x:%d,y:%d",x,y);
putText(src,temp_2,Point(pre_pt.x,pre_pt.y),FONT_HERSHEY_SIMPLEX,0.8,Scalar(0,255,255));
putText(src,temp_1,Point(x,y),FONT_HERSHEY_SIMPLEX,0.8,Scalar(0,255,255));
circle(src, pre_pt, 3, Scalar(255,0, 0), FILLED, 0);
circle(src, cur_pt, 3, Scalar(255,0, 0), FILLED, 0);
line(src, pre_pt, cur_pt, Scalar(0, 255,0), 2, 8 ,0);
imshow("liang-barsky", src);
}
else if (event == EVENT_LBUTTONUP){
dst.copyTo(src);
cur_pt = Point(x, y);
sprintf(temp_2,"x:%d,y:%d",pre_pt.x,pre_pt.y);
sprintf(temp_1,"x:%d,y:%d",x,y);
putText(src,temp_2,Point(pre_pt.x,pre_pt.y),FONT_HERSHEY_SIMPLEX,0.8,Scalar(0,255,255));
putText(src,temp_1,Point(x,y),FONT_HERSHEY_SIMPLEX,0.8,Scalar(0,255,255));
circle(src, pre_pt, 3, Scalar(255,0, 0), FILLED, 0);
circle(src, cur_pt, 3, Scalar(255,0, 0), FILLED, 0);
liang(pre_pt,cur_pt);
if(flag){
line(src, pre_pt, old_pt, Scalar(0, 255,0), 2, 8, 0);
line(src, old_pt, new_pt, Scalar(255, 0, 0), 4, 8, 0);
line(src, new_pt, cur_pt, Scalar(0, 255,0), 2, 8, 0);
}
else{
line(src, pre_pt, cur_pt, Scalar(0, 255,0), 2, 8, 0);
}
imshow("liang-barsky", src);
}
}
int main(){
namedWindow("liang-barsky", WINDOW_AUTOSIZE);
src=Mat(1000, 1000, CV_8UC3, Scalar(0));
xmax=ymax=600;
xmin=ymin=200;
rectangle(src,Rect(200,200,400,400),Scalar(255,255,255),2,1,0);
src.copyTo(dst);
setMouseCallback("liang-barsky", on_mouse, 0);
imshow("liang-barsky", src);
waitKey(0);
return 0;
}