diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..dcdbc8c Binary files /dev/null and b/.DS_Store differ diff --git a/sql/bearing.sql b/sql/bearing.sql new file mode 100644 index 0000000..87b6f15 --- /dev/null +++ b/sql/bearing.sql @@ -0,0 +1,67 @@ +-- Calculate bearing + +DELIMITER $$ +DROP FUNCTION IF EXISTS wp_bearing$$ +DROP FUNCTION IF EXISTS wp_bevier_ctrlpts$$ + +CREATE FUNCTION `wp_bearing` (p1 POINT, p2 POINT) RETURNS FLOAT +NO SQL DETERMINISTIC +BEGIN + DECLARE lat1 FLOAT; + DECLARE lng1 FLOAT; + DECLARE lat2 FLOAT; + DECLARE lng2 FLOAT; + DECLARE geom1 GEOMETRY; + DECLARE geom2 GEOMETRY; + DECLARE dLng FLOAT; + DECLARE y FLOAT; + DECLARE x FLOAT; + DECLARE bearing FLOAT; + + SET geom1 = wp_first_geom( p1 ); + SET geom2 = wp_first_geom( p2 ); + SET lat1 = RADIANS( ST_Y( geom1 )); + SET lng1 = RADIANS( ST_X( geom1 )); + SET lat2 = RADIANS( ST_Y( geom2 )); + SET lng2 = RADIANS( ST_X( geom2 )); + + SET dLng = lng2 - lng1 ; + + SET y = SIN( dLng ) * COS( lat2 ); + SET x = ( COS( lat1 ) * SIN ( lat2 ) ) - ( SIN( lat1 ) * COS( lat2 ) * COS( dLng ) ); + SET bearing = DEGREES( ATAN2( y, x ) ); + + RETURN bearing; +END$$ + + +CREATE FUNCTION `wp_bevier_ctrlpts` (p1 POINT, p2 POINT, p3 POINT, factor FLOAT) RETURNS MULTIPOINT +NO SQL DETERMINISTIC +BEGIN + DECLARE len_s FLOAT; + DECLARE len_t FLOAT; + DECLARE bearing_s FLOAT; + DECLARE bearing_t FLOAT; + DECLARE dbearing FLOAT; + DECLARE bearing_m FLOAT; + DECLARE ctrlpt1_text TEXT; + DECLARE ctrlpt2_text TEXT; + DECLARE ctrlpt1 GEOMETRY; + DECLARE ctrlpt2 GEOMETRY; + + SET len_s = wp_distance_point_real(p2 , p1, 1); + SET len_t = wp_distance_point_real(p2 , p3, 1); + SET bearing_s = (wp_bearing(p2, p1) + 180 + 360 ) % 360; + SET bearing_t = (wp_bearing(p2, p3) + 360 ) % 360; + SET dbearing = bearing_t - bearing_s ; + + SET bearing_m = bearing_s + dbearing * len_s / (len_s + len_t); + SET ctrlpt1_text = wp_point_bearing_distance_coord_pair( p2, bearing_m, - len_s / factor, 1 ); + SET ctrlpt2_text = wp_point_bearing_distance_coord_pair( p2, bearing_m, len_t / factor ,1 ); + SET ctrlpt1 = ST_GeomFromText( CONCAT('POINT(',ctrlpt1_text,')')); + SET ctrlpt2 = ST_GeomFromText( CONCAT('POINT(',ctrlpt2_text,')')); + + RETURN MULTIPOINT( ctrlpt1 , ctrlpt2 ); +END$$ + +DELIMITER ; diff --git a/wp-geoquery.php b/wp-geoquery.php index 951ebde..0625de9 100644 --- a/wp-geoquery.php +++ b/wp-geoquery.php @@ -223,15 +223,16 @@ private function handle_two_geom_bool_meta( &$clauses, $meta_query, $type, $prim $new_meta_value = "{$meta_query['compare']}( meta_value,ST_GeomFromText( %s, %d, 'axis-order=long-lat' ) )"; $new_meta_value = $wpdb->prepare( $new_meta_value, array( $geometry, WP_GeoUtil::get_srid() ) ); // @codingStandardsIgnoreLine - $std_query = "( $metatable.meta_key = %s AND CAST($metatable.meta_value AS $meta_type) = %s )"; - $std_queries[] = $wpdb->prepare( $std_query, array( $meta_query['key'], $meta_query['value'] ) ); // @codingStandardsIgnoreLine + $std_query = " CAST($metatable.meta_value AS $meta_type) = %s "; + $std_queries[] = $wpdb->prepare( $std_query, array( $meta_query['value'] ) ); // @codingStandardsIgnoreLine // In WP 4.6 and above CHAR values aren't cast anymore, so we do a replace on both versions // so that we maintain 4.5.x capabilities too. if ( 'CHAR' === $meta_type ) { - $std_query = "( $metatable.meta_key = %s AND $metatable.meta_value = %s )"; - $std_queries[] = $wpdb->prepare( $std_query, array( $meta_query['key'], $meta_query['value'] ) ); // @codingStandardsIgnoreLine + $std_query = " $metatable.meta_value = %s "; + $std_queries[] = $wpdb->prepare( $std_query, array( $meta_query['value'] ) ); // @codingStandardsIgnoreLine } + $geom_query = $wpdb->prepare( " $metatable.meta_value " ); // @codingStandardsIgnoreLine } else { // If we don't have a value, then our subquery gets written without parenthesis wraps. // IDK why. @@ -239,11 +240,11 @@ private function handle_two_geom_bool_meta( &$clauses, $meta_query, $type, $prim $std_query = " $metatable.meta_key = %s"; $std_queries[] = $wpdb->prepare( $std_query, array( $meta_query['key'] ) ); // @codingStandardsIgnoreLine - } - // Our geom_query will be against our aliased meta table so we just need to check for boolean true. - $geom_query = "( $metatable.meta_key = %s AND $metatable.meta_value )"; - $geom_query = $wpdb->prepare( $geom_query, array( $meta_query['key'] ) ); // @codingStandardsIgnoreLine + // Our geom_query will be against our aliased meta table so we just need to check for boolean true. + $geom_query = "( $metatable.meta_key = %s AND $metatable.meta_value )"; + $geom_query = $wpdb->prepare( $geom_query, array( $meta_query['key'] ) ); // @codingStandardsIgnoreLine + } $this->make_join_spatial( $clauses,$meta_query,$type,$primary_table,$primary_id_column,$context, $metatable, $geotable, $id_column, $new_meta_value ); diff --git a/wp-geoutil.php b/wp-geoutil.php index 0395c18..329b89f 100644 --- a/wp-geoutil.php +++ b/wp-geoutil.php @@ -180,6 +180,7 @@ class WP_GeoUtil { 'ST_LineStringFromText', 'ST_LineStringFromWKB', 'ST_LongFromGeoHash', + 'ST_MakeEnvelope', 'ST_NumGeometries', 'ST_NumInteriorRings', 'ST_NumPoints', @@ -209,6 +210,8 @@ class WP_GeoUtil { 'Within', 'X', 'Y', + 'WP_Bearing', + 'WP_Bevier_CtrlPts', 'WP_Buffer_Point_M', 'WP_Buffer_Point_Mi', 'WP_Buffer_Point_Real', @@ -485,8 +488,8 @@ public static function metaval_to_geom( $metaval = false, $force_multi = false ) if ( $force_multi && false === strpos( $wkt, 'MULTI' ) ) { if ( 0 === strpos( $wkt, 'POINT' ) ) { $wkt = preg_replace( '@^POINT@','MULTIPOINT', $wkt ); - } else if ( 0 === strpos( $wkt, 'LINE' ) || 0 === strpos( $wkt, 'POLYGON' ) ) { - $wkt = preg_replace( '@^(LINE|POLYGON)(\s*)(\(.*?\)[^,])@','MULTI$1$2($3)', $wkt ); + } else if ( 0 === strpos( $wkt, 'LINESTRING' ) || 0 === strpos( $wkt, 'POLYGON' ) ) { + $wkt = preg_replace( '@^(LINESTRING|POLYGON)(\s*)(\(.*?\)[^,])@','MULTI$1$2($3)', $wkt ); } } @@ -736,7 +739,7 @@ private static function run_spatial_query( $name, $arguments = array() ) { $maybe_geom = self::metaval_to_geom( $arg ); if ( false !== $maybe_geom ) { $arguments[ $idx ] = $maybe_geom; - $q .= 'GeomCollFromText(%s)'; + $q .= 'ST_GeomFromText(%s)'; } else { $q .= '%s'; } @@ -776,7 +779,7 @@ private static function run_spatial_query( $name, $arguments = array() ) { \'0001000004\', -- multipoint \'0001000005\', -- multiline \'0001000006\' -- multipolygon - ), false) , AsText( retval ), retval ) AS res FROM ( ' . $q . ' AS retval ) rq'; + ), false) , ST_AsText( retval ), retval ) AS res FROM ( ' . $q . ' AS retval ) rq'; $sql = $wpdb->prepare( $real_q, $arguments ); // @codingStandardsIgnoreLine