Index: trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoordsValue.php |
— | — | @@ -32,11 +32,21 @@ |
33 | 33 | * |
34 | 34 | * TODO: i18n keys still need to be moved |
35 | 35 | */ |
36 | | - public static function InitGeoCoordsType() { |
| 36 | + public static function initGeoCoordsType() { |
37 | 37 | SMWDataValueFactory::registerDatatype( '_geo', __CLASS__, 'Geographic coordinate' ); |
38 | 38 | return true; |
39 | | - } |
| 39 | + } |
40 | 40 | |
| 41 | + public static function initGeoCoordsTable( $propertyTables ) { |
| 42 | + /* |
| 43 | + $propertyTables['smw_coords'] = new SMWSQLStore2Table( |
| 44 | + 'sm_coords', |
| 45 | + array( 'lat' => 'f', 'lon' => 'f' ) |
| 46 | + ); |
| 47 | + */ |
| 48 | + return true; |
| 49 | + } |
| 50 | + |
41 | 51 | /** |
42 | 52 | * @see SMWDataValue::parseUserValue |
43 | 53 | */ |
Index: trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoords.php |
— | — | @@ -11,57 +11,93 @@ |
12 | 12 | * @author Markus Krötzsch |
13 | 13 | */ |
14 | 14 | |
| 15 | +// Registration of the GoeCoords class. |
| 16 | +$wgAutoloadClasses['SMGeoCoords'] = __FILE__; |
| 17 | + |
15 | 18 | // Registration of the Geographical Coordinate type. |
16 | | -$wgAutoloadClasses['SMGeoCoordsValue'] = $smgDir . 'GeoCoords/SM_GeoCoordsValue.php'; |
| 19 | +$wgAutoloadClasses['SMGeoCoordsValue'] = dirname( __FILE__ ) . '/SM_GeoCoordsValue.php'; |
17 | 20 | |
18 | 21 | // Registration of the Geographical Coordinate value description class. |
19 | | -$wgAutoloadClasses['SMGeoCoordsValueDescription'] = $smgDir . 'GeoCoords/SM_GeoCoordsValueDescription.php'; |
| 22 | +$wgAutoloadClasses['SMGeoCoordsValueDescription'] = dirname( __FILE__ ) . '/SM_GeoCoordsValueDescription.php'; |
20 | 23 | |
21 | 24 | // Hook for initializing the Geographical Coordinate type. |
22 | | -$wgHooks['smwInitDatatypes'][] = 'SMGeoCoordsValue::InitGeoCoordsType'; |
| 25 | +$wgHooks['smwInitDatatypes'][] = 'SMGeoCoordsValue::initGeoCoordsType'; |
23 | 26 | |
| 27 | +$wgHooks['SMWPropertyTables'][] = 'SMGeoCoordsValue::initGeoCoordsTable'; |
| 28 | + |
24 | 29 | // Hook for initializing the Geographical Proximity query support. |
25 | | -$wgHooks['smwGetSQLConditionForValue'][] = 'smfGetGeoProximitySQLCondition'; |
| 30 | +$wgHooks['smwGetSQLConditionForValue'][] = 'SMGeoCoords::getGeoProximitySQLCondition'; |
26 | 31 | |
27 | 32 | define( 'SM_CMP_NEAR', 101 ); // Define the near comparator for proximity queries. |
28 | 33 | |
29 | | - |
30 | | -/** |
31 | | - * Custom SQL query extension for matching geographic coordinates. |
32 | | - * |
33 | | - * TODO: Change the way coords are stored in the db from a string field to 2 float fields. |
34 | | - * The geographic coordinate value object should provide functions to access the lat and lon data directly. |
35 | | - * |
36 | | - * TODO: Add support for a per-coordinate set distance parameter. |
37 | | - */ |
38 | | -function smfGetGeoProximitySQLCondition( &$where, SMGeoCoordsValueDescription $description, $tablename, $fieldname, $dbs ) { |
39 | | - global $smgGeoCoordDistance; |
| 34 | +final class SMGeoCoords { |
40 | 35 | |
41 | | - $where = ''; |
42 | | - $dv = $description->getDatavalue(); |
43 | | - |
44 | | - // Only execute the query when the description's type is geographical coordinates, |
45 | | - // the description is valid, and the near comparator is used. |
46 | | - if ( ( $dv->getTypeID() != '_geo' ) |
47 | | - || ( !$dv->isValid() ) |
48 | | - || ( $description->getComparator() != SM_CMP_NEAR ) |
49 | | - ) return true; |
| 36 | + /** |
| 37 | + * Custom SQL query extension for matching geographic coordinates. |
| 38 | + * |
| 39 | + * TODO: Change the way coords are stored in the db from a string field to 2 float fields. |
| 40 | + * The geographic coordinate value object should provide functions to access the lat and lon data directly. |
| 41 | + * |
| 42 | + * TODO: Add support for a per-coordinate set distance parameter. |
| 43 | + */ |
| 44 | + public static function getGeoProximitySQLCondition( &$whereSQL, SMGeoCoordsValueDescription $description, $tablename, $fieldname, $dbs ) { |
| 45 | + // If the MapsGeoFunctions class is not loaded, we can not create the bounding box, so don't add any conditions. |
| 46 | + if ( !self::geoFunctionsAreAvailable() ) { |
| 47 | + return true; |
| 48 | + } |
50 | 49 | |
51 | | - $keys = $dv->getDBkeys(); |
52 | | - $geoarray = explode( ',', $keys[0] ); |
53 | | - |
54 | | - if ( ( count( $geoarray ) != 2 ) |
55 | | - || ( $geoarray[0] == '' ) |
56 | | - || ( $geoarray[1] == '' ) |
57 | | - ) return true; // There is something wrong with the lat/lon pair |
| 50 | + $dataValue = $description->getDatavalue(); |
58 | 51 | |
59 | | - $latitude = $dbs->addQuotes( $geoarray[0] ); |
60 | | - $longitude = $dbs->addQuotes( $geoarray[1] ); |
| 52 | + // Only execute the query when the description's type is geographical coordinates, |
| 53 | + // the description is valid, and the near comparator is used. |
| 54 | + if ( ( $dataValue->getTypeID() != '_geo' ) |
| 55 | + || ( !$dataValue->isValid() ) |
| 56 | + || ( $description->getComparator() != SM_CMP_NEAR ) |
| 57 | + ) return true; |
| 58 | + |
| 59 | + $dbKeys = $dataValue->getDBkeys(); |
| 60 | + |
| 61 | + global $smgGeoCoordDistance; |
| 62 | + $distance = $smgGeoCoordDistance; // TODO: get user provided distance |
| 63 | + |
| 64 | + $boundingBox = self::getBoundingBox( |
| 65 | + array( |
| 66 | + 'lat' => $dbKeys[0], |
| 67 | + 'lon' => $dbKeys[1] |
| 68 | + ), |
| 69 | + $distance |
| 70 | + ); |
| 71 | + |
| 72 | + $north = $dbs->addQuotes( $boundingBox['north'] ); |
| 73 | + $east = $dbs->addQuotes( $boundingBox['east'] ); |
| 74 | + $south = $dbs->addQuotes( $boundingBox['south'] ); |
| 75 | + $west = $dbs->addQuotes( $boundingBox['west'] ); |
| 76 | + |
| 77 | + $whereSQL .= "{$tablename}lat < $north && {$tablename}lat > $south && {$tablename}lon < $east && {$tablename}lon > $west"; |
| 78 | + |
| 79 | + return true; |
| 80 | + } |
| 81 | + |
| 82 | + private static function getBoundingBox( $centerCoordinates, $circleRadius ) { |
| 83 | + $north = MapsGeoFunctions::findDestination( $centerCoordinates, 0, $circleRadius ); |
| 84 | + $east = MapsGeoFunctions::findDestination( $centerCoordinates, 90, $circleRadius ); |
| 85 | + $south = MapsGeoFunctions::findDestination( $centerCoordinates, 180, $circleRadius ); |
| 86 | + $west = MapsGeoFunctions::findDestination( $centerCoordinates, 270, $circleRadius ); |
| 87 | + |
| 88 | + return array( |
| 89 | + 'north' => $north['lat'], |
| 90 | + 'east' => $east['lon'], |
| 91 | + 'south' => $south['lat'], |
| 92 | + 'west' => $west['lon'], |
| 93 | + ); |
| 94 | + } |
61 | 95 | |
62 | | - // Compute distances in miles: |
63 | | - $distance = "ROUND(((ACOS( SIN({$latitude} * PI()/180 ) * SIN(SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',1) * PI()/180 ) + COS({$latitude} * PI()/180 ) * COS(SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',1) * PI()/180 ) * COS(({$longitude} - SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',-1)) * PI()/180))*180/PI())*60*1.1515),6)"; |
| 96 | + /** |
| 97 | + * Returns a boolean indicating if MapsGeoFunctions is available. |
| 98 | + */ |
| 99 | + private static function geoFunctionsAreAvailable() { |
| 100 | + global $wgAutoloadClasses; |
| 101 | + return array_key_exists( 'MapsGeoFunctions', $wgAutoloadClasses ); |
| 102 | + } |
| 103 | +} |
64 | 104 | |
65 | | - $where = "{$distance} <= " . $dbs->addQuotes( $smgGeoCoordDistance ); |
66 | | - |
67 | | - return true; |
68 | | -} |
\ No newline at end of file |
Index: trunk/extensions/SemanticMaps/SemanticMaps.php |
— | — | @@ -35,7 +35,7 @@ |
36 | 36 | |
37 | 37 | // Only initialize the extension when all dependencies are present. |
38 | 38 | if ( defined( 'Maps_VERSION' ) && defined( 'SMW_VERSION' ) ) { |
39 | | - define( 'SM_VERSION', '0.6 a11' ); |
| 39 | + define( 'SM_VERSION', '0.6 a12' ); |
40 | 40 | |
41 | 41 | $smgScriptPath = ( isset( $wgExtensionAssetsPath ) && $wgExtensionAssetsPath ? $wgExtensionAssetsPath : $wgScriptPath . '/extensions' ) . '/SemanticMaps'; |
42 | 42 | $smgDir = dirname( __FILE__ ) . '/'; |