featureList, new Routeguide\Feature([ 'name' => $feature->name, 'location' => new Routeguide\Point([ 'latitude' => $feature->location->latitude, 'longitude' => $feature->location->longitude, ]), ])); } } private function findFeature(\Routeguide\Point $point) { foreach ($this->featureList as $feature) { $location = $feature->getLocation(); if ( $location->getLatitude() === $point->getLatitude() && $location->getLongitude() === $point->getLongitude() ) { return $feature; } } return null; } // The formula is based on http://mathforum.org/library/drmath/view/51879.html private function calculateDistance( \Routeguide\Point $start, \Routeguide\Point $end ) { $toRadians = function (float $num) { return $num * 3.1415926 / 180; }; $coordFactor = 10000000.0; $R = 6371000; // metres $lat_1 = $start->getLatitude() / $coordFactor; $lat_2 = $end->getLatitude() / $coordFactor; $lon_1 = $start->getLongitude() / $coordFactor; $lon_2 = $end->getLongitude() / $coordFactor; $lat_rad_1 = $toRadians($lat_1); $lat_rad_2 = $toRadians($lat_2); $delta_lat_rad = $toRadians($lat_2 - $lat_1); $delta_lon_rad = $toRadians($lon_2 - $lon_1); $a = pow(sin($delta_lat_rad / 2), 2) + cos($lat_rad_1) * cos($lat_rad_2) * pow(sin($delta_lon_rad / 2), 2); $c = 2 * atan2(sqrt($a), sqrt(1 - $a)); return $R * $c; } public function GetFeature( \Routeguide\Point $request, \Grpc\ServerContext $serverContext ): ?\Routeguide\Feature { $feature = $this->findFeature($request); $notFoundFeature = new Routeguide\Feature([ 'name' => '', 'location' => $request, ]); return $feature ?? $notFoundFeature; } public function ListFeatures( \Routeguide\Rectangle $request, \Grpc\ServerCallWriter $writer, \Grpc\ServerContext $serverContext ): void { $lo = $request->getLo(); $hi = $request->getHi(); $left = min($lo->getLongitude(), $hi->getLongitude()); $right = max($lo->getLongitude(), $hi->getLongitude()); $top = max($lo->getLatitude(), $hi->getLatitude()); $bottom = min($lo->getLatitude(), $hi->getLatitude()); foreach ($this->featureList as $feature) { $longitude = $feature->getLocation()->getLongitude(); $latitude = $feature->getLocation()->getLatitude(); if ( $longitude >= $left && $longitude <= $right && $latitude >= $bottom && $latitude <= $top ) { $writer->write($feature); } } $writer->finish(); } public function RecordRoute( \Grpc\ServerCallReader $reader, \Grpc\ServerContext $serverContext ): ?\Routeguide\RouteSummary { $point_count = 0; $feature_count = 0; $distance = 0; $previous = null; $start_time = time(); while ($point = $reader->read()) { $point_count++; $feature = $this->findFeature($point); if ($feature) { $feature_count++; if ($previous) { $distance += $this->calculateDistance($previous, $point); } $previous = $point; } } $summary = new \Routeguide\RouteSummary(); $summary->setPointCount($point_count); $summary->setFeatureCount($feature_count); $summary->setDistance($distance); $summary->setElapsedTime(time() - $start_time); return $summary; } public function RouteChat( \Grpc\ServerCallReader $reader, \Grpc\ServerCallWriter $writer, \Grpc\ServerContext $serverContext ): void { while ($note = $reader->read()) { foreach ($this->received_notes as $n) { if ( $n->getLocation()->getLatitude() === $note->getLocation()->getLatitude() && $n->getLocation()->getLongitude() === $note->getLocation()->getLongitude() ) { $writer->write($n); } } array_push($this->received_notes, $note); } $writer->finish(); } private $received_notes = []; private $featureList = []; }