@@ -57,6 +57,7 @@ PG_FUNCTION_INFO_V1(spheretrans_poly);
5757PG_FUNCTION_INFO_V1 (spheretrans_poly_inverse );
5858PG_FUNCTION_INFO_V1 (spherepoly_add_point );
5959PG_FUNCTION_INFO_V1 (spherepoly_add_points_finalize );
60+ PG_FUNCTION_INFO_V1 (spherepoly_is_convex );
6061
6162
6263/*
@@ -1478,3 +1479,53 @@ spherepoly_add_points_finalize(PG_FUNCTION_ARGS)
14781479}
14791480PG_RETURN_POINTER (poly );
14801481}
1482+
1483+
1484+ Datum
1485+ spherepoly_is_convex (PG_FUNCTION_ARGS )
1486+ {
1487+ Vector3D u ,
1488+ v ,
1489+ vsu ,
1490+ wsv ,
1491+ crs ;
1492+ float8 cur = 0 ,
1493+ prev = 0 ;
1494+ SPOLY * poly = (SPOLY * )PG_GETARG_POINTER (0 );
1495+
1496+ if (poly == NULL )
1497+ {
1498+ PG_RETURN_BOOL (false);
1499+ }
1500+
1501+ poly = PG_GETARG_SPOLY (0 );
1502+ if (poly -> npts == 3 )
1503+ {
1504+ PG_RETURN_BOOL (true);
1505+ }
1506+
1507+ for (int i = 0 ;i < poly -> npts ;i ++ )
1508+ {
1509+ const int j = (i - 1 + poly -> npts ) %poly -> npts ;
1510+ const int k = (i + 1 ) %poly -> npts ;
1511+
1512+ spoint_vector3d (& u ,& poly -> p [i ]);
1513+ spoint_vector3d (& v ,& poly -> p [j ]);
1514+ spoint_vector3d (& vsu ,& poly -> p [j ]);
1515+ spoint_vector3d (& wsv ,& poly -> p [k ]);
1516+
1517+ vector3d_addwithscalar (& vsu ,-1 ,& u );
1518+ vector3d_addwithscalar (& wsv ,-1 ,& v );
1519+
1520+ vector3d_cross (& crs ,& vsu ,& wsv );
1521+
1522+ cur = vector3d_scalar (& crs ,& v );
1523+ if (cur * prev < 0 )
1524+ {
1525+ PG_RETURN_BOOL (false);
1526+ }
1527+ prev = cur ;
1528+ }
1529+
1530+ PG_RETURN_BOOL (true);
1531+ }