Answer the question
In order to leave comments, you need to log in
Determining an occurrence of an address (coordinates) in a polygon?
Hello dear community!
Actually, there was a need to solve a simple problem, but the solution does not come to mind.
So, there is a catalog of online stores, each of which can create its own delivery zone using Yandex. Kart. The administrator creates "polygons", the coordinates of which are stored in the database. (By the way, for now they are stored in one coords field, but I believe that each LAT, LNG coordinate will have to be stored in separate fields)
When entering the catalog, the user enters his address of residence and all online stores that deliver to him are shown to him. Address coordinates are obtained from Yandex.Maps.
The search gave approximate solutions, like this habrahabr.ru/post/127446/but not exactly. It is necessary to determine in php and mysql which polygons include the desired address coordinates. Maybe someone will give you an idea?
Answer the question
In order to leave comments, you need to log in
He asked the question himself, he seems to have found the answer) you can google in the direction of Spatial Extensions
There is a GEOS library that can be built as a php extension. I think you'll understand in the manual.
Maybe someone will give you an idea?
MySQL has geographic types, and there are corresponding functions for working with them.
However, these functions make mistakes and I had to do the solution in PHP.
This is SQL
/**
* 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 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;
}
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;
}
Look at my solution to a particular case of your problem, namely to get all the points included in the rectangle. Link . Suddenly, what an idea will appear =)
You can try this simple class https://github.com/xopbatgh/sb-polygon-pointer
This mini library helped me a lot.
$polygonBox = [
[55.761515, 37.600375],
[55.759428, 37.651156],
[55.737112, 37.649566],
[55.737649, 37.597301],
];
$sbPolygonEngine = new sbPolygonEngine($polygonBox);
$isCrosses = $sbPolygonEngine->isCrossesWith(55.746768, 37.625605);
// $isCrosses is boolean
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question