795{
796 GBOX gbox, gbox1, gbox2;
801 double xwidth, ywidth;
804
805
806 g1 = PG_GETARG_GSERIALIZED_P(0);
807
809
811
812
814
815
817 elog(ERROR, "Error in geography_bestsrid calling gserialized_get_gbox_p(g1, &gbox1)");
818
819 POSTGIS_DEBUGF(4,
"calculated gbox = %s",
gbox_to_string(&gbox1));
820
822 elog(ERROR, "Error in geography_bestsrid calling with infinite coordinate geographies");
823 }
825
826
827 if (PG_NARGS() > 1)
828 {
829 g2 = PG_GETARG_GSERIALIZED_P(1);
833 elog(ERROR, "Error in geography_bestsrid calling gserialized_get_gbox_p(g2, &gbox2)");
834
835
837
839 elog(ERROR, "Error in geography_bestsrid calling with second arg infinite coordinate geographies");
840 }
842 }
843
844
845
846
847 else
848 {
849 gbox = gbox2 = gbox1;
850 }
851
852
853 if ( empty1 && empty2 )
854 PG_RETURN_NULL();
855
856
857 if ( empty1 )
858 gbox = gbox2;
859 else if ( empty2 )
860 gbox = gbox1;
861 else
863
865
866
869
870 POSTGIS_DEBUGF(2, "xwidth %g", xwidth);
871 POSTGIS_DEBUGF(2, "ywidth %g", ywidth);
872 POSTGIS_DEBUGF(2,
"center POINT(%g %g)", center.
x, center.
y);
873
874
875 if ( center.
y > 70.0 && ywidth < 45.0 )
876 {
877 PG_RETURN_INT32(SRID_NORTH_LAMBERT);
878 }
879
880
881 if ( center.
y < -70.0 && ywidth < 45.0 )
882 {
883 PG_RETURN_INT32(SRID_SOUTH_LAMBERT);
884 }
885
886
887
888
889
890
891
892 if ( xwidth < 6.0 )
893 {
894 int zone = floor((center.
x + 180.0) / 6.0);
895
896 if ( zone > 59 ) zone = 59;
897
898
899 if ( center.
y < 0.0 )
900 {
901 PG_RETURN_INT32( SRID_SOUTH_UTM_START + zone );
902 }
903
904 else
905 {
906 PG_RETURN_INT32( SRID_NORTH_UTM_START + zone );
907 }
908 }
909
910
911
912
913
914
915
916 if ( ywidth < 25.0 )
917 {
918 int xzone = -1;
919 int yzone = 3 + floor(center.
y / 30.0);
920
921
922 if ( (yzone == 2 || yzone == 3) && xwidth < 30.0 )
923 {
924 xzone = 6 + floor(center.
x / 30.0);
925 }
926
927 else if ( (yzone == 1 || yzone == 4) && xwidth < 45.0 )
928 {
929 xzone = 4 + floor(center.
x / 45.0);
930 }
931
932 else if ( (yzone == 0 || yzone == 5) && xwidth < 90.0 )
933 {
934 xzone = 2 + floor(center.
x / 90.0);
935 }
936
937
938 if ( xzone != -1 )
939 {
940 PG_RETURN_INT32(SRID_LAEA_START + 20 * yzone + xzone);
941 }
942 }
943
944
945
946
947
948 PG_RETURN_INT32(SRID_WORLD_MERCATOR);
949
950}
int gbox_union(const GBOX *g1, const GBOX *g2, GBOX *gout)
Update the output GBOX to be large enough to include both inputs.
char * gbox_to_string(const GBOX *gbox)
Allocate a string representation of the GBOX, based on dimensionality of flags.
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
lwflags_t gserialized_get_lwflags(const GSERIALIZED *g)
Read the flags from a GSERIALIZED and return a standard lwflag integer.
void lwgeom_free(LWGEOM *geom)
int lwgeom_isfinite(const LWGEOM *lwgeom)
Check if a LWGEOM has any non-finite (NaN or Inf) coordinates.
double gbox_angular_height(const GBOX *gbox)
GBOX utility functions to figure out coverage/location on the globe.
double gbox_angular_width(const GBOX *gbox)
Returns the angular width (longitudinal span) of the box in radians.
int gbox_centroid(const GBOX *gbox, POINT2D *out)
Computes the average(ish) center of the box and returns success.