In mySQL, there are geographic types, there are corresponding functions for working with them.

However, these functions make mistakes and I had to make the decision on PHP.

\r

This SQL

\r

`/** * Calculates whether Point is in Polygon or not. Uses mySql * @param array $aPoint * @param array $aCityBounds * @return boolean */ protected function isPointInCity(array $aPoint,array &$aCityBounds) { $lPointGeomText = 'Point(' . $aPoint[0] . '' . $aPoint[1] . ')'; $lPolyGeomText = "; foreach($aCityBounds as &$lBoundPoint) $lPolyGeomText .= (empty($lPolyGeomText) ? ": ',') . $lBoundPoint[0] . '' . $lBoundPoint[1]; // include first point to finish the polygon $lPolyGeomText = 'Polygon((' . $lPolyGeomText . ',' . $aCityBounds[0][0] . '' . $aCityBounds[0][1] . '))'; $lQuery = "SELECT MBRIntersects(GeomFromText('" . $lPolyGeomText . "'),GeomFromText('" . $lPointGeomText . "'))"; return intval(DbWrapper::dbGetValue($lQuery)) > 0 ? true : false; } `

\r

This without:

\r

`protected function isPointInCityBoundingBox(array $aPoint, array &$aCityBoundBox) { return $aPoint[0] >= $aCityBoundBox['minx'] && $aPoint[0] <= $aCityBoundBox['maxx'] && $aPoint[1] >= $aCityBoundBox['miny'] && $aPoint[1] <= $aCityBoundBox['maxy']; } /** * Calculate if point is inside polygon, more precisely than mySql now * @param array $aPoint * @param array $aCityBounds * @param array $aCityBoundBox * @return boolean */ protected function isPointInCityNoSql(array $aPoint, array &$aCityBounds, array &$aCityBoundBox) { if(!$this->isPointInCityBoundingBox($aPoint, $aCityBoundBox)) return false; $pj = 0; $pk = 0; $wrkx = 0; $yu = 0; $yl = 0; $lPointsCount = count($aCityBounds); for($pj = 0; $pj < $lPointsCount; $pj++) { $yu = $aCityBounds[$pj][1] > $aCityBounds[($pj + 1) % $lPointsCount][1] ? $aCityBounds[$pj][1] : $aCityBounds[($pj + 1) % $lPointsCount][1]; $yl = $aCityBounds[$pj][1] < $aCityBounds[($pj + 1) % $lPointsCount][1] ? $aCityBounds[$pj][1] : $aCityBounds[($pj + 1) % $lPointsCount][1]; if($aCityBounds[($pj + 1) % $lPointsCount][1] - $aCityBounds[$pj][1]) $wrkx = $aCityBounds[$pj][0] + ($aCityBounds[($pj + 1) % $lPointsCount][0] - $aCityBounds[$pj][0]) * ($aPoint[1] - $aCityBounds[$pj][1]) / ($aCityBounds[($pj + 1) % $lPointsCount][1] - $aCityBounds[$pj][1]); else $wrkx = $aCityBounds[$pj][0]; if($yu >= $aPoint[1]) if($yl < $aPoint[1]) { if($aPoint[0] > $wrkx) $pk++; if(abs($aPoint[0] - $wrkx) < 0.00001) return true; } if((abs($aPoint[1] - $yl) < 0.00001) && (abs($yu - $yl) < 0.00001) && (abs(abs($wrkx - $aCityBounds[$pj][0]) + abs($wrkx - $aCityBounds[($pj + 1) % $lPointsCount][0]) - abs($aCityBounds[$pj][0] - $aCityBounds[($pj + 1) % $lPointsCount][0])) < 0.0001)) return true; } return ($pk % 2) ? true : false; } `

\r

You can all your decision to shift entirely to mySQL, for each polygon from a big square to calculate the entry address of a user in the polygon.