function normalizedBoundingBox($center, $tolerance, $fromProj = null, $toProj = null) { if ($fromProj !== null || $toProj !== null) { $projector = new MapProjector(); } // create the bounding box in lat/lon first if ($fromProj !== null) { $projector->setSrcProj($fromProj); $center = $projector->projectPoint($center); } // approximate upper/lower bounds for lat/lon before calculating GCD $dLatRadians = $tolerance / EARTH_RADIUS_IN_METERS; // by haversine formula $dLonRadians = 2 * asin(sin($dLatRadians / 2) / cos($center['lat'] * M_PI / 180)); $dLatDegrees = $dLatRadians * 180 / M_PI; $dLonDegrees = $dLonRadians * 180 / M_PI; $min = array('lat' => $center['lat'] - $dLatDegrees, 'lon' => $center['lon'] - $dLonDegrees); $max = array('lat' => $center['lat'] + $dLatDegrees, 'lon' => $center['lon'] + $dLonDegrees); if ($toProj !== null) { $projector->setSrcProj(GEOGRAPHIC_PROJECTION); $projector->setDstProj($toProj); $min = $projector->projectPoint($min); $max = $projector->projectPoint($max); } return array('min' => $min, 'max' => $max, 'center' => $center); }
public function initializeForCommand() { if ($projection = $this->getArg('projection')) { $this->mapProjector = new MapProjector(); $this->mapProjector->setDstProj($projection); } switch ($this->command) { case 'index': $categories = array(); $response = array('displayType' => $this->getModuleDisplayType()); $groups = $this->getFeedGroups(); if ($groups) { foreach ($groups as $id => &$groupData) { if (isset($groupData['center'])) { $latlon = filterLatLon($groupData['center']); $groupData['lat'] = $latlon['lat']; $groupData['lon'] = $latlon['lon']; } $groupData['id'] = $id; $categories[] = $groupData; } $response['categories'] = $categories; } else { $feeds = $this->loadFeedData(); foreach ($feeds as $id => $feedData) { $categories[] = array('title' => $feedData['TITLE'], 'subtitle' => $feedData['SUBTITLE'], 'id' => $id); } } $this->setResponse($response); $this->setResponseVersion(1); break; case 'category': $this->loadFeedData(); $categoryId = $this->getArg('category'); $groups = $this->getFeedGroups(); if (isset($groups[$categoryId])) { $this->feedGroup = $categoryId; $groupData = $this->loadFeedData(); $categories = array(); foreach ($groupData as $id => $feed) { if (!isset($feed['HIDDEN']) || !$feed['HIDDEN']) { $category = array('id' => $id, 'title' => $feed['TITLE']); if (isset($feed['SUBTITLE'])) { $category['subtitle'] = $feed['SUBTITLE']; } $categories[] = $category; } } $response = array('categories' => $categories); $this->setResponse($response); $this->setResponseVersion(1); } else { $controller = $this->getDataModel(); if ($controller) { //if ($categoryId) { // $category = $controller->findCategory($categoryId); // $placemarks = $category->placemarks(); // $categories = $category->categories(); //} else { $placemarks = $controller->placemarks(); $categories = $controller->categories(); //} if ($placemarks) { $response['placemarks'] = array(); foreach ($placemarks as $placemark) { $response['placemarks'][] = $this->arrayFromPlacemark($placemark); } } if ($categories) { foreach ($categories as $aCategory) { $response['categories'][] = $this->arrayFromCategory($aCategory); } } if (!$placemarks && !$categories) { // need something in the response so that it will be // output as a JSON object rather than a JSON array $response = array('categories' => array()); } $this->setResponse($response); $this->setResponseVersion(1); } else { $error = new KurogoError("Could not find data source for requested category"); $this->throwError($error); } } break; case 'detail': $suppress = $this->getOptionalModuleVar('suppress', array(), 'details', 'page-detail'); $tabKeys = $this->getOptionalModuleVar('tabkeys', array(), 'tabs', 'page-detail'); $controller = $this->getDataModel(); $placemarkId = $this->getArg('id', null); if ($controller && $placemarkId !== null) { $placemarks = $controller->selectPlacemark($placemarkId); $placemark = current($placemarks); $fields = $placemark->getFields(); $geometry = $placemark->getGeometry(); $tabs = $this->getTabsForTabKeys($tabKeys, $this->command); $response = array('sections' => $tabs, 'id' => $placemarkId, 'title' => $placemark->getTitle(), 'subtitle' => $placemark->getSubtitle(), 'address' => $placemark->getAddress()); if ($this->requestedVersion >= 2) { $response['description'] = $placemark->getDescription($suppress); $responseVersion = 2; } else { $response['details'] = array('description' => $placemark->getDescription($suppress)); $photoURL = $placemark->getField('PhotoURL'); if ($photoURL) { $response['photoURL'] = $photoURL; } $responseVersion = 1; } if ($geometry) { $center = $geometry->getCenterCoordinate(); $response['lat'] = $center['lat']; $response['lon'] = $center['lon']; $response['geometryType'] = $this->getGeometryType($geometry); $response['geometry'] = $this->formatGeometry($geometry); } $this->setResponse($response); $this->setResponseVersion($responseVersion); } break; case 'search': $mapSearch = $this->getSearchClass($this->args); $lat = $this->getArg('lat', 0); $lon = $this->getArg('lon', 0); if ($lat || $lon) { // defaults values for proximity search $tolerance = 1000; $maxItems = 0; // check for settings in feedgroup config $configData = $this->getDataForGroup($this->feedGroup); if ($configData) { if (isset($configData['NEARBY_THRESHOLD'])) { $tolerance = $configData['NEARBY_THRESHOLD']; } if (isset($configData['NEARBY_ITEMS'])) { $maxItems = $configData['NEARBY_ITEMS']; } } // check for override settings in feeds $configData = $this->getCurrentFeed(); if (isset($configData['NEARBY_THRESHOLD'])) { $tolerance = $configData['NEARBY_THRESHOLD']; } if (isset($configData['NEARBY_ITEMS'])) { $maxItems = $configData['NEARBY_ITEMS']; } $searchResults = $mapSearch->searchByProximity(array('lat' => $lat, 'lon' => $lon), 1000, 10); } else { if ($searchTerms = $this->getArg(array('filter', 'q'))) { $this->setLogData($searchTerms); $searchResults = $mapSearch->searchCampusMap($searchTerms); } } $provider = null; if ($this->requestedVersion >= 2 && $this->getArg('provider', null)) { $providerId = $this->getArg('provider'); switch ($providerId) { case 'google': $provider = new GoogleJSMap(); break; case 'esri': $provider = new ArcGISJSMap(); break; } if ($provider && $projection) { $provider->setMapProjection($projection); } } $places = array(); foreach ($searchResults as $result) { if ($this->requestedVersion >= 2) { $place = array('attribs' => $this->shortArrayFromPlacemark($result)); } else { $place = $this->shortArrayFromPlacemark($result); } if ($provider) { if ($result instanceof MapPolygon) { $place['placemark'] = $provider->jsObjectForPolygon($result); } elseif ($result instanceof MapPolyline) { $place['placemark'] = $provider->jsObjectForPath($result); } else { $place['placemark'] = $provider->jsObjectForMarker($result); } } $places[] = $place; } $response = array('total' => count($places), 'returned' => count($places), 'results' => $places); $this->setResponse($response); $this->setResponseVersion(1); break; // ajax calls // ajax calls case 'projectPoint': $lat = $this->getArg('lat', 0); $lon = $this->getArg('lon', 0); $fromProj = $this->getArg('from', GEOGRAPHIC_PROJECTION); $toProj = $this->getArg('to', GEOGRAPHIC_PROJECTION); $projector = new MapProjector(); $projector->setSrcProj($fromProj); $projector->setDstProj($toProj); $result = $projector->projectPoint(array('lat' => $lat, 'lon' => $lon)); $this->setResponse($result); $this->setResponseVersion(1); break; case 'sortGroupsByDistance': $lat = $this->getArg('lat', 0); $lon = $this->getArg('lon', 0); $categories = array(); $showDistances = $this->getOptionalModuleVar('SHOW_DISTANCES', true); if ($lat || $lon) { foreach ($this->getFeedGroups() as $id => $groupData) { $center = filterLatLon($groupData['center']); $distance = greatCircleDistance($lat, $lon, $center['lat'], $center['lon']); $category = array('title' => $groupData['title'], 'id' => $id); if ($showDistances && ($displayText = $this->displayTextFromMeters($distance))) { $category['distance'] = $displayText; } $categories[] = $category; $distances[] = $distance; } array_multisort($distances, SORT_ASC, $categories); } $this->setResponse($categories); $this->setResponseVersion(1); break; case 'staticImageURL': $params = array('STATIC_MAP_BASE_URL' => $this->getArg('baseURL'), 'STATIC_MAP_CLASS' => $this->getArg('mapClass')); $dc = Kurogo::deviceClassifier(); $mapDevice = new MapDevice($dc->getPagetype(), $dc->getPlatform()); $mapController = MapImageController::factory($params, $mapDevice); if (!$mapController->isStatic()) { $error = new KurogoError(0, "staticImageURL must be used with a StaticMapImageController subclass"); $this->throwError($error); } $currentQuery = $this->getArg('query'); $mapController->parseQuery($currentQuery); $overrides = $this->getArg('overrides'); $mapController->parseQuery($overrides); $zoomDir = $this->getArg('zoom'); if ($zoomDir == 1 || $zoomDir == 'in') { $level = $mapController->getLevelForZooming('in'); $mapController->setZoomLevel($level); } elseif ($zoomDir == -1 || $zoomDir == 'out') { $level = $mapController->getLevelForZooming('out'); $mapController->setZoomLevel($level); } $scrollDir = $this->getArg('scroll'); if ($scrollDir) { $center = $mapController->getCenterForPanning($scrollDir); $mapController->setCenter($center); } $url = $mapController->getImageURL(); $this->setResponse($url); $this->setResponseVersion(1); break; case 'geocode': // TODO: this is not fully implemented. do not use this API. includePackage('Maps', 'Geocoding'); $locationSearchTerms = $this->getArg('q'); $geocodingDataRetrieverClass = $this->getOptionalModuleVar('GEOCODING_DATA_RETRIEVER_CLASS'); $geocodingDataParserClass = $this->getOptionalModuleVar('GEOCODING_DATA_PARSER_CLASS'); $geocoding_base_url = $this->getOptionalModuleVar('GEOCODING_BASE_URL'); $arguments = array('BASE_URL' => $geocoding_base_url, 'CACHE_LIFETIME' => 86400, 'PARSER_CLASS' => $geocodingDataParserClass); $controller = DataRetriever::factory($geocodingDataRetrieverClass, $arguments); $controller->addCustomFilters($locationSearchTerms); $response = $controller->getParsedData(); // checking for Geocoding service error if ($response['errorCode'] == 0) { unset($response['errorCode']); unset($response['errorMessage']); $this->setResponse($response); $this->setResponseVersion(1); } else { $kurogoError = new KurogoError($response['errorCode'], "Geocoding service Erroe", $response['errorMessage']); $this->setResponseError($kurogoError); $this->setResponseVersion(1); } break; default: $this->invalidCommand(); break; } }
public function initializeForCommand() { switch ($this->command) { case 'index': $categories = array(); $groups = $this->getFeedGroups(); if ($groups) { foreach ($groups as $id => &$groupData) { if (isset($groupData['center'])) { $latlon = filterLatLon($groupData['center']); $groupData['lat'] = $latlon['lat']; $groupData['lon'] = $latlon['lon']; } $groupData['id'] = $id; $categories[] = $groupData; } $response = array('categories' => $categories); } else { $feeds = $this->loadFeedData(); foreach ($feeds as $id => $feedData) { $categories[] = array('title' => $feedData['TITLE'], 'subtitle' => $feedData['SUBTITLE'], 'id' => $id); } } $this->setResponse($response); $this->setResponseVersion(1); break; case 'category': $this->loadFeedData(); $category = $this->getArg('category'); $groups = $this->getFeedGroups(); if (isset($groups[$category])) { $this->feedGroup = $category; $groupData = $this->loadFeedData(); $categories = array(); foreach ($groupData as $id => $feed) { if (!isset($feed['HIDDEN']) || !$feed['HIDDEN']) { $category = array('id' => $id, 'title' => $feed['TITLE']); if (isset($feed['SUBTITLE'])) { $category['subtitle'] = $feed['SUBTITLE']; } $categories[] = $category; } } $response = array('categories' => $categories); $this->setResponse($response); $this->setResponseVersion(1); } else { $dataController = $this->getDataController(); if ($dataController) { $listItems = $dataController->getListItems(); $placemarks = array(); $categories = array(); foreach ($listItems as $listItem) { if ($listItem instanceof Placemark) { $placemarks[] = $this->shortArrayFromPlacemark($listItem); } else { $categories[] = $this->arrayFromCategory($listItem); } } $response = array(); if ($placemarks) { $response['placemarks'] = $placemarks; } if ($categories) { $response['categories'] = $categories; } $this->setResponse($response); $this->setResponseVersion(1); } else { $error = new KurogoError("Could not find data source for requested category"); $this->throwError($error); } } break; case 'detail': $dataController = $this->getDataController(); $placemarkId = $this->getArg('id', null); if ($dataController && $placemarkId !== null) { $placemark = $dataController->selectPlacemark($placemarkId); $fields = $placemark->getFields(); $geometry = $placemark->getGeometry(); $response = array('id' => $placemarkId, 'title' => $placemark->getTitle(), 'subtitle' => $placemark->getSubtitle(), 'address' => $placemark->getAddress(), 'details' => $placemark->getFields()); if ($geometry) { $center = $geometry->getCenterCoordinate(); $response['lat'] = $center['lat']; $response['lon'] = $center['lon']; $response['geometryType'] = $this->getGeometryType($geometry); $response['geometry'] = $this->formatGeometry($geometry); } $this->setResponse($response); $this->setResponseVersion(1); } break; case 'search': $mapSearch = $this->getSearchClass($this->args); $lat = $this->getArg('lat', 0); $lon = $this->getArg('lon', 0); if ($lat || $lon) { // defaults values for proximity search $tolerance = 1000; $maxItems = 0; // check for settings in feedgroup config $configData = $this->getDataForGroup($this->feedGroup); if ($configData) { if (isset($configData['NEARBY_THRESHOLD'])) { $tolerance = $configData['NEARBY_THRESHOLD']; } if (isset($configData['NEARBY_ITEMS'])) { $maxItems = $configData['NEARBY_ITEMS']; } } // check for override settings in feeds $configData = $this->getCurrentFeed(); if (isset($configData['NEARBY_THRESHOLD'])) { $tolerance = $configData['NEARBY_THRESHOLD']; } if (isset($configData['NEARBY_ITEMS'])) { $maxItems = $configData['NEARBY_ITEMS']; } $searchResults = $mapSearch->searchByProximity(array('lat' => $lat, 'lon' => $lon), 1000, 10); } else { $searchTerms = $this->getArg('q'); if ($searchTerms) { $searchResults = $mapSearch->searchCampusMap($searchTerms); } } $places = array(); foreach ($searchResults as $result) { $places[] = $this->shortArrayFromPlacemark($result); } $response = array('total' => count($places), 'returned' => count($places), 'results' => $places); $this->setResponse($response); $this->setResponseVersion(1); break; // ajax calls // ajax calls case 'projectPoint': $lat = $this->getArg('lat', 0); $lon = $this->getArg('lon', 0); $fromProj = $this->getArg('from', GEOGRAPHIC_PROJECTION); $toProj = $this->getArg('to', GEOGRAPHIC_PROJECTION); $projector = new MapProjector(); $projector->setSrcProj($fromProj); $projector->setDstProj($toProj); $result = $projector->projectPoint(array('lat' => $lat, 'lon' => $lon)); $this->setResponse($result); $this->setResponseVersion(1); break; case 'sortGroupsByDistance': $lat = $this->getArg('lat', 0); $lon = $this->getArg('lon', 0); $categories = array(); $showDistances = $this->getOptionalModuleVar('SHOW_DISTANCES', true); if ($lat || $lon) { foreach ($this->getFeedGroups() as $id => $groupData) { $center = filterLatLon($groupData['center']); $distance = greatCircleDistance($lat, $lon, $center['lat'], $center['lon']); $category = array('title' => $groupData['title'], 'id' => $id); if ($showDistances && ($displayText = $this->displayTextFromMeters($distance))) { $category['distance'] = $displayText; } $categories[] = $category; $distances[] = $distance; } array_multisort($distances, SORT_ASC, $categories); } $this->setResponse($categories); $this->setResponseVersion(1); break; case 'staticImageURL': $params = array('STATIC_MAP_BASE_URL' => $this->getArg('baseURL'), 'STATIC_MAP_CLASS' => $this->getArg('mapClass')); $dc = Kurogo::deviceClassifier(); $mapDevice = new MapDevice($dc->getPagetype(), $dc->getPlatform()); $mapController = MapImageController::factory($params, $mapDevice); if (!$mapController->isStatic()) { $error = new KurogoError(0, "staticImageURL must be used with a StaticMapImageController subclass"); $this->throwError($error); } $currentQuery = $this->getArg('query'); $mapController->parseQuery($currentQuery); $overrides = $this->getArg('overrides'); $mapController->parseQuery($overrides); $zoomDir = $this->getArg('zoom'); if ($zoomDir == 1 || $zoomDir == 'in') { $level = $mapController->getLevelForZooming('in'); $mapController->setZoomLevel($level); } elseif ($zoomDir == -1 || $zoomDir == 'out') { $level = $mapController->getLevelForZooming('out'); $mapController->setZoomLevel($level); } $scrollDir = $this->getArg('scroll'); if ($scrollDir) { $center = $mapController->getCenterForPanning($scrollDir); $mapController->setCenter($center); } $url = $mapController->getImageURL(); $this->setResponse($url); $this->setResponseVersion(1); break; case 'geocode': $locationSearchTerms = $this->getArg('q'); $geocodingDataControllerClass = $this->getOptionalModuleVar('GEOCODING_DATA_CONTROLLER_CLASS'); $geocodingDataParserClass = $this->getOptionalModuleVar('GEOCODING_DATA_PARSER_CLASS'); $geocoding_base_url = $this->getOptionalModuleVar('GEOCODING_BASE_URL'); $arguments = array('BASE_URL' => $geocoding_base_url, 'CACHE_LIFETIME' => 86400, 'PARSER_CLASS' => $geocodingDataParserClass); $controller = DataController::factory($geocodingDataControllerClass, $arguments); $controller->addCustomFilters($locationSearchTerms); $response = $controller->getParsedData(); // checking for Geocoding service error if ($response['errorCode'] == 0) { unset($response['errorCode']); unset($response['errorMessage']); $this->setResponse($response); $this->setResponseVersion(1); } else { $kurogoError = new KurogoError($response['errorCode'], "Geocoding service Erroe", $response['errorMessage']); $this->setResponseError($kurogoError); $this->setResponseVersion(1); } break; default: $this->invalidCommand(); break; } }