PostgreSQL 三角函数的用法举例 - 已知3点求夹角(旋转门续)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: 背景 前几天写了一篇关于旋转门的数据压缩算法在PostgreSQL中的实现,里面用到了PostGIS里面的ST_Azimuth函数用来计算夹角,其实在PostgreSQL 中,我们还可以使用三角函数,以及三边来求夹角。 https://yq.aliyun.com/articles/59101

背景

前几天写了一篇关于旋转门的数据压缩算法在PostgreSQL中的实现,里面用到了PostGIS里面的ST_Azimuth函数用来计算夹角,其实在PostgreSQL 中,我们还可以使用三角函数,以及三边来求夹角。

https://yq.aliyun.com/articles/59101

screenshot

文中用到的计算夹角的方法如下

      SELECT 180-ST_Azimuth(
                              ST_MakePoint(o_x, o_val+i_radius),    -- 门上点
                              ST_MakePoint(v_x, v_val)              -- next point
                           )/(2*pi())*360 as degAz,                 -- 上夹角
                 ST_Azimuth(
                              ST_MakePoint(o_x, o_val-i_radius),    -- 门下点
                              ST_MakePoint(v_x, v_val)              -- next point
                           )/(2*pi())*360 As degAzrev               -- 下夹角
      INTO v_angle1, v_angle2; 

余弦定理

cosA=(b²+c²-a²)/(2bc)

screenshot

定点为A、B、C; 对的边分别为a、b、c;

PostgreSQL 支持的三角函数

https://www.postgresql.org/docs/9.6/static/functions-math.html

Function (radians) Function (degrees) Description
acos(x) acosd(x) inverse cosine
asin(x) asind(x) inverse sine
atan(x) atand(x) inverse tangent
atan2(y, x) atan2d(y, x) inverse tangent of y/x
cos(x) cosd(x) cosine
cot(x) cotd(x) cotangent
sin(x) sind(x) sine
tan(x) tand(x) tangent

例子

已知三个点A(3,2),B(1,2.5),C(1,1)。 求夹角B, C。

screenshot

套用余弦公式

cosB=(a²+c²-b²)/(2ac)   
  
cosC=(b²+a²-c²)/(2ba)     

首先求三条边长

postgres=# select point_distance(point(3,2), point(1,2.5)) as c , point_distance(point(3,2), point(1,1)) as b , point_distance(point(1,1), point(1,2.5)) as a;
        c         |        b         |  a  
------------------+------------------+-----
 2.06155281280883 | 2.23606797749979 | 1.5
(1 row)  

运算如下

cosB=(a²+c²-b²)/(2ac)      
=(1.5^2 + 2.06155281280883^2 - 2.23606797749979^2) / (2*1.5*2.06155281280883)  
=0.24253562503633260164  
  
cosC=(b²+a²-c²)/(2ba)     
=(1.5^2 + 2.23606797749979^2 - 2.06155281280883^2) / (2*2.23606797749979*1.5)  
=0.44721359549995825124  

求夹角 1 度数

postgres=# select acosd(0.24253562503633260164);
      acosd       
------------------
 75.9637565320735
(1 row)

求夹角 2 度数

postgres=# select acosd(0.44721359549995825124);
      acosd      
-----------------
 63.434948822922
(1 row)

比对使用PostGIS计算的结果一致

test=>  SELECT 180-ST_Azimuth(
                              ST_MakePoint(1,2.5),    -- 门上点
                              ST_MakePoint(3,2)              -- next point
                           )/(2*pi())*360 as degAz,                 -- 上夹角
                 ST_Azimuth(
                              ST_MakePoint(1,1),    -- 门下点
                              ST_MakePoint(3,2)              -- next point
                           )/(2*pi())*360 As degAzrev ;
      degaz       |    degazrev     
------------------+-----------------
 75.9637565320735 | 63.434948822922
(1 row)

源码

三角函数属于浮点运算中的函数

src/backend/utils/adt/float.c

/*
 *              acosd_q1                - returns the inverse cosine of x in degrees, for x in
 *                                                the range [0, 1].  The result is an angle in the
 *                                                first quadrant --- [0, 90] degrees.
 *
 *                                                For the 3 special case inputs (0, 0.5 and 1), this
 *                                                function will return exact values (0, 60 and 90
 *                                                degrees respectively).
 */
