GIS算法的计算几何基础(1)

一、实验目标

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),为确保不同对顶点能得到相同的结果,分别输入了主对角线对顶点以及副对角线对顶点,均得到相同且正确的结果

相关推荐
荒古前42 分钟前
龟兔赛跑 PTA
c语言·算法
Colinnian1 小时前
Codeforces Round 994 (Div. 2)-D题
算法·动态规划
用户0099383143011 小时前
代码随想录算法训练营第十三天 | 二叉树part01
数据结构·算法
shinelord明1 小时前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
დ旧言~1 小时前
专题八:背包问题
算法·leetcode·动态规划·推荐算法
_WndProc1 小时前
C++ 日志输出
开发语言·c++·算法
努力学习编程的伍大侠2 小时前
基础排序算法
数据结构·c++·算法
XiaoLeisj2 小时前
【递归,搜索与回溯算法 & 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)
数据结构·算法·leetcode·决策树·深度优先·剪枝