一、实验目标
1. 矢量叉积计算
要求从键盘上输入数据,计算叉积
分析输入两个矢量的坐标信息,输出其二者的叉积,应用矢量叉积公式
2. 折线拐向判断
要求从键盘上输入数据,判断其拐向
分析输入折线的端点坐标,输出折线的拐向信息,应用矢量叉积公式
3. 判断矩形是否包含点
要求从键盘上输入点与矩形,判断点是否在矩形内
分析输入点坐标和矩形的一对对顶点,输出点是否在矩形内的判断结果
二、基本原理
1. 矢量叉积计算
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> P ( x 1 , y 1 ) × Q ( x 2 , y 2 ) = x 1 y 2 − x 2 y 1 P(x_1, y_1) × Q(x_2, y_2) = x_1y_2 - x_2y_1 </math>P(x1,y1)×Q(x2,y2)=x1y2−x2y1
2. 折线拐向判断
将两段折线 <math xmlns="http://www.w3.org/1998/Math/MathML"> P 0 P 1 P_0P_1 </math>P0P1、 <math xmlns="http://www.w3.org/1998/Math/MathML"> P 0 P 2 P_0P_2 </math>P0P2抽象成两个矢量P、Q,由矢量叉乘的定义:
① <math xmlns="http://www.w3.org/1998/Math/MathML"> P × Q > 0 P×Q > 0 </math>P×Q>0,P在Q的顺时针方向 => 折线在 <math xmlns="http://www.w3.org/1998/Math/MathML"> P 1 P_1 </math>P1处右拐
② <math xmlns="http://www.w3.org/1998/Math/MathML"> P × Q = 0 P×Q = 0 </math>P×Q=0,P与Q共线 => <math xmlns="http://www.w3.org/1998/Math/MathML"> P 0 、 P 1 、 P 2 P_0、P_1、P_2 </math>P0、P1、P2三点共线
③ <math xmlns="http://www.w3.org/1998/Math/MathML"> P × Q < 0 P×Q < 0 </math>P×Q<0,P在Q的逆时针方向 => 折线在 <math xmlns="http://www.w3.org/1998/Math/MathML"> P 1 P_1 </math>P1处左拐
转化为数学表达式: <math xmlns="http://www.w3.org/1998/Math/MathML"> P 0 ( x 0 , y 0 ) 、 P 1 ( x 1 , y 1 ) 、 P 2 ( x 2 , y 2 ) = > P × Q = ( x 2 − x 0 ) ( y 1 − y 0 ) − ( x 1 − x 0 ) ( y 2 − y 0 ) P_0(x_0, y_0)、P_1(x_1, y_1)、P_2(x_2, y_2) => P×Q = (x_2-x_0)(y_1-y_0) - (x_1-x_0)(y_2-y_0) </math>P0(x0,y0)、P1(x1,y1)、P2(x2,y2)=>P×Q=(x2−x0)(y1−y0)−(x1−x0)(y2−y0)
3. 判断矩形是否包含点
在坐标系中,确定一个矩形需要四个参数: <math xmlns="http://www.w3.org/1998/Math/MathML"> x m i n 、 x m a x 、 y m i n 、 y m a x x_{min}、x_{max}、y_{min}、y_{max} </math>xmin、xmax、ymin、ymax,仅需一对对顶点即可获取上述的四个参数,如:
<math xmlns="http://www.w3.org/1998/Math/MathML"> P 1 、 P 1 ′ : x 1 = x m i n 、 y 1 = y m i n 、 x 1 ′ = x m a x 、 y 1 ′ = y m a x P_1、P_1': x_1 = x_{min} 、y_1 = y_{min} 、x_1' = x_{max} 、y_1' = y_{max} </math>P1、P1′:x1=xmin、y1=ymin、x1′=xmax、y1′=ymax
<math xmlns="http://www.w3.org/1998/Math/MathML"> P 2 、 P 2 ′ : x 2 = x m i n 、 y 2 = y m i n 、 x 2 ′ = x m a x 、 y 2 ′ = y m a x P_2、P_2': x_2 = x_{min} 、y_2 = y_{min} 、x_2' = x_{max} 、y_2' = y_{max} </math>P2、P2′:x2=xmin、y2=ymin、x2′=xmax、y2′=ymax
若 <math xmlns="http://www.w3.org/1998/Math/MathML"> x m i n < x 0 < x m a x x_{min} < x_0 < x_{max} </math>xmin<x0<xmax且 <math xmlns="http://www.w3.org/1998/Math/MathML"> y m i n < y 0 < y m a x y_{min} < y_0 < y_{max} </math>ymin<y0<ymax则点在矩形内部
三、实现思路
1. 矢量叉积计算
① 用结构体来保存矢量,为保障程序处理数据的多样性,矢量的两个分量使用双精度类型来定义
C
typedef struct {
double x;
double y;
} Vector;
② 运用"原理"中推出的数学表达式,编写函数计算矢量叉积
C
double operation(Vector v1, Vector v2){
return (v1.x*v2.y) - (v1.y*v2.x);
}
③ 在主函数中读入用户输入的矢量,并调用运算函数计算出结果,将结果打印出来
C
int main(){
Vector v1,v2;
printf("请输入第一个矢量:");
scanf("%lf,%lf",&v1.x,&v1.y);
printf("请输入第二个矢量:");
scanf("%lf,%lf",&v2.x,&v2.y);
double result = operation(v1,v2);
printf("叉乘结果为%.1lf\n",result);
return 0;
}
2. 折线拐向判断
① 用结构体来保存线段的端点,为保障程序处理数据的多样性,点的x、y坐标值使用双精度类型来定义
C
typedef struct {
double x;
double y;
} Point;
② 构造函数来判断折线的拐向。将折线抽象成共起点的两个矢量,使用矢量叉乘结果(转为整型)的正负来判断折线的拐向,并直接打印出来
C
void Judge(Point P1, Point P2, Point P0){
int product;
product= (int)(P2.x-P0.x)*(P1.y-P0.y)-(P1.x-P0.x)*(P2.y-P0.y);
if(product>0){
printf("折线在P1点右拐");
}
else if(product<0)
printf("折线在P1点左拐");
else if(product==0)
printf("三个点在一条直线上");
}
③ 在主函数中读入用户输入的矢量,并调用运算函数计算出结果
C
int main(){
//输入线段的两个点P1和P2
Point P1,P2,P0;
printf("请依次输入线段的顶点和两个端点\n");
scanf("%lf,%lf",&P0.x,&P0.y);
scanf("%lf,%lf",&P1.x,&P1.y);
scanf("%lf,%lf",&P2.x,&P2.y);
//使用函数进行判断
Judge(P1, P2, P0);
return 0;
}
3. 判断矩形是否包含点
① 用结构体来保存线段的端点,为保障程序处理数据的多样性,点的x、y坐标值使用双精度类型来定义
C
typedef struct {
double x;
double y;
} Point;
② 构造最大最小值函数用于判断矩形对顶点坐标的最大最小值
C
double Max(double x, double y){
return x>y?x:y;
}
double Min(double x, double y){
return x<y?x:y;
}
③ 构造函数判断点是否在矩形中。由前文中的"原理"可知,仅需一对对顶点即可确定矩形的坐标范围,使用flag变量返回0和1来表达是和否
C
int Judge(Point P1, Point P2, Point P0){
int flag;
if (((P1.x<=P0.x)&&(P1.y<=P0.y))&&((P2.x>P0.x)&&(P2.y>P0.y)))
return flag=1;
else
return flag=0;
}
④ 在main函数中获取用户输入的信息,调用最大最小值函数确定矩形的范围,将值传递进判断函数中进行判断,最后输出判断结果
C
int main(){
//输入线段的两个点P1和P2
Point P1,P2;
double x1,x2,y1,y2;
printf("请输入矩形的两个对顶点\n");
scanf("%lf,%lf",&x1,&y1);
getchar(); // 吸收回车键
scanf("%lf,%lf",&x2,&y2);
getchar(); // 吸收回车键
P1.x = Min(x1,x2);
P2.x = Max(x1,x2);
P1.y = Min(y1,y2);
P2.y = Max(y1,y2);
//输入待判断的点坐标
Point P0;
printf("请输入待判断的点坐标\n");
scanf("%lf,%lf",&P0.x,&P0.y);
//使用函数进行判断
int judgement = Judge(P1, P2, P0);
if(judgement)
printf("点在矩形内部");
else{
printf("点在矩形外部");
}
return 0;
}
四、测试及运行
1. 矢量叉积计算
验证数据选取 <math xmlns="http://www.w3.org/1998/Math/MathML"> P 1 ( 1 , 1 ) 、 P 2 ( 1 , 2 ) P_1(1,1)、P_2(1,2) </math>P1(1,1)、P2(1,2),计算结果应为1.0,使用程序运行该组数据,输出结果与预期结果一致。
2. 折线拐向判断
验证数据选取 <math xmlns="http://www.w3.org/1998/Math/MathML"> P 0 ( 1 , 1 ) 、 P 1 ( 1 , 2 ) 、 P 2 ( 2 , 1 ) P_0(1,1)、P_1(1,2)、P_2(2,1) </math>P0(1,1)、P1(1,2)、P2(2,1)以及 <math xmlns="http://www.w3.org/1998/Math/MathML"> P 0 ( 1 , 1 ) 、 P 1 ( 2 , 1 ) 、 P 2 ( 1 , 2 ) P_0(1,1)、P_1(2,1)、P_2(1,2) </math>P0(1,1)、P1(2,1)、P2(1,2),两次的结果应分别为右拐和左拐,使用程序运行该组数据,输出结果与预期结果一致。
3. 判断矩形是否包含点
验证数据选取以点 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 1 , 1 ) 、 ( 1 , 3 ) 、 ( 3 , 3 ) 、 ( 3 , 1 ) (1,1)、(1,3)、(3,3)、(3,1) </math>(1,1)、(1,3)、(3,3)、(3,1)为顶点的矩形和点 <math xmlns="http://www.w3.org/1998/Math/MathML"> P 0 ( 2 , 2.5 ) P_0(2,2.5) </math>P0(2,2.5),为确保不同对顶点能得到相同的结果,分别输入了主对角线对顶点以及副对角线对顶点,均得到相同且正确的结果