static double
acosd_q1(double x)
{
        /*
         * Stitch together inverse sine and cosine functions for the ranges [0,
         * 0.5] and (0.5, 1].  Each expression below is guaranteed to return
         * exactly 60 for x=0.5, so the result is a continuous monotonic function
         * over the full range.
         */
        if (x <= 0.5)
        {
                volatile float8 asin_x = asin(x);

                return 90.0 - (asin_x / asin_0_5) * 30.0;
        }
        else
        {
                volatile float8 acos_x = acos(x);

                return (acos_x / acos_0_5) * 60.0;
        }
}


/*
 *              dacosd                  - returns the arccos of arg1 (degrees)
 */
Datum
dacosd(PG_FUNCTION_ARGS)
{
        float8          arg1 = PG_GETARG_FLOAT8(0);
        float8          result;

        /* Per the POSIX spec, return NaN if the input is NaN */
        if (isnan(arg1))
                PG_RETURN_FLOAT8(get_float8_nan());

        INIT_DEGREE_CONSTANTS();

        /*
         * The principal branch of the inverse cosine function maps values in the
         * range [-1, 1] to values in the range [0, 180], so we should reject any
         * inputs outside that range and the result will always be finite.
         */
        if (arg1 < -1.0 || arg1 > 1.0)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("input is out of range")));

        if (arg1 >= 0.0)
                result = acosd_q1(arg1);
        else
                result = 90.0 + asind_q1(-arg1);

        CHECKFLOATVAL(result, false, true);
        PG_RETURN_FLOAT8(result);
}
man asin 
NAME
       asin, asinf, asinl - arc sine function

SYNOPSIS
       #include <math.h>

       double asin(double x);
       float asinf(float x);
       long double asinl(long double x);

///

CONFORMING TO
       C99, POSIX.1-2001.  The variant returning double also conforms to SVr4, 4.3BSD, C89.

SEE ALSO
       acos(3), atan(3), atan2(3), casin(3), cos(3), sin(3), tan(3)

祝大家玩得开心,欢迎随时来 阿里云促膝长谈业务需求 ,恭候光临

阿里云的小伙伴们加油,努力 做好内核与服务,打造最贴地气的云数据库

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
SQL 关系型数据库 PostgreSQL
PostgreSQL datediff 日期间隔(单位转换)兼容SQL用法
标签 PostgreSQL , datediff 背景 使用datediff,对时间或日期相减,得到的间隔,转换为目标单位(日、月、季度、年、小时、秒。。。等)的数值。 DATEDIFF ( datepart, {date|timestamp}, {date|timestamp} ) 周...
15457 0
|
关系型数据库 PostgreSQL
PostgreSQL listagg within group (order by) 聚合兼容用法 string_agg ( order by) - 行列变换,CSV构造...
标签 PostgreSQL , order-set agg , listagg , string_agg , order 背景 listagg — Rows to Delimited Strings The listagg function transforms values from a g...
6282 0
|
7月前
|
关系型数据库 MySQL 数据库
Docker 部署 Mysql 举例
Docker 部署 Mysql 举例
89 0
|
存储 关系型数据库 MySQL
MySQL的临时表以及视图与存储过程、触发器等功能概念详细解释说明以及它们的使用方法举例?
MySQL的临时表以及视图与存储过程、触发器等功能概念详细解释说明以及它们的使用方法举例?
|
关系型数据库 MySQL 数据库
Docker 部署 Mysql 举例
Docker 部署 Mysql 举例
96 0
|
存储 关系型数据库 MySQL
MySQL逻辑条件判断相关语句、函数使用举例介绍
MySQL逻辑条件判断相关语句、函数使用举例介绍
107 0
|
存储 SQL 监控
16PostgreSQL 本地分区表的用法和优化|学习笔记
快速学习16PostgreSQL 本地分区表的用法和优化
902 0
16PostgreSQL 本地分区表的用法和优化|学习笔记
|
SQL 安全 关系型数据库
17PostgreSQL shared nothing分布式用法讲解|学习笔记(三)
快速学习17PostgreSQL shared nothing分布式用法讲解
279 0
17PostgreSQL shared nothing分布式用法讲解|学习笔记(三)
|
SQL 存储 移动开发
PostgreSQL psql的使用,SQL语法,数据类型,递归SQL用法(四)|学习笔记
快速学习3 PostgreSQL psql的使用,SQL语法,数据类型,递归SQL用法(四)
 PostgreSQL psql的使用,SQL语法,数据类型,递归SQL用法(四)|学习笔记
|
SQL JSON 关系型数据库
postgresql 高级用法
postgresql 高级用法

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版