博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PostgreSQL 三角函数的用法举例 - 已知3点求夹角(旋转门续)
阅读量:7119 次
发布时间:2019-06-28

本文共 5177 字,大约阅读时间需要 17 分钟。

背景

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

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 支持的三角函数

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 doubleacosd_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) */Datumdacosd(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 functionSYNOPSIS       #include 
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)

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

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

转载地址:http://qwdel.baihongyu.com/

你可能感兴趣的文章
二分查找及其变种简单易懂的模版
查看>>
mysql优化小技巧
查看>>
CardinalSpline样条曲线(沿着正方形路线走)
查看>>
设计模式之观察者设计模式
查看>>
HDOJ_ACM_Bone Collector
查看>>
第三章:垃圾回收器:垃圾回收器的两种算法
查看>>
力扣算法题—091解码
查看>>
两直线异面的充要条件
查看>>
2018软工实践_团队作业_1
查看>>
leetcode-001-Two sum
查看>>
eclipse Java注释模版
查看>>
LCS(打印全路径) POJ 2264 Advanced Fruits
查看>>
逆序数 UVALive 6508 Permutation Graphs
查看>>
读《大学之路》有感③
查看>>
TYVJ P1068 STR Label:KMP匹配 不懂
查看>>
AIX系统日志
查看>>
dataguard类型转换与模式转化
查看>>
Linux下解决中文乱码问题
查看>>
C++ STL之LIST详解A
查看>>
ANG-----全方位保障您的数字资产安全
查看>>