RouteGuideService.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php
  2. /*
  3. *
  4. * Copyright 2020 gRPC authors.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. */
  19. class RouteGuideService extends \Routeguide\RouteGuideStub
  20. {
  21. public function __construct($dbFilePath)
  22. {
  23. $dbFilePath = $dbFilePath ?? dirname(__FILE__) . '/route_guide_db.json';
  24. $dbData = file_get_contents($dbFilePath);
  25. if (!$dbData) {
  26. throw new InvalidArgumentException(
  27. "Error reading route db file: " . $dbFilePath
  28. );
  29. }
  30. $featureList = json_decode($dbData);
  31. if (!$featureList) {
  32. throw new InvalidArgumentException(
  33. "Error decoding route db file: " . $dbFilePath
  34. );
  35. }
  36. foreach ($featureList as $feature) {
  37. array_push($this->featureList, new Routeguide\Feature([
  38. 'name' => $feature->name,
  39. 'location' => new Routeguide\Point([
  40. 'latitude' => $feature->location->latitude,
  41. 'longitude' => $feature->location->longitude,
  42. ]),
  43. ]));
  44. }
  45. }
  46. private function findFeature(\Routeguide\Point $point)
  47. {
  48. foreach ($this->featureList as $feature) {
  49. $location = $feature->getLocation();
  50. if (
  51. $location->getLatitude() === $point->getLatitude()
  52. && $location->getLongitude() === $point->getLongitude()
  53. ) {
  54. return $feature;
  55. }
  56. }
  57. return null;
  58. }
  59. // The formula is based on http://mathforum.org/library/drmath/view/51879.html
  60. private function calculateDistance(
  61. \Routeguide\Point $start,
  62. \Routeguide\Point $end
  63. ) {
  64. $toRadians = function (float $num) {
  65. return $num * 3.1415926 / 180;
  66. };
  67. $coordFactor = 10000000.0;
  68. $R = 6371000; // metres
  69. $lat_1 = $start->getLatitude() / $coordFactor;
  70. $lat_2 = $end->getLatitude() / $coordFactor;
  71. $lon_1 = $start->getLongitude() / $coordFactor;
  72. $lon_2 = $end->getLongitude() / $coordFactor;
  73. $lat_rad_1 = $toRadians($lat_1);
  74. $lat_rad_2 = $toRadians($lat_2);
  75. $delta_lat_rad = $toRadians($lat_2 - $lat_1);
  76. $delta_lon_rad = $toRadians($lon_2 - $lon_1);
  77. $a = pow(sin($delta_lat_rad / 2), 2) +
  78. cos($lat_rad_1) * cos($lat_rad_2) * pow(sin($delta_lon_rad / 2), 2);
  79. $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
  80. return $R * $c;
  81. }
  82. public function GetFeature(
  83. \Routeguide\Point $request,
  84. \Grpc\ServerContext $serverContext
  85. ): ?\Routeguide\Feature {
  86. $feature = $this->findFeature($request);
  87. $notFoundFeature = new Routeguide\Feature([
  88. 'name' => '',
  89. 'location' => $request,
  90. ]);
  91. return $feature ?? $notFoundFeature;
  92. }
  93. public function ListFeatures(
  94. \Routeguide\Rectangle $request,
  95. \Grpc\ServerCallWriter $writer,
  96. \Grpc\ServerContext $serverContext
  97. ): void {
  98. $lo = $request->getLo();
  99. $hi = $request->getHi();
  100. $left = min($lo->getLongitude(), $hi->getLongitude());
  101. $right = max($lo->getLongitude(), $hi->getLongitude());
  102. $top = max($lo->getLatitude(), $hi->getLatitude());
  103. $bottom = min($lo->getLatitude(), $hi->getLatitude());
  104. foreach ($this->featureList as $feature) {
  105. $longitude = $feature->getLocation()->getLongitude();
  106. $latitude = $feature->getLocation()->getLatitude();
  107. if (
  108. $longitude >= $left && $longitude <= $right
  109. && $latitude >= $bottom && $latitude <= $top
  110. ) {
  111. $writer->write($feature);
  112. }
  113. }
  114. $writer->finish();
  115. }
  116. public function RecordRoute(
  117. \Grpc\ServerCallReader $reader,
  118. \Grpc\ServerContext $serverContext
  119. ): ?\Routeguide\RouteSummary {
  120. $point_count = 0;
  121. $feature_count = 0;
  122. $distance = 0;
  123. $previous = null;
  124. $start_time = time();
  125. while ($point = $reader->read()) {
  126. $point_count++;
  127. $feature = $this->findFeature($point);
  128. if ($feature) {
  129. $feature_count++;
  130. if ($previous) {
  131. $distance += $this->calculateDistance($previous, $point);
  132. }
  133. $previous = $point;
  134. }
  135. }
  136. $summary = new \Routeguide\RouteSummary();
  137. $summary->setPointCount($point_count);
  138. $summary->setFeatureCount($feature_count);
  139. $summary->setDistance($distance);
  140. $summary->setElapsedTime(time() - $start_time);
  141. return $summary;
  142. }
  143. public function RouteChat(
  144. \Grpc\ServerCallReader $reader,
  145. \Grpc\ServerCallWriter $writer,
  146. \Grpc\ServerContext $serverContext
  147. ): void {
  148. while ($note = $reader->read()) {
  149. foreach ($this->received_notes as $n) {
  150. if (
  151. $n->getLocation()->getLatitude() ===
  152. $note->getLocation()->getLatitude()
  153. && $n->getLocation()->getLongitude() ===
  154. $note->getLocation()->getLongitude()
  155. ) {
  156. $writer->write($n);
  157. }
  158. }
  159. array_push($this->received_notes, $note);
  160. }
  161. $writer->finish();
  162. }
  163. private $received_notes = [];
  164. private $featureList = [];
  165. }