<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>I want to be free &#187; geo</title>
	<atom:link href="http://i1t2b3.com/category/geo/feed/" rel="self" type="application/rss+xml" />
	<link>http://i1t2b3.com</link>
	<description>Any fool can make things bigger and more complex</description>
	<lastBuildDate>Wed, 11 Apr 2012 12:59:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Detect if city is within area</title>
		<link>http://i1t2b3.com/2011/12/13/detect-if-city-is-within-area/</link>
		<comments>http://i1t2b3.com/2011/12/13/detect-if-city-is-within-area/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 18:58:36 +0000</pubDate>
		<dc:creator>Skakunov Alexander</dc:creator>
				<category><![CDATA[db]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[geo]]></category>

		<guid isPermaLink="false">http://i1t2b3.com/?p=778</guid>
		<description><![CDATA[We at SunnyRentals are working a lot with geo data. The last task I was solving was inclusion of all cities in a touristic regions bounds automatically. Yes, there are MySQL spatial data types, so region border and cities coordinates can be stored in native data types, but the processing functions are not implemented right: [...]]]></description>
			<content:encoded><![CDATA[<p>We at SunnyRentals are working a lot with geo data. </p>
<p>The last task I was solving was inclusion of all cities in a touristic regions bounds automatically.</p>
<p>Yes, there are <a rel="nofollow" href="http://dev.mysql.com/doc/refman/5.1/en/mysql-spatial-datatypes.html">MySQL spatial data types</a>, so region border and cities coordinates can be stored in native data types, but the processing functions are not implemented right: they only operate on MBRs (minimum bounding rectangles) to make things simpler&#8230;</p>
<p><img src="http://i1t2b3.com/wp-content/uploads/2011/12/284_theory_fig_one1.png" alt="" title="point in polygon" width="200" height="148" class="alignright size-full wp-image-793" />So, let&#8217;s create our own MySQL function for that.</p>
<p>There are different approaches to distinguish if a point is within a given polygon. I prefered the way to iterate the edges of the polygon and check where the point relatively to the edge is &#8211; at right or at left; if the point is always at the same side, it lies within the border.</p>
<p>So we came to a fact that we need 2 functions:</p>
<ol>
<li>Distinguish the side at which the point lies from the line</li>
<li>Check that for every edge in the polygon.</li>
</ol>
<p>Here is the first function: <code class="sql">
<pre>DELIMITER //

DROP FUNCTION `GetPointPositionOfLine`//
CREATE FUNCTION `GetPointPositionOfLine`( a POINT, b POINT, p POINT) RETURNS tinyint NO SQL
  COMMENT 'Distinguish the side at which the point lies from the line'
BEGIN
  DECLARE s DOUBLE;
  SET s = (X(b) - X(a))*(Y(p) - Y(a)) - (Y(b) - Y(a))*(X(p) - X(a));
  IF s &gt; 0 THEN
    RETURN 1;
  END IF;
  IF s &lt; 0 THEN
    RETURN -1;
  END IF;
  RETURN 0;
END //</pre>
<p></code><br />
All three params are of type POINT. Points <code>a</code> and <code>b</code> are the beginning and end of the line. Point <code>p</code> is the point we check.</p>
<p>Here is the main function: <code class="sql">
<pre>DELIMITER //

DROP FUNCTION `IsPointWithin`//
CREATE FUNCTION `IsPointWithin`( ls LINESTRING, p POINT) RETURNS tinyint(1) NO SQL
BEGIN
  DECLARE i INT;
  DECLARE a, b POINT;
  DECLARE LineStringNumPoints INT;
  DECLARE Position, PrevPosition TINYINT;

  SET i = 1;
  SET PrevPosition = 0;
  SET LineStringNumPoints = NumPoints(ls);

  WHILE i &lt;= LineStringNumPoints DO
    SET a = PointN( ls, i);
    IF i = LineStringNumPoints THEN
      SET b = StartPoint( ls);
    ELSE
      SET b = PointN( ls, i+1);
    END IF;

    SET Position = GetPointPositionOfLine( a, b, p);
    IF Position &lt;&gt; 0 THEN
      IF Position &lt;&gt; PrevPosition AND PrevPosition &lt;&gt; 0 THEN
        RETURN FALSE;
      END IF;
      SET PrevPosition = Position;
    END IF;
    SET i = i + 1;
  END WHILE;
  RETURN TRUE;
END //</pre>
<p></code><br />
It checks if a point <code>p</code> lies within a polygon of type LINESTRING.</p>
<p>Usage example. Given you have coordinates of cities in the separate float columns (to keep them readable) <code>lat</code> and <code>lng</code> of <code>city</code> table, and the polygon is given as a string too &mdash; but of course you can use a column of type LINESTRING:<br />
<code class="sql">
<pre>SELECT *
FROM `city` c
WHERE IsPointWithin(GeomFromText('LINESTRING(4 8, 15 16, 23 42)'), POINT(c.`lat`, c.`lng`));
</pre>
<p></code></p>
<p>The solution works pretty fast, especially if you first limit the cities by the rectangle that the polygon lies in.</p>
]]></content:encoded>
			<wfw:commentRss>http://i1t2b3.com/2011/12/13/detect-if-city-is-within-area/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reverse Geocoding</title>
		<link>http://i1t2b3.com/2009/09/06/reverse-geocoding/</link>
		<comments>http://i1t2b3.com/2009/09/06/reverse-geocoding/#comments</comments>
		<pubDate>Sun, 06 Sep 2009 07:48:18 +0000</pubDate>
		<dc:creator>Skakunov Alexander</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[geo]]></category>

		<guid isPermaLink="false">http://i1t2b3.com/?p=512</guid>
		<description><![CDATA[Reverse Geocoding is process opposite to Geocoding (when you get map coordinates by city/country given). So the idea is to get city name by coordinates on the map. Why you may need it? For example, user is supposed to add a marker on the map, and you want to check that the marker is within [...]]]></description>
			<content:encoded><![CDATA[<p>Reverse Geocoding is process opposite to Geocoding (when you get map coordinates by city/country given). So the idea is to get city name by coordinates on the map.</p>
<p>Why you may need it? For example, user is supposed to add a marker on the map, and you want to check that the marker is within a particular country or region.</p>
<p>Solutions:</p>
<ol>
<li><noindex><a rel="nofollow" href="http://code.google.com/intl/en/apis/maps/documentation/services.html#ReverseGeocoding">Google GeoCoder </a></noindex>(JavaScript) can work with coordinates to retrieve location name. Advantage is that return information is translated to the preferred language of your browser. Here is <noindex><a rel="nofollow" href="http://code.google.com/intl/en/apis/maps/documentation/examples/geocoding-reverse.html">an example</a></noindex> you can play with.</li>
<li><noindex><a rel="nofollow" href="http://www.geonames.org/export/web-services.html">GeoNames.org</a></noindex> offers several services, among which you can find Reverse Geocoding web service (REST or JSON) which can work with coordinates and postal codes. Advantage &mdash; you can download city/region/country names and <abbr title="Points of Interest">POI</abbr> with coordinates.</li>
</ol>
<p><img src="http://i1t2b3.com/wp-content/uploads/2009/09/globe1.gif" alt="GeoNames" title="GeoNames" width="50" height="50" class="alignright size-full wp-image-520" />By the way, here are results of benchmarking <noindex><a rel="nofollow" href="http://www.peterbe.com/plog/google-reverse-geocoding-vs.-geonames">Google vs. GeoNames</a></noindex>.</p>
]]></content:encoded>
			<wfw:commentRss>http://i1t2b3.com/2009/09/06/reverse-geocoding/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

