<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1218157414905973664</id><updated>2012-01-06T20:00:49.929+01:00</updated><category term='Visual Studio'/><category term='specialization'/><category term='doxygen'/><category term='Extent'/><category term='SQL Server'/><category term='unit tests'/><category term='boost'/><category term='WKT'/><category term='ranges'/><category term='tag dispatching'/><category term='SQLite'/><category term='extension methods'/><category term='delphi'/><category term='C++'/><category term='boolean operations'/><category term='set theory'/><category term='side'/><category term='spherical'/><category term='Boost.Geometry'/><category term='SqlGeometry'/><category term='union'/><category term='dissolve'/><category term='distance'/><category term='Debugging'/><category term='orientation'/><category term='traits'/><category term='makevalid'/><category term='bjam'/><category term='LINQ'/><category term='math'/><category term='Boost.Range'/><category term='PostGIS'/><category term='shapefile'/><category term='Visualizer'/><category term='intersections'/><category term='quickbook'/><category term='world'/><category term='precision'/><category term='sqrt'/><category term='iterators'/><category term='geometry'/><category term='C#'/><category term='Boost.Polygon'/><category term='MSVC'/><category term='svg'/><category term='generics'/><category term='countries'/><category term='Envelope'/><category term='orm'/><category term='Qt'/><category term='equals'/><category term='boost.build'/><category term='.NET'/><title type='text'>Boost.Geometry (and more)</title><subtitle type='html'>Boost.Geometry is being finished now. Boost.Geometry is a generic C++ library for geometry. In November 2009 it was accepted into Boost. Boost is a well-known peer-reviewed Open Source library collection for C++.

This blog describes some of the problems I have, thoughts, small researches, questions, progress made, etc.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-8443802973609792868</id><published>2011-12-04T14:16:00.010+01:00</published><updated>2011-12-07T20:25:06.218+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQLite'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='geometry'/><title type='text'>SQLite, Ado.Net, SpatiaLite</title><content type='html'>&lt;br&gt;
&lt;h1&gt;SQLite, Ado.Net, SpatiaLite&lt;/h1&gt;
&lt;br&gt;
SQLite is a small but great database. SpatiaLite is its spatial
extension. ADO.NET is &lt;span style="font-style: italic;"&gt;the&lt;/span&gt;
method to access databases in .NET.&lt;br&gt;
&lt;br&gt;
This&amp;nbsp;blog shows how to combine them, because I did found all
information on the
web but not a complete and up-to-date story.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;h2&gt;SQLite and Ado.Net&lt;/h2&gt;
An introduction (up and running in 3 minutes) is &lt;a
 href="http://www.mikeduncan.com/sqlite-on-dotnet-in-3-mins"&gt;here&lt;/a&gt;.
It is good but not&amp;nbsp;up-to-date. In the meantime the ADO.NET
driver
is transferred from sourceforge/phxsoftware to sqlite.org, which is of
course a good sign.&lt;br&gt;
&lt;br&gt;
There is only one piece of software which you really need and that is
the ADO.NET driver. Furthermore there are some optional (but very
useful tools) which I describe below.
&lt;br&gt;&lt;br&gt;&lt;br&gt;
&lt;h3&gt;ADO.NET driver&lt;/h3&gt;
The current ADO.NET driver page is&amp;nbsp;&lt;a
 href="http://system.data.sqlite.org/index.html/doc/trunk/www/index.wiki"&gt;here&lt;/a&gt;,
and more specificly you can download the drivers from this &lt;a
 href="http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki"&gt;page&lt;/a&gt;.
Download for example the &lt;span style="font-weight: bold;"&gt;sqlite-netFx40-setup-bundle-x86-2010-1.0.77.0.exe
(10.25 MiB)&amp;nbsp; &lt;/span&gt;(at least I did) and install it.
The
installation folder will contain the driver, and also&amp;nbsp;a manual
and a sample database
(northwindEF.db).&lt;br&gt;
&lt;br&gt;
&lt;h3&gt;Setting up the project&lt;/h3&gt;
Create a new project (or use an existing) in C# Express or Visual
Studio (I'm using 2010). I created a Console Project.&lt;br&gt;
&lt;br&gt;
Most important is of course to add a reference.
Typically&amp;nbsp;you need&amp;nbsp; the System.Data.SQLite.dll
from&amp;nbsp;the
installation folder (typically "c:\Program Files
(x86)\System.Data.SQLite\2010\bin" ). You can either reference it from
there or copy it to your project folder and reference it.&lt;br&gt;&lt;br&gt;
&lt;h3&gt;Writing the code.&lt;/h3&gt;
See also the original 3 minutes introduction for some code.
Here&amp;nbsp;a different sample is presented. I like complete code and
I also include some
extra optional pieces which I needed (creating a new database from
scratch, and turning on foreign keys).&lt;br&gt;
&lt;br&gt;
So a complete program looks like:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Green;"&gt;// Copyright (c) 2011 Barend Gehrels&lt;/span&gt; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Data.Common; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Data.SQLite; &lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;namespace&lt;/span&gt; SQLiteAndAdoDotNet &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; Program &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;const&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; mydb = &lt;span
 style="color: Maroon;"&gt;@"c:\temp\mydatabase.db"&lt;/span&gt;; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; Main(&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt;[] args) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;bool&lt;/span&gt; isNew = &lt;span
 style="color: Maroon;"&gt;false&lt;/span&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;if&lt;/span&gt; (!System.IO.File.Exists(mydb)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Create a new SQLite database if it does not exist&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SQLiteConnection.CreateFile(mydb); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;isNew = &lt;span
 style="color: Maroon;"&gt;true&lt;/span&gt;; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; (SQLiteConnection connection = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; SQLiteConnection(&lt;span
 style="color: Maroon;"&gt;@"Data Source="&lt;/span&gt; + mydb)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;connection.Open(); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Recommended action for any SQLite database&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ExecuteStatement(&lt;span
 style="color: Maroon;"&gt;"PRAGMA foreign_keys = ON"&lt;/span&gt;, connection); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;if&lt;/span&gt; (isNew) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Create a table for a new database&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ExecuteStatement(&lt;span
 style="color: Maroon;"&gt;@" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;create table mytable &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;id integer primary key autoincrement, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myfield text, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mydate integer -- dates can be stored as either text, real or integer &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"&lt;/span&gt;, connection); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Insert something&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ExecuteStatement(&lt;span
 style="color: Maroon;"&gt;"insert into mytable(myfield,mydate) values('my row',date('now'))"&lt;/span&gt;, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;connection); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Retrieve something&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; (SQLiteCommand command = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; SQLiteCommand(&lt;span
 style="color: Maroon;"&gt;"select *,datetime(mydate) as dt_ok from mytable"&lt;/span&gt;, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;connection)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; (DbDataReader reader = command.ExecuteReader())&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;while&lt;/span&gt; (reader.Read()) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.WriteLine(String.Format( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Maroon;"&gt;"Row id={0} field={1} date={2}, dt={3}"&lt;/span&gt;, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;reader[&lt;span
 style="color: Maroon;"&gt;"id"&lt;/span&gt;], reader[&lt;span
 style="color: Maroon;"&gt;"myfield"&lt;/span&gt;], &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;reader[&lt;span
 style="color: Maroon;"&gt;"mydate"&lt;/span&gt;], reader[&lt;span
 style="color: Maroon;"&gt;"dt_ok"&lt;/span&gt;])); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.WriteLine(&lt;span
 style="color: Maroon;"&gt;"Done"&lt;/span&gt;); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; ExecuteStatement(&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; statement, SQLiteConnection connection)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; (SQLiteCommand command = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; SQLiteCommand(statement, connection))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;command.ExecuteNonQuery(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;} &lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
I factored out one method to avoid repetitions. In another blog I'll
show you a different approach.&lt;br&gt;
&lt;br&gt;
The foreign key pragma is of course not necessary in this short sample.
But in
a "real" database, with a datamodel and foreign keys, you will need it.
Otherwise cascaded
deletes will fail unexpectedly!
&lt;br&gt;&lt;br&gt;
&lt;h3&gt;One caveat&lt;/h3&gt;
Beware for datetime fields, stored as real or integer! SQLite stores date types in &lt;a
 href="http://www.sqlite.org/datatype3.html"&gt;any field&lt;/a&gt;,
which is reasonable. But if you select such a date(time) field in the
normal way you will
get only the year back! So alas you have to cast it with the SQLite
datetime function (described &lt;a
 href="http://www.sqlite.org/lang_datefunc.html"&gt;here&lt;/a&gt;). Dates stored as text do not have this caveat.
&lt;br&gt;&lt;br&gt;
&lt;h3&gt;Useful tools&lt;/h3&gt;
I like the SQLite Studio which can be downloaded freely from &lt;a
 href="http://sqlitestudio.one.pl"&gt;here&lt;/a&gt;. You can
hardly without such a tool and this one is really cool. If you are
coming from SQL Server you might also like a converter, and &lt;a
 href="http://www.codeproject.com/KB/database/convsqlservertosqlite.aspx"&gt;this
one&lt;/a&gt; is good, free, and with source.&lt;br&gt;&lt;br&gt;
&lt;h2&gt;Using SpatialLite&lt;/h2&gt;
Using SpatialLite is pretty much the same, from ADO.NET perspective.
But of course you have to download some extra libraries. The
SpatialLite library of course, but you also need at least two extra
libraries. So here we go (see also &lt;a href="http://stackoverflow.com/questions/1556436/sqlite-spatialite-problems"&gt;StackOverflow&lt;/a&gt;):&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;download the SpatiaLite DLL from &lt;a
 href="http://www.gaia-gis.it/spatialite/binaries.html"&gt;this
page&lt;/a&gt; (libspatialite-win-x86-2.3.1.zip)&lt;/li&gt;
  &lt;li&gt;download proj-win as well from the same page
(proj-win-x86-4.6.1.zip)&lt;/li&gt;
  &lt;li&gt;download iconv as well from the same page
(libiconv-win-x86-1.9.2.zip)&lt;/li&gt;
  &lt;li&gt;download geos as well from the same page
(geos-win-x86-3.1.1.zip) &lt;i&gt;(I added geos later, after the comment of rmales, for me it was not necessary because it was found in my path, via PostGIS.)&lt;/i&gt;&lt;/li&gt;


&lt;/ul&gt;
But them all into your binary folder (Debug and Release). For our test
project we also need a spatial database. You can create one from a
shapefile (using the spatialite-gui from the same page) or download a
test database from SpatialLite, &lt;a
 href="http://www.gaia-gis.it/spatialite/resources.html"&gt;here&lt;/a&gt;.
I downloaded and extracted world.7z because I like to see world
countries (see my other blogs).&lt;br&gt;
&lt;br&gt;
Then, before you have to use it, you have to load the extension. That
is pretty easy with an SQL statement, &lt;span
 style="font-weight: bold; color: rgb(204, 0, 0);"&gt;select
load_extension('libspatialite-1.dll')&lt;/span&gt;. If it finds this
DLL and the other two, it will run fine (and otherwise it will mention
which is missing). Alas I could not get it working in sqlitestudio.&lt;br&gt;
&lt;br&gt;
Then below is the program I used, and it runs&amp;nbsp;fine. It is
quite similar to the one above but I prefer to list it completely
again. In next blog(s) we will do&amp;nbsp;other interesting and maybe
surprising things with it.&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Green;"&gt;// Copyright (c) 2011 Barend Gehrels&lt;/span&gt; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Data.Common; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Data.SQLite; &lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;namespace&lt;/span&gt; SQLiteAndAdoDotNet &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; Program &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;const&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; mydb = &lt;span
 style="color: Maroon;"&gt;@"c:\bdata\blogs\data\world.sqlite"&lt;/span&gt;; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; Main(&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt;[] args) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; (SQLiteConnection connection = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; SQLiteConnection(&lt;span
 style="color: Maroon;"&gt;@"Data Source="&lt;/span&gt; + mydb)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;connection.Open(); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Recommended action for any SQLite database&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ExecuteStatement(&lt;span
 style="color: Maroon;"&gt;"PRAGMA foreign_keys = ON"&lt;/span&gt;, connection); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Required action for any SpatiaLite database&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ExecuteStatement(&lt;span
 style="color: Maroon;"&gt;"select load_extension('libspatialite-1.dll')"&lt;/span&gt;, connection); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Retrieve some cities in Europe&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; (SQLiteCommand command = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; SQLiteCommand(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Maroon;"&gt;@" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;select wup_aggl,AsText(Geometry) as wkt,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;X(Geometry) as x,Y(Geometry) as y&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;from Cities &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where MBRContains(BuildMBR(-2,40,10,80),Geometry) = 1 &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"&lt;/span&gt;, connection)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; (DbDataReader reader = command.ExecuteReader())&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;while&lt;/span&gt; (reader.Read()) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.WriteLine(String.Format( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Maroon;"&gt;"City: {0} location: {1}, {2} wkt: {3}"&lt;/span&gt;, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;reader[&lt;span
 style="color: Maroon;"&gt;"wup_aggl"&lt;/span&gt;], reader[&lt;span
 style="color: Maroon;"&gt;"x"&lt;/span&gt;], reader[&lt;span
 style="color: Maroon;"&gt;"y"&lt;/span&gt;], reader[&lt;span
 style="color: Maroon;"&gt;"wkt"&lt;/span&gt;])); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.WriteLine(&lt;span
 style="color: Maroon;"&gt;"Done"&lt;/span&gt;); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; ExecuteStatement(&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; statement, SQLiteConnection connection)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; (SQLiteCommand command = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; SQLiteCommand(statement, connection))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;command.ExecuteNonQuery(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;} &lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;&lt;br&gt;
&lt;h3&gt;Useful tools&lt;/h3&gt;
Of course you can use &lt;a href="http://www.qgis.org/"&gt;Quantum
GIS&lt;/a&gt; to perfectly visualize your SpatiaLite database. The
SpatiaLite page also contains many useful links.&lt;br&gt;&lt;br&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
Above two complete programs to use SQLite and/or SpatiaLite in your
.NET application. This is the C# version, VB.NET will work either.&lt;br&gt;

&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-8443802973609792868?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/8443802973609792868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/12/sqlite-adonet-spatialite.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/8443802973609792868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/8443802973609792868'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/12/sqlite-adonet-spatialite.html' title='SQLite, Ado.Net, SpatiaLite'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-4509769845648604911</id><published>2011-11-19T18:14:00.000+01:00</published><updated>2011-11-19T18:14:28.241+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PostGIS'/><category scheme='http://www.blogger.com/atom/ns#' term='intersections'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='geometry'/><title type='text'>Linestring/polygon intersection</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Linestring/polygon intersection&lt;/h1&gt;
&lt;br&gt;
After a long while a blog again, a short one this time. I'm currently
implementing intersections linestring/polygon for Boost.Geometry. Well, the basics (calculating intersection points) are already there for a long time, but for this combination the intersection points should be followed in another way and the correct pieces should be outputted.&lt;br&gt;
&lt;br&gt;
When I do these things I normally check the results with both PostGIS
and SQL Server. However, I'm encountering something weird in both of
them.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;The testcase&lt;/h2&gt;
My testcase is looking like this:&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 164px; height: 155px;" alt=""
 src="https://lh3.googleusercontent.com/-tk8vmhtus70/TsfemwYYlxI/AAAAAAAABs0/aRib68OQ-sg/s164/loverpoly.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;SQL Server&lt;/h2&gt;
In SQL Server the intersection is correctly done, but the linestring is
reversed! I'm using this query:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: black;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;with&lt;/span&gt; viewy &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt;&lt;br&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(51, 51, 255);"&gt;select&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;geometry::STGeomFromText('&lt;span
 style="color: rgb(204, 0, 0);"&gt;POLYGON((1 1,1 3,3 3,3 1,1 1))&lt;/span&gt;', 0) &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; p,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;geometry::STGeomFromText('&lt;span
 style="color: rgb(204, 0, 0);"&gt;LINESTRING(2 2,1 2,1 3,2 3)&lt;/span&gt;', 0) &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; q&lt;br&gt;)&lt;br&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;select&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;p.STIntersection(q).STLength() &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; len,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;p.STIntersection(q).STAsText() &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; wkt&lt;br&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;from&lt;/span&gt; viewy;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
and this is my output:&lt;br&gt;
&lt;br&gt;
&lt;big&gt;&lt;span style="font-weight: bold; font-family: monospace;"&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;
LINESTRING (2 3, 1 3, 1 2, 2 2)&lt;/span&gt;&lt;br&gt;
&lt;/big&gt;&lt;br&gt;
You see, the linestring is &lt;span style="font-weight: bold;"&gt;reversed!&lt;/span&gt;
It is not only reversed with this linestring, but with all linestrings.
Even if they are, for example, complete inside the polygon. If I
reverse the polygon (from clockwise to counter clockwise), the output
is still reversed. Mysterious...&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;PostGIS&lt;/h2&gt;
Also a surprise in PostGIS.The query is looking there as following:&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;/span&gt;
&lt;pre&gt;&lt;span style="color: black;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;with&lt;/span&gt; viewy &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt;&lt;br&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(51, 51, 255);"&gt;select&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ST_GeomFromText('&lt;span
 style="color: rgb(204, 0, 0);"&gt;POLYGON((1 1,1 3,3 3,3 1,1 1))&lt;/span&gt;') &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; p,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ST_GeomFromText('&lt;span
 style="color: rgb(204, 0, 0);"&gt;LINESTRING(2 2,1 2,1 3,2 3)&lt;/span&gt;') &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; q&lt;br&gt;)&lt;br&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;select&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ST_Length(ST_Intersection(p, q)) &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; len,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ST_AsText(ST_Intersection(p, q)) &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; wkt &lt;span
 style="color: rgb(51, 51, 255);"&gt;&lt;br&gt;from&lt;/span&gt; viewy;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
and this is here the result:&lt;br&gt;
&lt;br&gt;
&lt;big&gt;&lt;span style="font-weight: bold; font-family: monospace;"&gt;3;"MULTILINESTRING((1
2,1 3),(1 3,2 3),(2 2,1 2))"&lt;/span&gt;&lt;/big&gt;&lt;br&gt;
&lt;br&gt;
I'm getting a &lt;b&gt;multilinestring&lt;/b&gt; back! With respect to contents, it is
OK. But it is surprising...&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;OGC&lt;/h2&gt;
I did not look it up but I don't think this specific behaviour is
specified. So yes, all implementations will be correct but...&lt;br&gt;&lt;br&gt;
&lt;h2&gt;Boost.Geometry&lt;/h2&gt;
At the moment of writing, technically more difficult cases as this is one are not
completely finished. But I can already tell that the linestring will not be
reversed and that the output will consist of only one linestring...&lt;br&gt;
&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-4509769845648604911?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/4509769845648604911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/11/linestringpolygon-intersection.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/4509769845648604911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/4509769845648604911'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/11/linestringpolygon-intersection.html' title='Linestring/polygon intersection'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh3.googleusercontent.com/-tk8vmhtus70/TsfemwYYlxI/AAAAAAAABs0/aRib68OQ-sg/s72-c/loverpoly.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-7167534594558445839</id><published>2011-06-24T23:56:00.006+02:00</published><updated>2011-06-25T00:20:38.156+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='orientation'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='spherical'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><category scheme='http://www.blogger.com/atom/ns#' term='geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='side'/><title type='text'>Spherical Side Formula</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Spherical Side Formula&lt;/h1&gt;
&lt;br&gt;
This&amp;nbsp;blog describes an
algorithm and a formula to determine the side of one point relative to
a segment (two
other points), all three points located on a sphere.&lt;br&gt;
&lt;br&gt;
The side informarmation is necessary for Boost.Geometry. It is used,
among others, in the &lt;span style="font-weight: bold;"&gt;within&lt;/span&gt;
algorithm, to check if a point is inside a polygon (point in polygon).
With the spherical version of &lt;span style="font-weight: bold;"&gt;side&lt;/span&gt;,
it can be checked if a point on a sphere (the earth) is inside a
spherical polygon (e.g. a polygon measured in latitude, longitude).&lt;br&gt;
&lt;br&gt;
It is also known as &lt;span style="font-weight: bold;"&gt;orientation&lt;/span&gt;
(see also &lt;a
 href="http://en.wikipedia.org/wiki/Cross_product#Computational_geometry"&gt;here&lt;/a&gt;
and &lt;a href="http://www.saipanyam.net/tag/computational-geometry"&gt;here&lt;/a&gt;)&lt;br&gt;
&lt;br&gt;
The Cartesian side is shown below. Point &lt;span
 style="font-weight: bold;"&gt;p&lt;/span&gt; is on the right
side of segment &lt;span style="font-weight: bold;"&gt;p1-p2&lt;/span&gt;:&lt;br&gt;
&lt;img style="width: 218px; height: 196px;" alt="cs"
 src="https://lh6.googleusercontent.com/-kB21L8kFUbs/Td-fs9a70iI/AAAAAAAABmk/OSMTC0BmSFo/cartesian_side.png"&gt;&lt;br&gt;
&lt;br&gt;
A visualization of ths spherical side is shown below, also here, point &lt;span
 style="font-weight: bold;"&gt;p&lt;/span&gt; is right of
segment &lt;span style="font-weight: bold;"&gt;p1-p2&lt;/span&gt;.&lt;br&gt;
&lt;img style="width: 485px; height: 488px;" alt="ss"
 src="https://lh6.googleusercontent.com/-TuUWRfQGSB4/Td-ft4MbViI/AAAAAAAABmw/--XDbE4-rU4/framed_sphere_with_side.png"&gt;&lt;br&gt;
&lt;br&gt;
Note that if the cartesian side formula would be used on lat-long
coordinates, this specific point would result on the left side.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Former approach&lt;/h2&gt;
Boost.Geometry's former approach for spherical side used the useful
aviation formulae of
Williams,
listed &lt;a href="http://williams.best.vwh.net/avform.htm#Crs"&gt;here&lt;/a&gt;.
That did work&amp;nbsp;but I was not completely satisfied about it:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;it takes two * (3 &lt;span
 style="font-weight: bold; font-style: italic;"&gt;cos&lt;/span&gt;,
3 &lt;span style="font-weight: bold; font-style: italic;"&gt;sin&lt;/span&gt;,
1 &lt;span style="font-weight: bold; font-style: italic;"&gt;atan&lt;/span&gt;)
for the course, and
then another 2 &lt;span style="font-weight: bold; font-style: italic;"&gt;sin&lt;/span&gt;,
and 1 &lt;span style="font-weight: bold; font-style: italic;"&gt;asin&lt;/span&gt;,
so in total 17 goniometric functions&lt;/li&gt;
  &lt;li&gt;it is non defined at the poles&lt;/li&gt;
  &lt;li&gt;I don't understand it fully, it seemed to me that there
should be an easier way&lt;/li&gt;
&lt;/ul&gt;
An obvious alternative is translate to 3D cartesian coordinates
and why not? After working this out a bit, it appeared that it
indeed&amp;nbsp;requires less goniometric functions. These goniometric
functions are less performant and less precise, so if they can be
avoided, the better. Also the new approach is also relatively easy,
from mathematical perspective.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;New approach&lt;/h2&gt;
The
new approach also uses &lt;span
 style="font-weight: bold; font-style: italic;"&gt;sin&lt;/span&gt;
and &lt;span style="font-weight: bold; font-style: italic;"&gt;cos&lt;/span&gt;,
but &amp;nbsp;less: for each of the
points: 2 &lt;span style="font-weight: bold; font-style: italic;"&gt;sin&lt;/span&gt;
and 2 &lt;span style="font-weight: bold; font-style: italic;"&gt;cos&lt;/span&gt;,
in total 12 goniometric functions. Less then
the former 17. More important, by design of
Boost.Geometry, these might be precalculated such that for a spherical
polygon it is not necessary to recalculate this again and again.&lt;br&gt;
&lt;br&gt;
Besides that, the algorithm is easier to follow.&lt;br&gt;&lt;br&gt;
&lt;h2&gt;The algorithm&lt;/h2&gt;
Let us calculate a plane through the two points of the segment, and the
center of the
sphere. &lt;span style="font-style: italic;"&gt;This is the
plane also contains the Great Circle&lt;/span&gt;. Let us then
calculate at which side of the plane the
point is located, either left of the plane, or right of the plane, or
on the plane itself. The side with respect to the plane is also the
side of the point with respect to the segment&amp;nbsp;on the sphere.&lt;br&gt;
&lt;br&gt;
To calculate a plane, all three points are transformed from spherical
coordinates (longitude, latitude) to cartesian coordinates (x, y, z).
Described a.o. &lt;a
 href="http://users.aber.ac.uk/ruw/teach/237/polar.php"&gt;here&lt;/a&gt;
with clear images. We can use the unit
sphere, it is not necessary to take the radius of the Earth (or another
sphere or sphere-like object) into account. Amsteram, for example, then
lies somewhere here: (&lt;span style="font-style: italic;"&gt;0.614161755
0.042946374&amp;nbsp;0.788010754&lt;/span&gt;).&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Converting&amp;nbsp;can conveniently be done using Boost.Geometry's
transform algorithm (if p1 is stored in cs::spherical_equatorial):&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typedef model::point&amp;lt;coordinate_type, 3, cs::cartesian&amp;gt;
point3d;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
point3d c1, c2, c3;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;transform(p1,
c1);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;transform(p2,
c2);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;transform(p,
c3);&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 532px; height: 415px;"
 alt="coordinate system"
 src="https://lh6.googleusercontent.com/-Vgmof9rKrAk/TgUB6_GBmdI/AAAAAAAABoQ/T8kYr0sTq98/lambda_delta_xyz.png"&gt;&lt;br&gt;
&lt;br&gt;
Then
we define a plane through the center of the Earth (0,0,0) and the two
points. We use the generalized plane equation for that (a x + b y + c z
+ d = 0), described e.g. &lt;a
 href="http://www.netcomuk.co.uk/%7Ejenolive/vect15.html"&gt;here&lt;/a&gt;.
This
is done by taking the cross product of the two vectors (a vector is
here: a mathematical vector). These two vectors are normally called &lt;span
 style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;v&lt;/span&gt;&lt;/span&gt; and &lt;span
 style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;w&lt;/span&gt;&lt;/span&gt;.
Because we use (0,0,0) the points &lt;span style="font-weight: bold;"&gt;are&lt;/span&gt;
the vectors, we don't have to subtract anything to create a vector. So &lt;span
 style="font-weight: bold; font-style: italic;"&gt;v&lt;/span&gt;
is equivalent to &lt;span
 style="font-weight: bold; font-style: italic;"&gt;c1&lt;/span&gt;,
&lt;span style="font-weight: bold; font-style: italic;"&gt;w&lt;/span&gt;
is equivalent to &lt;span
 style="font-weight: bold; font-style: italic;"&gt;c2&lt;/span&gt;.&lt;br&gt;
&lt;br&gt;
The cross product is&amp;nbsp;the normal vector, called &lt;span
 style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;n&lt;/span&gt;&lt;/span&gt;,
normal to
the plane, so perpendicular to the great circle of the two points. So
we can&amp;nbsp;take the cross product:&lt;br&gt;
&lt;br&gt;
vector_type const n =&amp;nbsp;geometry::cross_product(v, w);&lt;br&gt;
&lt;br&gt;
We now have our generalized plane equation. To make that explicit, we
can use the conventional symbols a, b, c:&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
coordinate_type const a =&amp;nbsp;get&amp;lt;0&amp;gt;(n);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
coordinate_type const b =&amp;nbsp;get&amp;lt;1&amp;gt;(n);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
coordinate_type const c =&amp;nbsp;get&amp;lt;2&amp;gt;(n);&lt;br&gt;
&lt;br&gt;
For the generalized plane equation, we should calculate &lt;span
 style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;d&lt;/span&gt;&lt;/span&gt;&amp;nbsp;by
subsituting one of the points going through the plane. Let us
take (0,0,0)! By taking 0,0,0, all terms a x, b y, c z will be zero, so
d is zero. Therefore we don't have to calculate &lt;span
 style="font-weight: bold;"&gt;d&lt;/span&gt;.&lt;br&gt;
&lt;br&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; double const d = 0;&lt;br&gt;
&lt;br&gt;
The
generalized plane equation has the property that, if you substitute
another point, it is either on the plane (then the result = 0), or at
one side of the plane (then the result is positive), or at another side
of the plane (then the result is negative). Just like the Cartesian
side, described above. And that is exactly what we
need: &lt;br&gt;
&lt;br&gt;
distance_measure = a *&amp;nbsp;get&amp;lt;0&amp;gt;(c3) + b
*&amp;nbsp;get&amp;lt;1&amp;gt;(c3) + c
*&amp;nbsp;get&amp;lt;2&amp;gt;(c3) + d;&lt;br&gt;
&lt;br&gt;
and we have the result: &lt;br&gt;
&lt;br&gt;
int side&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;=&amp;nbsp;distance_measure
&amp;gt; 0 ? 1 // left&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
:&amp;nbsp;distance_measure &amp;lt; 0 ? -1 // right&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
: 0;&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Spherical Side Formula&lt;/h2&gt;
We
used convenient vector calculation here, making it a mathematical
exercise. Of course we could write them all out and get a lot of
goniometric functions back.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;One big note here&lt;/span&gt;:
geographers (as I am) always refer to&amp;nbsp;coordinates on a
sphere by defining 0 at the equator. But mathematicians define 0 at the
upper pole of a sphere. Watch out, it is different. This blog assumes
the geographic convention, so assumes a spherical equatorial
coordinate system.&lt;br&gt;
&lt;br&gt;
Let's present it as mathematic formulae
(thanks to &lt;a href="TODO"&gt;mathcast&lt;/a&gt;):&lt;br&gt;
&lt;br&gt;
&lt;img src="https://lh6.googleusercontent.com/-yayju7wIZkQ/TgUMPr-yuRI/AAAAAAAABog/4CM-jbjkduo/ssf.png"&gt;&lt;br&gt;
&lt;br&gt;
The
first formula converts to x,y,z. Be sure to enter all angles in
radians. Also, be sure that &lt;big&gt;&lt;span
 style="font-weight: bold;"&gt;λ&lt;/span&gt;&lt;/big&gt; is
longitude (and comes first in
Boost.Geometry) and &lt;big&gt;&lt;span style="font-weight: bold;"&gt;δ&lt;/span&gt;&lt;/big&gt;
is latitude (there are many conventions for this but I'm using them
from &lt;a href="http://mathworld.wolfram.com/GreatCircle.html"&gt;here&lt;/a&gt;,
and &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt;
from &lt;a
 href="http://en.wikipedia.org/wiki/Geographic_coordinate_system"&gt;here&lt;/a&gt;
and &lt;a
 href="http://en.wikipedia.org/wiki/Spherical_coordinate_system#Conventions"&gt;here&lt;/a&gt; and &lt;a
 href="http://en.wikipedia.org/wiki/Spherical_coordinate_system#Geographic_coordinates"&gt;here)&lt;/a&gt;.
Latitude is 0 at the equator, 90 at the North Pole (&lt;span
 style="font-style: italic;"&gt;again: mathematicians use 0 at the
North Pole, 90 at the aquator; that is known as the &lt;/span&gt;&lt;span
 style="font-weight: bold; font-style: italic;"&gt;spherical
(polar) coordinate system&lt;/span&gt;&lt;span
 style="font-style: italic;"&gt;, we now refer to the &lt;/span&gt;&lt;span
 style="font-weight: bold; font-style: italic;"&gt;spherical
equatorial coordinate system&lt;/span&gt;).&lt;br&gt;
&lt;br&gt;
The second formula is the cross product and defines the terms of the
generalized plane equation. The third formula calculates the distance
measure (&lt;span style="font-style: italic;"&gt;dm&lt;/span&gt;).
Because (2) and (3) do not have repetitive clauses, they could be
combined into&amp;nbsp;(4) and then, if wished, again, with the
conversion,
into (5).&lt;br&gt;
&lt;br&gt;
The sixth pseudo-formula then defines the result, it is an
interpretation of the distance measure &lt;span
 style="font-style: italic;"&gt;dm&lt;/span&gt;.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Ellipsoidal Earth&lt;/h2&gt;
The
Earth is not spherical but approximates an ellipsoid, it is flattened
at the poles. But the described
spherical side formula works&amp;nbsp;well on Earth. Let me try to
prove that
(&lt;span style="font-style: italic;"&gt;note: I'm&amp;nbsp;a
geographer, not a
mathematician&lt;/span&gt;).&lt;br&gt;
&lt;br&gt;
A
location defined by (&lt;big&gt;&lt;span style="font-weight: bold;"&gt;λ&lt;/span&gt;&lt;/big&gt;,&amp;nbsp;&lt;big&gt;&lt;span
 style="font-weight: bold;"&gt;δ&lt;/span&gt;&lt;/big&gt;)
essentially means a vector, either on a
sphere, or on an ellipsoid. These vectors always have&amp;nbsp;the same
direction, so the same on a sphere as on an ellipsoid.
Their lengths differ (on an ellipsoid they are often shorter) but the
length of a vector does not influence
the&amp;nbsp;plane it encompasses. Therefore the plane formed by two
locations&amp;nbsp;and the
center of the Earth is exactly the same plane as it is using a perfect
sphere.&lt;br&gt;
&lt;br&gt;
So: two points (a segment), on a sphere or on an ellipsoid, define the
same plane.&lt;br&gt;
&lt;br&gt;
The
same applies for the third point. It is also a vector, having a
direction. That vector, either on a sphere or on an ellipsoid, is
located at the same side of the plane.&lt;br&gt;
&lt;br&gt;
Q.E.D.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Code&lt;/h2&gt;
Because of the formulae above, I don't give (pseudo)code. It is quite
easy. I created a small&amp;nbsp;Excel sheet containing the formula is &lt;a
 href="http://www.xs4all.nl/%7Ebarend/blogs/ssf.xlsx"&gt;here&lt;/a&gt;. It contains this example (on this useful site): &lt;a href="http://www.gcmap.com/mapui?P=30N+10E-50N+50E,42N+30E"&gt;gcmap&lt;/a&gt;
The formula is also in Boost.Geometry.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
Using some high-school mathematics I
presented an algorithm and a formula to calculate at which side a point
is with resepect to a segment, on a sphere or on the Earth. Google did
not find this for me. So I hope that it will be of some use for some
people. At least, it is useful for Boost.Geometry&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-7167534594558445839?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/7167534594558445839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/06/spherical-side-formula.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/7167534594558445839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/7167534594558445839'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/06/spherical-side-formula.html' title='Spherical Side Formula'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh6.googleusercontent.com/-kB21L8kFUbs/Td-fs9a70iI/AAAAAAAABmk/OSMTC0BmSFo/s72-c/cartesian_side.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-2047442549678250360</id><published>2011-05-18T22:40:00.004+02:00</published><updated>2011-05-18T23:07:41.766+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visualizer'/><category scheme='http://www.blogger.com/atom/ns#' term='MSVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Debugging'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Debugger Visualizers</title><content type='html'>&lt;br&gt;&lt;h1&gt;Debugger Visualizers&lt;/h1&gt;&lt;br&gt;
When debugging in Visual Studio, watching the contents of a variable
can be of great help. But as soon as a variable is of a custom type, it
might be inconvenient.&lt;br&gt;
&lt;br&gt;
For example Boost.Geometry. You
can examine the contents of a point or a polygon in the Debugger Watch
Window. But the representation of
a point type is cumbersome: "{...}". If you
click that open, you will see m_values and a meaningless pointer. Still
awkward. If
you click that m_values open, you see it again, in the Values
column&amp;nbsp;the same pointer again. Still no coordinates. If you click &lt;span
 style="font-weight: bold;"&gt;that&lt;/span&gt; pointer open,
yes, you finally see the values! But it takes three&amp;nbsp;steps
(clicks).&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 1032px; height: 239px;" alt="dv1"
 src="https://lh6.googleusercontent.com/_6zrdK5O_LIg/TdQoIR581kI/AAAAAAAABl4/vcFnUUWJoKA/debugger_visualizers1.png"&gt;&lt;br&gt;
&lt;br&gt;
If you examine a polygon, you have to do these three steps for each
point in
each of its rings!&lt;br&gt;
&lt;br&gt;
You will be tired of that soon, especially if you know it can
be helped using the Visual Studio Debugger Visualizers. It seems this method is not documented by Microsoft, so it is a bit of hacking, but descriptions can be found on the web (references below).&lt;br&gt;
&lt;br&gt;
This is the recipe how to do it:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;go to the folder &lt;span style="font-style: italic;"&gt;"c:\Program
Files (x86)\Microsoft Visual Studio 10.0\Common7\Packages\Debugger" &lt;/span&gt;(usually
there, path may change, this path is for VS 2010)&lt;/li&gt;
  &lt;li&gt;make a backup of the file &lt;span
 style="font-weight: bold;"&gt;autoexp.dat&lt;/span&gt; because
we are going to change it&lt;/li&gt;
  &lt;li&gt;open &lt;span style="font-weight: bold;"&gt;autoexp.dat&lt;/span&gt;
in an editor (it is (on Windows 7) convenient to edit
in another path, because saving requires Administrator rights)&lt;/li&gt;
  &lt;li&gt;go to the bottom, just before [hresult]&lt;/li&gt;
  &lt;li&gt;enter the cryptic lines shown below this bullet list&lt;/li&gt;
  &lt;li&gt;save the file (if you did edit it in another path, copy it
back, giving Administrator rights)&lt;/li&gt;
&lt;/ul&gt;
These are the lines to add:
&lt;pre  style="color: black;"&gt;boost::geometry::model::d2::point_xy&amp;lt;*,*&amp;gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; preview ( #("(x=", $e.m_values[0], " ,y=", $e.m_values[1], ")") )&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;
It is a bit abstruse. In preview ( #( ) ) you have to enter 
member variables of your class (which should be called $e for enigmatic reasons).
You can mix them up with strings. All is comma separated. Note that the parentheses should be placed as displayed.&lt;br&gt;
&lt;br&gt;
After this exercise, restart Visual Studio and debug again and... you
will see a much better appearance of our point in the Watch window:&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 1024px; height: 239px;" alt="dv2"
 src="https://lh6.googleusercontent.com/_6zrdK5O_LIg/TdQod9Jqf2I/AAAAAAAABmE/3gVG7WHU7_Q/debugger_visualizers2.png"&gt;&lt;br&gt;
We don't have to click at all. Our point is just there, x- and y-
coordinates specified. Oh yes, 4.56 is now 4.55999 but that is
something different, it has to do with floating point precision. We
ignore that in this blog.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Definition for Boost.Geometry&lt;/h2&gt;
At this moment I have point_xy but also model::point defined. I could
have more but this is already very useful. Linestrings or polygons
automatically use these point&amp;nbsp;presentations, and because
std::vectors
are visualized by Microsoft (in that same file autoexp.dat), it is all
very clear in the Watch Window.&lt;br&gt;
&lt;br&gt;
So the section I defined looks like this:&lt;br&gt;
&lt;br style="color: black;"&gt;
&lt;pre style="color: black;"&gt;; BOOST.GEOMETRY&lt;br&gt;&lt;br&gt;boost::geometry::model::point&amp;lt;*,2,*&amp;gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; preview ( #("(", $e.m_values[0], " , ", $e.m_values[1], ")") )&lt;br&gt;}&lt;br&gt;&lt;br&gt;boost::geometry::model::point&amp;lt;*,3,*&amp;gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; preview ( #("(", $e.m_values[0], " , ", $e.m_values[1], " , ", $e.m_values[2], ")") )&lt;br&gt;}&lt;br&gt;&lt;br&gt;boost::geometry::model::d2::point_xy&amp;lt;*,*&amp;gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; preview ( #("(x=", $e.m_values[0], " ,y=", $e.m_values[1], ")") )&lt;br&gt;} &lt;/pre&gt;
I have it running&amp;nbsp;in Visual Studio C++ 2010 Express, and also
in Visual Studio C++ 2005 Express. Debugging
visualizers is a bit tricky, if you make an error you might get an
exception window. But in version 2010 it is&amp;nbsp;better than it was
in version 2005.&lt;br&gt;&lt;br&gt;
&lt;h2&gt;References&lt;/h2&gt;
There is more than this. More is explained on these pages:
&lt;ul&gt;
  &lt;li&gt;&lt;a
 href="http://www.virtualdub.org/blog/pivot/entry.php?id=120"&gt;http://www.virtualdub.org/blog/pivot/entry.php?id=120&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a
 href="http://www.idigitalhouse.com/Blog/?p=83"&gt;http://www.idigitalhouse.com/Blog/?p=83&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a
 href="https://svn.boost.org/trac/boost/wiki/DebuggerVisualizers"&gt;https://svn.boost.org/trac/boost/wiki/DebuggerVisualizers&lt;/a&gt;
(for Boost types)&lt;/li&gt;
&lt;/ul&gt;
And in .NET (but this is actually another solution, implementing a
custom visualizer in code):&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a
 href="http://geekswithblogs.net/technetbytes/archive/2008/06/11/122792.aspx"&gt;http://geekswithblogs.net/technetbytes/archive/2008/06/11/122792.aspx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;&lt;Br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-2047442549678250360?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/2047442549678250360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/05/debugger-visualizers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/2047442549678250360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/2047442549678250360'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/05/debugger-visualizers.html' title='Debugger Visualizers'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh6.googleusercontent.com/_6zrdK5O_LIg/TdQoIR581kI/AAAAAAAABl4/vcFnUUWJoKA/s72-c/debugger_visualizers1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-4258165195418170199</id><published>2011-05-06T21:45:00.007+02:00</published><updated>2011-05-06T22:25:54.751+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PostGIS'/><category scheme='http://www.blogger.com/atom/ns#' term='Extent'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='SqlGeometry'/><title type='text'>SqlGeometry and Boxes</title><content type='html'>&lt;br&gt;
&lt;h1&gt;SqlGeometry and Boxes&lt;/h1&gt;
&lt;br&gt;
I wanted to write a blog about
partitioning (calling an algorithm using an on-the-fly quadtree or
octree) and how it is implemented in Boost.Geometry, and how it could
also be used / implemented for the SqlGeometry type. But somehow that
blog will be too large and I blog here just about a box/rectangle in
SqlGeometry. It is not too difficult, but I just googled and did not
find other blogs saying the same things, so I hope it adds something.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;STEnvelope&lt;/h2&gt;
&lt;br&gt;
The OGC/ISO STEnvelope function,
supported by spatial databases and many geometry libraries, returns the
envelope of a geometry. An envelope is: a bounding box or bounding
rectangle, also known as an axis
aligned bounding box (aabb), a bbox, a minimum bounding
rectangle (mbr) or an extent.&lt;br&gt;
&lt;br&gt;
More in detail, STEnvelope returns a Geometry object
describing a rectangle. OGC does not know the notion of a box. That is
sometimes a bit inconvenient, but it is how it is. Boost.Geometry
created a Box
Concept, because Boost.Geometry is strongly typed, and envelopes
returning polygons
with always four or five points would confuse the non-OGC users of our
library.&lt;br&gt;
&lt;br&gt;
I blogged earlier about the spatial extent of a query in SQL Server, &lt;a
 href="/2011/04/extent-of-sql-server-spatial-table.html"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
A
box is a simple geometry, with (in 2D) a minimum x and y and a maximum
x and y. But how to get that from a geometry in a spatial database... I
mean,
the envelope returns a polygon containing five points (assuming it is
closed), is the first point lower left? And is that guaranteed? The OGC
specifications say: &lt;span style="font-style: italic;"&gt;The
minimum bounding box for this Geometry, returned as a Geometry. The
polygon is defined by the corner points of the bounding box [(MINX,
MINY), (MAXX, MINY), (MAXX, MAXY), (MINX, MAXY), (MINX, MINY)].&lt;/span&gt;
So yes, it should be guaranteed.&lt;br&gt;
&lt;br&gt;
Let's look at it in more detail.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;SQL Server&lt;/h2&gt;
&lt;br&gt;
In SQL Server it indeed seems the case that the first point of the
polygon
returned by STEnvelope is the lower left point. Then, the third
point &lt;span style="font-weight: bold;"&gt;must&lt;/span&gt;
be the upper right
point. Because, if you consider the polygon clockwise, it is the third
point, and if it is counterclockwise, it is also the third point.&lt;br&gt;
&lt;br&gt;
We use this query:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: black;"&gt;select geometry::STGeomFromText('POLYGON((0 0,2 5,4 1,0 0))',0).STEnvelope().STPointN(3).STAsText()&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
... to get the
third point (which should be upper right), and it indeed gives
me:&amp;nbsp;&lt;span style="font-weight: bold;"&gt;POINT(4 5)&lt;/span&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;PostGIS&lt;/h2&gt;
&lt;br&gt;
In PostGIS, the first point of the polygon returned by ST_Envelope
is&amp;nbsp;the lower left point as well. Great.&lt;span
 style="font-weight: bold;"&gt; &lt;br&gt;
&lt;br&gt;
&lt;/span&gt;As you (maybe) know, SQLGeometry uses methods, PostGIS
uses functions. So the corresponding nested function calls would be:
&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: black;"&gt;select ST_AsText(ST_PointN((ST_Envelope(ST_GeomFromText('POLYGON((0 0,2 5,4 1,0 0))',0))), 3))&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
But... no result, we get a &lt;span style="font-weight: bold;"&gt;null&lt;/span&gt;
value back. Looking at the OGC specs, this is correct: NumPoints is
defined for &lt;span style="font-weight: bold;"&gt;a LineString&lt;/span&gt;
and not for a &lt;span style="font-weight: bold;"&gt;Polygon&lt;/span&gt;.
SqlServer is somewhat more relaxed here (as is Boost.Geometry),
returning the total number of points of a polygon (including interior
rings, if any).&lt;br&gt;
&lt;br&gt;
OK, behaviour is correct, so we try again, now inserting the
ST_Boundary function (making a
linestring of the boundary of a polygon). Our new function call is:
&lt;br&gt;
&lt;br&gt;
&lt;pre style="color: black;"&gt;select ST_AsText(ST_PointN(ST_Boundary((ST_Envelope(ST_GeomFromText('POLYGON((0 0,2 5,4 1,0 0))',0)))), 3))&lt;/pre&gt;
&lt;br&gt;
... and we have our upper right point.
Using a 1 for the last value (the index of ST_PointN is one-based)
would return the
lower left point.
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Boost.Geometry&lt;/h2&gt;
&lt;br&gt;
Boost.Geometry, as said, returns a &lt;span style="font-weight: bold;"&gt;box&lt;/span&gt;
(conforming a Box Concept) for the envelope (or assigns one). So this
is more or less outside the discussion... Having a box you can
get&amp;nbsp;the minimum-corner coordinates (might
be 2D, might be 3D, or more) and the maximum-corner coordinates.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;SqlGeometry&lt;/h2&gt;
&lt;br&gt;
I blogged about the useful SqlGeometry type &lt;a
 href="/2011/04/sqlgeometry-types-and-linq.html"&gt;here&lt;/a&gt;.
The SqlGeometry type is polymorphic, it can be any OGC geometry.
But, therefore, it cannot be a Rectangle (because, remember, a
rectangle is
not an OGC Geometry). So if it contains a Rectangle, it is a Polygon.&lt;br&gt;
&lt;br&gt;
Using
C#, it would be useful to get the coordinates from a Polygon returned
by STEnvelope and that goes like this. Note that (in the light of
defensive programming) we don't even assume that the first point is the
lower left point. We add this code as a function (we could
add it to a class GeometryExtensions, but for now we don't). It is
called BoxToCoordinates, see the code below.&lt;br&gt;
&lt;br&gt;
And,
for symmetry, and because it is convenient, or often necessary (last
reason
most important ;-) ) we add a counterpart function as well, which
creates a rectangle for you given four coordinate values. We call that
one CoordinatesToBox, see code below.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;The code&lt;/h2&gt;
&lt;br&gt;
OK, this was some preparation for next blog, not too difficult, and now
we can convert an STEnvelope
result to coordinate values, and back. The full code is displayed
below. Between BoxToCoordinates and CoordinatesToBox, there will be
some more interesting calculations in the next blog. Stay tuned.&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: black;"&gt;&lt;span
 style="color: blue;"&gt;using&lt;/span&gt; System;&lt;br&gt;&lt;span
 style="color: blue;"&gt;using&lt;/span&gt; Microsoft.SqlServer.Types;&lt;br&gt;&lt;br&gt;&lt;span
 style="color: blue;"&gt;namespace&lt;/span&gt; BlogSqlGeometryBox&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: blue;"&gt;class&lt;/span&gt; Program&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: rgb(204, 51, 204);"&gt;&lt;span
 style="color: rgb(51, 153, 153);"&gt;SqlGeometry&lt;/span&gt; &lt;/span&gt;FromWkt(&lt;span
 style="color: blue;"&gt;string&lt;/span&gt; text, &lt;span
 style="color: blue;"&gt;int&lt;/span&gt; srid)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: blue;"&gt;return&lt;/span&gt; &lt;span
 style="color: rgb(204, 51, 204);"&gt;&lt;span
 style="color: rgb(51, 153, 153);"&gt;SqlGeometry&lt;/span&gt;.&lt;/span&gt;STGeomFromText(&lt;span
 style="color: blue;"&gt;new&lt;/span&gt; System.Data.SqlTypes.SqlChars(text), srid);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: rgb(204, 51, 204);"&gt;&lt;span
 style="color: rgb(51, 153, 153);"&gt;SqlGeometry&lt;/span&gt; &lt;/span&gt;CoordinatesToBox(&lt;span
 style="color: blue;"&gt;double&lt;/span&gt; x1, &lt;span
 style="color: blue;"&gt;double&lt;/span&gt; y1, &lt;span
 style="color: blue;"&gt;double&lt;/span&gt; x2, &lt;span
 style="color: blue;"&gt;double&lt;/span&gt; y2, &lt;span
 style="color: blue;"&gt;int&lt;/span&gt; srid)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(204, 51, 204);"&gt;&lt;span
 style="color: rgb(51, 153, 153);"&gt;SqlGeometryBuilder&lt;/span&gt; &lt;/span&gt;builder = &lt;span
 style="color: blue;"&gt;new&lt;/span&gt; &lt;span
 style="color: rgb(204, 51, 204);"&gt;&lt;span
 style="color: rgb(51, 153, 153);"&gt;SqlGeometryBuilder&lt;/span&gt;&lt;span
 style="color: black;"&gt;();&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;builder.SetSrid(srid);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;builder.BeginGeometry(&lt;span
 style="color: rgb(204, 51, 204);"&gt;&lt;span
 style="color: rgb(51, 153, 153);"&gt;OpenGisGeometryType&lt;/span&gt;&lt;span
 style="color: black;"&gt;.Polygon&lt;/span&gt;&lt;/span&gt;&lt;span
 style="color: black;"&gt;);&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;builder.BeginFigure(x1, y1);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;builder.AddLine(x1, y2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;builder.AddLine(x2, y2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;builder.AddLine(x2, y1);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;builder.AddLine(x1, y1); &lt;span
 style="color: green;"&gt;// Yes, we close it neatly&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;builder.EndFigure();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;builder.EndGeometry();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: blue;"&gt;return&lt;/span&gt; builder.ConstructedGeometry;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: blue;"&gt;void&lt;/span&gt; MakeFirstSmaller&amp;lt;T&amp;gt;(&lt;span
 style="color: blue;"&gt;ref&lt;/span&gt; T a, &lt;span
 style="color: blue;"&gt;ref&lt;/span&gt; T b) &lt;span
 style="color: rgb(51, 51, 255);"&gt;where&lt;/span&gt; T : &lt;span
 style="color: rgb(51, 153, 153);"&gt;IComparable&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: blue;"&gt;if&lt;/span&gt; (a.CompareTo(b) &amp;gt; &lt;span
 style="color: maroon;"&gt;0&lt;/span&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: green;"&gt;// Exchange the two values&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;T t = a;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a = b;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b = t;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: blue;"&gt;void&lt;/span&gt; BoxToCoordinates(&lt;span
 style="color: rgb(51, 153, 153);"&gt;SqlGeometry&lt;/span&gt; box, &lt;span
 style="color: blue;"&gt;out&lt;/span&gt; &lt;span
 style="color: blue;"&gt;double&lt;/span&gt; x1, &lt;span
 style="color: blue;"&gt;out&lt;/span&gt; &lt;span
 style="color: blue;"&gt;double&lt;/span&gt; y1, &lt;span
 style="color: blue;"&gt;out&lt;/span&gt; &lt;span
 style="color: blue;"&gt;double&lt;/span&gt; x2, &lt;span
 style="color: blue;"&gt;out&lt;/span&gt; &lt;span
 style="color: blue;"&gt;double&lt;/span&gt; y2)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(204, 51, 204);"&gt;&lt;span
 style="color: rgb(51, 153, 153);"&gt;SqlGeometry&lt;/span&gt; &lt;/span&gt;lower_left = box.STPointN(&lt;span
 style="color: maroon;"&gt;1&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(204, 51, 204);"&gt;&lt;span
 style="color: rgb(51, 153, 153);"&gt;SqlGeometry&lt;/span&gt; &lt;/span&gt;upper_right = box.STPointN(&lt;span
 style="color: maroon;"&gt;3&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x1 = lower_left.STX.Value;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;y1 = lower_left.STY.Value;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x2 = upper_right.STX.Value;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;y2 = upper_right.STY.Value;&lt;br&gt;&lt;/span&gt;&lt;span
 style="color: black;"&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span
 style="color: black;"&gt;&lt;span style="color: green;"&gt;// Defensive programming:&lt;/span&gt;&lt;/span&gt;&lt;span
 style="color: black;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span
 style="color: black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MakeFirstSmaller(&lt;span
 style="color: blue;"&gt;ref&lt;/span&gt; x1, &lt;span
 style="color: blue;"&gt;ref&lt;/span&gt; x2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MakeFirstSmaller(&lt;span
 style="color: blue;"&gt;ref&lt;/span&gt; y1, &lt;span
 style="color: blue;"&gt;ref&lt;/span&gt; y2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: blue;"&gt;void&lt;/span&gt; Main(&lt;span
 style="color: blue;"&gt;string&lt;/span&gt;[] args)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(204, 51, 204);"&gt;&lt;span
 style="color: rgb(51, 153, 153);"&gt;SqlGeometry&lt;/span&gt; &lt;/span&gt;triangle = FromWkt(&lt;span
 style="color: maroon;"&gt;"POLYGON((0 0,2 5,4 1,0 0))"&lt;/span&gt;, &lt;span
 style="color: maroon;"&gt;0&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(204, 51, 204);"&gt;&lt;span
 style="color: rgb(51, 153, 153);"&gt;SqlGeometry&lt;/span&gt; &lt;/span&gt;box = triangle.STEnvelope();&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: blue;"&gt;double&lt;/span&gt; x1, y1, x2, y2;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BoxToCoordinates(box, &lt;span
 style="color: blue;"&gt;out&lt;/span&gt; x1, &lt;span
 style="color: blue;"&gt;out&lt;/span&gt; y1, &lt;span
 style="color: blue;"&gt;out&lt;/span&gt; x2, &lt;span
 style="color: blue;"&gt;out&lt;/span&gt; y2);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: green;"&gt;// Do something with these coordinates. Let's create a larger box&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x1 -= &lt;span
 style="color: maroon;"&gt;1&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;y1 -= &lt;span
 style="color: maroon;"&gt;1&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x2 += &lt;span
 style="color: maroon;"&gt;1&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;y2 += &lt;span
 style="color: maroon;"&gt;1&lt;/span&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;box = CoordinatesToBox(x1, y1, x2, y2, &lt;span
 style="color: maroon;"&gt;0&lt;/span&gt;);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.WriteLine(box.STAsText().ToSqlString().ToString());&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;}&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
Writing:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: black;"&gt;POLYGON ((-1 -1, -1 6, 5 6, 5 -1, -1 -1))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-4258165195418170199?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/4258165195418170199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/05/sqlgeometry-and-boxes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/4258165195418170199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/4258165195418170199'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/05/sqlgeometry-and-boxes.html' title='SqlGeometry and Boxes'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-6658940722664343123</id><published>2011-04-29T18:53:00.007+02:00</published><updated>2011-04-29T19:06:21.265+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='SqlGeometry'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>SqlGeometry types and LINQ</title><content type='html'>&lt;h1&gt;SqlGeometry types and LINQ&lt;/h1&gt;
&lt;br&gt;
Last year I started to use the
Microsoft .NET SqlGeometry types and I like them very much. Thanks to
&lt;a href="http://twitter.com/#!/berttemme"&gt;Bert Temme&lt;/a&gt; who attended us (at Geodan) on their existance. See also &lt;a
 href="http://msdn.microsoft.com/nl-nl/library/bb933790.aspx"&gt;this
page&lt;/a&gt; with an introduction.&lt;br&gt;
&lt;br&gt;
In short,
the &lt;a
 href="http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeometry.aspx"&gt;SqlGeometry&lt;/a&gt;
is the type used for the SQL Server Spatial geometry
objects. But it can also be used outside of SQL Server environments: it
is contained in a pure
.NET assembly. The download page says: &lt;span
 style="font-style: italic;"&gt;"This component can be installed
separately from the server to allow client applications to use these
types outside of the server." &lt;/span&gt;&lt;br&gt;
&lt;br&gt;
So the SqlGeometry type is comparable to
other Geometry libraries, such as Boost.Geometry, GEOS and NTS (the JTS
for .NET).&lt;br&gt;
&lt;br&gt;
SqlGeometry functionality follows the
OGC/ISO specifications quite closely. This means there is not much more
than OGC
functionality. Sometimes there is the wish to do other things than
that. For example: select only the polygons from a geometry collection.
Or: select only the polygons larger than X square meters from a
MultiPolygon. There comes LINQ into place.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Installing the assemblies to use SqlGeometry&lt;/h2&gt;
To use SQLGeometry, you need to have a reference to
Microsoft.SqlServer.Types, which can be found in C:\Program
Files\Microsoft SQL Server\100\SDK\Assemblies (on my (64 bit) machine
in c:\Program Files (x86)\..., indicating&amp;nbsp;32 bits). If not
there, download it from &lt;a
 href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=CEB4346F-657F-4D28-83F5-AAE0C5C83D52"&gt;here&lt;/a&gt;
(there &lt;span style="font-weight: bold;"&gt;is&lt;/span&gt; a
64 bits version there).&lt;br&gt;
Note that you have to add the reference manually, by browsing on the
file system, it does not appear in the reference tab (at least not on
my system, using Microsoft Visual C# 2010 Express).&lt;br&gt;
&lt;br&gt;
After that, just add:
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span style="color: Blue;"&gt;using&lt;/span&gt; Microsoft.SqlServer.Types;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;h2&gt;The geometry collection&lt;/h2&gt;
A
&lt;a href="http://en.wikipedia.org/wiki/Well-known_text"&gt;geometry
collection&lt;/a&gt; is one geometry consisting of several
sub-geometries, which possibly can have different types (e.g.
linestrings and polygons).&lt;br&gt;
&lt;br&gt;
A&amp;nbsp;geometry collection is
sometimes not&amp;nbsp;convenient. For example: MapServer cannot
display
them. And there are probably more GIS packages which do not display
geometry collections, because most mapping software is based on layers,
and most layers are defined either on a layer with points (or
multi-points), or a layer with lines (or multi-linestrings), or on a
layer with polygons (or multi-polygons), but in most cases not on a
layer with polygons and lines, and in even more cases not on a layer
with geometry collections.&lt;br&gt;
&lt;br&gt;
Geometry collections can come into existence during an intersection. If
you overlay, for example, two valid polygons which share a part of
their
boundaries in opposite directions, that shared boundary will form a
linestring, while the rest of the intersection (if any) will form a
polygon. The polygon and the linestring&amp;nbsp;form together a
geometry collection. The next
SQL statement generates a (probably&amp;nbsp;unwanted) geometry
collection:
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;select&lt;/span&gt; &lt;span
 style="color: rgb(51, 51, 255);"&gt;geometry&lt;/span&gt;::STGeomFromText(&lt;span
 style="color: Red;"&gt;'POLYGON((0 0,0 8,8 8,8 4,4 4,4 0,0 0))'&lt;/span&gt;, &lt;span
 style="color: Red;"&gt;0&lt;/span&gt;) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.STIntersection(&lt;span
 style="color: rgb(51, 51, 255);"&gt;geometry&lt;/span&gt;::STGeomFromText(&lt;span
 style="color: Red;"&gt;'POLYGON((4 0,4 8,8 8,8 0,4 0))'&lt;/span&gt;,&lt;span
 style="color: Red;"&gt; 0&lt;/span&gt;))&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
The result is: &lt;span style="font-family: monospace;"&gt;GEOMETRYCOLLECTION
(POLYGON ((4 4, 8 4, 8 8, 4 8, 4 4)),
LINESTRING (4 4, 4 0))&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
Because geometry collections are often not&amp;nbsp;displayed,
functionality to remove all
linestrings from a geometry collection would be very useful, or
crucial.
SqlGeometry does not offer
this functionality, but it is possible to build it. It can be built by
creating WKT's of all sub-geometries, and parsing and recombining them,
but&amp;nbsp;LINQ offers&amp;nbsp;a more elegant
way.&lt;br&gt;&lt;br&gt;
&lt;h2&gt;Selecting polygons from a geometry collection&lt;/h2&gt;
We design our algorithm as: &lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;create a list of geometries from the geometry collection&lt;/li&gt;
  &lt;li&gt;remove the linestrings and points from this list&lt;/li&gt;
  &lt;li&gt;build a Polygon or a MultiPolygon from the polygons kept in
the list&lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;
&lt;h2&gt;Creating the list&lt;/h2&gt;
Creating a list of geometries can be done using the STGeometryN and
STNumGeometries functions, which are available. We can iterate through
the single geometries and add them to the list, using:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;var&lt;/span&gt; list = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; List&amp;lt;SqlGeometry&amp;gt;(); &lt;br&gt;&lt;span
 style="color: Blue;"&gt;for&lt;/span&gt; (&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; i = &lt;span
 style="color: Maroon;"&gt;1&lt;/span&gt;; i &amp;lt;= geometry.STNumGeometries().Value; i++)&lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;list.Add(geometry.STGeometryN(i)); &lt;br&gt;} &lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;span style="color: Black;"&gt;&lt;/span&gt;Note that
STGeometryN uses a one-based index, instead of the usual zero-based
index.&lt;br&gt;
&lt;br&gt;
Because we think this functionality is general, and will often be
reused, we make an &lt;a
 href="http://en.wikipedia.org/wiki/Extension_method"&gt;extension
method&lt;/a&gt; of it (I really like them!). So we make a static class
called GeometryExtensions and we
add a static method containing the piece above, and we can just call:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;IList&amp;lt;SqlGeometry&amp;gt; list = geom.ToList();&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
on any variable geom of type SqlGeometry. See source code below for the
extension method.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Creating a geometry from a list&lt;/h2&gt;
Of course, we want to have the reverse as well, making an SqlGeometry
from a list of polygons. The key is that an
STUnion is required to make a valid result. If two polygons of the list
mutually overlap, this overlap will be resolved by STUnion. Even if
there is no overlap, the STUnion has to be called because there is no
STAdd function available. Alternatively we could make use of the
&lt;a
 href="http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeometrybuilder.aspx"&gt;SqlGeometryBuilder&lt;/a&gt;
type which is available in the SqlGeometry library.
However, using STUnion guarantees a valid result. The next loop does
this for us:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;SqlGeometry result = &lt;span
 style="color: Blue;"&gt;null&lt;/span&gt;; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;foreach&lt;/span&gt; (SqlGeometry g &lt;span
 style="color: Blue;"&gt;in&lt;/span&gt; list)&lt;br&gt;{ &lt;br&gt;&lt;/span&gt;&lt;span
 style="color: Black;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;result = result == &lt;span
 style="color: Blue;"&gt;null&lt;/span&gt; ? g : result.STUnion(g);&lt;br&gt;} &lt;/span&gt;&lt;br&gt;
&lt;/pre&gt;
&lt;h2&gt;Using LINQ&lt;/h2&gt;
So having programmed step 1 and step 3 as extension methods, and having
a convenient list, we can now
implement step 2 using LINQ:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;var&lt;/span&gt; result = (&lt;span
 style="color: rgb(51, 51, 255);"&gt;from&lt;/span&gt; g &lt;span
 style="color: Blue;"&gt;in&lt;/span&gt; geom.ToList() &lt;span
 style="color: rgb(51, 51, 255);"&gt;where&lt;/span&gt; g.STGeometryType().ToString().ToLower() == &lt;span
 style="color: Maroon;"&gt;"polygon"&lt;/span&gt; &lt;span
 style="color: rgb(51, 51, 255);"&gt;select&lt;/span&gt; g).ToSqlGeometry(); &lt;/span&gt;&lt;/pre&gt;
The magic. This one line&amp;nbsp;statement with LINQ selects the
polygons from an on-the-fly list, and put them via&amp;nbsp;another
list back into an SqlGeometry. In the listing below it is formatted as
three lines.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;The complete listing&lt;/h2&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Collections.Generic; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Linq; &lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; Microsoft.SqlServer.Types; &lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;namespace&lt;/span&gt; SqlGeometryBlog1 &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; GeometryExtensions&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Converts a multi-geometry to a list of single-geometries&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; List&amp;lt;SqlGeometry&amp;gt; ToList(&lt;span
 style="color: Blue;"&gt;this&lt;/span&gt; SqlGeometry geometry)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: rgb(51, 51, 255);"&gt;var&lt;/span&gt; list = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; List&amp;lt;SqlGeometry&amp;gt;(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;for&lt;/span&gt; (&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; i = &lt;span
 style="color: Maroon;"&gt;1&lt;/span&gt;; i &amp;lt;= geometry.STNumGeometries().Value; i++)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;list.Add(geometry.STGeometryN(i)); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; list; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Converts a list of geometries to a multi-geometry&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; SqlGeometry ToSqlGeometry(&lt;span
 style="color: Blue;"&gt;this&lt;/span&gt; IEnumerable&amp;lt;SqlGeometry&amp;gt; list)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlGeometry result = &lt;span
 style="color: Blue;"&gt;null&lt;/span&gt;; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;foreach&lt;/span&gt; (SqlGeometry g &lt;span
 style="color: Blue;"&gt;in&lt;/span&gt; list)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;result = result == &lt;span
 style="color: Blue;"&gt;null&lt;/span&gt; ? g : result.STUnion(g);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; result; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// For convenience, we add two extra methods&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; SqlGeometry FromWkt(&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; text, &lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; srid)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; SqlGeometry.STGeomFromText(&lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; System.Data.SqlTypes.SqlChars(text), srid);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; String ToWkt(&lt;span
 style="color: Blue;"&gt;this&lt;/span&gt; SqlGeometry geometry)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; geometry.STAsText().ToSqlString().Value; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; Program &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; Main(&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt;[] args) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: rgb(51, 51, 255);"&gt;var&lt;/span&gt; geom1 = GeometryExtensions.FromWkt(&lt;span
 style="color: Maroon;"&gt;"POLYGON((0 0,0 8,8 8,8 4,4 4,4 0,0 0))"&lt;/span&gt;, &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: rgb(51, 51, 255);"&gt;var&lt;/span&gt; geom2 = GeometryExtensions.FromWkt(&lt;span
 style="color: Maroon;"&gt;"POLYGON((4 0,4 8,8 8,8 0,4 0))"&lt;/span&gt;, &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: rgb(51, 51, 255);"&gt;var&lt;/span&gt; geom = geom1.STIntersection(geom2); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine(geom.STIsValid().Value); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine(geom.ToWkt()); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: rgb(51, 51, 255);"&gt;var&lt;/span&gt; list = geom.ToList(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: rgb(51, 51, 255);"&gt;var&lt;/span&gt; selection = &lt;span
 style="color: rgb(51, 51, 255);"&gt;from&lt;/span&gt; g &lt;span
 style="color: Blue;"&gt;in&lt;/span&gt; list &lt;span
 style="color: rgb(51, 51, 255);"&gt;where&lt;/span&gt; g.STGeometryType().ToString().ToLower() == &lt;span
 style="color: Maroon;"&gt;"polygon"&lt;/span&gt; &lt;span
 style="color: rgb(51, 51, 255);"&gt;select&lt;/span&gt; g; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; geom = selection.ToSqlGeometry(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine(geom.ToWkt()); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;} &lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;h2&gt;The output&lt;/h2&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;True&lt;br&gt;GEOMETRYCOLLECTION (POLYGON ((4 4, 8 4, 8 8, 4 8, 4 4)), LINESTRING (4 4, 4 0))&lt;br&gt;POLYGON ((4 4, 8 4, 8 8, 4 8, 4 4))&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-6658940722664343123?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/6658940722664343123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/04/sqlgeometry-types-and-linq.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/6658940722664343123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/6658940722664343123'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/04/sqlgeometry-types-and-linq.html' title='SqlGeometry types and LINQ'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-5001365674215645033</id><published>2011-04-08T23:10:00.002+02:00</published><updated>2011-04-08T23:12:23.786+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PostGIS'/><category scheme='http://www.blogger.com/atom/ns#' term='Extent'/><category scheme='http://www.blogger.com/atom/ns#' term='Envelope'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Extent of a SQL Server Spatial table</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Extent of a SQL Server Spatial table&lt;/h1&gt;
&lt;br&gt;
PostGIS does have a convenient spatial aggregation function: &lt;a
 href="http://postgis.refractions.net/documentation/manual-1.5/ST_Extent.html"&gt;ST_Extent&lt;/a&gt;.
SQL Server Spatial does not have that functionality. This little blog shows how to
achieve its effect.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;PostGIS&lt;/h2&gt;&lt;br&gt;
Given a table (e.g. called &lt;span
 style="font-weight: bold;"&gt;world1&lt;/span&gt;) with a geometry column (e.g. called &lt;span
 style="font-weight: bold;"&gt;geom&lt;/span&gt;), a call to the
PostGIS function&amp;nbsp;ST_Extent will give a neat box containing all
geometries. For example:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: black;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;select&lt;/span&gt; ST_Extent(geom) &lt;span
 style="color: rgb(51, 51, 255);"&gt;from&lt;/span&gt; world1;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
returns a bounding box:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: black;"&gt;BOX(-180 -89.9,180 83.674733)&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;h2&gt;SQL Server Spatial&lt;/h2&gt;&lt;br&gt;
SQL Server Spatial follows&amp;nbsp;OGC&amp;nbsp;closely and therefore
does not implement this functionality. Neither it has implemented it as a
so-called extended geometry method. I've seen various creative
solutions on the web, e.g. &lt;a
 href="http://geographika.co.uk/sql-server-spatial-sql"&gt;here&lt;/a&gt;
and &lt;a
 href="http://social.msdn.microsoft.com/Forums/en/sqlspatial/thread/382adbf6-3a8e-4437-8926-0279e4ddf14f"&gt;here&lt;/a&gt;
and &lt;a
 href="http://www.gisbelowsealevel.nl/Blog/post/Showing-SQL-Server-Geometries-in-a-WPF-Application-Part-1.aspx"&gt;here&lt;/a&gt;. Most of these efforts are based on iterating through the rows,
which is possible but often inconvenient (because of the required loop) and (also therefore) probably less performant. I will
not say that my solution is performing better, but at least it is one
SQL statement.&lt;br&gt;
&lt;br&gt;
Be prepared on use of &lt;span style="font-weight: bold;"&gt;with&lt;/span&gt;,
my current favorite SQL clause. &amp;nbsp;I described it earlier &lt;a
 href="/2011/01/precision-cause-of-spikes.html"&gt;here&lt;/a&gt;.
&lt;br&gt;
&lt;br&gt;
So what happens: we define a sort of on-the-fly view of all the
envelopes (select geom.MakeValid().STEnvelope() as envelope from
world1). &lt;i&gt;(The call to MakeValid() is only necessary if there might be
invalid geometries in the table).&lt;/i&gt; Then we ask for the corner points of
that viewy thingy. An envelope is a rectangle, always containing five points, where
the fifth point is closing point and therefore the same as the first
point. So either point 1 and 3, or point 2 and 4 are the opposite
corners of a rectangle. So we take point 1 and point 3 (as done in
first creative solution I referenced above). We define a second
on-the-fly view of this, using the first view as input. To get both diagonally opposite
points, we union them (&lt;span
 style="font-weight: bold; font-style: italic;"&gt;union all&lt;/span&gt;
is required). Note that I'm referring to an SQL union here, not to a
spatial union.&lt;br&gt;
&lt;br&gt;
Those&amp;nbsp;on-the-fly views can be (very conveniently) implemented
using &lt;b&gt;&lt;i&gt;with&lt;/i&gt;&lt;/b&gt;. I name them then &lt;span style="font-weight: bold;"&gt;viewy&lt;/span&gt;
but that's up to you. So &lt;span style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;envelope_viewy&lt;/span&gt;&lt;/span&gt;
is the first one and &lt;span style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;corner_viewy&lt;/span&gt;&lt;/span&gt;
is the second one.&lt;br&gt;
&lt;br&gt;
The complete SQL statement is then, for a column called &lt;span
 style="font-style: italic; font-weight: bold;"&gt;geom&lt;/span&gt;
in a table called &lt;span style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;world&lt;/span&gt;&lt;/span&gt;:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: black;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;with&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;envelope_viewy &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(51, 51, 255);"&gt;select&lt;/span&gt; geom.MakeValid().STEnvelope() &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; envelope &lt;span
 style="color: rgb(51, 51, 255);"&gt;from&lt;/span&gt; world1&lt;br&gt;&amp;nbsp;&amp;nbsp;),&lt;br&gt;&amp;nbsp;&amp;nbsp;corner_viewy &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(51, 51, 255);"&gt;select&lt;/span&gt; envelope.STPointN(1) &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; point &lt;span
 style="color: rgb(51, 51, 255);"&gt;from&lt;/span&gt; envelope_viewy &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(51, 51, 255);"&gt;union all select&lt;/span&gt; envelope.STPointN(3) &lt;span
 style="color: rgb(51, 51, 255);"&gt;from&lt;/span&gt; envelope_viewy&lt;br&gt;&amp;nbsp;&amp;nbsp;)&lt;br&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;select&lt;/span&gt; min(point.STX) &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; min_x,min(point.STY) &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; min_y,max(point.STX) &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; max_x,max(point.STY) &lt;span
 style="color: rgb(51, 51, 255);"&gt;as&lt;/span&gt; max_y &lt;br&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;from&lt;/span&gt; corner_viewy&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;
And voilà, you will get:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: black;"&gt;min_x&amp;nbsp;&amp;nbsp;&amp;nbsp; min_y&amp;nbsp;&amp;nbsp;&amp;nbsp; max_x&amp;nbsp;&amp;nbsp;&amp;nbsp; max_y&lt;br&gt;-180&amp;nbsp;&amp;nbsp;&amp;nbsp; -89.9&amp;nbsp;&amp;nbsp;&amp;nbsp; 180&amp;nbsp;&amp;nbsp;&amp;nbsp; 83.674733&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
The same! (Of course, I used the same table, world1, used from my
shapefile research-still-to-be-finished).&lt;br&gt;
&lt;br&gt;
You can also create a stored procedure of this (e.g. called ST_Extent).&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;PostGIS remark&lt;/h2&gt;&lt;br&gt;
Writing this blog, I noticed a strange thing of the PostGIS ST_Extent. It only works for 2D, there is explicitly written in the documentation that it does not work for 3D (use a ST_Extent3D for
that). But it delivers a 3D box. And indeed it is explicitly typed
as a 3D box. I wonder why.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-5001365674215645033?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/5001365674215645033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/04/extent-of-sql-server-spatial-table.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/5001365674215645033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/5001365674215645033'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/04/extent-of-sql-server-spatial-table.html' title='Extent of a SQL Server Spatial table'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-8525674304829951522</id><published>2011-03-31T19:13:00.000+02:00</published><updated>2011-03-31T19:13:48.682+02:00</updated><title type='text'>Leaving Geodan</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Leaving Geodan...&lt;/h1&gt;
&lt;br&gt;
As of tomorrow, April 1, I'm not employed with Geodan anymore. I've
worked there for nearly 17 years and it has been a fantastic time.
However, this year&amp;nbsp;it is time for a change. I will continue
with software development, now on my own, as a freelance programmer of
Open Source, Geographical, Geometric, .NET and C++ software.&lt;br&gt;
&lt;br&gt;
This change is also the reason that there were no new blogs last month
on this blogspot. There are still some blog-answers to be given and
blog-things to be continued. Will happen. I was quite busy finishing
everything, handing over projects, with the release of Boost.Geometry,
and with the new start-up.&lt;br&gt;
&lt;br&gt;
Of course I will continue with my Open Source activities, of which
Boost.Geometry is by far the most important. It is close to release
now, in Boost 1.47 it will be included.&lt;br&gt;
&lt;br&gt;
And I also take part in a charity/Open Source project, together with
Geodan, I will blog about this soon. It is nice to stay related to that
great company.&lt;br&gt;
&lt;br&gt;
Next Monday I will start in Leiden for a four months contract.&lt;br&gt;
&lt;br&gt;
Adios, all my great former Geodan-collegues, thanks for all!&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-8525674304829951522?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/8525674304829951522/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/03/leaving-geodan.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/8525674304829951522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/8525674304829951522'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/03/leaving-geodan.html' title='Leaving Geodan'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-7398287590512118527</id><published>2011-02-19T21:37:00.002+01:00</published><updated>2011-02-22T18:09:07.482+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dissolve'/><category scheme='http://www.blogger.com/atom/ns#' term='PostGIS'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='makevalid'/><title type='text'>Dissolving the Pentagram</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Dissolving the Pentagram&lt;/h1&gt;
&lt;br&gt;
A week ago Denis asked the &lt;a
 href="http://lists.osgeo.org/pipermail/ggl/2011-February/000999.html"&gt;GGL-list&lt;/a&gt;
if the internal segments of a self-intersecting polygon could be
dropped. He attached this figure:&lt;br&gt;
&lt;img style="width: 257px; height: 236px;" alt="si"
 src="http://lists.osgeo.org/pipermail/ggl/attachments/20110211/e25d72b4/animation-0001.png"&gt;&lt;br&gt;
&lt;br&gt;
I answered that dissolve should do this. But it does not in this case.
Dissolve can remove self-intersections, but under certain circumstances
and even then it is not always perfect. So this is a reason to remove
dissolve to the extensions folder - it should not yet be part of
Boost.Geometry as it is released, hopefully in Boost 1.47&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Pentagram&lt;/h2&gt;
A &lt;a href="http://en.wikipedia.org/wiki/Pentagram"&gt;pentagram&lt;/a&gt;
is a five pointed star which can be drawn with a linestring of five
segments. This is a Well-Known text presentation of a pentagram:&lt;br&gt;
&lt;br&gt;
POLYGON((5 0,2.5 9,9.5 3.5,0.5 3.5,7.5 9,5 0))&lt;br&gt;
&lt;br&gt;
As I often do, I compare the behaviour of algorithms on this WKT with
SQL Server, PostGIS, and other packages (in this case Quantum GIS and
SVG).&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;SVG&lt;/h2&gt;
Boost.Geometry can create SVG images. This is really useful and I often
use it in test programs. SVG's can then be depicted in FireFox. (In
Google Chrome dropping the second SVG let it crash...).&lt;br&gt;
&lt;br&gt;
SVG has thousands of properties, and one of them is the &lt;span
 style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;fill-rule&lt;/span&gt;&lt;/span&gt;&lt;span
 style="font-weight: bold; font-style: italic;"&gt;&lt;/span&gt;.
It can be set to &lt;span
 style="font-weight: bold; font-style: italic;"&gt;winding&lt;/span&gt;
and to &lt;span style="font-weight: bold; font-style: italic;"&gt;non-zero&lt;/span&gt;.
This delivers two different presentations:&lt;br&gt;
&lt;br&gt;
&lt;table style="text-align: left; width: 100%;" border="0"
 cellpadding="2" cellspacing="2"&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 285px; height: 293px;"
 alt="winding"
 src="https://lh3.googleusercontent.com/_6zrdK5O_LIg/TWAkVQxVM2I/AAAAAAAABjw/iVxH6WusBWE/pentagram_winding.png"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;img style="width: 306px; height: 298px;"
 alt="non-zero"
 src="https://lh6.googleusercontent.com/_6zrdK5O_LIg/TWAkVp2Xn_I/AAAAAAAABj0/aI3R5QYc6c0/pentagram_nonzero.png"&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;winding&lt;/td&gt;
      &lt;td&gt;non-zero&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;SQL Server&lt;/h2&gt;
In SQL Server the pentagram is drawn as such:&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 521px; height: 513px;" alt="sql server"
 src="https://lh6.googleusercontent.com/_6zrdK5O_LIg/TWAfjJht6NI/AAAAAAAABjQ/9iMKcps78aI/pentagram_sqlserver.png"&gt;&lt;br&gt;
So it is using the winding rule.&lt;br&gt;
&lt;br&gt;
The polygon is not valid, of course, it has five self-intersection
points. SQL Server has a very good method to
make polygons valid. It is obviously called MakeValid(). It is a SQL
Server extension, not an OGC Method. I wrote "&lt;span
 style="font-weight: bold;"&gt;very good&lt;/span&gt;" and I
mean that, we used it a lot in real-world problems and it has always
worked very well.&lt;br&gt;
&lt;br&gt;
With this specific pentagram MakeValid() creates a
multi-polygon containing five triangles. So it directly uses the
winding rule to create a multi-geometry. Sounds logical. If we
calculate the area we get 17.7316840044235, the summed area of the five
triangles. Calculating the area of a non-valid polygon is not possible
in SQL Server. The statement is:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: black;"&gt;
select geometry::STGeomFromText('POLYGON((5 0,2.5 9,9.5 3.5,0.5 3.5,7.5 9,5 0))',0)
.MakeValid().STArea()
&lt;/span&gt;&lt;/pre&gt;
&lt;h2&gt;PostGIS&lt;/h2&gt;
PostGIS does not have a drawing engine. In PostGIS we can calculate the
area of an invalid polygon and it gives us: 33.5. There is (AFAIK) not
yet a function to make polygons valid, though it is&amp;nbsp;&lt;a
 href="http://postgis.refractions.net/documentation/manual-svn/ST_MakeValid.html"&gt;announced&lt;/a&gt;.
The good old trick is to use a buffer with buffer-distance 0, so we do
this:&lt;br&gt;
&lt;br&gt;
&lt;pre style="color: black;"&gt;select ST_Area(ST_Buffer(ST_GeomFromText(&lt;br&gt;'POLYGON((5 0,2.5 9,9.5 3.5,0.5 3.5,7.5 9,5 0))',0),0))&lt;/pre&gt;
and we get an area of 25.6158419936921. If we draw the zero-buffered
result we&amp;nbsp;get a filled polygon.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Boost.Geometry&lt;/h2&gt;
Boost.Geometry can calculate the area of an invalid polygon and it also
gives us: 33.5. The simple always-working Surveyor's formula just
calculates this for us.&lt;br&gt;
&lt;br&gt;
If we use the algorithm &lt;span style="font-weight: bold;"&gt;dissolve&lt;/span&gt;
we indeed get a polygon with all internal corners dropped in this case.
The area of the dissolved polygon is 25.6158412 and this is the right
area. So the Surveyor's formula actually cannot be used with invalid
polygons, SQL Server is right to prohibit this.&lt;br&gt;
&lt;br&gt;
The SVG files displayed above are both created using Boost.Geometry so
no picture here.&lt;br&gt;
&lt;h2&gt;Quantum GIS&lt;/h2&gt;
Quantum GIS has a great extension, QuickWKT, with which WKT geometries
can be drawn. It uses the winding rule. It can calculate the area of
the polygons (using the Info tool we can get it) and we get 33.5.
Right, the Surveyor's formula.&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 437px; height: 424px;" alt="qgis"
 src="https://lh4.googleusercontent.com/_6zrdK5O_LIg/TWAfjESL0JI/AAAAAAAABjM/T9T1Ocu1X9o/pentagram_qgis.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;What should happen&lt;/h2&gt;
What should happen is not that simple. In these four programs, only SQL
Server was consistent by prohibiting area calculation and creating a
multi-geometry which looks like the image it depicts. All other
programs and libraries were consistent, using the Surveyor's formula
and creating a closed five-pointed polygon. &lt;br&gt;
&lt;br&gt;
The reasoning of Boost.Geometry is that it takes direction into
account. So if we draw arrows aside of all linestrings, we get:&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 406px; height: 411px;" alt="arrowed"
 src="https://lh3.googleusercontent.com/_6zrdK5O_LIg/TWAfi_JT3MI/AAAAAAAABjI/zdDjUt15JGQ/pentagram_arrowed.png"&gt;&lt;br&gt;
&lt;br&gt;
And here we see, in the triangle with the smaller arrows, that the
direction is not consistent. That triangle should not be generated. Of
this whole pentagram several polygons can be drawn with consistent
directions, and the largest of them is the whole polygon. So the
dissolve function is expected to generate a five-pointed star here. And
it does.&lt;br&gt;
&lt;br&gt;
There is also a pentagon in the center with consistent directions.
Because it has the same orientation as the outer polygon, it should be
discarded. And it is. If it would have been orientated
counterclockwise, a hole should have been formed.&lt;br&gt;
&lt;br&gt;
So there are reasons to say that this pentagram indeed should be
converted into a solid five-pointed star. There is no winding rule or
non-zero rule involved there, it is just derived by the directions of
the segments created by the intersection.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;But now the sample&lt;/h2&gt;
Anyway, using the sample of Denis Pesotsky, Boost.Geometry's results were not that
clever. It generates two polygons which are indeed as expected, with
consistent directions. The outer polygon does not have a consistent
direction and therefore should not be generated, correct. But there is
one polygon with consistent direction missing, in the lower right. That
one is discarded but should not have been...&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 538px; height: 502px;" alt="denis"
 src="https://lh3.googleusercontent.com/_6zrdK5O_LIg/TWAfc0IzyhI/AAAAAAAABi0/gsxVdeg0xbQ/dissolve_denis.png"&gt;&lt;br&gt;
&lt;br&gt;
Because this, and because we have to think more about the behaviour,
the dissolve algorithm has to be moved to the extensions folder. That
means it will not be part of the initial release of Boost.Geometry, in
the Release branch.&lt;br&gt;
&lt;br&gt;
This is the WKT of the input polygon:&lt;br&gt;
&lt;br&gt;
POLYGON((55 10, 141 237, 249 23, 21 171, 252 169, 24 89, 266 73, 55 10))&lt;br&gt;
&lt;br&gt;
The white pieces are by the winding rule, and in SQL Server it is
looking the same (no picture here). SQL Server's MakeValid() creates 9
polygons here.&lt;br&gt;
&lt;br&gt;
PostGIS, using the buffer, creates one polygon, looking like this:&lt;br&gt;
&lt;img style="width: 373px; height: 363px;" alt="postgis"
 src="https://lh4.googleusercontent.com/_6zrdK5O_LIg/TWAo-O2nA3I/AAAAAAAABj4/MK4EexLjrps/dissolve_postgis.png"&gt;&lt;br&gt;
&lt;br&gt;
And that polygon is indeed the largest polygon which can be formed,
following all arrows in clockwise direction. So this is the polygon
that was expected by the dissolve algorithm...&lt;br&gt;
&lt;br&gt;
Anyway, it is not the result that Denis asked for.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Useful usage&lt;/h2&gt;
Dissolve &lt;span style="font-weight: bold; font-style: italic;"&gt;can&lt;/span&gt;&lt;span
 style="font-style: italic;"&gt;
&lt;/span&gt;be very useful so I end this blog by just listing some of
the testcases
where it makes sense:&lt;br&gt;
&lt;br&gt;
Inaccurate corners (extra intersection):&lt;br&gt;
&lt;img style="width: 316px; height: 310px;"
 alt="inaccurate corners"
 src="https://lh3.googleusercontent.com/_6zrdK5O_LIg/TWAhVJFaSMI/AAAAAAAABjU/YGvnnZNEvmA/dissolve_messy_hole.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Messy corners:&lt;br&gt;
&lt;img style="width: 417px; height: 332px;" alt="dkn"
 src="https://lh4.googleusercontent.com/_6zrdK5O_LIg/TWAfc1MMjiI/AAAAAAAABi4/_tbWRbD3rJg/dissolve_dkn.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Keyholed holes:&lt;br&gt;
&lt;img style="width: 311px; height: 333px;" alt="keyhole"
 src="https://lh3.googleusercontent.com/_6zrdK5O_LIg/TWAfdB3yLqI/AAAAAAAABi8/HVfNTdugJeg/dissolve_keyhole.png"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
Due to shortcomings in the dissolve algorithm and vagueness in
behaviour in general we have to move the dissolve function to the
extensions folder. It has to be thought over more thoroughly.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-7398287590512118527?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/7398287590512118527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/02/dissolving-pentagram.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/7398287590512118527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/7398287590512118527'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/02/dissolving-pentagram.html' title='Dissolving the Pentagram'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh3.googleusercontent.com/_6zrdK5O_LIg/TWAkVQxVM2I/AAAAAAAABjw/iVxH6WusBWE/s72-c/pentagram_winding.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-2269303753955669374</id><published>2011-02-13T23:46:00.005+01:00</published><updated>2011-02-13T23:56:08.459+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Qt'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><title type='text'>Qt World Mapper with Boost.Geometry</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Qt World Mapper with Boost.Geometry&lt;/h1&gt;
&lt;br&gt;
Last year I created a simple world mapper using &lt;a
 href="http://en.wikipedia.org/wiki/WxWidgets"&gt;WxWidgets&lt;/a&gt;.
For various
reasons I decided to make the &lt;a
 href="http://en.wikipedia.org/wiki/Qt_%28framework%29"&gt;Qt&lt;/a&gt;
equivalent as well.&lt;br&gt;
&lt;br&gt;
Both Qt and WxWidgets are well-known cross-platform windows frameworks.
Qt is used in &lt;a href="http://www.qgis.org/"&gt;Quantum GIS&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
The World Mapper I created with WxWidgets did read world countries from
a WKT (well-known text) file, and displayed them. Moving the mouse did
highlight the country. For Qt it is&amp;nbsp;similar (the highlighting
is
not yet been done).&lt;br&gt;
&lt;br&gt;
The nice thing is that, by setting Boost.Geometry in this context, its
force is shown:&lt;br&gt;
&lt;br&gt;
Look below to lines marked with &lt;span
 style="font-weight: bold; color: Green;"&gt;// Adapt&lt;/span&gt;.
The QPointF and QPolygonF are just
registered. From now on&amp;nbsp;they act as normal Boost.Geometry
geometries. So they can be used in area calculation, distance,
transform, etc. We only use transform in this example.&lt;br&gt;
&lt;br&gt;
So also look at lines commented with &lt;span
 style="font-weight: bold; color: Green;"&gt;// This
is the essention&lt;/span&gt;. Here a QPolygonF is declared, a ring (a
normal Boost.Geometry part of a polygon, part of a multi-polygon) is
transformed using the transformer to a QPolygonF. And the last one is
of course displayed without any problem.&lt;br&gt;
&lt;br&gt;
Delivering this application:&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 816px; height: 538px;" alt="world"
 src="https://lh4.googleusercontent.com/_6zrdK5O_LIg/TVhcOZj-zkI/AAAAAAAABik/oCV_aU71jYE/qthelloworld.png"&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;h2&gt;Complete C++ Code&lt;/h2&gt;
&lt;br&gt;&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;fstream&amp;gt; &lt;br&gt;&lt;br&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;QtGui&amp;gt; &lt;br&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;QWidget&amp;gt; &lt;br&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;QObject&amp;gt; &lt;br&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;QPainter&amp;gt; &lt;br&gt;&lt;br&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;boost/foreach.hpp&amp;gt; &lt;br&gt;&lt;br&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;boost/geometry/geometry.hpp&amp;gt; &lt;br&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;boost/geometry/geometries/&lt;span
 style="color: Blue;"&gt;register&lt;/span&gt;/point.hpp&amp;gt;&lt;br&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;boost/geometry/geometries/&lt;span
 style="color: Blue;"&gt;register&lt;/span&gt;/ring.hpp&amp;gt;&lt;br&gt;&lt;br&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;boost/geometry/multi/multi.hpp&amp;gt; &lt;br&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;boost/geometry/extensions/algorithms/selected.hpp&amp;gt;&lt;br&gt;#&lt;span
 style="color: Blue;"&gt;include&lt;/span&gt; &amp;lt;boost/geometry/extensions/gis/io/wkt/wkt.hpp&amp;gt; &lt;br&gt;&lt;br&gt;&lt;span
 style="color: Green;"&gt;// Adapt a QPointF such that it can be handled by Boost.Geometry&lt;/span&gt;&lt;br&gt;BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(QPointF, &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt;, cs::cartesian, x, y, setX, setY)&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Green;"&gt;// Adapt a QPolygonF as well.&lt;/span&gt; &lt;br&gt;&lt;span
 style="color: Green;"&gt;// A QPolygonF has no holes (interiors) so it is similar to a Boost.Geometry ring&lt;/span&gt;&lt;br&gt;BOOST_GEOMETRY_REGISTER_RING(QPolygonF) &lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; boost::geometry::model::d2::point_xy&amp;lt;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt;&amp;gt; point_2d; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; boost::geometry::model::multi_polygon &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;boost::geometry::model::polygon&amp;lt;point_2d&amp;gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;gt; country_type; &lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; WorldMapper : &lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; QWidget&lt;br&gt;{ &lt;br&gt;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt;: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WorldMapper(&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::vector&amp;lt;country_type&amp;gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; countries, boost::geometry::model::box&amp;lt;point_2d&amp;gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; box)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;: m_countries(countries) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;, m_box(box) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setPalette(QPalette(QColor(&lt;span
 style="color: Maroon;"&gt;200&lt;/span&gt;, &lt;span
 style="color: Maroon;"&gt;250&lt;/span&gt;, &lt;span
 style="color: Maroon;"&gt;250&lt;/span&gt;)));&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setAutoFillBackground(true); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;protected&lt;/span&gt;: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; paintEvent(QPaintEvent*) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;map_transformer_type transformer(m_box, &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;-&amp;gt;width(), &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;-&amp;gt;height()); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;QPainter painter(&lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;painter.setBrush(Qt::green); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BOOST_FOREACH(country_type &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; country, m_countries)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; boost::range_value&amp;lt;country_type&amp;gt;::type polygon_type;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BOOST_FOREACH(polygon_type &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; polygon, country)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; boost::geometry::ring_type&amp;lt;polygon_type&amp;gt;::type ring_type;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span
 style="color: Black;"&gt; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;ring_type &lt;span style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; ring = boost::geometry::exterior_ring(polygon);&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span
 style="color: Black;"&gt; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// This is the essention:&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span
 style="color: Black;"&gt; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// Directly transform from a multi_polygon (ring-type) to a QPolygonF&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span
 style="color: Black;"&gt; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;&amp;nbsp; QPolygonF qring; &lt;br&gt;&lt;/span&gt;&lt;span
 style="color: Black;"&gt; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; boost::geometry::transform(ring, qring, transformer); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span
 style="color: Black;"&gt; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; painter.drawPolygon(qring); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt;: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; boost::geometry::strategy::transform::map_transformer&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point_2d, QPointF, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; true, true &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;gt; map_transformer_type; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::vector&amp;lt;country_type&amp;gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; m_countries;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;boost::geometry::model::box&amp;lt;point_2d&amp;gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; m_box;&lt;br&gt;}; &lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; MapperWidget : &lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; QWidget&lt;br&gt;{ &lt;br&gt;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt;: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MapperWidget(&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::vector&amp;lt;country_type&amp;gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; countries, boost::geometry::model::box&amp;lt;point_2d&amp;gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; box, QWidget *parent = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;: QWidget(parent) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WorldMapper* mapper = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; WorldMapper(countries, box);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;QPushButton *quit = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; QPushButton(tr(&lt;span
 style="color: Maroon;"&gt;"Quit"&lt;/span&gt;)); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quit-&amp;gt;setFont(QFont(&lt;span
 style="color: Maroon;"&gt;"Times"&lt;/span&gt;, &lt;span
 style="color: Maroon;"&gt;18&lt;/span&gt;, QFont::Bold)); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;connect(quit, SIGNAL(clicked()), qApp, SLOT(quit())); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;QVBoxLayout *layout = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; QVBoxLayout; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;layout-&amp;gt;addWidget(mapper); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;layout-&amp;gt;addWidget(quit); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setLayout(layout); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;}; &lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; Geometry, &lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; Box&amp;gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;inline&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; read_wkt(&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; filename, &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::vector&amp;lt;Geometry&amp;gt;&amp;amp; geometries, Box&amp;amp; box)&lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::ifstream cpp_file(filename.c_str()); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;if&lt;/span&gt; (cpp_file.is_open()) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;while&lt;/span&gt; (! cpp_file.eof() ) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; line; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::getline(cpp_file, line); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;if&lt;/span&gt; (! line.empty()) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Geometry geometry; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;    &lt;/span&gt;&lt;span
 style="color: Black;"&gt;boost::geometry::read_wkt(line, geometry); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;    &lt;/span&gt;&lt;span
 style="color: Black;"&gt;geometries.push_back(geometry); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span
 style="color: Black;"&gt;    &lt;/span&gt;&lt;span
 style="color: Black;"&gt;boost::geometry::combine(box, boost::geometry::make_envelope&amp;lt;Box&amp;gt;(geometry)); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;} &lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; main(&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; argc, &lt;span
 style="color: Blue;"&gt;char&lt;/span&gt; *argv[])&lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::vector&amp;lt;country_type&amp;gt; countries; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;boost::geometry::model::box&amp;lt;point_2d&amp;gt; box; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;boost::geometry::assign_inverse(box); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;read_wkt(&lt;span
 style="color: Maroon;"&gt;"../data/world.wkt"&lt;/span&gt;, countries, box); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;QApplication app(argc, argv); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MapperWidget widget(countries, box); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;widget.setWindowTitle(&lt;span
 style="color: Maroon;"&gt;"Boost.Geometry for Qt - Hello World!"&lt;/span&gt;); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;widget.setGeometry(&lt;span
 style="color: Maroon;"&gt;50&lt;/span&gt;, &lt;span
 style="color: Maroon;"&gt;50&lt;/span&gt;, &lt;span
 style="color: Maroon;"&gt;800&lt;/span&gt;, &lt;span
 style="color: Maroon;"&gt;500&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;widget.show(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; app.exec(); &lt;br&gt;}&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
With less than 160 lines of code, Qt and Boost.Geometry we showed how
it can&amp;nbsp;quite conveniently combine together.&lt;br&gt;
The source is shown above and in SVN it can be found&amp;nbsp;&lt;a
 href="http://svn.boost.org/svn/boost/trunk/libs/geometry/example/with_external_libs/x06_qt_world_mapper.cpp"&gt;here&lt;/a&gt;.
&lt;br&gt;
&lt;br&gt;
Actually this application (and its WxWidgets counterpart) was for me
the reason to start the shapefile research, which final conclusions
still have to be drawn.&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-2269303753955669374?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/2269303753955669374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/02/qt-world-mapper-with-boostgeometry.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/2269303753955669374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/2269303753955669374'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/02/qt-world-mapper-with-boostgeometry.html' title='Qt World Mapper with Boost.Geometry'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh4.googleusercontent.com/_6zrdK5O_LIg/TVhcOZj-zkI/AAAAAAAABik/oCV_aU71jYE/s72-c/qthelloworld.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-2452378740774201366</id><published>2011-02-13T13:37:00.003+01:00</published><updated>2011-02-13T23:41:55.204+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='intersections'/><category scheme='http://www.blogger.com/atom/ns#' term='boolean operations'/><category scheme='http://www.blogger.com/atom/ns#' term='precision'/><title type='text'>Spikes: research with ESRI</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Spikes: research with ESRI&lt;/h1&gt;
&lt;br&gt;A short follow-up on my previous &lt;a
 href="/2011/01/sql-server-postgis-stdifference-and.html"&gt;blog&lt;/a&gt;
about spikes and their &lt;a
 href="/2011/01/precision-cause-of-spikes.html"&gt;causes&lt;/a&gt;.
My collegue &lt;a href="http://twitter.com/#%21/berttemme"&gt;Bert&lt;/a&gt;
recoded the scenario in C# using ESRI. Thanks Bert! The full code is
shown below.&lt;br&gt;
&lt;br&gt;
The answer is this: with ESRI the spikes are not there. The program
produces:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;font size="3"&gt;area: 295.44447138901, perimeter: 92.5058167188044
&lt;br&gt;select geometry::STGeomFromText ('POLYGON((180956.436999999&lt;br&gt;313716.998,180953.978700001 313701.0152,180926.420299999&lt;br&gt;313732.510699999,180954.359000001&lt;br&gt;313720.504000001,180956.436999999 313716.998,180956.436999999&lt;br&gt;313716.998))', 28992)&lt;/font&gt;&lt;/span&gt;&lt;/pre&gt;

And this result is right, area and perimeter are without spikes and if
you visualize this WKT (e.g. with SQL Server) you get the right
picture...&lt;br&gt;
&lt;br&gt;
Interesting is that all coordinates seems to be rounded on one
millimeter or a tenth of it. That is probably the result
of&amp;nbsp;the &lt;a
 href="http://edndoc.esri.com/arcobjects/9.2/net/shared/geoprocessing/Coverage_Tools/how_clean_coverage_works.htm"&gt;fuzzy
tolerance policy&lt;/a&gt; that ESRI uses. Personally I'm normally a
bit sceptic about that approach: though it can avoid spikes and
slivers, it also brings some fuzzyness into the result. It is sometimes
quite hard to determine a tolerance which is sufficient for cleaning
and sufficient for not destroying features... Anyway, in this scenario
it works well.&lt;br&gt;
&lt;br&gt;
It seems interesting
to check, if you use &lt;a href="http://geometrylibrary.geodan.nl/qbk/libs/geometry/doc/html/geometry/reference/algorithms/for_each/for_each_point_2.html"&gt;rounding&lt;/a&gt; in&amp;nbsp;e.g.&amp;nbsp;Boost.Geometry,
would&amp;nbsp;the spikes be gone... The answer is (of course),
sometimes yes, sometimes no. The rounding is applied on a larger grid,
so the effect remains the same. Rounding is not enough. To get rid of
spikes, in this scenario, the spike removal functionality is advised.
Which uses&amp;nbsp;a gap distance, which can be seen as a sort of
fuzzy tolerance...&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;C# Code for "difference after cut" with ESRI&lt;/h2&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Blue;"&gt;using&lt;/span&gt;&lt;span
 style="color: Black;"&gt; System; &lt;/span&gt;&lt;br&gt;&lt;span
 style="color: Black;"&gt;&lt;span style="color: Blue;"&gt;using&lt;/span&gt; System.Collections.Generic; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.ComponentModel; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Data; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Drawing; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Text; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Windows.Forms; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; ESRI.ArcGIS.Geometry; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; ESRI.ArcGIS.esriSystem; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; Microsoft.SqlServer.Types; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Data.SqlTypes; &lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;namespace&lt;/span&gt; SpikesResearchWithEsri &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;partial&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; Form1 : Form&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; Form1() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InitializeComponent(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; InitializeLicense()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AoInitialize aoi = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; AoInitializeClass(); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;//Additional license choices can be included here.&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; esriLicenseProductCode productCode = &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; esriLicenseProductCode.esriLicenseProductCodeArcEditor; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;if&lt;/span&gt; (aoi.IsProductCodeAvailable(productCode) == &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; esriLicenseStatus.esriLicenseAvailable) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; aoi.Initialize(productCode); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; button1_Click(&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Desktop); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InitializeLicense(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPolygon parcel = &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.GetParcel(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPolyline line = &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.GetCutLine(); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPolygon bufferedLine=(IPolygon)((ITopologicalOperator)line).Buffer(&lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;&lt;span
 style="color: Maroon;"&gt;.1&lt;/span&gt;); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IGeometry result=((ITopologicalOperator)parcel).Difference(bufferedLine); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPolygon4 p = (IPolygon4)result; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// Big part:&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPolygon firstPolygon = &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.GetPolygon(p, &lt;span
 style="color: Maroon;"&gt;true&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// Small part:&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPolygon secondPolygon = &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.GetPolygon(p, &lt;span
 style="color: Maroon;"&gt;false&lt;/span&gt;);&lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// use if we do a cutpolygon&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;//IGeometry leftPolygon;&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;//IGeometry rightPolygon;&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;//((ITopologicalOperator)parcel).Cut(line, out leftPolygon, out rightPolygon);&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;//IPolyline cutline=(IPolyline)((ITopologicalOperator)(ICurve)parcel).Intersect(line, esriGeometryDimension.esriGeometryNoDimension);&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;//IPolygon firstPolygon = (IPolygon)leftPolygon;&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;//IPolygon secondPolygon = (IPolygon)rightPolygon;&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;//this.textBox1.Text=("from: " + cutline.FromPoint.X.ToString() + ", " +&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// cutline.FromPoint.Y.ToString() + ", " +&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// "to: " + cutline.ToPoint.X.ToString() + ", " +&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// cutline.ToPoint.Y.ToString()) + Environment.NewLine;&lt;/span&gt; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.textBox1.Text += &lt;span
 style="color: Maroon;"&gt;"Small polygon stats: "&lt;/span&gt; + System.Environment.NewLine; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.textBox1.Text += GetStats(secondPolygon); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.textBox1.Text += GetWkt(secondPolygon); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// now calculate the difference between original and the big part (result should be the small part)&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPolygon4 pol2= (IPolygon4)((ITopologicalOperator)parcel).Difference(firstPolygon); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.textBox1.Text += &lt;span
 style="color: Maroon;"&gt;"Result Small polygon stats: "&lt;/span&gt; + System.Environment.NewLine; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.textBox1.Text += GetStats(pol2); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.textBox1.Text += GetWkt(pol2); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; GetStats(IPolygon pol)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; area = ((IArea)pol).Area; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; perimeter = ((ICurve)pol).Length; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;"area: "&lt;/span&gt; + area.ToString() + &lt;span
 style="color: Maroon;"&gt;", perimeter: "&lt;/span&gt; + perimeter.ToString() + System.Environment.NewLine; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; GetWkt(IPolygon pol)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; res = GeomHelper.aoGeomToWkt(pol, &lt;span
 style="color: Maroon;"&gt;false&lt;/span&gt;, &lt;span
 style="color: Maroon;"&gt;28992&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; res = res.Substring(&lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;, res.Length - &lt;span
 style="color: Maroon;"&gt;1&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; print = &lt;span
 style="color: Maroon;"&gt;"select geometry::STGeomFromText ('"&lt;/span&gt; + res + &lt;span
 style="color: Maroon;"&gt;"', 28992)"&lt;/span&gt; + Environment.NewLine; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; print; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; IPolygon GetPolygon(IPolygon4 input, &lt;span
 style="color: Blue;"&gt;bool&lt;/span&gt; first)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IGeometryBag exteriorRings = input.ExteriorRingBag; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumGeometry exteriorRingsEnum = exteriorRings &lt;span
 style="color: Blue;"&gt;as&lt;/span&gt; IEnumGeometry;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; exteriorRingsEnum.Reset(); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IRing firstRing = exteriorRingsEnum.Next() &lt;span
 style="color: Blue;"&gt;as&lt;/span&gt; IRing;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPointCollection pcFirst = (IPointCollection)firstRing; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IRing secondRing = exteriorRingsEnum.Next() &lt;span
 style="color: Blue;"&gt;as&lt;/span&gt; IRing;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPointCollection pcSecond = (IPointCollection)secondRing; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPolygon p = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; PolygonClass(); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;if&lt;/span&gt;(first)((IPointCollection)p).AddPointCollection(pcFirst); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;if&lt;/span&gt;(!first)((IPointCollection)p).AddPointCollection(pcSecond); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; p; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; IPolygon GetParcel() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; wkt = &lt;span
 style="color: Maroon;"&gt;"POLYGON ((180956.437 313716.998, 180954.359 313720.504, 180906.303 313741.156, 180896.82 313744.272, 180890.456 313748.17, 180831.49 313797.135, 180809.668 313816.098, 180776.418 313842.336, 180771.483 313846.102, 180746.934 313843.764, 180731.738 313840.386, 180717.32 313833.763, 180710.827 313828.438, 180704.982 313820.515, 180699.267 313811.813, 180698.488 313801.162, 180700.826 313793.889, 180705.539 313791.06, 180706.021 313790.771, 180710.156 313789.208, 180766.157 313768.042, 180825.515 313744.013, 180878.636 313724.271, 180945.593 313695.884, 180952.801 313693.358, 180956.437 313716.998))"&lt;/span&gt;; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IGeometryFactory factory = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; GeometryEnvironmentClass();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlGeometry g = SqlGeometry.Parse(wkt); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IGeometry geom2 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; PolygonClass(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; countout; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; factory.CreateGeometryFromWkbVariant(g.STAsBinary().Value, &lt;span
 style="color: Blue;"&gt;out&lt;/span&gt; geom2, &lt;span
 style="color: Blue;"&gt;out&lt;/span&gt; countout);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; geom2.SpatialReference = &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.GetProjectedSpatialReference(&lt;span
 style="color: Maroon;"&gt;28992&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; (IPolygon) geom2; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; IPolyline GetCutLine() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; line = &lt;span
 style="color: Maroon;"&gt;"LINESTRING(180955 313700,180920 313740)"&lt;/span&gt;; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IGeometryFactory factory = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; GeometryEnvironmentClass();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlGeometry g = SqlGeometry.Parse(line); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IGeometry geom2 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; PolylineClass(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; geom2.SpatialReference = &lt;span
 style="color: Blue;"&gt;this&lt;/span&gt;.GetProjectedSpatialReference(&lt;span
 style="color: Maroon;"&gt;28992&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; countout; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; factory.CreateGeometryFromWkbVariant(g.STAsBinary().Value, &lt;span
 style="color: Blue;"&gt;out&lt;/span&gt; geom2, &lt;span
 style="color: Blue;"&gt;out&lt;/span&gt; countout);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; (IPolyline)geom2; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; ISpatialReference GetProjectedSpatialReference(&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; pcsType)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ISpatialReferenceFactory pSRF = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; SpatialReferenceEnvironmentClass();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IProjectedCoordinateSystem m_ProjectedCoordinateSystem = pSRF.CreateProjectedCoordinateSystem(pcsType);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ISpatialReference spatialReference = (ISpatialReference)m_ProjectedCoordinateSystem; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; spatialReference; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;} &lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-2452378740774201366?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/2452378740774201366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/02/spikes-research-with-esri.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/2452378740774201366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/2452378740774201366'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/02/spikes-research-with-esri.html' title='Spikes: research with ESRI'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-3704613455644875484</id><published>2011-01-30T21:30:00.002+01:00</published><updated>2011-02-01T16:55:07.035+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PostGIS'/><category scheme='http://www.blogger.com/atom/ns#' term='intersections'/><category scheme='http://www.blogger.com/atom/ns#' term='precision'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Precision, the cause of spikes</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Precision, the cause of spikes&lt;/h1&gt;
&lt;br&gt;
This is a&amp;nbsp;follow-up on my last &lt;a
 href="/2011/01/sql-server-postgis-stdifference-and.html"&gt;blog&lt;/a&gt;.
The spikey effects we have seen are perfectly explainable and
understandable.&lt;br&gt;
&lt;br&gt;
What we did&amp;nbsp;was:&lt;br&gt;
&lt;ol&gt;
  &lt;li&gt;cut a parcel in two pieces&lt;/li&gt;
  &lt;ol type="a"&gt;
    &lt;li&gt;create a cutline and make a (nearly&amp;nbsp;linear)
cutting polygon of
it (using buffer)&lt;/li&gt;
    &lt;li&gt;subtract that cutline from the geometry, using
STDifference&lt;/li&gt;
  &lt;/ol&gt;
  &lt;li&gt;keep one piece, using STGeometryN&lt;/li&gt;
  &lt;li&gt;subtract that piece from the parcel, using STDifference&lt;/li&gt;
&lt;/ol&gt;
The result should be the discarded piece, but we got back two free
spikes
extra.&lt;br&gt;
&lt;br&gt;
This short blog will explain this a little more and, as a side note,
use just another SQL syntax for the same result.&lt;br&gt;&lt;br&gt;
&lt;h2&gt;Side note: &lt;span style="color: rgb(51, 51, 255);"&gt;with&lt;/span&gt;&lt;/h2&gt;
The query from my previous blog can be rewritten much more elegantly
using the &lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;with&lt;/span&gt;
syntax:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;with&lt;/span&gt; myquery &lt;span
 style="color: rgb(0, 0, 255);"&gt;as&lt;/span&gt; &lt;br&gt;(&lt;br&gt;&lt;span
 style="color: rgb(0, 0, 255);"&gt;&amp;nbsp;&amp;nbsp;select&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(0, 0, 255);"&gt;geometry&lt;/span&gt;::STGeomFromWKB(&lt;span
 style="color: rgb(0, 153, 0);"&gt;0x0103000000010000001A00000023DBF97EE316064146B6F3FDD32513415A643BDFD216064175931804E225134196438B6C52150641C976BE9F34261341F6285C8F06150641022B871641261341F853E3A5D3140641E17A14AE50261341B81E85EBFB120641A4703D8A142713414E6210584D120641AC1C5A64602713414E621058431106414E621058C9271341A01A2FDD1B11064121B07268D8271341F4FDD478571006411904560ECF271341448B6CE7DD0F06418195438BC1271341F6285C8F6A0F06413BDF4F0DA72713410E2DB29D360F06416F1283C091271341E5D022DB070F0641F6285C0F7227134160E5D022DA0E06416F1283404F271341448B6CE7D30E0641F853E3A52427134154E3A59BE60E06411904568E07271341643BDF4F0C0F0641D7A3703DFC2613414A0C022B100F064125068115FB26134191ED7C3F310F0641B6F3FDD4F42613414C378941F11006414A0C022BA0261341EC51B81ECC1206413BDF4F0D40261341022B87167514064125068115F1251341B4C876BE8C160641C74B37897F25134121B07268C6160641508D976E7525134123DBF97EE316064146B6F3FDD3251341&lt;/span&gt;,28992)&lt;br&gt;&lt;span
 style="color: rgb(0, 0, 255);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;as&lt;/span&gt; parcel,&lt;br&gt;&lt;span
 style="color: rgb(0, 0, 255);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;geometry&lt;/span&gt;::STGeomFromText('&lt;span
 style="color: red;"&gt;LINESTRING(180955 313700,180920 313740)&lt;/span&gt;', &lt;span
 style="color: rgb(0, 153, 0);"&gt;28992&lt;/span&gt;).STBuffer(&lt;span
 style="color: rgb(0, 153, 0);"&gt;0.1&lt;/span&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: rgb(0, 0, 255);"&gt;as&lt;/span&gt; cutline&lt;br&gt;)&lt;br&gt;&lt;span
 style="color: rgb(0, 0, 255);"&gt;select&lt;/span&gt; parcel.STDifference((&lt;span
 style="color: rgb(0, 0, 255);"&gt;select&lt;/span&gt; parcel.STDifference(cutline).STGeometryN(&lt;span
 style="color: rgb(0, 153, 0);"&gt;2&lt;/span&gt;) &lt;span
 style="color: rgb(0, 0, 255);"&gt;from&lt;/span&gt; myquery))&lt;br&gt;&lt;span
 style="color: rgb(0, 0, 255);"&gt;from&lt;/span&gt; myquery&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
The &lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;with&lt;/span&gt;
clause is useful to avoid repeating pieces (as&amp;nbsp;having the WKB
twice), and is essential to do recursive queries. You define an inlined
viewy thingy (here "myquery") and use it.&lt;br&gt;
&lt;br&gt;
Both SQL Server and PostGreSQL support &lt;span
 style="font-weight: bold; color: rgb(51, 51, 255);"&gt;with&lt;/span&gt;
queries. See also this &lt;a href="http://gennick.com/with.html"&gt;link&lt;/a&gt;
which explains&amp;nbsp;&lt;span
 style="font-weight: bold; color: rgb(51, 51, 255);"&gt;with&lt;/span&gt;
in depth.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Floating point precision&lt;span
 style="color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/h2&gt;
Floating
points are really awful. Everyone knows that if you divide one by six
(1/6) and multiply the result with six ((1/6) * 6) you should get one
back. However, with floating points this is not always the case. You
might get 0.9999999 back. If you try it, you might also get the correct
1.0 back. That is (according to this &lt;a
 href="http://books.google.com/books?isbn=9780123742971&amp;amp;printsec=frontcover"&gt;book&lt;/a&gt;)
because intermediate results are stored in the floating point register
of the CPU. So it is by chance that it is right. In reality it will be
wrong.&lt;br&gt;
&lt;br&gt;
See also this &lt;a
 href="http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/"&gt;link&lt;/a&gt;
and scroll to "Rounding errors can play havoc with math-intense
programs". Adding ten 0.1 values will result into 0.99999999999999989.
I repeated this and indeed this is the case with a double. With a float
the result is 1.0000001192092896. With ttmath it is 1.0, but as soon as
you do the same trick with eleven 1/11 additions, you might get
0.9999999999999999999999999999999 back, or 1.0, depending on which
precision you specify. Using Boost.Rational you get always 1/1,
guaranteed, because it calculates in another way. It uses fractions and
keeps fractions all the time. That is great in this use case.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;What then caused the spikes&lt;/h2&gt;
Now
that we realize again that floating points are awful, we investigate
how
imprecision causes the spikes. The damage happens in the first phase.
The first STDifference is used to cut the parcel into two pieces.&lt;br&gt;
&lt;br&gt;
See
the picture below. The grid is the so-called floating point grid. The
smallest difference in a 32 bits floating point value (&lt;a href="http://www.cprogramming.com/tutorial/floating_point/understanding_floating_point_representation.html"&gt;1.175e-38&lt;/a&gt;) is
depicted. Any point (with float) must be located on one of the
gridpoints. &lt;span style="font-style: italic;"&gt;(In reality
the FP-grid
is irregular, but the idea will be clear).&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
So in this case (in most cases), the intersection point happens
to fall between the gridpoints... All the vertices of both input
polygons are located on the gridpoints, of course. But the &lt;span
 style="font-weight: bold;"&gt;real &lt;/span&gt;intersection
point does not. It is rounded to one of
the four gridpoints. It is just by chance to which one it is rounded.
So the &lt;span style="font-weight: bold;"&gt;rounded&lt;/span&gt;
intersection point is located on a gridpoint.&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 768px; height: 488px;" alt="a"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TUV3dWGb8JI/AAAAAAAABhY/2wFIJqKKiAM/precision2_a.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Suppose it rounds to the&amp;nbsp;point labeled "3". We then get a
resulting
polygon as partly depicted here:&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 768px; height: 414px;" alt="b"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TUV3dlmRyOI/AAAAAAAABhc/C3zRkQbYpIc/precision2_b.png"&gt;&lt;br&gt;
&lt;br&gt;
The
resulting polygon (in blue) is too small. There is a small piece of the
original polygon which is
not covered by this piece, at the north side, upperleft of point 3.
Subtract this resulting polygon from the original and of course, you
will get the spike. There is also a similar small piece at the east
side but that will not create a visual effect in this use case.&lt;br&gt;
&lt;br&gt;
There is no obvious solution. It is the same as adding ten times
0.1. You get too much or too little. These spikes are too little in the
first phase, and after the second difference, the two resulting spikes
are a bit too much. This explains that sometimes you get zero,
sometimes you get one and sometimes you get two spikes. It is by
chance. If the rounding would go to point "1" in the picture above,
there would be no spike there.&lt;br&gt;
&lt;br&gt;
The spikes are not the result of flawed logic, or wrong decisions
somewhere. It is just the rounding.&lt;br&gt;
&lt;br&gt;
Use &lt;a href="http://www.ttmath.org/"&gt;ttmath&lt;/a&gt;
if you want to minimize the chance on it. Or work around it, e.g. by
buffering the result with a small value e.g. -0.000001. Boost.Geometry
now has some algorithms to find
spikes and remove them.&lt;br&gt;&lt;br&gt;
By the way, the nice trick on cutting a parcel into two pieces was introduced in our project by our partners from &lt;a href="http://www.b3partners.nl"&gt;B3Partners&lt;/a&gt;. The project where this study is from extracted is the &lt;a href="http://www.portaalnatuurenlandschap.nl"&gt;Portaal Natuur en Landschap&lt;/a&gt;

&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
In this use case, spikes are&amp;nbsp;the geometric visualization of
floating point imprecision.&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-3704613455644875484?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/3704613455644875484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/01/precision-cause-of-spikes.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/3704613455644875484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/3704613455644875484'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/01/precision-cause-of-spikes.html' title='Precision, the cause of spikes'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_6zrdK5O_LIg/TUV3dWGb8JI/AAAAAAAABhY/2wFIJqKKiAM/s72-c/precision2_a.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-992391328784970760</id><published>2011-01-28T21:45:00.011+01:00</published><updated>2011-01-29T00:03:11.358+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PostGIS'/><category scheme='http://www.blogger.com/atom/ns#' term='boolean operations'/><category scheme='http://www.blogger.com/atom/ns#' term='precision'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>SQL Server, PostGIS, STDifference and Precision</title><content type='html'>&lt;br&gt;
&lt;h1&gt;SQL Server, PostGIS, STDifference and Precision&lt;/h1&gt;
&lt;br&gt;
Today I encountered a problem related to the OGC difference function. I
will describe this problem in this blog. I created a sort
of minimal sample, without database, and present that here.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;The problem&lt;/h2&gt;
The problem I encountered is precision: both SQL Server (where I
encountered it) and
PostGIS (where I verified it) do not handle the situation described
here sufficiently. The results is a polygon with &lt;span
 style="font-style: italic; color: rgb(51, 51, 255);"&gt;&lt;span
 style="font-weight: bold;"&gt;two spikes&lt;/span&gt;&lt;/span&gt;
which should &lt;span style="font-weight: bold; font-style: italic;"&gt;not&lt;/span&gt;&lt;span
 style="font-style: italic;"&gt; &lt;/span&gt;be there. The
cause must be imprecision of floating point types. The message is: &lt;span
 style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;&lt;span style="color: red;"&gt;be
warned&lt;/span&gt;!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
The situation is as following: there is a &lt;span
 style="font-weight: bold; font-style: italic;"&gt;parcel&lt;/span&gt;.
That parcel is cut
into two pieces (I will explain below how). One piece is thrown away,
the other piece is kept. That kept piece is subtracted from the
original parcel. What you would expect is having the original piece
that was earlier thrown away. But what is happening is that you
get one or two spikes extra...&lt;br&gt;
&lt;br&gt;
The&amp;nbsp;parcel and the cutline are shown here:&lt;br&gt;
&lt;img style="width: 571px; height: 639px;" alt="cl"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TUMnjbfAyRI/AAAAAAAABhI/7aYgROMq6NM/blog_difference_parcel_cutline.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Cutting into two pieces&lt;/h2&gt;
We cut (for this experiment) the
polygon into two pieces by buffering the cutline, and subtracting (with
STDifference) that
from the parcel. The cutline is shown in the figure above as the dotted
red line. Then we
keep one of the two resulting polygons using the STGeometryN function.
By trying we get the left piece
which we want to keep by index 2.&lt;br&gt;
&lt;br&gt;
So this piece of SQL is, for SQL Server:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;select &lt;span
 style="color: rgb(51, 51, 255);"&gt;geometry&lt;/span&gt;::STGeomFromWKB(&lt;span
 style="color: rgb(0, 153, 0);"&gt;0x0103000000010000001A00000023DBF97EE316064146B6F3FDD32513415A643BDFD216064175931804E225134196438B6C52150641C976BE9F34261341F6285C8F06150641022B871641261341F853E3A5D3140641E17A14AE50261341B81E85EBFB120641A4703D8A142713414E6210584D120641AC1C5A64602713414E621058431106414E621058C9271341A01A2FDD1B11064121B07268D8271341F4FDD478571006411904560ECF271341448B6CE7DD0F06418195438BC1271341F6285C8F6A0F06413BDF4F0DA72713410E2DB29D360F06416F1283C091271341E5D022DB070F0641F6285C0F7227134160E5D022DA0E06416F1283404F271341448B6CE7D30E0641F853E3A52427134154E3A59BE60E06411904568E07271341643BDF4F0C0F0641D7A3703DFC2613414A0C022B100F064125068115FB26134191ED7C3F310F0641B6F3FDD4F42613414C378941F11006414A0C022BA0261341EC51B81ECC1206413BDF4F0D40261341022B87167514064125068115F1251341B4C876BE8C160641C74B37897F25134121B07268C6160641508D976E7525134123DBF97EE316064146B6F3FDD3251341&lt;/span&gt;,28992)&lt;br&gt;.STDifference(&lt;span
 style="color: rgb(51, 51, 255);"&gt;geometry&lt;/span&gt;::STGeomFromText(&lt;span
 style="color: red;"&gt;'LINESTRING(180955 313700,180920 313740)'&lt;/span&gt;,&lt;span
 style="color: rgb(0, 51, 51);"&gt; &lt;span
 style="color: rgb(51, 51, 255);"&gt;28992&lt;/span&gt;&lt;/span&gt;).STBuffer(0.1)).STGeometryN(2)&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;br&gt;
And for PostGIS it is:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;select ST_GeometryN(ST_Difference(&lt;br&gt;ST_SetSRID('&lt;span
 style="color: rgb(0, 153, 0);"&gt;0103000000010000001A00000023DBF97EE316064146B6F3FDD32513415A643BDFD216064175931804E225134196438B6C52150641C976BE9F34261341F6285C8F06150641022B871641261341F853E3A5D3140641E17A14AE50261341B81E85EBFB120641A4703D8A142713414E6210584D120641AC1C5A64602713414E621058431106414E621058C9271341A01A2FDD1B11064121B07268D8271341F4FDD478571006411904560ECF271341448B6CE7DD0F06418195438BC1271341F6285C8F6A0F06413BDF4F0DA72713410E2DB29D360F06416F1283C091271341E5D022DB070F0641F6285C0F7227134160E5D022DA0E06416F1283404F271341448B6CE7D30E0641F853E3A52427134154E3A59BE60E06411904568E07271341643BDF4F0C0F0641D7A3703DFC2613414A0C022B100F064125068115FB26134191ED7C3F310F0641B6F3FDD4F42613414C378941F11006414A0C022BA0261341EC51B81ECC1206413BDF4F0D40261341022B87167514064125068115F1251341B4C876BE8C160641C74B37897F25134121B07268C6160641508D976E7525134123DBF97EE316064146B6F3FDD3251341&lt;/span&gt;'&lt;br&gt; ::geometry, &lt;span
 style="color: rgb(51, 51, 255);"&gt;28992&lt;/span&gt;)&lt;br&gt;, (ST_Buffer(ST_GeomFromText('&lt;span
 style="color: red;"&gt;LINESTRING(180955 313700,180920 313740)&lt;/span&gt;',&lt;span
 style="color: rgb(51, 51, 255);"&gt;28992&lt;/span&gt;),0.1))), 2)&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
Note that the 28992 is just an SRID of a coordinate system (the Dutch),
it probably works (or better stated: does not work) with any coordinate
system. The result is this:&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 493px; height: 556px;" alt="pieces"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TUMnjsx0vfI/AAAAAAAABhM/7lgZjwhezXA/blog_difference_parcel_piece.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Subtracting one of the pieces from the original&lt;/h2&gt;
After cutting we subtract the piece we kept from the original parcel.
This will result in&amp;nbsp;the other
piece. In fact we get the area covered by the small buffer as well, but
that
is hardly visible, and is not important for this story.&lt;br&gt;
&lt;br&gt;
This is how it should look like:&lt;br&gt;
&lt;img style="width: 594px; height: 634px;" alt="results"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TUMnjzfJ7PI/AAAAAAAABhQ/saUTJQcAp7g/blog_difference_parcel_results.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
And this is the complete query in SQL Server:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;select&lt;br&gt;geometry::STGeomFromWKB(&lt;span
 style="color: rgb(0, 153, 0);"&gt;0x0103000000010000001A00000023DBF97EE316064146B6F3FDD32513415A643BDFD216064175931804E225134196438B6C52150641C976BE9F34261341F6285C8F06150641022B871641261341F853E3A5D3140641E17A14AE50261341B81E85EBFB120641A4703D8A142713414E6210584D120641AC1C5A64602713414E621058431106414E621058C9271341A01A2FDD1B11064121B07268D8271341F4FDD478571006411904560ECF271341448B6CE7DD0F06418195438BC1271341F6285C8F6A0F06413BDF4F0DA72713410E2DB29D360F06416F1283C091271341E5D022DB070F0641F6285C0F7227134160E5D022DA0E06416F1283404F271341448B6CE7D30E0641F853E3A52427134154E3A59BE60E06411904568E07271341643BDF4F0C0F0641D7A3703DFC2613414A0C022B100F064125068115FB26134191ED7C3F310F0641B6F3FDD4F42613414C378941F11006414A0C022BA0261341EC51B81ECC1206413BDF4F0D40261341022B87167514064125068115F1251341B4C876BE8C160641C74B37897F25134121B07268C6160641508D976E7525134123DBF97EE316064146B6F3FDD3251341&lt;/span&gt;,&lt;span
 style="color: rgb(51, 51, 255);"&gt;28992&lt;/span&gt;)&lt;br&gt;.STDifference&lt;br&gt;(&lt;br&gt;&amp;nbsp; (&lt;br&gt; select &lt;br&gt; geometry::STGeomFromWKB(&lt;span
 style="color: rgb(0, 153, 0);"&gt;0x0103000000010000001A00000023DBF97EE316064146B6F3FDD32513415A643BDFD216064175931804E225134196438B6C52150641C976BE9F34261341F6285C8F06150641022B871641261341F853E3A5D3140641E17A14AE50261341B81E85EBFB120641A4703D8A142713414E6210584D120641AC1C5A64602713414E621058431106414E621058C9271341A01A2FDD1B11064121B07268D8271341F4FDD478571006411904560ECF271341448B6CE7DD0F06418195438BC1271341F6285C8F6A0F06413BDF4F0DA72713410E2DB29D360F06416F1283C091271341E5D022DB070F0641F6285C0F7227134160E5D022DA0E06416F1283404F271341448B6CE7D30E0641F853E3A52427134154E3A59BE60E06411904568E07271341643BDF4F0C0F0641D7A3703DFC2613414A0C022B100F064125068115FB26134191ED7C3F310F0641B6F3FDD4F42613414C378941F11006414A0C022BA0261341EC51B81ECC1206413BDF4F0D40261341022B87167514064125068115F1251341B4C876BE8C160641C74B37897F25134121B07268C6160641508D976E7525134123DBF97EE316064146B6F3FDD3251341&lt;/span&gt;,&lt;span
 style="color: rgb(51, 51, 255);"&gt;28992&lt;/span&gt;)&lt;br&gt; .STDifference(geometry::STGeomFromText('&lt;span
 style="color: red;"&gt;LINESTRING(180955 313700,180920 313740)&lt;/span&gt;', &lt;span
 style="color: rgb(51, 51, 255);"&gt;28992&lt;/span&gt;).STBuffer(0.1)).STGeometryN(2)&lt;br&gt; )&lt;br&gt;)&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
And in PostGIS:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;br&gt;select ST_Perimeter(ST_Difference(&lt;br&gt;ST_SetSRID('&lt;span
 style="color: rgb(0, 153, 0);"&gt;0103000000010000001A00000023DBF97EE316064146B6F3FDD32513415A643BDFD216064175931804E225134196438B6C52150641C976BE9F34261341F6285C8F06150641022B871641261341F853E3A5D3140641E17A14AE50261341B81E85EBFB120641A4703D8A142713414E6210584D120641AC1C5A64602713414E621058431106414E621058C9271341A01A2FDD1B11064121B07268D8271341F4FDD478571006411904560ECF271341448B6CE7DD0F06418195438BC1271341F6285C8F6A0F06413BDF4F0DA72713410E2DB29D360F06416F1283C091271341E5D022DB070F0641F6285C0F7227134160E5D022DA0E06416F1283404F271341448B6CE7D30E0641F853E3A52427134154E3A59BE60E06411904568E07271341643BDF4F0C0F0641D7A3703DFC2613414A0C022B100F064125068115FB26134191ED7C3F310F0641B6F3FDD4F42613414C378941F11006414A0C022BA0261341EC51B81ECC1206413BDF4F0D40261341022B87167514064125068115F1251341B4C876BE8C160641C74B37897F25134121B07268C6160641508D976E7525134123DBF97EE316064146B6F3FDD3251341&lt;/span&gt;'::geometry,&lt;span
 style="color: rgb(51, 51, 255);"&gt;28992&lt;/span&gt;)&lt;br&gt;,&lt;br&gt;(select ST_GeometryN(ST_Difference(&lt;br&gt;ST_SetSRID('&lt;span
 style="color: rgb(0, 153, 0);"&gt;0103000000010000001A00000023DBF97EE316064146B6F3FDD32513415A643BDFD216064175931804E225134196438B6C52150641C976BE9F34261341F6285C8F06150641022B871641261341F853E3A5D3140641E17A14AE50261341B81E85EBFB120641A4703D8A142713414E6210584D120641AC1C5A64602713414E621058431106414E621058C9271341A01A2FDD1B11064121B07268D8271341F4FDD478571006411904560ECF271341448B6CE7DD0F06418195438BC1271341F6285C8F6A0F06413BDF4F0DA72713410E2DB29D360F06416F1283C091271341E5D022DB070F0641F6285C0F7227134160E5D022DA0E06416F1283404F271341448B6CE7D30E0641F853E3A52427134154E3A59BE60E06411904568E07271341643BDF4F0C0F0641D7A3703DFC2613414A0C022B100F064125068115FB26134191ED7C3F310F0641B6F3FDD4F42613414C378941F11006414A0C022BA0261341EC51B81ECC1206413BDF4F0D40261341022B87167514064125068115F1251341B4C876BE8C160641C74B37897F25134121B07268C6160641508D976E7525134123DBF97EE316064146B6F3FDD3251341&lt;/span&gt;'::geometry,&lt;span
 style="color: rgb(51, 51, 255);"&gt;28992&lt;/span&gt;)&lt;br&gt;,(ST_Buffer(ST_GeomFromText(&lt;span
 style="color: red;"&gt;'LINESTRING(180955 313700,180920 313740)&lt;/span&gt;', &lt;span
 style="color: rgb(51, 51, 255);"&gt;28992&lt;/span&gt;),0.1))),2)&lt;br&gt;)))&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;h2&gt;Results&lt;/h2&gt;
To my surprise I got two spikes in SQL Server. To verify this, I looked
into PostGIS. I got two spikes as well. First I
thought it was caused by precision, going to WKT and back. But also if
you use WKB, or if you use the geometry from the underlying database
(not shown here), you will get the same. So it is the imprecision of
the handling. When varying the cutline a bit (changing 180955 to
180960), I get one spike in SQL Server and still two in PostGIS.&lt;br&gt;
&lt;br&gt;
The spikes are shown here, bordering the blue result:&lt;br&gt;
&lt;img style="width: 530px; height: 580px;" alt="spikes"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TUMnkOdWo4I/AAAAAAAABhU/m8RIO4iTNKI/blog_difference_parcel_spikes.png"&gt;&lt;br&gt;
&lt;br&gt;
The &lt;span style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;perimeter&lt;/span&gt;&lt;/span&gt;
of the result is interesting. The result, without spikes, should be
92.5 meter. But including the spikes it is 151.792871568541 (in SQL
Server, using the function .STLength() and 151.792880859545 (in
PostGIS, using the function ST_Perimeter(...). &lt;br&gt;
&lt;br&gt;
The &lt;span style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;area&lt;/span&gt; &lt;/span&gt;is
everywhere about 295.4 square meter, with or without spikes, indicating
that the spikes have an area about zero (so those are real spikes).&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Why would you do such a thing... Creating a parcel, cutting, throwing
away one, subtracting and getting the&amp;nbsp;other one...&lt;br&gt;
&lt;br&gt;
Well, I was just testing our application.
Our application has WebGIS functionality to create parcels. And to cut
parcels into two pieces. And to throw away pieces. And to fill-up space
which is left from a parcel and a piece. So just this scenario. And to
my annoyance, often you get spikes! This project is done with SQL
Server, and we get spikes. But this little research shows that, would
we have done it with PostGIS, we would have had resulting spikes as
well.&lt;br&gt;
&lt;br&gt;
It is as a simple mathematical exercise. We cut 5 into two pieces, 3
and 2. We throw away the 2 and keep the 3. We subtract 3 from our 5.
And we get the 2 back, of course. In geometry we subtract (difference)
twice but that is just because the &lt;span style="font-weight: bold;"&gt;cut&lt;/span&gt;
is not an OGC operation. So we trick it.&lt;br&gt;&lt;br&gt;
Note that I didn't get this &lt;b&gt;just once&lt;/b&gt;. I got it several times for different geometries. Note also that it can easily be solved using a STBuffer of -0.00001 on the resulting polygon, which will eliminate the spikes and have no visual impact (it &lt;b&gt;has&lt;/b&gt; an impact though...).


&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;With Boost.Geometry&lt;br&gt;
&lt;/h2&gt;
Of course I was curious what Boost.Geometry would do with this.&lt;br&gt;
&lt;br&gt;
The buffer of Boost.Geometry is not completely implemented, so I create
the buffer in SQL Server,
saving the WKB. &lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;select &lt;span
 style="color: rgb(51, 51, 255);"&gt;geometry&lt;/span&gt;::STGeomFromText('&lt;span
 style="color: red;"&gt;LINESTRING(180955 313700,180920 313740)&lt;/span&gt;', &lt;span
 style="color: rgb(51, 51, 255);"&gt;28992&lt;/span&gt;).STBuffer(0.1).STAsBinary()&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
and draft some C++ code:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; T&amp;gt; &lt;br&gt;&lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; test_difference_parcel_precision() &lt;br&gt;{&lt;br&gt;&lt;/span&gt;&lt;span
 style="color: Black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span
 style="color: Black;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;namespace&lt;/span&gt; bg = boost::geometry;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; bg::model::d2::point_xy&amp;lt;T&amp;gt; point_type; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; bg::model::polygon&amp;lt;point_type&amp;gt; polygon_type;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::vector&amp;lt;boost::uint8_t&amp;gt; byte_vector;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;polygon_type parcel, buffer; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;byte_vector wkb; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bg::hex2wkb(&lt;span
 style="color: Maroon;"&gt;"0103000000010000001A00000023DBF97EE316064146B6F3FDD32513415A643BDFD216064175931804E225134196438B6C52150641C976BE9F34261341F6285C8F06150641022B871641261341F853E3A5D3140641E17A14AE50261341B81E85EBFB120641A4703D8A142713414E6210584D120641AC1C5A64602713414E621058431106414E621058C9271341A01A2FDD1B11064121B07268D8271341F4FDD478571006411904560ECF271341448B6CE7DD0F06418195438BC1271341F6285C8F6A0F06413BDF4F0DA72713410E2DB29D360F06416F1283C091271341E5D022DB070F0641F6285C0F7227134160E5D022DA0E06416F1283404F271341448B6CE7D30E0641F853E3A52427134154E3A59BE60E06411904568E07271341643BDF4F0C0F0641D7A3703DFC2613414A0C022B100F064125068115FB26134191ED7C3F310F0641B6F3FDD4F42613414C378941F11006414A0C022BA0261341EC51B81ECC1206413BDF4F0D40261341022B87167514064125068115F1251341B4C876BE8C160641C74B37897F25134121B07268C6160641508D976E7525134123DBF97EE316064146B6F3FDD3251341"&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::back_inserter(wkb)); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bg::read_wkb(wkb.begin(), wkb.end(), parcel); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;byte_vector wkb; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bg::hex2wkb(&lt;br&gt;&lt;span
 style="color: Maroon;"&gt;"01030000000100000083000000000032FCD716064100009E998F25134100000706D81606410040A4998F2513410000DA0FD816064100C0E6998F2513410000A819D81606410080659A8F25134100806A23D816064100C0209B8F25134100801E2DD81606410080189C8F2513410000BE36D816064100404D9D8F25134100004540D816064100C0BE9E8F2513410000AF49D816064100806DA08F2513410000F752D8160641008059A28F2513410000195CD816064100C082A48F25134100800F65D81606410080E9A68F2513410000D66DD816064100408EA98F25134100006876D816064100C070AC8F2513410000C17ED8160641000091AF8F2513410080DC86D816064100C0EFB28F25134100009E8ED816064100C081B68F2513410080EC95D816064100803ABA8F2513410080C79CD8160641000018BE8F25134100002FA3D8160641008017C28F251341008022A9D8160641000037C68F2513410080A1AED8160641000074CA8F2513410000ACB3D81606410040CCCE8F251341000042B8D816064100403DD38F251341000062BCD81606410000C5D78F25134100000DC0D8160641000061DC8F251341000042C3D816064100000FE18F251341000001C6D81606410080CCE58F251341008049C8D8160641004097EA8F25134100001BCAD816064100006DEF8F251341008075CBD816064100804BF48F251341008058CCD8160641004030F98F2513410000C4CCD8160641000019FE8F2513410080B7CCD81606410080030390251341008032CCD81606410000ED0790251341000035CBD81606410000D40C902513410080BEC9D81606410040B511902513410000CFC7D816064100408F1690251341008065C5D816064100005F1B90251341008082C2D81606410080222090251341000025BFD81606410080D7249025134100004DBBD816064100807B29902513410080FAB6D816064100800C2E9025134100002DB2D816064100C08732902513410080E3ACD81606410000EB369025134100801EA7D81606410000343B902513410000DEA0D81606410080603F902513410080209AD816064100406E43902513410080209AC015064100406E43302613410080FC92C015064100004F473026134100008B8BC01506410040F64A302613410000D083C015064100C0634E302613410000D17BC0150641008097513026134100009273C015064100409154302613410000186BC015064100C050573026134100806762C01506410000D6593026134100808559C01506410000215C3026134100007650C01506410000315E3026134100003E47C015064100800660302613410000E23DC01506410000A1613026134100006734C015064100800063302613410080D12AC015064100C024643026134100002621C015064100800D653026134100006917C015064100C0BA653026134100809F0DC015064100402C66302613410000CE03C015064100006266302613410000F9F9BF15064100C05B6630261341000026F0BF1506410040196630261341000058E6BF15064100809A6530261341008095DCBF1506410040DF64302613410080E1D2BF1506410080E76330261341000042C9BF15064100C0B262302613410000BBBFBF1506410040416130261341000051B6BF1506410080925F30261341000009ADBF1506410080A65D302613410000E7A3BF15064100407D5B302613410080F09ABF150641008016593026134100002A92BF15064100C071563026134100009889BF15064100408F533026134100003F81BF15064100006F503026134100802379BF1506410040104D3026134100006271BF15064100407E49302613410080136ABF1506410080C5453026134100803863BF1506410000E841302613410000D15CBF1506410080E83D302613410080DD56BF1506410000C9393026134100805E51BF15064100008C35302613410000544CBF15064100C03331302613410000BE47BF15064100C0C22C3026134100009E43BF15064100003B28302613410000F33FBF15064100009F23302613410000BE3CBF1506410000F11E302613410000FF39BF1506410080331A302613410080B637BF15064100C06815302613410000E535BF150641000093103026134100808A34BF1506410080B40B302613410080A733BF15064100C0CF063026134100003C33BF1506410000E7013026134100804833BF1506410080FCFC2F2613410080CD33BF150641000013F82F2613410000CB34BF15064100002CF32F26134100804136BF15064100C04AEE2F26134100003138BF15064100C070E92F26134100809A3ABF1506410000A1E42F26134100807D3DBF1506410080DDDF2F2613410000DB40BF150641008028DB2F2613410000B344BF150641008084D62F26134100800549BF1506410080F3D12F2613410000D34DBF150641004078CD2F26134100801C53BF150641000015C92F2613410080E158BF1506410000CCC42F2613410000225FBF15064100809FC02F2613410080DF65BF15064100C091BC2F2613410080DF65D716064100C091BC8F2513410080036DD71606410000B1B88F25134100007574D716064100C009B58F2513410000307CD716064100409CB18F25134100002F84D7160641008068AE8F25134100006E8CD716064100C06EAB8F2513410000E894D71606410040AFA88F2513410080989DD716064100002AA68F25134100807AA6D71606410000DFA38F25134100008AAFD71606410000CFA18F2513410000C2B8D71606410080F99F8F25134100001EC2D716064100005F9E8F251341000099CBD71606410080FF9C8F25134100802ED5D71606410040DB9B8F2513410000DADED71606410080F29A8F251341000097E8D71606410040459A8F251341008060F2D716064100C0D3998F251341000032FCD716064100009E998F251341"&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::back_inserter(wkb)); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bg::read_wkb(wkb.begin(), wkb.end(), buffer); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bg::correct(parcel); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bg::correct(buffer); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::vector&amp;lt;polygon_type&amp;gt; pieces; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bg::difference(parcel, buffer, pieces); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::vector&amp;lt;polygon_type&amp;gt; filled_out; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bg::difference(parcel, pieces.back(), filled_out); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; std::setprecision(16) &amp;lt;&amp;lt; bg::wkt(filled_out.front()) &amp;lt;&amp;lt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;endl&lt;/span&gt;; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; bg::area(filled_out.front()) &amp;lt;&amp;lt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;endl&lt;/span&gt;; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; bg::perimeter(filled_out.front()) &amp;lt;&amp;lt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;endl&lt;/span&gt;; &lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
We are using WKB here to not loose precision. I run this with three
different numeric types (float, double and ttmath high precision).
And&amp;nbsp;&lt;span style="font-weight: bold;"&gt;that&lt;/span&gt;
is the essence of Boost.Geometry! Not one type! Many types! All types!&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; main(&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;char&lt;/span&gt;* [])&lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;test_difference_parcel_precision&amp;lt;&lt;span
 style="color: Blue;"&gt;float&lt;/span&gt;&amp;gt;(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;test_difference_parcel_precision&amp;lt;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt;&amp;gt;(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;test_difference_parcel_precision&amp;lt;ttmath_big&amp;gt;(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;; &lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
Using these three types we get:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;float: one spike, perimeter 136.28&lt;br&gt;
  &lt;/li&gt;
  &lt;li&gt;double: two spikes, perimeter 151.793&lt;br&gt;
  &lt;/li&gt;
  &lt;li&gt;ttmath: zero spikes, correct result, perimeter
92.50548050416428971188559805054187252&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;br&gt;
&lt;/h2&gt;
&lt;h2&gt;Conclusions&lt;br&gt;
&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;SQL Server is not perfect, it can cause spikey features&lt;br&gt;
  &lt;/li&gt;
  &lt;li&gt;PostGIS is not perfect, it can cause spikey features&lt;br&gt;
  &lt;/li&gt;
  &lt;li&gt;The cause is not WKT, nor it is WKB&lt;br&gt;
  &lt;/li&gt;
  &lt;li&gt;Boost.Geometry, using double, is not perfect because it
causes the same spikey features&lt;br&gt;
  &lt;/li&gt;
  &lt;li&gt;Boost.Geometry, using ttmath, gives the correct results&lt;br&gt;
  &lt;/li&gt;
  &lt;li&gt;Boost.Geometry, using float, gives one spikey feature&lt;br&gt;
  &lt;/li&gt;
  &lt;li&gt;Changing the cutline a bit causes only one spikey feature
within SQL Server, still two in PostGIS, and zero in Boost.Geometry
(with all numeric types).&lt;br&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;span
 style="font-weight: bold; font-style: italic; color: red;"&gt;Be aware
of floating point precision&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-992391328784970760?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/992391328784970760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/01/sql-server-postgis-stdifference-and.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/992391328784970760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/992391328784970760'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/01/sql-server-postgis-stdifference-and.html' title='SQL Server, PostGIS, STDifference and Precision'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_6zrdK5O_LIg/TUMnjbfAyRI/AAAAAAAABhI/7aYgROMq6NM/s72-c/blog_difference_parcel_cutline.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-3227098173914366290</id><published>2011-01-09T23:59:00.005+01:00</published><updated>2011-01-10T22:13:51.424+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='world'/><category scheme='http://www.blogger.com/atom/ns#' term='countries'/><category scheme='http://www.blogger.com/atom/ns#' term='shapefile'/><title type='text'>Free Shapefiles of Countries of the World (4)</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Free Shapefiles of&amp;nbsp;Countries of the World (4)&lt;/h1&gt;
&lt;br&gt;
There was the suggestion to look at &lt;a
 href="http://www.gadm.org/world"&gt;gadm&lt;/a&gt; (Global
Administrative Areas), thanks for this suggestion. This&amp;nbsp;blog
handles this new source in detail. Note that some sources are
apparently hard to find, i.e. not found immediately by googling to
"world country shapefiles" or similar. I'm glad that this blog appears
now in the first 10 results, so hope to provide by this an index to
world country shapefiles.&lt;br&gt;
&lt;br&gt;
Look also at &amp;nbsp;&lt;a
 href="/2010/12/free-shapefile-of-countries-of-world.html"&gt;part
1&lt;/a&gt;,&amp;nbsp; &lt;a
 href="/2010/12/free-shapefiles-of-of-world-2.html"&gt;part 2&lt;/a&gt;,
and &lt;a href="/2010/12/free-shapefiles-of-of-world-3.html"&gt;part
3&lt;/a&gt; of this blog.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;Large&lt;/span&gt;&lt;/h2&gt;
This&amp;nbsp;newly found shapefile is very interesting. The first
observation is that it is rather large, the zipfile is 158MB and takes
several minutes of downloading. Unzipped the triplet (shp,shx,dbf) is
almost half a gigabyte. When we zoom in, we see how this is caused, it
is a shapefile taken from a grid:&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 500px; height: 427px;" alt="elba"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TSoxGBgYEjI/AAAAAAAABgM/C488wqBFvQ0/w13_gridded.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
The image above is a piece of the island Elba, the magenta line is the
kml-ified shapefile displayed in Google Earth (yes, I like Google
Earth).&lt;br&gt;
&lt;br&gt;
I don't know if I like all those cornery borders... At least, it is not
necessary to keep them, why&amp;nbsp;are they not dropped or
generalized away?&lt;br&gt;
&lt;br&gt;
Anyway, if we zoom out a little again, the borders seem to be
reasonably accurate at the first sight, here is the whole island Elba:&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 500px; height: 311px;" alt="elba2"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TSoxGSyz9TI/AAAAAAAABgQ/PJoiqZLPAqE/w13_elba.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;Vatican City
and Liechtenstein&lt;/span&gt;&lt;/h2&gt;
In last blog I described the small countries in and around Italy. So I
shortly redo this for this new datasource. The &lt;span
 style="font-weight: bold; font-style: italic;"&gt;gadm&lt;/span&gt;
contains really the most accurate approximatino of Vatican City,
compared with Google Earth as still our Single Point of Truth...&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 500px; height: 424px;" alt="vatican"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TSoxLRUhVwI/AAAAAAAABgk/g7tLwcnNoaY/w13_vatican.png"&gt;&lt;br&gt;
&lt;br&gt;
It is much better than all other sources found, and it therefore raises
an interesting question: what is that little block where it differs,
just to the southwest of &lt;a
 href="http://en.wikipedia.org/wiki/Saint_Peter%27s_Square"&gt;Saint
Peter's Square&lt;/a&gt;? Who is right there? And who is wrong?
Interesting questions in the neighbourhood of the heart of the Roman
Church... But we mean it geographically. Is Google failing here, as in
Nicaragua and Costa Rica, nearly causing a war? Or is it the gadm.org
website, a particular initiative providing freely available shapefiles
for academic and non-commercial use (e.g. blogging)? According to
Wikipedia, there indeed
is a &lt;a
 href="http://en.wikipedia.org/wiki/List_of_territorial_disputes"&gt;border
dispute&lt;/a&gt; near Vatican City, but that is a little more to the
east...&lt;br&gt;
&lt;br&gt;
And look, we see a similar issue with Liechtenstein, probably a
disputed valley...&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 500px; height: 426px;" alt="liechtenstein"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TSoxGjhderI/AAAAAAAABgU/IFu3RBV7lmk/w13_liechtenstein.png"&gt;&lt;br&gt;
&lt;br&gt;
But for the rest also here this shapefile is relatively accurate. For
its size, accuracty is expected, of course...&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;Monaco&lt;/span&gt;&lt;/h2&gt;
In last blog we saw that the borders of Monaco were correct in only one
of the compared shapefiles... Alas, wrong again here:&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 500px; height: 404px;" alt="Monaco"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TSoxG3kEImI/AAAAAAAABgY/n9JoRJiXKXg/w13_monaco.png"&gt;&lt;br&gt;
&lt;br&gt;
It seems hard to create a correct shapefile... What is the source of
all those errors? Who is really right here? Of course Google! For all
certainty I checked this at &lt;a
 href="http://en.wikipedia.org/wiki/Monaco"&gt;Wikipedia&lt;/a&gt;
(because I've never been in Monaco). Yes, the yellow line of Google is
following Monaco's portrayal within the Wiki page of Monaco. So alas, &lt;span
 style="font-weight: bold; font-style: italic;"&gt;gadm&lt;/span&gt;
is totally wrong here.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;The Netherlands&lt;/span&gt;&lt;/h2&gt;
I'm living there, in that little country which is so difficult to be
stored
in free shapefiles... There is really a large lake, only bordered from
the sea by a dike. That lake should be displayed, and it is not. If
very small and uninhabited islands are displayed, the lake should
really be there. And it is not the only error, in Zeeland the (smaller)
water bodies behind the dikes are omitted as well.&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 330px; height: 330px;" alt="nl"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TSo40_6qmiI/AAAAAAAABgs/1pEJ_aq5HIE/world13.gif"&gt;&lt;br&gt;
&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;The Caspian Sea&lt;/span&gt;&lt;/h2&gt;
This was another requirement (CS1). It is not as bad as it was in some
other shapefiles, where the Caspian Sea was divided between surrounding
countries. But the Caspian Sea is included as a separate country in &lt;span
 style="font-weight: bold; font-style: italic;"&gt;gadm&lt;/span&gt;...
Interesting. Do they issue passports?&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;Validity&lt;/span&gt;&lt;/h2&gt;
Finally there is validity. All countries should be modelled as
multi-polygons and be valid in both SQL Server and PostGIS. We've
already seen that this requirement is&amp;nbsp;met in only one caes,
until now (11). And also for this case, 13, alas, there are many
multi-polygons invalid in SQL Server. In PostGIS it is OK, though the
query runs for a long time due to the excessive size of &amp;nbsp;the
geometries. The values are post-editted in the &lt;a
 href="/2010/12/free-shapefiles-of-of-world-3.html"&gt;previous
blog&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
Actually it is nice to show a variant of the query, using the &lt;span
 style="font-weight: bold;"&gt;with&lt;/span&gt; syntax:&lt;br&gt;
&lt;br&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span
 style="font-family: monospace;"&gt;with valid as (select
ST_IsValid(the_geom) as v from world13)&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;select v,count(1)
from valid group by v;&lt;/span&gt;&lt;/div&gt;
&lt;br&gt;&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;/h2&gt;
As always I'm glad with new shapefiles. This one is quite accurate, and
in many aspects the best until now. But also, it is way too large, too
cornery, and contains errors, as all others do...&lt;br&gt;
&lt;br&gt;
So&amp;nbsp;I think a good and freely available shapefile of the
countries of the world is
still very welcome.&lt;br&gt;
&lt;br&gt;
If there are more shapefiles, I'm still interested, but especially I'm
interested in a the Google country borders in any format? Are they
available? &lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-3227098173914366290?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/3227098173914366290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2011/01/free-shapefiles-of-countries-of-world-4.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/3227098173914366290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/3227098173914366290'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2011/01/free-shapefiles-of-countries-of-world-4.html' title='Free Shapefiles of Countries of the World (4)'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_6zrdK5O_LIg/TSoxGBgYEjI/AAAAAAAABgM/C488wqBFvQ0/s72-c/w13_gridded.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-5975819948065847810</id><published>2010-12-27T23:28:00.008+01:00</published><updated>2011-01-12T20:32:29.075+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='world'/><category scheme='http://www.blogger.com/atom/ns#' term='countries'/><category scheme='http://www.blogger.com/atom/ns#' term='shapefile'/><title type='text'>Free Shapefiles of Countries of the World (3)</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Free Shapefiles of&amp;nbsp;Countries of the World (3)&lt;/h1&gt;
&lt;br&gt;
This
is part three of the comparison of free shapefiles of countries of the
world. After feedback, new sources, blogs and tweets (thanks everyone)
on my
previous blogs (&lt;a
 href="/2010/12/free-shapefile-of-countries-of-world.html"&gt;part
1&lt;/a&gt; and &lt;a
 href="/2010/12/free-shapefiles-of-of-world-2.html"&gt;part 2&lt;/a&gt;),
I decided to show some things more.&lt;br&gt;
&lt;br&gt;
&lt;i&gt;&lt;b&gt;Edited:&lt;/b&gt; Note that &lt;a
 href="/2011/01/free-shapefiles-of-countries-of-world-4.html"&gt;part
4&lt;/a&gt; handles an additional shapefile, referred as 13 here.&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
Let's now look at the north of Italy, where several countries are
situates: Italy
itself, France, Switzerland, Austria, Germany, Slovenia, Croatia, and
some very small countries:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;San Marino&lt;/li&gt;
  &lt;li&gt;Liechtenstein&lt;/li&gt;
  &lt;li&gt;Monaco&lt;/li&gt;
  &lt;li&gt;Vatican City&lt;/li&gt;
&lt;/ul&gt;
And I can't really believe what I saw today. Vatican City has been
moved by some shapefile creators...&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Vatican City&lt;/h2&gt;
With
respect to Vatican City, all shapefiles that I found are wrong. Below
an image created with Google Earth showing boundaries. The yellow one
is Google's, so not
from a shapefile. It is accurate. I really&amp;nbsp;want a shapefile
with Google's country borders! Didn't found it until now, even not in
KML-format. All others displayed, 3, 5, 6, 7, 9 are not accurate, but
acceptable. I
know that Vatican City&amp;nbsp;is a very small country, that on a
worldscale map you
could not expect too much detail, so it might make sense that they
display the country border only roughly. So these are all reckoned &lt;span
 style="font-weight: bold;"&gt;sufficient&lt;/span&gt;... with
respect to the requirements, see more about that below.&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 500px; height: 519px;" alt="im3b"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TRjYJtFcN2I/AAAAAAAABdw/W5nObWne6fA/intersections_3b.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
But I was really amazed by the other ones, in the zoom
out&amp;nbsp;below. Those (1, 2, 8, 12) are all &lt;span
 style="font-weight: bold;"&gt;wrong&lt;/span&gt;. &lt;span
 style="font-style: italic;"&gt;(Remember that all numbers refer
to numbered sources from previous blog, completely listed below).&lt;/span&gt;
About 1: we already knew that it was far too rough, and it is actually
understandable: it exaggarates small countries to show them on a
worldscale map. Understandable. But 2, 8 and 12 are completely wrong.
Especially from 12 (source: &amp;nbsp;&lt;a
 href="http://epp.eurostat.ec.europa.eu/portal/page/portal/gisco/popups/references/administrative_units_statistical_units_1%60"&gt;eurostat&lt;/a&gt;,
europa.eu) you would &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt;
expect this. What has happened here...&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 880px; height: 533px;" alt="im3a"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TRjZCMLfbHI/AAAAAAAABd4/al6tMMCVmAw/intersections_3a.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Some sources (4, 11) do not have Vatican City at all.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Monaco&lt;/h2&gt;
For Monaco it is a little better, in the sence that countries are not
moved by 24 kilometers. But most shapefiles are more or less wrong, 12
being the only exception.&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 500px; height: 453px;" alt="im2c"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TRjlhhTlYTI/AAAAAAAABeI/2rHyXFnnYHA/intersections_3c.png"&gt;&lt;br&gt;
&lt;br&gt;
The Yellow line is Google again, and 12 is the cyan one following it.
All the rest&amp;nbsp;is wrong.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Liechtenstein and San Marino&lt;br&gt;
&lt;/h2&gt;
The other small countries, San Marino and Liechtenstein, are both
displayed more or less acceptable in all but 1, 2 and 8 (all omitted in
the pictures - 8 is for Liechtenstein OK). Number 12 (cyan) also here
follows Google the most closely.&lt;br&gt;
&lt;img style="width: 569px; height: 397px;" alt="im3d"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TRjkmUO1HzI/AAAAAAAABeA/Sp3UxA93eUc/intersections_3d.png"&gt;&lt;br&gt;
&lt;br&gt;
Based on this pictures, 12 (from Eurostat) is following Google's
country borders the most closely, with an amazing exception being
Vatican City, where it is totally wrong. The rest of the sources shows
not a real winner here.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Elba&lt;/h2&gt;
Not a country, but also compared, the&amp;nbsp;island &lt;a
 href="http://en.wikipedia.org/wiki/Elba"&gt;Elba&lt;/a&gt; is
another sample where the vertices of source 12 (Eurostat) follow the
borders of the island quite closely. Cyan is the 3M
version,&amp;nbsp;blue the 10M, darker (and paler) blue the 20M. In the
60M version Elba is omitted. I agree with this all. The other borders,
magenta here below, are all worse. And I omitted 1,2 and 8 here because
they are even more wrong.&lt;br&gt;
&lt;br&gt;
&lt;img
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TRkCwQcdCtI/AAAAAAAABeU/6QgiXpmiuTA/intersections_3e.png"
 alt="intersections_3e.png (500×355)"&gt;&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Requirements&lt;/h2&gt;
In the last two blogs I made remarks about the quality, but I
didn't really listed them as formal requirements. So let's start with
that now. They are composed on the fly, and maybe a bit subjective, I
know that.&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;NL1: The five inhabited islands in the Waddensea in the
Netherlands should be present&lt;/li&gt;
  &lt;li&gt;NL2: The inner lake in the Netherlands should be included&lt;/li&gt;
  &lt;li&gt;NL3:
The polders in the Netherlands should be visualized correctly, so
absence of non-existing polders and presence of polders existing since
1968 (sometimes you have to make requirements quite explicitly...)&lt;/li&gt;
  &lt;li&gt;CS1: The Caspian Sea should be there&lt;/li&gt;
  &lt;li&gt;DB1: Countries should be one multi_polygon per country, not
separate polygons&lt;/li&gt;
  &lt;li&gt;DB2: All (multi)geometries should be valid within SQL
Server 2008&lt;/li&gt;
  &lt;li&gt;DB2: All (multi)geometries should be valid
within&amp;nbsp;PostGIS&lt;/li&gt;
  &lt;li&gt;SM1: Vatican City should not be moved and (probably) not be
omitted&lt;/li&gt;
  &lt;li&gt;SM2: Monaco's borders should follow real borders&lt;/li&gt;
  &lt;li&gt;SM3: San Marino's borders should follow real borders&lt;/li&gt;
  &lt;li&gt;SM4: Liechtenstein's borders should follow real borders&lt;/li&gt;
  &lt;li&gt;SM5: Elba's borders should be followed&lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;
In the table below the requirement list is crossed against the
shapefiles.&lt;br&gt;
&lt;br&gt;
&lt;table style="text-align: left; width: 100%;" border="1"
 cellpadding="2" cellspacing="2"&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;#&lt;/td&gt;
      &lt;td&gt;NL1&lt;/td&gt;
      &lt;td&gt;NL2&lt;/td&gt;
      &lt;td&gt;NL3&lt;/td&gt;
      &lt;td&gt;CS1&lt;/td&gt;
      &lt;td&gt;DB1&lt;/td&gt;
      &lt;td&gt;DB2&lt;/td&gt;
      &lt;td&gt;DB3&lt;/td&gt;
      &lt;td&gt;SM1&lt;/td&gt;
      &lt;td&gt;SM2&lt;/td&gt;
      &lt;td&gt;SM3&lt;/td&gt;
      &lt;td&gt;SM4&lt;/td&gt;
      &lt;td&gt;SM5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;-&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;Enlarged&lt;/td&gt;
      &lt;td&gt;Enlarged&lt;/td&gt;
      &lt;td&gt;Enlarged&lt;/td&gt;
      &lt;td&gt;Enlarged&lt;/td&gt;
      &lt;td&gt;Very poor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;26 km off&lt;/td&gt;
      &lt;td&gt;Very poor&lt;/td&gt;
      &lt;td&gt;Very poor&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Very poor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;34&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Good&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;polygons&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;Omitted&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;26 km off&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Very poor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;17&lt;/td&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9b&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;br&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9c&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Omitted&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Omitted&lt;br&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;11&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;omitted&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Good&lt;/td&gt;
      &lt;td&gt;Omitted&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;12 (3m)&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;13&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;24 km off&lt;/td&gt;
      &lt;td&gt;Excellent&lt;/td&gt;
      &lt;td&gt;Excellent&lt;/td&gt;
      &lt;td&gt;Excellent&lt;/td&gt;
      &lt;td&gt;Excellent&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;12 (10m)&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;24 km off&lt;/td&gt;
      &lt;td&gt;Good&lt;/td&gt;
      &lt;td&gt;Good&lt;/td&gt;
      &lt;td&gt;Good&lt;/td&gt;
      &lt;td&gt;Good&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;12 (20m)&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;24 km off&lt;/td&gt;
      &lt;td&gt;Good&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;12 (60m)&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;OK&lt;/td&gt;
      &lt;td&gt;24 km off&lt;/td&gt;
      &lt;td&gt;Sufficient&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
      &lt;td&gt;Omitted&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;Edited: &lt;/span&gt;13&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;OK&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;-&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;-&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;as separate&lt;br&gt;
country&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;OK&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;47&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;OK&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;Excellent&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;Poor&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;Excellent&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;Excellent&lt;/td&gt;
      &lt;td style="font-style: italic;"&gt;Excellent&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;h2&gt;All sources compared by image&lt;/h2&gt;
The images below show the same picture, using all shapefiles, as we did
in the previous blog, but now showing these four countries, Italy, and
parts of the surrounding countries.&lt;br&gt;
&lt;table style="text-align: left; width: 100%;" border="0"
 cellpadding="2" cellspacing="10"&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i1"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TRkPcS9oeAI/AAAAAAAABfA/PfxuE3Q23yw/italy1.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(1)&lt;/li&gt;
        &lt;li&gt;from &lt;a
 href="http://www.aprsworld.net/gisdata/world/"&gt;aprs&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file world.shp &lt;/li&gt;
      &lt;/ul&gt;
      &lt;br&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i2"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TRkPcWSJFNI/AAAAAAAABfE/iOi7SaVIYYA/italy2.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(2)&lt;/li&gt;
        &lt;li&gt;from &lt;a
 href="http://www.brothersoft.com/world-map-data-97757.html"&gt;brothersoft&lt;/a&gt;,
serving blue marble data&lt;/li&gt;
        &lt;li&gt;file World_countries_shp.shp&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i3"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TRkPcmcrc_I/AAAAAAAABfI/g-fxU_ILaJo/italy3.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(3)&lt;/li&gt;
        &lt;li&gt;from &lt;a href="http://www.geodan.com/"&gt;Geodan&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file WorldCountries.shp&lt;/li&gt;
      &lt;/ul&gt;
      &lt;br&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i4"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TRkPcu1_rVI/AAAAAAAABfM/jQFySgo4wqg/italy4.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(4)&lt;/li&gt;
        &lt;li&gt;from &lt;a href="http://www.mappinghacks.com/data/"&gt;mapping
hacks&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file world_borders.shp &lt;/li&gt;
      &lt;/ul&gt;
      &lt;br&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i5"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TRkPc26ngxI/AAAAAAAABfQ/TgN10X6Lp7Q/italy5.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(5)&lt;/li&gt;
        &lt;li&gt;from&amp;nbsp;&lt;a
 href="http://thematicmapping.org/downloads/world_borders.php"&gt;thematic
mapping&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file TM_WORLD_BORDERS-0.3.shp&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i6"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TRkPloBhxrI/AAAAAAAABfU/Kf0jihOBJ6k/italy6.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(6)&lt;/li&gt;
        &lt;li&gt;from openmap &lt;a
 href="http://openmap.bbn.com/data/shape/"&gt;here&lt;/a&gt;,
called cntry02&lt;/li&gt;
        &lt;li&gt;file cntry02.shp&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i7"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TRkPlwBAxeI/AAAAAAAABfY/w1a0YN41fko/italy7.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(7)&lt;/li&gt;
        &lt;li&gt;from this&amp;nbsp;&lt;a
 href="http://www.baruch.cuny.edu/geoportal/data/esri/esri_intl.htm"&gt;site&lt;/a&gt;&amp;nbsp;ESRI
data&lt;/li&gt;
        &lt;li&gt;file cntry08.shp &lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i8"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TRkPl67W72I/AAAAAAAABfc/RH7mbCBaUWk/italy8.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(8)&lt;/li&gt;
        &lt;li&gt;from &lt;a href="http://www.vdstech.com/map_data.htm"&gt;vdstech&lt;/a&gt;
via&amp;nbsp;&lt;a
 href="http://blog.sqlauthority.com/2010/03/30/sql-server-world-shapefile-download-and-upload-to-database-spatial-database/"&gt;this
blog&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file world.shp &lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i9a"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TRkPl4SfgDI/AAAAAAAABfg/NvJr5jLtAbM/italy9.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(9)&lt;/li&gt;
        &lt;li&gt;from &lt;a
 href="=http://www.naturalearthdata.com/downloads/"&gt;natural
earth&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file 10m-admin-0-countries.shp&amp;nbsp;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i9b"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TRkPmNMkZ3I/AAAAAAAABfk/11S2Wa5zJkQ/italy9b.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(9b)&lt;/li&gt;
        &lt;li&gt;from &lt;a
 href="=http://www.naturalearthdata.com/downloads/"&gt;natural
earth&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file 50m_admin_0_countries.shp&amp;nbsp;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i9c"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TRkPq96hbZI/AAAAAAAABfo/b4eNAmf3f_E/italy9c.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(9c)&lt;/li&gt;
        &lt;li&gt;from &lt;a
 href="=http://www.naturalearthdata.com/downloads/"&gt;natural
earth&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file 110m_admin_0_countries.shp&amp;nbsp;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;(10). Empty&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i11"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TRkPrH_XQ9I/AAAAAAAABfs/rB7tkAn7VjY/italy11.gif"&gt;&lt;br&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(11)&lt;/li&gt;
        &lt;li&gt;from&amp;nbsp;&lt;a
 href="http://huebler.blogspot.com/2005/11/creating-maps-with-stata.html"&gt;huebler&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file world_adm0.shp&amp;nbsp;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i12_3"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TRkPrcN8J0I/AAAAAAAABfw/ncMlvTOXQX0/italy12_3m.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(12 1:3m)&lt;/li&gt;
        &lt;li&gt;from&amp;nbsp;&lt;a
 href="http://epp.eurostat.ec.europa.eu/portal/page/portal/gisco/popups/references/administrative_units_statistical_units_1"&gt;eurostat&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file cntr_rg_03m_2006.SHP&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i12_10m"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TRkPreAHvgI/AAAAAAAABf0/s9F9EaM6SQw/italy12_10m.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(12 1:10m)&lt;/li&gt;
        &lt;li&gt;from&amp;nbsp;&lt;a
 href="http://epp.eurostat.ec.europa.eu/portal/page/portal/gisco/popups/references/administrative_units_statistical_units_1"&gt;eurostat&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file cntr_rg_10m_2006.SHP&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i12_10m"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TRkPriHxtfI/AAAAAAAABf4/yRKbNLEawjM/italy12_20m.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(12 1:20m)&lt;/li&gt;
        &lt;li&gt;from&amp;nbsp;&lt;a
 href="http://epp.eurostat.ec.europa.eu/portal/page/portal/gisco/popups/references/administrative_units_statistical_units_1"&gt;eurostat&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file cntr_rg_20m_2006.SHP&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 600px; height: 600px;"
 alt="i12-60m"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TRkPtvsZyoI/AAAAAAAABf8/FYzx24R9wU4/italy12_60m.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(12 1:60m)&lt;/li&gt;
        &lt;li&gt;from&amp;nbsp;&lt;a
 href="http://epp.eurostat.ec.europa.eu/portal/page/portal/gisco/popups/references/administrative_units_statistical_units_1"&gt;eurostat&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file cntr_rg_60m_2006.SHP&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;/h2&gt;
Again thanks to commentor Alectora who suggested Eurostat, it is a nice
set of four datasets in different scales. The 1:3 million version is
excellent in most measures, but it is a pity that Vatican is displaced
and the IJsselmeer in the Netherlands is omitted. And that some
polygons are not valid...&lt;br&gt;
&lt;br&gt;
I still think a good and free shapefile of the world is
still&amp;nbsp;welcome.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-5975819948065847810?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/5975819948065847810/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/free-shapefiles-of-of-world-3.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/5975819948065847810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/5975819948065847810'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/free-shapefiles-of-of-world-3.html' title='Free Shapefiles of&amp;nbsp;Countries of the World (3)'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_6zrdK5O_LIg/TRjYJtFcN2I/AAAAAAAABdw/W5nObWne6fA/s72-c/intersections_3b.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-1828229308266344438</id><published>2010-12-24T22:48:00.006+01:00</published><updated>2011-03-12T15:16:43.479+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quickbook'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='doxygen'/><title type='text'>Doxygen and QuickBook</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Doxygen and QuickBook&lt;/h1&gt;
&lt;br&gt;
&lt;a href="http://www.doxygen.org"&gt;Doxygen&lt;/a&gt; and &lt;a
 href="http://www.boost.org/doc/tools/quickbook"&gt;QuickBook&lt;/a&gt;
are both great tools for generating documentation from C++ code. But
their cooperation is quite complex... let's say, a challenge.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Quickbook&lt;/h2&gt;
QuickBook (QBK) is based on BoostBook, which used to be the
documentation tool for Boost
Libraries. BoostBook is on its turn based on DocBook.&lt;br&gt;
&lt;br&gt;
With QuickBook (and also BoostBook) you can make&amp;nbsp;good looking
library
documentation describing headers, examples, syntax highlighting, etc.
Look
at the QBK website for more information. For example, I like the &lt;a
 href="http://www.boost.org/doc/libs/1_45_0/doc/html/quickbook/syntax.html#quickbook.syntax.block.import.callouts"&gt;callouts&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
QuickBook input files (extension .qbk) are plain text files with Wiki
style commands. However, when using QuickBook alone it is not
maintainable to document hundreds of classes and functions, you really
should have a link to the source code. And that is what Doxygen is
doing.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Doxygen&lt;/h2&gt;
Doxygen is a standalone tool, accepting C++ source code (it accepts
other languages as well) with JavaDoc
style comments to document function parameters, etc. Look at the
website for a manual. While Doxygen does a great job, the generated
documentation is often considered a bit too technical. In the review
report
was included:&lt;br&gt;
&lt;br&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span
 style="font-style: italic;"&gt;Using Doxygen alone as a
documentation tool has its (known) shortcomings when it comes to
generic libraries.
&lt;br&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;And&amp;nbsp;the individual reviews mentioned
things&amp;nbsp;as : &lt;span style="font-style: italic;"&gt;"I
think doxygen is convenient for developers but not very useful for
users, because of the high structure/content ratio."&lt;/span&gt; and &lt;span
 style="font-style: italic;"&gt;"I really did not like the
doxygen generated content.&amp;nbsp; I found it difficult to find the
real documentation among all the doxygen generated fluff."&lt;/span&gt;
and &lt;span style="font-style: italic;"&gt;"I have a general
problem with doxygen generated docu with regard to generic libraries.
It not easy to separate the important classes and fuctions from the
implementation details. GGL helps with this through Grouping by modules
and a overview Page, but&amp;nbsp; it could be even better. I think the
Modules should them self be further grouped, and the most important
should be highlighted.".&lt;/span&gt;&amp;nbsp;&lt;span
 style="font-style: italic;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This does not mean that Doxygen is&amp;nbsp;wrong or bad, and
maybe we did not spend enough time to configure it right. An individual
review also mentioned:&amp;nbsp;&lt;span style="font-style: italic;"&gt;"Doc:
Excellent. Looks very nice. Only an index is missing - but extensive
Doxygenation including Doxygen comments are far above what passes for
documentation in many packages".&lt;/span&gt; We did our best at least.&lt;/p&gt;
&lt;p&gt;Anyway, people do like QuickBook generated documentation, so
we, with Boost.Geometry, are moving to QuickBook. But we want to keep
Doxygen there to link with the source code.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Doxygen -&amp;gt; QuickBook via XSLT&lt;/h2&gt;
It &lt;span style="font-weight: bold;"&gt;is&lt;/span&gt;
certainly possible to let Doxygen and QuickBook work together. Doug
Gregor wrote &lt;a
 href="http://gcc.gnu.org/ml/libstdc++/2007-11/msg00029.html"&gt;here&lt;/a&gt;:
&lt;br&gt;
&lt;p style="font-family: monospace;"&gt;(...) If I haven't
scared you yet, I'll put it in a diagram:&lt;/p&gt;
&lt;p style="font-family: monospace;"&gt;C++ sources -&amp;gt;
Doxygen XML -&amp;gt; BoostBook XML -\&lt;br&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -&amp;gt; Merged
BoostBook XML&lt;br&gt;
Quickbook sources -&amp;gt; BoostBook XML ----------/&lt;/p&gt;
&lt;p style="font-family: monospace;"&gt;Then, for the output:&lt;/p&gt;
&lt;p style="font-family: monospace;"&gt;Merged &amp;nbsp;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;/--&amp;gt; HTML&lt;br&gt;
BoostBook --&amp;gt; DocBook XML ------&amp;gt; FO --------&amp;gt; PDF&lt;br&gt;
XML &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
\--&amp;gt; Man pages&lt;/p&gt;
&lt;p style="font-family: monospace;"&gt;Look complex? It is.
(...)&lt;/p&gt;
So it is complex. Especially the XSLT file to convert from Doxygen XML
to BoostBook XML proved complex and sometimes incomplete, we (Mateusz)
spent time on it and achieved good documentation, but it was really
complex. And in the end, you don't get QuickBook, you get BoostBook...
Suppose you want something different, for example adding "complexity"
to the documentation... It means changing the XSLT files again.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;What is in the docs?&lt;/h2&gt;
I like to see in documentation,&amp;nbsp;per function or per class:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;What it does&lt;/li&gt;
  &lt;li&gt;The header where the function or class is found&lt;/li&gt;
  &lt;li&gt;Its parameters (for a function)&lt;/li&gt;
  &lt;li&gt;Its return type (for a function)&lt;/li&gt;
  &lt;li&gt;Its limitations&lt;/li&gt;
  &lt;li&gt;An example (this is very important)&lt;/li&gt;
  &lt;li&gt;An image (very important for a geometry-library, probably
not for all libraries) to show what it is doing&lt;/li&gt;
  &lt;li&gt;Behaviour in various combinations&lt;/li&gt;
  &lt;li&gt;Its complexity&lt;/li&gt;
&lt;/ul&gt;
The cplusplus documentation has for every function or method a little &lt;a
 href="http://www.cplusplus.com/reference/stl/vector/push_back/"&gt;example&lt;/a&gt;,
I like that. It is great for programmers who program by example.
Examples need to be compilable examples, they need to be extracted from
real compiled code, otherwise old constructs or other obsolete things
or typos will stay there unnoticed. You see that often.&lt;br&gt;
&lt;br&gt;
About behaviour: within Boost.Geometry, one function (e.g. &lt;span
 style="font-weight: bold;"&gt;distance&lt;/span&gt;) can do
many things (distance between two points, between point-and-polygon,
etc). We also have multiple dimensions (2D, 3D) and coordinate systems.
The behaviour of the functions might be different in different
circumstances. Therefore, we want to have a possibility to document
these differences explicitly.&lt;br&gt;
&lt;br&gt;
Besides this, we often have two overloads, one with a so-called
strategy, giving the library user the tools to change default
calculation methods, or one without, so sticking to the defaults.
Besides these differences, these overloads are the same. So
documentation is the same. Where does the documentation come from? From
the sources. Do we want to have the same documentation duplicated for
two functions? No. Or probably not.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Don't repeat yourself, and macro's&lt;/h2&gt;
Doxygen does have an overload option, but it seems to work only for
overloaded member functions. We are overloading free functions, which
are often heavily templated. I didn't have success to get Doxygen's
overload construct running with our code.&lt;br&gt;
&lt;br&gt;
Anyway, Doxygen provides a great utility: an &lt;a
 href="http://www.stack.nl/%7Edimitri/doxygen/config.html#cfg_aliases"&gt;alias&lt;/a&gt;.
This is a sort of a macro, expanding to whatever you specify. So when
we think we repeat ourself (e.g. writing for a template parameter
"Coordinate system (e.g. cs::cartesian)", which will be found at many
places) we can introduce an alias there, param_macro_coorsystem, and we
can use it in the documentation.&lt;br&gt;
&lt;br&gt;
The result looks cryptic, but at least you don't repeat yourself and if
you want to change that sentence, you do it in one place.&lt;br&gt;
&lt;br&gt;
To make the picture complete: QuickBook also provides a great utility:
a &lt;a
 href="http://www.boost.org/doc/libs/1_45_0/doc/html/quickbook/syntax.html#quickbook.syntax.block.macros"&gt;macro&lt;/a&gt;.
This is doing about the same: it is a placeholder which is replaced by
quickbook by the actual text.&lt;br&gt;
&lt;br&gt;
So we can actually chose: write plain English, take an alias, take a
macro. Or mix them.&lt;br&gt;
&lt;br&gt;
Repeating yourself is usually not so good, but in documentation, it
cannot always be avoided. Refactoring &lt;span
 style="font-weight: bold;"&gt;all&lt;/span&gt; repetitions from
comments and document fragments will result in a very cryptic
developer-defined language. Actually, it is already looking
cryptic&amp;nbsp;now, read on...&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br&gt;
&lt;h2&gt;Doxygen -&amp;gt; QuickBook via parser&lt;/h2&gt;
As described above, the XSLT process to go from Doxygen to
BoostBook&amp;nbsp;was not completely satisfactory for us, with all our
requirements to documentation. It probably can be done, but requires
high XSLT skills, and who nowadays still writes XSLT? There are a lot
of libraries parsing XML, in C++ (and in&amp;nbsp;other languages), and
for a C++ programmer it is quite easy to parse the Doxygen XML and
output QuickBook. So that is what is done... We developed a new
tool, doxygen_xml2qbk. It goes from the XML's generated by Doxygen
to QBK.&lt;br&gt;
&lt;br&gt;
The tool might be more useful in general (for more Boost libraries),
but currently it does its job for Boost.Geometry.&lt;br&gt;
&lt;br&gt;
It is currently (lightly) based on &lt;a
 href="http://rapidxml.sourceforge.net/"&gt;RapidXML&lt;/a&gt;
(great library, by the way, and super fast).&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;The markup&lt;/h2&gt;
So we document functions like this, I take here the area function:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;/*!&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;\brief
\brief_calc{area}&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;\ingroup area&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;\details
\details_calc{area}. \details_default_strategy&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
So these&amp;nbsp;lines use macros to say that it is calculating the
area (brief), and again that it is doing that (detail). The differences
in brief and detail are Doxygen differences, sometimes convenient,
sometimes not. Then&amp;nbsp; a remark-macro is added that this
function takes the default strategy. That is the case with a lot of
functions, therefore it is a macro, to avoid repetition. Then it
continues:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;\tparam Geometry
\tparam_geometry&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;\param geometry
\param_geometry&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;\return
\return_calc{area}&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
So here the parameters are described. There is a template-parameter
(Doxygen's tparam) and a parameter (Doxygen's param). Those are
similar, geometry! Not literally the same, but the parameter geometry
(lower case) is of the type Geometry (Camel Case). This is the case for
most of the functions, accepting sometimes one, sometimes two
geometries. Therefore macro's (\tparam_geometry) are introduced here...
Below we will see that they can be handled in the same line! Though not
everyone is convinced of that feature. It might go away or be made
flexible.&lt;br&gt;
&lt;br&gt;
Avoiding repetitions: it the same for the return value, after Doxygen's
\return. It would be possible to write here: "the function area
calculates the area of the input geometry". For the function &lt;span
 style="font-weight: bold; font-style: italic;"&gt;length&lt;/span&gt;
we will write (about) the same comment (replace area with length). For &lt;span
 style="font-weight: bold; font-style: italic;"&gt;perimeter&lt;/span&gt;
the same. Et cetera. So, to avoid repetition, we created&amp;nbsp;the
cryptic macro \return_calc, with a parameter a literal string (in this
case "area").&lt;br&gt;
&lt;br&gt;
We continue:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;\qbk{example,area_polygon}&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;\qbk{example,area_polygon_spherical}&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
So this is a Doxygen Alias (\qbk) to generate an XML node called
&amp;lt;qbk.example&amp;gt;, it generates two of them, one per line.
Such an XML node is recognized by our new tool doxygen_xml2qbk. And
that tool generates, as expected, an example section. So these two
lines generates this QuickBook syntax:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;[heading Examples]&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;[area_polygon]&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;[area_polygon_spherical]&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;br&gt;
Where area_polygon can be found in one of the examples, using a
QuickBook construct to show a syntax highlighted example.&lt;br&gt;
&lt;br&gt;
We continue:&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;/span&gt;&lt;span style="font-family: monospace;"&gt;\qbk{behavior,__0dim__:[qbk_ret
0]}&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;\qbk{behavior,__1dim__:[qbk_ret
0]}&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;\qbk{behavior,__2dim__:[qbk_ret
the area]}&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;\qbk{behavior,__cart__:[qbk_ret
the area] __cs_units__}&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;\qbk{behavior,__sph__:[qbk_ret
the area] __sph1__}&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;\qbk{behavior,__rev__:[qbk_ret
the negative area]}&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;This all goes to a xml.behavior node, and then to a
QuickBook behavior section, a table describing the behaviour for 0
dimensions (point), 1 dimension (linear), etc. All this is macro'd,
where __sph__ is also a QuickBook macro, and [qbk_ret] is also a
QuickBook macro. They can be nested as well. qbk_ret just says
"returns". It has the same length, the only advantage is that you don't
repeat yourself &lt;span style="font-weight: bold;"&gt;&lt;span
 style="font-style: italic;"&gt;in words&lt;/span&gt;&lt;/span&gt;
but now &lt;span style="font-style: italic;"&gt;&lt;span
 style="font-weight: bold;"&gt;in macros&lt;/span&gt;&lt;/span&gt;.&lt;br&gt;
&lt;br&gt;
OK, using two macro systems through each other, some having a specific
meaning for our converter tool, this is quite complex and I realize
that. But on the other hand, if everything is written in words here, it
is probably unmaintainable.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;The results&lt;/h2&gt;
Let's finally show the results here, as screen-dumps.&lt;br&gt;
&lt;br&gt;
Doxygen generates this piece:&lt;br&gt;
&lt;img alt="q1a"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TRUUos2s8QI/AAAAAAAABdA/pfwrAcsKRJs/quickbook1a.png"&gt;&lt;br&gt;
&lt;br&gt;
To be honest, we must say that examples (using syntax highlighting)
within Doxygen are certainly possible as well.&lt;br&gt;
&lt;br&gt;
With Doxygen-conversion-QuickBook the following piece is generated:&lt;br&gt;
&lt;br&gt;
&lt;img alt="qb1b"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TRUUo6q1RaI/AAAAAAAABdE/2AXuc1KDdHw/s720/quickbook1b.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
So we see what our \qbk alias does here... It generates the sections
behavior, complexity, examples, and might generate more.&lt;br&gt;
&lt;br&gt;
I like it, despite its complexity.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-1828229308266344438?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/1828229308266344438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/doxygen-and-quickbook.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/1828229308266344438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/1828229308266344438'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/doxygen-and-quickbook.html' title='Doxygen and QuickBook'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_6zrdK5O_LIg/TRUUos2s8QI/AAAAAAAABdA/pfwrAcsKRJs/s72-c/quickbook1a.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-1222666594515417783</id><published>2010-12-22T22:53:00.006+01:00</published><updated>2010-12-22T23:51:16.229+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unit tests'/><category scheme='http://www.blogger.com/atom/ns#' term='set theory'/><category scheme='http://www.blogger.com/atom/ns#' term='intersections'/><category scheme='http://www.blogger.com/atom/ns#' term='boolean operations'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><title type='text'>Intersections (2), "recursive polygons"</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Intersections (2), "recursive polygons"&lt;/h1&gt;
&lt;br&gt;
The Boost.Geometry review report &lt;a
 href="http://permalink.gmane.org/gmane.comp.lib.boost.announce/246"&gt;said&lt;/a&gt;:&lt;br&gt;
&lt;br&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span
 style="font-style: italic;"&gt;Testing: several reviewers
mentioned the need for a thorough testing&lt;/span&gt;&lt;span
 style="font-style: italic;"&gt; framework allowing the
verification of the correctness of the algorithms in&lt;/span&gt;&lt;span
 style="font-style: italic;"&gt; a wide range of use cases.
Different test strategies need to be employed,&lt;/span&gt;&lt;span
 style="font-style: italic;"&gt; such as high volume and random
tests, known border case tests, tests using&lt;/span&gt;&lt;span
 style="font-style: italic;"&gt; different numeric precision
types, etc.&lt;/span&gt;&lt;br&gt;
&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br&gt;
This blog will discuss a part of this, a program called &lt;a
 href="https://svn.boost.org/svn/boost/sandbox/geometry/libs/geometry/test/algorithms/overlay/robustness/recursive_polygons.cpp"&gt;recursive_polygon.cpp&lt;/a&gt;,
which is a test in the category high volume an random, using different
numeric precision types.&lt;br&gt;&lt;br&gt;
&lt;h2&gt;Recursively made polygons&lt;/h2&gt;
In this testprogram,&amp;nbsp;polygons are created in a recursive way.
In the first step two polygons are created. They are created at a
random place and either a box, or a triangle (in this case: a box with
one coordinate omitted). &lt;span style="font-style: italic;"&gt;The
first version of the program was called recursive_boxes because it then
did only boxes.&lt;/span&gt; Those two polygons are&amp;nbsp;unioned
and the result is either a polygon, or a multi-polygon. In the first
step, it is probably a multi-polygon.&lt;br&gt;
&lt;br&gt;
After this, two other polygons like this, based on random coordinates,
are unioned and result in another multi-polygon.&lt;br&gt;
&lt;br&gt;
In the second step, the results of these two earlier unioned
multi-polygons are again unioned. This will deliver a third
multi-polygon. And so the process goes on, each time creating more
complex multi-polygons, and after a a while holes are generated,
self-tangencies.&lt;br&gt;
&lt;br&gt;
The figure below shows the idea more clearly.&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 709px; height: 329px;" alt="i2a"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TRJkyo3_UJI/AAAAAAAABcg/jhD6tNM4f2o/intersections_2a.png"&gt;&lt;br&gt;
&lt;br&gt;
In this figure, a field of 3x3 is used and intersections are done up to
level 3.&lt;br&gt;
&lt;br&gt;
The test and recursive structure and sequence can be compared to a
genealogical &lt;a href="http://en.wikipedia.org/wiki/Ahnentafel"&gt;Ahnentafel&lt;/a&gt;,
the unions to marriages, the number 15 to the proband, having two
parents, four grandparents, eight great-grandparents, et cetera.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Checking results&lt;/h2&gt;
While we can run the program and see the results (the
program&amp;nbsp;optionally creates an SVG file), we have to have a
mechanism to check if the results are correct.&lt;br&gt;
&lt;br&gt;
Luckily we are doing geometry, we are doing mathematics, we are doing
set theory, so we can use that to check our results.&lt;br&gt;
&lt;br&gt;
Checks are done in each step, so during the processing of two polygons.
Besides a union (&lt;span style="font-weight: bold;"&gt;u&lt;/span&gt;),
an intersection (&lt;span style="font-weight: bold;"&gt;i&lt;/span&gt;)
is done. The area is calculated of the original polygons (&lt;span
 style="font-weight: bold;"&gt;p&lt;/span&gt; and &lt;span
 style="font-weight: bold;"&gt;q&lt;/span&gt;), of the union,
and of the intersection. And it always must be that the area of the
union equals to the area of both input polygons, minus the area of the
intersection. So: A(u) == A(p) + A(q) - A(i). A simple check, all done
by the library itself.&lt;br&gt;
&lt;br&gt;
So we can run the check for thousands of times, and for various levels,
field sizes, boxes and triangles. It now also runs for counter
clockwise polygons and open polygons.&lt;br&gt;
&lt;br&gt;
It is not the case that it was without errors the first time... There
have been many errors, especially in the self-tangencies, points were
two polygons in a multi-polygon touch each other. That all have been
solved. So running this test was absolutely valuable.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Seven levels&lt;/h2&gt;
After seven levels in a field of 10x10 we might get the next results:&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 877px; height: 406px;" alt="i2c"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TRJoIQUN-8I/AAAAAAAABco/X0NiRTkrp44/intersections_c.png"&gt;&lt;br&gt;
&lt;br&gt;
At the left the two input polygons (green and blue), at the right the
union in red. After these seven levels in the 10x10 field, the unions
are that large that they nearly completely fill up the whole area.&lt;br&gt;
&lt;br&gt;
Last&amp;nbsp;month I did most tests in this configuration, 10x10 and
up to 7 levels. 7 levels results in 255 tests, this is 2&lt;sup&gt;8&lt;/sup&gt;-1&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Twelve levels&lt;/h2&gt;
Twelve levels results in 2&lt;sup&gt;12&lt;/sup&gt;-1 unions and shows
in a 100x100 field like this:&lt;br&gt;
&lt;img style="width: 752px; height: 754px;" alt="1c"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TRJkype0hfI/AAAAAAAABck/cAM_jywTkdw/intersections_2b.png"&gt;&lt;br&gt;
&lt;br&gt;
and we can go further and further, but for Boost.Geometry the tests do
not give&amp;nbsp;problems anymore. It all runs fine. This test (so
8191 unions and intersections ending in this complexity) runs in two
seconds on my current machine (&lt;span style="font-style: italic;"&gt;actually,
to be precise, it is doing the union twice because the overlay &lt;a
 href="https://svn.boost.org/svn/boost/sandbox/geometry/libs/geometry/test/algorithms/overlay/robustness/test_overlay_p_q.hpp"&gt;function&lt;/a&gt;
is reused in other tests as well&lt;/span&gt;).&lt;br&gt;&lt;br&gt;
&lt;h2&gt;Unit test&lt;/h2&gt;
It &lt;span style="font-weight: bold;"&gt;is&lt;/span&gt; a
sort of a &lt;span style="font-weight: bold;"&gt;unit test&lt;/span&gt;,
because the program checks itself. I also use it as a unit test. But
note that the program is based on random input, and that&amp;nbsp;a
30-level test resuls in 2&lt;sup&gt;30&lt;/sup&gt;-1 unions and
intersections (~1G). So it runs for a while, and including this in the
standard Boost test suite will not be appreciated. So this &lt;span
 style="font-weight: bold;"&gt;recursive_polygons&lt;/span&gt;
can be run manually, and there are parameters to specify the number of
levels, et cetera.&lt;br&gt;
&lt;br&gt;
By the way, there &lt;span style="font-weight: bold;"&gt;are&lt;/span&gt;
many real unit tests within Boost.Geometry, there are currently 118
source files using the (great!) &lt;a
 href="http://live.boost.org/doc/libs/1_45_0/libs/test"&gt;Boost.Test&lt;/a&gt;
library, and some of them use polygons which are created by this
testprogram as their input.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
This recursive polygon unit test has been very valuable and, besides
that, such tests are nice to program. The whole program, links are
given above, is rather short, and it is of course Open Source. This
test might be useful for other libraries as well.&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-1222666594515417783?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/1222666594515417783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/intersections-2-recursive-polygons.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/1222666594515417783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/1222666594515417783'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/intersections-2-recursive-polygons.html' title='Intersections (2), &quot;recursive polygons&quot;'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_6zrdK5O_LIg/TRJkyo3_UJI/AAAAAAAABcg/jhD6tNM4f2o/s72-c/intersections_2a.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-6939584855783360523</id><published>2010-12-19T18:14:00.006+01:00</published><updated>2010-12-19T18:37:24.538+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='set theory'/><category scheme='http://www.blogger.com/atom/ns#' term='intersections'/><category scheme='http://www.blogger.com/atom/ns#' term='boolean operations'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='geometry'/><title type='text'>Intersections (1)</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Intersections (1)&lt;/h1&gt;
&lt;br&gt;
The &lt;a
 href="http://en.wikipedia.org/wiki/Boolean_operations_on_polygons"&gt;boolean
operations&lt;/a&gt; are probably&amp;nbsp;the most interesting parts
of the Boost.Geometry library. &lt;br&gt;
&lt;br&gt;
Boolean operations are, based
on two polygons:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;span style="font-weight: bold;"&gt;intersection&lt;/span&gt;,
returning polygons containing areas present
in both input polygons&lt;/li&gt;
  &lt;li&gt;&lt;span style="font-weight: bold;"&gt;union&lt;/span&gt;,
returning polygons containing all areas present in
either one of the input polygons&lt;/li&gt;
  &lt;li&gt;&lt;span style="font-weight: bold;"&gt;difference&lt;/span&gt;,
returning polygons containing areas present in
one of the input polygons, but not in the other&lt;/li&gt;
  &lt;li&gt;&lt;span style="font-weight: bold;"&gt;symmetric
difference&lt;/span&gt;, returning polygons containing areas
present in one of either input polygons, but not in both&lt;/li&gt;
&lt;/ul&gt;
In other words, boolean operations are spatial implementations of
mathematical &lt;a href="http://en.wikipedia.org/wiki/Set_theory"&gt;set
theoretic&lt;/a&gt;
operations. Based on two polygons A and B:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;span style="font-weight: bold;"&gt;intersection&lt;/span&gt;:
A and B, also written as A ∩ B&lt;/li&gt;
  &lt;li&gt;&lt;span style="font-weight: bold;"&gt;union&lt;/span&gt;:
A or B,&amp;nbsp;also written as&amp;nbsp;A ∪ B&lt;/li&gt;
  &lt;li&gt;&lt;span style="font-weight: bold;"&gt;difference&lt;/span&gt;:
A and not B,&amp;nbsp;also written as&amp;nbsp;A \ B&lt;/li&gt;
  &lt;li&gt;&lt;span style="font-weight: bold;"&gt;symmetric
difference&lt;/span&gt;: A xor B,&amp;nbsp;also written as&amp;nbsp;A ∆
B&lt;/li&gt;
&lt;/ul&gt;
The &lt;span style="font-weight: bold;"&gt;difference&lt;/span&gt;
operation (also known as &lt;a
 href="http://en.wikipedia.org/wiki/Complement_%28set_theory%29"&gt;relative
complement&lt;/a&gt;) is the only operation of these which is not
commutative,&amp;nbsp;A \ B results in another geometry than&amp;nbsp;B
\ A.&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;The basics&lt;/h2&gt;
&lt;img style="width: 546px; height: 539px;" alt="1a"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TQ4Z0-tX0YI/AAAAAAAABaU/YVyILt2q2PE/intersection_1a.png"&gt;&lt;br&gt;
&lt;br&gt;
This blog will not explain the whole algorithm, that would be way too
long. Other of my future blogs or a future article will explain more
details. The
algorithm used in Boost.Geometry is an adapted version of the &lt;a
 href="http://en.wikipedia.org/wiki/Weiler%E2%80%93Atherton"&gt;Weiler-Atherton&lt;/a&gt;
algorithm. The basics are quite simple, and explained &lt;a
 href="http://www.cs.drexel.edu/%7Edavid/Classes/CS430/HWs/p214-weiler.pdf"&gt;here&lt;/a&gt;,
and also in adapted versions as from &lt;a
 href="http://davis.wpi.edu/%7Ematt/courses/clipping/"&gt;Greiner-Hormann&lt;/a&gt;.
Note that I have adapted the algorithm myself,&amp;nbsp;such that
intersection points are &lt;span style="font-weight: bold;"&gt;not
inserted&lt;/span&gt; in the originals but &lt;span
 style="font-weight: bold;"&gt;stored
separately&lt;/span&gt;. Which is essential because we don't want to
change the input polygons, and we neither want to copy the input
polygons. I have made more adaptations, such that all situations
including self-tangencies (in some articles called degenerations) and
robustness are
handled.&lt;br&gt;
&lt;br&gt;
So only the very basics in this blog. There are&amp;nbsp;two input
polygons, A
and B (here: green and blue), both oriented clockwise. The arrows
indicate orientation at the starting points. Intersection points
(orange) are calculated. During the calculation of the intersection
points, traversal information is gathered: for an intersection
(usually: go to the right), would
it continue following the green or the blue outline... For example,
at point 0, above, it is figured out that for an intersection the green
line
should be followed, and for a union the blue line. Both until the next
intersection point is encountered. That requires sorting which is used
heavily within the algorithm.&lt;br&gt;
&lt;br&gt;
Turning right for intersections or left for unions is also visualized
below, from an older part of the GGL-doc:&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 282px; height: 507px;" alt="1f"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TQ4eX5KGTCI/AAAAAAAABao/L5I_uqDdrmU/intersection_1f.png"&gt;&lt;br&gt;
&lt;br&gt;
How traversal information is figured out, and how intersection points
are sorted, will be explained in another blog, maybe much later.&lt;br&gt;
&lt;br&gt;
So intersection points and turn information are basically all that is
necessary up to this point. The
traverse function uses this information, and adds points to the
accumulated
output polygon. Added points can be&amp;nbsp;either intersection points
or original vertices. The
output intersection then looks like this (slightly shifted by hand to
show it better):&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;&lt;img
 style="width: 291px; height: 289px;" alt="1c"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TQ4Z1dyMCcI/AAAAAAAABac/Hhug2Kyz_Uw/intersection_1c.png"&gt;&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
Note that it can become (often much) more complicated, holes,
intersections at vertices, self-tangencies, polygons-within-holes,
multi-polygons, etc.&amp;nbsp;&lt;br&gt;
&lt;br&gt;
Here the process for the intersection of a polygon with a polygon with
two holes:&lt;br&gt;
&lt;span style="text-decoration: underline;"&gt;&lt;img
 style="width: 570px; height: 525px;" alt="qg"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TQ4wWL-LKZI/AAAAAAAABaw/utx9sj30oo4/intersection_1g.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;Note that the numbers of the intersection points are shown
in
the order found, and not in the order of traversal. It is not possible
to indicate intersection points with an order of traversal, because
that order differs for intersection and union (check this in the
picture above). The (manually
added) red arrows depict the&amp;nbsp;traversal for intersection,
starting with the red
"0".&lt;br&gt;
&lt;br&gt;
Note also that holes are not a big addition to the algorithm, if they
are oriented
counterclockwise in clockwise polygons (and vice versa). This is an
assumption that &lt;span style="font-weight: bold;"&gt;is&lt;/span&gt;
made within Boost.Geometry. If this is the case, traversal can take its
routes always in the same way. The union operation would create two
holes, which are different from the original holes and stored
automatically in the correct orientation.&lt;br&gt;
&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;br&gt;
&lt;h2&gt;All boolean algorithms are the same&lt;/h2&gt;
I mean to say here: intersection, union, and (symmetric) difference are
all the same.&lt;br&gt;
&lt;br&gt;
We have seen above that for intersection and union the same information
is gathered. Only one variable, the traversal-direction, determines
what is the output. So easy, we have one algorithm in which we
calculate &lt;span style="font-weight: bold;"&gt;intersection&lt;/span&gt;
or &lt;span style="font-weight: bold;"&gt;union&lt;/span&gt;.&lt;br&gt;
&lt;br&gt;
Now for the &lt;span style="font-weight: bold;"&gt;difference&lt;/span&gt;,
it turns out that if we reverse one of the polygons (e.g. green one),
such that it is oriented counter-clockwise,&amp;nbsp;the difference is
calculated automatically by calculating the intersection of that
reversed A and the still normal B. That is not that strange, because it
follows from a mathematical rule. The difference of A and B is the same
as the intersection of the complement of A with&amp;nbsp;B. And the
complement of A (A&lt;sup&gt;c&lt;/sup&gt;) is just its reverse. Voila,
we do another function with the same algorithm.&lt;br&gt;
&lt;br&gt;
The complement (from older GGL-doc) of polygon A is the whole world but
A.&lt;br&gt;
&lt;img style="width: 450px; height: 395px;" alt="1e"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TQ4eXjlxwhI/AAAAAAAABak/ljNoEVeEAM4/intersection_1e.png"&gt;&lt;br&gt;
&lt;br&gt;
The &lt;span style="font-weight: bold;"&gt;symmetric
difference&lt;/span&gt;, A xor B, is just adding the two differences:
it is also defined as A and not B unioned by B and not A.&lt;br&gt;
&lt;br&gt;
Concluding this: all operations &lt;span style="font-weight: bold;"&gt;intersection&lt;/span&gt;,
&lt;span style="font-weight: bold;"&gt;union&lt;/span&gt;, &lt;span
 style="font-weight: bold;"&gt;difference&lt;/span&gt; and &lt;span
 style="font-weight: bold;"&gt;symmetric
difference&lt;/span&gt; are calculated with this one algorithm. The
algorithm consists of several sub algorithms, relevant for all
operations, and I hope to describe them later in more detail.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Reversing&lt;/h2&gt;
How do we take the reverse in the algorithm? In the past, I
cheated&amp;nbsp;and reversed the polygon before doing the algorithm.
That was easy, but has two drawbacks: 1) the input must be copyable and
2) it takes time to reverse. So we don't do this anymore. We just
iterate through it in reverse way. That is easy enough, using an
iterator walking reversely though the vertices. Or, in the case of
Boost.Geometry, we use a reversible_range, as explained in previous &lt;a
 href="http://barendgehrels.blogspot.com/2010/12/range-adaptors.html"&gt;blog&lt;/a&gt;.
It is all implemented using specializations and meta-programming.&lt;br&gt;
&lt;br&gt;
The difference is shown below. On the left side the
result,&amp;nbsp;again shifted slightly to make things more clear. The
right side shows the same but in a different&amp;nbsp;way: the
intersection of the complement of A (green) with B (blue).&lt;br&gt;
&lt;span style="font-style: italic;"&gt;&lt;span
 style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
&lt;img style="width: 648px; height: 325px;" alt="1b2"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TQ4j_E3UNhI/AAAAAAAABas/IdmKG3svBSE/intersection_1b2.png"&gt;&lt;br&gt;
&lt;span style="font-style: italic;"&gt;&lt;span
 style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
&lt;h2&gt;The one algorithm handles all geometries&lt;/h2&gt;
We have seen above that one algorithm is enough and that we can walk in
reverse through the polygons to support differences. What if we have
&lt;span style="font-weight: bold;"&gt;counterclockwise&lt;/span&gt;
polygons? The answer is the same, we walk through it
using our reversible ranges, which are in fact Boost.Range
reverse_range adaptors. So we calk backwards through it during getting
intersection points, and later when vertices are necessary for the
output, and actually everywhere where it is used.&lt;br&gt;
&lt;br&gt;
So we can handle &lt;span style="font-weight: bold;"&gt;clockwise&lt;/span&gt;
and &lt;span style="font-weight: bold;"&gt;counterclockwise&lt;/span&gt;
input polygons, and we
can even handle one clockwise, one counterclockwise, and the output can
also be clockwise or counterclockwise at wish. That last feature is
done
by appending points during traversal to the back of the output rings,
or inserting them at the front.&lt;br&gt;
&lt;br&gt;
The algorithm also handles combinations of &lt;span
 style="font-weight: bold;"&gt;rectangles&lt;/span&gt; and &lt;span
 style="font-weight: bold;"&gt;polygons&lt;/span&gt;,
because a rectangle can be seen as a polygon. The only difference is
that the calculation of intersection points is done more efficient.
Furthermore, multi-polygons can be handled. Note that&amp;nbsp;the
intersection of two polygons can result in a multi-polygon.&lt;br&gt;
&lt;br&gt;
So this seems a litany of what the algorithm can handle, and it does
not stop here. Because Boost.Geometry algorithms are independant on
their input point types, and also independant on their input polygon
types, and other geometry types, the algorithm can handle any geometry
type based on any point type. So it can handle &lt;span
 style="font-weight: bold;"&gt;4-byte-floats&lt;/span&gt; but
also
&lt;span style="font-weight: bold;"&gt;8-byte-doubles&lt;/span&gt;
or &lt;span style="font-weight: bold;"&gt;high-precision types&lt;/span&gt;
like &lt;a href="http://www.ttmath.org/ttmath"&gt;TTMath&lt;/a&gt;.
It can
handle &lt;span style="font-weight: bold;"&gt;boost::geometry
polygons&lt;/span&gt; but also &lt;span style="font-weight: bold;"&gt;ESRI
polygons&lt;/span&gt;, provided those
polygons are adapted to Boost.Geometry.&lt;br&gt;
&lt;br&gt;
Another aspect of this algorithm is that it is &lt;span
 style="font-weight: bold;"&gt;coordinate system
agnostic&lt;/span&gt;. It can handle cartesian polygons, but can also
calculate
intersections of spherical polygons. This is possible because the
algorithm is based on sub-algorithms as calculating the intersection
points, and finding the side (left/right) of a point with respect to
two other points. If those algorithms are provided (currently they are
not...) the intersection algorithm will handle them.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;The fastest...&lt;/h2&gt;
Finally, the implementation of boolean operations in Boost.Geometry is
also the most efficient intersection
algorithm which can be found.&amp;nbsp;If people don't believe this, or
want
to test it, or help benchmarking: there are Open Source benchmarks.
Other people are more independant as I am,&amp;nbsp;help would be
welcome.&lt;br&gt;
&lt;br&gt;
Below intersection of two multi-polygons with self-tangencies,
intersection is again shifted slightly. This comes from one of the
robustness tests.&lt;br&gt;
&lt;br&gt;
&lt;img style="width: 405px; height: 401px;" alt="1d"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TQ4cZPCfF5I/AAAAAAAABag/n_KY0GST0OI/intersection_1d.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Final remarks&lt;/h2&gt;
Using the reversible_range for (symmetric) difference instead of
reversing geometries, in the implementaiton,&amp;nbsp; was done
yesterday. So all this stuff above was planned but, until yesterday,
not implemented like it is today. So another step forwards is made.&lt;br&gt;
&lt;br&gt;
The review report (from now more than a year ago) said:&lt;br&gt;
&lt;br&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span
 style="font-style: italic;"&gt;Boolean operations: while the
library provides a set of Boolean operations&lt;/span&gt;&lt;span
 style="font-style: italic;"&gt; those seem to be not complete
and/or robust in terms of&lt;/span&gt;&lt;span
 style="font-style: italic;"&gt; clockwise/counterclockwise
geometries, closed/open polygons. Robust Boolean&lt;/span&gt;&lt;span
 style="font-style: italic;"&gt; operations are a strong
requirement, so this should be fixed as reported by&lt;/span&gt;&lt;span
 style="font-style: italic;"&gt; at least one reviewer.&lt;/span&gt;&lt;br
 style="font-style: italic;"&gt;
&lt;/div&gt;
&lt;br&gt;
This point is now dealt with. There are still a few tweaks to be done
but they will disappear coming weeks. I didn't discuss robustness in
this blog, and open polygons neither, but these issues are already
addressed too.&lt;br&gt;
&lt;br&gt;
Don't think you can implement boolean operations easily, though the
basic algorithm is quite simple... There are about 100 cases for
extraction of turn information from two intersecting segments. Besides
that there are also dozens of cases necessary for self-tangencies, in
GIS not so ubiquitous, but in games certainly important. I started the
algorithm in January 2008 and rewrote it two times after that, one time
before the review, and another time after it because there were issues
with the implementation, self-tangencies, and robustness. Now it should
be ready for production.&lt;br&gt;
&lt;br&gt;
The implementation is heavily based on C++, generic programming,
templates, specialization and meta-programming. I don't think it is
easily translatable into another language (but D). Also in C#,
where&amp;nbsp;specializations (at runtime) are possible according to
one of my previous &lt;a
 href="http://barendgehrels.blogspot.com/2010/07/c-specializations-by-traits-i.html"&gt;blogs&lt;/a&gt;,
metaprogramming is not possible, it is a compile-time mechanism.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-6939584855783360523?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/6939584855783360523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/intersections-1.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/6939584855783360523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/6939584855783360523'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/intersections-1.html' title='Intersections (1)'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_6zrdK5O_LIg/TQ4Z0-tX0YI/AAAAAAAABaU/YVyILt2q2PE/s72-c/intersection_1a.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-5776316430871284814</id><published>2010-12-13T22:57:00.002+01:00</published><updated>2010-12-20T22:45:20.899+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Range'/><category scheme='http://www.blogger.com/atom/ns#' term='iterators'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><category scheme='http://www.blogger.com/atom/ns#' term='traits'/><category scheme='http://www.blogger.com/atom/ns#' term='ranges'/><title type='text'>Range adaptors</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Range adaptors&lt;/h1&gt;
&lt;br&gt;
I seem to like doing blogs in series... (Or ranges ;-) .) See my
previous blog about
ranges &lt;a href="/2010/12/range-return-types-and-references.html"&gt;here&lt;/a&gt;.
This is a short bonus.&lt;br&gt;
&lt;br&gt;
Since Boost 1.43 released in May 2010, just before BoostCon'10, the
Boost.Range library has &lt;a
 href="http://www.boost.org/doc/libs/1_43_0/libs/range/doc/html/range/upgrade/upgrade_from_1_42.html"&gt;Range
Adaptors&lt;/a&gt;. Range adaptors enable users to change range
behaviour on the fly, for example traverse it in reverse order.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Reversing through geometries&lt;/h2&gt;
See this small and working snippet.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;using namespace&lt;/span&gt;
boost;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;geometry::model::linestring&amp;lt;P&amp;gt;
ls;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;geometry::read_wkt(&lt;span
 style="color: rgb(204, 0, 0);"&gt;"linestring(1
1,2 2,3 3,4 4)"&lt;/span&gt;, ls);&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;std::cout
&amp;lt;&amp;lt;&amp;nbsp;geometry::wkt(ls) &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;std::cout
&amp;lt;&amp;lt;
geometry::wkt(ls&amp;nbsp;|&amp;nbsp;adaptors::reversed)
&amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
This &amp;nbsp;will print out:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;LINESTRING(1 1,2 2,3
3,4 4)&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;LINESTRING(4 4,3 3,2
2,1 1)&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
So the original one and the reversed one. Works great, and great syntax.&lt;br&gt;
&lt;br&gt;
To
let this work, I had to adapt the Boost.Range reverse_range to
Boost.Geometry, such that Boost.Geometry knows the adapted
range&amp;nbsp;is a linestring.
In this case it is a linestring, but it might also be a ring (also a
range) or a
multi-point (also a range), etc. So I adapted it like this:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;namespace&lt;/span&gt;
traits &lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;{&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;template&lt;/span&gt;&amp;lt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;typename&lt;/span&gt;
Geometry&amp;gt;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;struct&lt;/span&gt;
tag&amp;lt;boost::range_detail::reverse_range&amp;lt;Geometry&amp;gt;
&amp;gt;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;{&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typedef&lt;/span&gt; typename
geometry::tag&amp;lt;Geometry&amp;gt;::type type;&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;};&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;}&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;br&gt;
Just
meta-programming, if a reverse_range is specified, it defines its tag
as it is for the unreversed geometry. This should work for all these
geometries because all of them are very light-weight, essentially only
requiring the tag metafunction in namespace traits. (Well, one
exception, the linear_ring (ring for short) also might optionally
define point order and closure.)&lt;br&gt;
&lt;br&gt;
We do the same for the other
Boost.Range adaptors, where relevant, and then have&amp;nbsp;filtered,
sliced, strided,
uniqued, reversed all out of the box. Great! I already liked
Boost.Range, and this new feature is cool either.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Why ranges are cool, revisited&lt;/h2&gt;
We
see here again why ranges can be preferred above iterators, and make some other statements:&lt;br&gt;
&lt;br&gt;
First we state in another way (than in the previous blog) that ranges are like normal
objects:
&lt;br&gt;&lt;span
 style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);"&gt;Ranges
are first class citizens, while iterators should be implementation
details&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;And then we make a statement about the cool adaptors we encountered in
Boost.Range:
&lt;br&gt;&lt;span
 style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);"&gt;A
range allows overloading&amp;nbsp;operators, in contrast with iterators&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
&lt;h2&gt;reverse_view&lt;/h2&gt;
Before ranges were there in May 2010,&amp;nbsp;I developed a
small utility class called reversed_view, where ranges are traversed in
either forward or backward direction.&lt;br&gt;
&lt;br&gt;
This reversed_view class is still there, but now greatly simplified,
the reverse one expressed&amp;nbsp;in terms of the
reversed_range adaptor. It is now defined like this:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;enum&lt;/span&gt;
iterate_direction { iterate_forward, iterate_reverse };&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&lt;span
 style="color: rgb(51, 51, 255);"&gt;template&lt;/span&gt;
&amp;lt;&lt;span style="color: rgb(51, 51, 255);"&gt;typename&lt;/span&gt;
Range, iterate_direction Direction&amp;gt;&lt;br&gt;
&lt;span style="color: rgb(51, 51, 255);"&gt;struct&lt;/span&gt;
reversible_view {};&lt;br&gt;
&lt;br&gt;
&lt;span style="color: rgb(51, 51, 255);"&gt;template&lt;/span&gt;
&amp;lt;&lt;span style="color: rgb(51, 51, 255);"&gt;typename&lt;/span&gt;
Range&amp;gt;&lt;br&gt;
&lt;span style="color: rgb(51, 51, 255);"&gt;struct&lt;/span&gt;
reversible_view&amp;lt;Range, iterate_forward&amp;gt;&lt;br&gt;
{&lt;br&gt;
&lt;span style="color: rgb(51, 51, 255);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typedef&lt;/span&gt; identity_view&amp;lt;Range&amp;gt; type;&lt;br&gt;
};&lt;br&gt;
&lt;br&gt;
&lt;span style="color: rgb(51, 51, 255);"&gt;template&lt;/span&gt;
&amp;lt;&lt;span style="color: rgb(51, 51, 255);"&gt;typename&lt;/span&gt;
Range&amp;gt;&lt;br&gt;
&lt;span style="color: rgb(51, 51, 255);"&gt;struct&lt;/span&gt;
reversible_view&amp;lt;Range, iterate_reverse&amp;gt; &lt;br&gt;
{&lt;br&gt;
&lt;span style="color: rgb(51, 51, 255);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typedef&lt;/span&gt;
boost::range_detail::reverse_range&amp;lt;Range&amp;gt; type;&lt;br&gt;
};&lt;br&gt;
&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;br&gt;
All
meta-functions. Seeming empty classes, but of great value. In the first
version it were not meta-functions but normal classes,
derived
from something or defining something. Therefore they needed an own
constructor etc. These are only typedef's, do not define any code,
therefore simpler and therefore better. In this case they exist because
templated typedefs are not there.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;closeable_view&lt;/h2&gt;
Boost.Geometry
also has a closeable view but alas I didn't find this in Boost.Range
adaptors, for obvious reasons (the adaptors strip, replace or adapt,
but do not add things). So the closeable_view is still there, but now
also expressed as meta-functions, the actively-closing one is a real
implementation, the already-closed on is another type definition.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-5776316430871284814?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/5776316430871284814/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/range-adaptors.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/5776316430871284814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/5776316430871284814'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/range-adaptors.html' title='Range adaptors'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-3517502952818469500</id><published>2010-12-12T13:32:00.000+01:00</published><updated>2010-12-12T22:23:13.341+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Range'/><category scheme='http://www.blogger.com/atom/ns#' term='iterators'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Polygon'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><category scheme='http://www.blogger.com/atom/ns#' term='ranges'/><title type='text'>Range, return types and references</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Range, return types and references&lt;/h1&gt;
&lt;br&gt;
During &lt;a href="http://www.boostcon.com"&gt;BoostCon&lt;/a&gt;
2009 the &lt;a
 href="http://www.boostcon.com/program/previous/2009#alexandrescu-iterators-must-go"&gt;keynote
speaker&lt;/a&gt; was &lt;a
 href="http://en.wikipedia.org/wiki/Andrei_Alexandrescu"&gt;Andrei
Alexandrescu&lt;/a&gt;, who wrote the book &lt;a
 href="http://en.wikipedia.org/wiki/Modern_C%2B%2B_Design"&gt;Modern
C++ Design&lt;/a&gt; in 2001. Andrei held a fabulous &lt;a
 href="http://blip.tv/file/2432106"&gt;presentation&lt;/a&gt; with
the name &lt;a
 href="http://www.boostcon.com/site-media/var/sphene/sphwiki/attachment/2009/05/08/iterators-must-go.pdf"&gt;"Iterators
Must Go"&lt;/a&gt;,
in which he point out several serious drawbacks of iterators. Iterators
have been the basic mechanism to use the Standard
Template Library classes, so this speach was revolutionary, and
enjoyable. Andrei not only critized iterators, he also gave an
alternative: &lt;span style="font-weight: bold;"&gt;ranges&lt;/span&gt;.
Ranges are for him the basic piece.&lt;br&gt;
&lt;br&gt;
The keynote was the forenote for an article that Andrei wrote, now with
the&amp;nbsp;title &lt;a
 href="http://www.informit.com/articles/printerfriendly.aspx?p=1407357"&gt;"On
Iteration"&lt;/a&gt;. The title is changed into a more subtile, but the
message is more
or less the same. I quote: &lt;span style="font-style: italic;"&gt;"STL
iterators are marred by lack of safety, difficulty of usage, difficulty
of definition" &lt;/span&gt;.&lt;br&gt;
&lt;br&gt;
Before BoostCon '09 with its famous keynote, I already knew the
&lt;a href="http://www.boost.org/doc/libs/1_45_0/libs/range"&gt;Boost.Range&lt;/a&gt;
library quite well. Most of the algorithms in
Boost.Geometry are based on ranges. We use Boost.Range everywhere.
Ranges are very nice. A std::vector is a range, but a std::pair of
iterators is also handled as a range, and a Boost.Array is also handled
as a range, and you can create your own ranges. Yes, like iterators,
but ranges are more elegant.&lt;br&gt;
&lt;br&gt;
Andrei Alexandrescu mentioned Boost.Range during his keynote, of
course. He said that Boost.Range was a good start, but should be worked
out way further. Until now, that has not been realized as far as I
know. But even without changes, Boost.Ranges are far more convenient
than iterators.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Iterators&lt;/h2&gt;
People reading this blog will know iterators and otherwise will have
stopped reading here. However, I like to explain the very basics
shortly because of the point
that Andrei &amp;nbsp;made: "iterators are unnecessary difficult", I've
always found that. This is how standard iterators work:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;std::vector&amp;lt;int&amp;gt;
a;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;// fill a&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;for
(std::vector&amp;lt;int&amp;gt;::const_iterator it = a.begin(); it !=
a.end(); ++it)&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;// do something with
*it&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
When I first worked with the std::library, somewhere in 199X, I refused
to do this and&amp;nbsp;wrote:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;for (int i = 0; i
&amp;lt; a.size(); i++)&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;// do something with
a[i]&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
This is half the size, easier to write, easier to read. But it is
(much) less efficient and should therefore not be done like that.&lt;br&gt;
&lt;br&gt;
Note also
that C++ programmers always write ++it and not it++ because it is
slightly (and detectably) more efficient.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Boost.Ranges&lt;/h2&gt;
A Boost.Range is a sort of view on a std::vector, or on any other
iterable instance. Boost.Range still defines and works with iterators.
It is another level of abstraction above the std:: library. With
iterators you iterate like this (still vector a):&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;for
(boost::range_iterator&amp;lt;std::vector&amp;lt;int&amp;gt;
const&amp;gt;::type it = boost::begin(a); it != boost::end(a); ++it)&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;// do something with
*it&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;Hey, this is even much longer! Yes, in this sample this is
true
and in general it is true, but ranges are normally (at least within
Boost.Geometry) used in a template environment, where it becomes:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;for
(typename boost::range_iterator&amp;lt;Range const&amp;gt;::type it =
boost::begin(a); it != boost::end(a); ++it)&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&lt;/span&gt;&lt;br&gt;
Not shorter but more generic: a Range can be anything.&lt;br&gt;
&lt;br&gt;
There
are shortcuts as well: with BOOST_FOREACH or BOOST_AUTO. They are
macro's, so often avoided, but they make things more readable and can
save template metaprogramming, see below. But first we will see why
ranges are so convenient.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;From Iterators to Ranges&lt;/h2&gt;
Boost.Geometry supports geometry algorithms such as &lt;span
 style="font-weight: bold;"&gt;distance&lt;/span&gt;. They are
defined in a generic way, so&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;template
&amp;lt;typename Geometry1, typename Geometry2&amp;gt;&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;double distance(&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt;Geometry1&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt; const&amp;amp; g1,&amp;nbsp;&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt;Geometry2 const&amp;amp; g2&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt;)&lt;/span&gt;
&lt;br&gt;
&lt;br&gt;
(The real version does not have the &lt;span
 style="font-style: italic;"&gt;double&lt;/span&gt; there but a
metafunction). With distance users can calculate the distance between
two points, or a point and a line (linestring), or a point and a
polygon, etc.&lt;br&gt;
&lt;br&gt;
The earlier version of Boost.Geometry (then called GGL), before going
to ranges,
could calculate the distance to of a part of a linestring by specifying
two
iterators as well:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;template
&amp;lt;typename Geometry1, typename Iterator&amp;gt;&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;double distance(&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt;Geometry1&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt; const&amp;amp; g1, Iterator&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt;&amp;nbsp;it1,
Iterator&amp;nbsp;it2&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt;)&lt;/span&gt;
&lt;br&gt;
&lt;br&gt;
This is great functionality, but it is completely inconvenient to
implement:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;all other functions are generic, having two arguments, why
does this one has three arguments?&lt;/li&gt;
  &lt;li&gt;all other functions are reversable, the distance from a
point to a line, and from a line to a point, both result into the same
implementation. For iterator support we would need to create an
overload having the iterators first&amp;nbsp;&lt;/li&gt;
  &lt;li&gt;there are more versions (for example: with a strategy), we
would need those overloads for those two, leading into another
combinatorial explosion (there are more algorithms too...)&lt;/li&gt;
&lt;/ul&gt;
When we discussed the GGL previews on the list, Mathias Gaunard &lt;a
 href="http://article.gmane.org/gmane.comp.lib.boost.devel/181215"&gt;suggested&lt;/a&gt;
to use ranges instead of Boost.Geometries and we took this over and
were very glad with this change.&lt;br&gt;
&lt;br&gt;
This is quite an argument for ranges instead of iterators in a
template-library environment, and this is why I emphasis this at this
point.&lt;br&gt;
&lt;br&gt;
So let me state:&lt;span
 style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);"&gt;
Ranges are compatible with other objects, while iterator-pairs are not.&lt;/span&gt;&lt;br&gt;
&lt;h2&gt;References&lt;/h2&gt;
After this lengthy introduction we consider how
iterators and ranges are passed.&lt;br&gt;
&lt;br&gt;
Iterators are normally passed by &lt;span
 style="font-style: italic; font-weight: bold;"&gt;value&lt;/span&gt;.
The main reason for this is explained nicely in &lt;a
 href="http://stackoverflow.com/questions/843996/whats-wrong-with-passing-c-iterator-by-reference"&gt;StackOverflow&lt;/a&gt;:
by passing by value you can create local copies, like v.begin().&lt;br&gt;
&lt;br&gt;
Ranges are normally passed by &lt;span
 style="font-style: italic; font-weight: bold;"&gt;reference&lt;/span&gt;.
Ranges might be non-copyable containers, so &lt;a
 href="http://www.boost.org/doc/libs/1_45_0/libs/range/doc/html/range/concepts/overview.html"&gt;passing
by reference&lt;/a&gt;
is required.&amp;nbsp; Besides the non-copyable issue, a std::vector &lt;span
 style="font-weight: bold; font-style: italic;"&gt;is&lt;/span&gt;
a
range. You definitely don't want to pass a std::vector by value.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Boost.Geometry's polygon&lt;/h2&gt;
Boost.Geometry contains models of geometries like &lt;span
 style="font-weight: bold;"&gt;linestring&lt;/span&gt; and &lt;span
 style="font-weight: bold;"&gt;ring&lt;/span&gt;.
They are defined as std::vector or a std::deque, but handled in the
code as a range. Any linestring or ring fulfilling the Range Concept
can be handled by Boost.Geometry, at least that is the basic idea. A
polygon is more more complex because it might contain holes, in the
definition of OGC and Boost.Geometry. So a polygon has an exterior ring
and zero or more interior rings, defining the holes. The exterior ring
fulfills the Ring Concept, the interior ring is a &lt;span
 style="font-weight: bold;"&gt;Range of Rings&lt;/span&gt;, so a
&lt;span style="font-weight: bold;"&gt;Range of Ranges&lt;/span&gt;,
a collection or rings.&lt;br&gt;
&lt;br&gt;
Boost.Geometry contains a free function &lt;span
 style="font-weight: bold;"&gt;exterior_ring&lt;/span&gt; which
returns the exterior ring by reference. And it also contains a free
function &lt;span style="font-weight: bold;"&gt;interior_rings&lt;/span&gt;
where the collection of interior rings are returned by reference. Both
functions have a const and a non-const version. Of course they don't
return the rings by value: polygons can be huge geometries, I've
recently processed a polygon of 6 megabytes (in WKT-format). They
should never be returned by value.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Other polygons&lt;/h2&gt;
With
Boost.Geometry, geometry classes of other libraries can be adapted,
such that Boost.Geometry can run algorithms on them as if it was one of
its own geometry classes. There are examples showing this with libgd's
points, WxWidgets's points, Qt's polygons, etc. With traits classes
these geometry classes can be adapted.&lt;br&gt;
&lt;br&gt;
However, until today, polygons were &lt;span style="font-weight: bold;"&gt;required&lt;/span&gt;
to return the exterior ring and interior rings by reference. But what
if those geometries do not use ranges?&lt;br&gt;
&lt;br&gt;
We encountered this adapting &lt;span style="font-weight: bold;"&gt;Boost.Polygon&lt;/span&gt;,
our sister library within the Boost family. &lt;a
 href="http://www.boost.org/doc/libs/1_45_0/libs/polygon/doc/index.htm"&gt;Boost.Polygon&lt;/a&gt;
defines a polygon-with-holes-concept, where iterators begin_holes and
end_holes are returned.&lt;br&gt;
&lt;br&gt;
So
after successfully adapting Boost.Polygon's point, rectangle and
polygon (without holes, so we call it a ring) to our library, I started
with the polygon. It is no problem that Boost.Polygon do not use the
range concept internally. Because we can build a sort of proxy,
simulating a range. So the adaptation of a Boost.Polygon
polygon-with-data consists of defining:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;an iterator to iterate through holes&lt;/li&gt;
  &lt;li&gt;a ring-proxy with an iterator-pair (point-begin, point-end)&lt;/li&gt;
  &lt;li&gt;an interior-ring-collection-proxy with an iterator-pair
(holes-begin, holes-end).&lt;/li&gt;
&lt;/ul&gt;
But there was one problem:&lt;br&gt;
&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;Returning local
references?&lt;/span&gt;&lt;/h2&gt;
Local
variables can (of course) not be returned as references. So you can
create ring-proxies, but they cannot be returned... That is to say,
they cannot be returned&amp;nbsp;&lt;span
 style="font-weight: bold; font-style: italic;"&gt;as a
reference&lt;/span&gt;. Of course, they can be returned by value.&lt;br&gt;
&lt;br&gt;
There are several solutions to this problem:&lt;br&gt;
&lt;ol&gt;
  &lt;li&gt;Change
the Boost.Geometry polygon concept to work with&amp;nbsp;iterators, so
let
it return iterators. This would be quite a lot of rework,
and&amp;nbsp;sounds like going ten years back. So discarded.&lt;/li&gt;
  &lt;li&gt;Change
Boost.Polygon's polygon concept. But that is of course not wished and
not possible. Boost.Polygon&amp;nbsp;is now an incorporated library.
Besides that, Boost.Polygon is an
example here, many polygon libraries will have polygon types having no
ranges internally. For
example, shapelib's geometry is just a set of pointers...
Boost.Geometry should&amp;nbsp;handle any geometry. So discarded&lt;/li&gt;
  &lt;li&gt;Let
Boost.Geometry's polygon concept return ranges always as values. This
is possible, but the return value for its own polygon should then &lt;span
 style="font-weight: bold;"&gt;not&lt;/span&gt; be the ring but
a&amp;nbsp;&lt;span style="font-weight: bold;"&gt;proxy&lt;/span&gt;
containing the reference of the ring.&lt;/li&gt;
  &lt;li&gt;Let Boost.Geometry's polygon concept return ranges
sometimes as value, sometimes as references&lt;/li&gt;
&lt;/ol&gt;
I've
chatted with my companion Bruno Lalande about this. He&amp;nbsp;had the
opinion that we definitely not should&amp;nbsp;go back to iterators. He
suggested the
fourth solution. Let me quote Bruno: &lt;span
 style="font-style: italic;"&gt;in Boost.Geometry, generic
functions like exterior_ring() or interior_ring() that only forward the
job to the actual adapted function, shouldn't make any assumption on
their return type. Currently they seem to be generic in this regard
since they get the return type by calling a metafunction, but they're
not fully generic because they arbitrarily add a "&amp;amp;" to it.&lt;/span&gt;
Boost.Range returns ranges &lt;a
 href="http://www.boost.org/doc/libs/1_45_0/libs/range/doc/html/range/reference/algorithms/mutating/reverse.html"&gt;by
reference&lt;/a&gt; and&amp;nbsp;&lt;a
 href="http://www.boost.org/doc/libs/1_45_0/libs/range/doc/html/range/reference/utilities/iterator_range.html"&gt;by
value&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
Andrei
Alexandrescu returns ranges in his article, on various places. We might
change our own polygon type, returning proxies to ranges, and returning
them by value. This would be solution 3. However, as long as this is
not necessary, we prefer solution 4, to avoid an unecessary proxy in
between, and to enable range-based polygon-types to return references
to ranges.&lt;br&gt;
&lt;br&gt;
Exterior rings should sometimes be returned as values, and sometimes as
references. &lt;br&gt;
&lt;br&gt;
So I changed the Boost.Geometry library into &lt;span
 style="font-style: italic;"&gt;range-return-type agnostic
behaviour.&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
So let me summarize:&lt;span
 style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);"&gt;
Ranges
can be&amp;nbsp;returned as values or as references&lt;/span&gt;&lt;br&gt;
&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;More
metaprogramming&lt;/span&gt;&lt;/h2&gt;
To
implement solution 4 mentioned above, Boost.Geometry's polygon needed
two characters extra: two ampersands. So its traits function ring_type
now reads:&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;template&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;lt;&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typename Point,&lt;/span&gt;&lt;span style="font-family: monospace;"&gt;
bool ClockWise, bool Closed,&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
template&amp;lt;typename, typename&amp;gt; class PointList,&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
template&amp;lt;typename, typename&amp;gt; class RingList,&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
template&amp;lt;typename&amp;gt; class PointAlloc,&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt;
template&amp;lt;typename&amp;gt; class RingAlloc&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;gt;&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;struct ring_type&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;lt;&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
model::polygon&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Point, ClockWise, Closed,&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PointList, RingList, PointAlloc, RingAlloc&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;gt;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;gt;&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;{&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typedef typename model::polygon&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Point, ClockWise, Closed,&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PointList, RingList,&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PointAlloc, RingAlloc&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;gt;::ring_type&lt;span style="font-weight: bold;"&gt;&amp;amp;&lt;/span&gt;
type;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;};&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;br style="font-family: monospace;"&gt;
where the ampersand is added... Meaning, the ring-returning-type is now
a reference!&lt;br&gt;
&lt;br&gt;
Of course some more changes were necessary, but not more. The free
function &lt;span style="font-weight: bold;"&gt;exterior_ring&lt;/span&gt;
now uses a meta-function to define its return type. That meta-function
uses the traits-function ring_type, so returns sometimes a reference,
sometimes a value. For const and non-const, another metafunction is
created:&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;template
&amp;lt;typename T&amp;gt;&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;struct
ensure_const_reference&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;{&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typedef typename mpl::if_&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typename boost::is_reference&amp;lt;T&amp;gt;::type,&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typename boost::add_reference&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typename boost::add_const&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typename boost::remove_reference&amp;lt;T&amp;gt;::type&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;gt;::type&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;gt;::type,&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
T&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;gt;::type type;&lt;/span&gt;&lt;br style="font-family: monospace;"&gt;
&lt;span style="font-family: monospace;"&gt;};&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;br&gt;
I
like metaprogramming. If the type was a reference, it removes it, adds
a const, and adds a reference again. If it was not a reference, it
keeps it unchanged. This is type calculation, metaprogramming.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;Iterating
through const/non const collections of values/references&lt;/span&gt;&lt;/h2&gt;
At
every place where Boost.Range iterators were used to iterate through
interior rings, a change was necessary. This was possible creating
another metafunction, but Bruno suggested to use BOOST_AUTO here. This
avoids new metafunctions, and makes all iterations more readable. This
works perfectly for both const and non const iterators, so in fact it
is all much more simple than before. Loops are now written like this:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;for (BOOST_AUTO(it,
boost::begin(interior_rings(polygon)));&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt; &lt;br&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;it !=
boost::end(interior_rings(polygon));&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt; &amp;nbsp;&lt;br&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;++it)&lt;/span&gt;&lt;br
 style="font-family: monospace;"&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;&lt;span
 style="color: red;"&gt;&lt;/span&gt;&lt;/span&gt;This
BOOST_AUTO word, which anticipates the C++0x auto keyword, saves
defining and declaring metafunctions all the time. It is a macro (yack)
but very valuable here, also because if we change things another time,
this can stay as it is now.&lt;br&gt;
&lt;br&gt;
One thing is noteworthy, there are two calls to interior_rings
returning (in the return-by-value case) two copies. Because these
copies are suspected to be proxies, containing references to the
original (single) object, the iterator-behaviour will be all right,
they are both pointing to the same original range.&lt;br&gt;
&lt;br&gt;
However, better
safe then sorry, better defensive, so we should write here:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-family: monospace;"&gt;BOOST_AUTO(irings, &lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt;interior_rings(polygon));&lt;br&gt;
&lt;/span&gt;&lt;span style="font-family: monospace;"&gt;for
(BOOST_AUTO(it, boost::begin(irings));&lt;/span&gt;&lt;span
 style="font-family: monospace;"&gt;&amp;nbsp;it !=
boost::end(irings);&lt;/span&gt;&lt;span style="font-family: monospace;"&gt;
&amp;nbsp;++it)&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
which might be also more efficient in some cases.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;&lt;span style="font-weight: bold;"&gt;Conclusions&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Ranges are great.&lt;/li&gt;
  &lt;li&gt;Ranges are compatible with other objects, while
iterator-pairs are not&lt;/li&gt;
  &lt;li&gt;Ranges can be returned as values or as references&lt;/li&gt;
  &lt;li&gt;Boost.Geometry's polygon concept uses ranges, allowing
adaption of other polygon types using implementation of range proxies&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-3517502952818469500?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/3517502952818469500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/range-return-types-and-references.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/3517502952818469500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/3517502952818469500'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/range-return-types-and-references.html' title='Range, return types and references'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-3960748557494857137</id><published>2010-12-08T23:27:00.004+01:00</published><updated>2011-01-10T21:59:51.150+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='world'/><category scheme='http://www.blogger.com/atom/ns#' term='WKT'/><category scheme='http://www.blogger.com/atom/ns#' term='countries'/><category scheme='http://www.blogger.com/atom/ns#' term='shapefile'/><title type='text'>Free Shapefiles of Countries of the World (2)</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Free Shapefiles of&amp;nbsp;Countries of the World (2)&lt;/h1&gt;
&lt;br&gt;
&lt;i&gt;Note: read also &lt;a href="/2010/12/free-shapefiles-of-of-world-3.html"&gt;part 3&lt;/a&gt; 
and &lt;a href="/2011/01/free-shapefiles-of-countries-of-world-4.html"&gt;part 4&lt;/a&gt;
of this blog.&lt;/i&gt;
&lt;br&gt;&lt;br&gt;


After input on my &lt;a
 href="/2010/12/free-shapefile-of-countries-of-world.html"&gt;recent
blog&lt;/a&gt; (thanks!) and after that I find two more,
another post about this.&lt;br&gt;
&lt;br&gt;
To judge the quality of the dataset, I use my own country (the
Netherlands) as the primary measure. I've a mental map about my
country, and know how it should look like. In many of the found
datasets it looks completely destroyed. Therefore, personally I would
discard them at once. Other datasets quite precisely depict my country.
Maybe it is not only because I live here, but also about the
topography: it has a large inner lake, it has some islands, and it has
a distinctive shape.&lt;br&gt;
&lt;br&gt;
So here the previous datasets, and four more, and some variations, come
again...&lt;br&gt;
&lt;br&gt;
&lt;table style="text-align: left; width: 100%;" border="0"
 cellpadding="2" cellspacing="10"&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world1"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TP_-RX4aJJI/AAAAAAAABYE/5FHuyXjoJSI/world1.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(1)&lt;/li&gt;
        &lt;li&gt;from &lt;a
 href="http://www.aprsworld.net/gisdata/world/"&gt;aprs&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file world.shp &lt;/li&gt;
        &lt;li&gt;from 2002&lt;/li&gt;
        &lt;li&gt;244 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;Missing
a polder existing since 1968&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;br&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world2"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TP_-RQx2nLI/AAAAAAAABYI/2IYm4AAExjk/world2.gif"&gt;
      &lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(2)&lt;/li&gt;
        &lt;li&gt;from &lt;a
 href="http://www.brothersoft.com/world-map-data-97757.html"&gt;brothersoft&lt;/a&gt;,
serving blue marble data&lt;/li&gt;
        &lt;li&gt;file World_countries_shp.shp&lt;/li&gt;
        &lt;li&gt;from 1996&lt;/li&gt;
        &lt;li&gt;239 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;All
shape is destroyed&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world3"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TP_-ReuXANI/AAAAAAAABYM/TBXUTN-Kz-Q/world3.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(3)&lt;/li&gt;
        &lt;li&gt;from &lt;a
 href="http://www.mapcruzin.com/free-world-country-arcgis-maps-shapefiles.htm"&gt;&lt;/a&gt;&lt;a
 href="http://www.geodan.com/"&gt;Geodan&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file WorldCountries.shp&lt;/li&gt;
        &lt;li&gt;from 2003&lt;/li&gt;
        &lt;li&gt;253 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;The
Netherlands are depicted correctly&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;br&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world4"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TP_-RjQXETI/AAAAAAAABYQ/3ZlZ55wqEmk/world4.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(4)&lt;/li&gt;
        &lt;li&gt;from &lt;a href="http://www.mappinghacks.com/data/"&gt;mapping
hacks&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file world_borders.shp &lt;/li&gt;
        &lt;li&gt;from 2004&lt;/li&gt;
        &lt;li&gt;251 countries, 3784 polygons&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;Showing
a polder which is never realized&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;br&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world5"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TP_-Rr5ZX-I/AAAAAAAABYU/WqwfNcpBf1o/world5.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(5)&lt;/li&gt;
        &lt;li&gt;from&amp;nbsp;&lt;a
 href="http://thematicmapping.org/downloads/world_borders.php"&gt;thematic
mapping&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file TM_WORLD_BORDERS-0.3.shp&lt;/li&gt;
        &lt;li&gt;from 2008&lt;/li&gt;
        &lt;li&gt;246 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;Showing
a polder which is never realized&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;br&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world5b"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TP_-VzMsgzI/AAAAAAAABYY/-q_C3OAFUX8/world5b.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(5b)&lt;/li&gt;
        &lt;li&gt;also from&amp;nbsp;&lt;a
 href="http://thematicmapping.org/downloads/world_borders.php"&gt;thematic
mapping&lt;/a&gt;&amp;nbsp;but the simplified version&lt;/li&gt;
        &lt;li&gt;file TM_WORLD_BORDERS_SIMPL-0.3.shp &lt;/li&gt;
        &lt;li&gt;also from 2008&lt;/li&gt;
        &lt;li&gt;also 246 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;Badly
simplified&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world6"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TP_-Vyu-AHI/AAAAAAAABYc/VWeEh7l_DHI/world6.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(6)&lt;/li&gt;
        &lt;li&gt;from openmap &lt;a
 href="http://openmap.bbn.com/data/shape/"&gt;here&lt;/a&gt;,
called cntry02&lt;/li&gt;
        &lt;li&gt;file cntry02.shp &lt;/li&gt;
        &lt;li&gt;from 2002&lt;/li&gt;
        &lt;li&gt;251 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;Showing
a polder which is never realized, missing three islands&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world7"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TP_-WN4ypSI/AAAAAAAABYg/0qjV32fPCkw/world7.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(7)&lt;/li&gt;
        &lt;li&gt;from this&amp;nbsp;&lt;a
 href="http://www.baruch.cuny.edu/geoportal/data/esri/esri_intl.htm"&gt;site&lt;/a&gt;&amp;nbsp;ESRI
data&lt;/li&gt;
        &lt;li&gt;file cntry08.shp &lt;/li&gt;
        &lt;li&gt;from 2008&lt;/li&gt;
        &lt;li&gt;249 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;Missing
three (inhabited) islands in the North. For the rest it looks like a
good map on this scale&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world8"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TP_-WM5T_qI/AAAAAAAABYk/kjnTaUOr22Y/world8.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(8)&lt;/li&gt;
        &lt;li&gt;from &lt;a href="http://www.vdstech.com/map_data.htm"&gt;vdstech&lt;/a&gt;
via&amp;nbsp;&lt;a
 href="http://blog.sqlauthority.com/2010/03/30/sql-server-world-shapefile-download-and-upload-to-database-spatial-database/"&gt;this
blog&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file world.shp &lt;/li&gt;
        &lt;li&gt;from 2001&lt;/li&gt;
        &lt;li&gt;251 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;Badly
simplified&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world9"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TP_-WEWjI1I/AAAAAAAABYo/IkjrDH-kpEY/world9.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(9)&lt;/li&gt;
        &lt;li&gt;from &lt;a
 href="=http://www.naturalearthdata.com/downloads/"&gt;natural
earth&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file 10m-admin-0-countries.shp&amp;nbsp;&lt;/li&gt;
        &lt;li&gt;from 2009&lt;/li&gt;
        &lt;li&gt;251 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;Missing
the inner lake the IJsselmeer&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world9b"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TP_-ZJKyFaI/AAAAAAAABYs/kxcS1SxND7s/world9b.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(9b)&lt;/li&gt;
        &lt;li&gt;from &lt;a
 href="=http://www.naturalearthdata.com/downloads/"&gt;natural
earth&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file 50m_admin_0_countries.shp&amp;nbsp;&lt;/li&gt;
        &lt;li&gt;from 2010&lt;/li&gt;
        &lt;li&gt;240 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;Missing
the inner lake the IJsselmeer&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world9c"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TP_-ZKJCfAI/AAAAAAAABYw/jYn7xWZSM_U/world9c.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(9c)&lt;/li&gt;
        &lt;li&gt;from &lt;a
 href="=http://www.naturalearthdata.com/downloads/"&gt;natural
earth&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file 110m_admin_0_countries.shp&amp;nbsp;&lt;/li&gt;
        &lt;li&gt;from 2010&lt;/li&gt;
        &lt;li&gt;177 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;Too
much simplified&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;(10). I wanted to do &lt;a
 href="http://gis-lab.info/qa/vmap0-eng.html"&gt;VMAP0&lt;/a&gt;
/ VMAP1 here. However, my little research concerns a (one) shapefile of
countries of the world. Vmap0 is great but to let users figure out all
the detailed files and merge them for four parts&lt;br&gt;
of the world is not the purpose I started the research with... so no
picture here. Thanks for the tip anyway.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img style="width: 330px; height: 330px;"
 alt="world11"
 src="http://lh3.ggpht.com/_6zrdK5O_LIg/TP_-Zeh2uUI/AAAAAAAABY0/3fxErybadu0/world11.gif"&gt;&lt;/td&gt;
      &lt;td&gt;
      &lt;ul&gt;
        &lt;li&gt;(11)&lt;/li&gt;
        &lt;li&gt;from&amp;nbsp;&lt;a
 href="http://huebler.blogspot.com/2005/11/creating-maps-with-stata.html"&gt;huebler&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;file world_adm0.shp&amp;nbsp;&lt;/li&gt;
        &lt;li&gt;from 2002&lt;/li&gt;
        &lt;li&gt;209 countries&lt;/li&gt;
        &lt;li&gt;&lt;span style="color: rgb(228, 0, 0);"&gt;Missing
the inner lake the IJsselmeer&lt;/span&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;br&gt;
Based on this series, (3) would probably be the best choice, though a
bit heavily detailed. Surprisingly, it is created in the Netherlands...
So we cannot judge its quality from this series. Furthermore,&amp;nbsp;
(7) would be a reasonable choice,&amp;nbsp;but we saw in the previous
blog that (7) is wrong with respect to the Caspian sea. The new dataset (9b) is looking quite good to me for a map on world scale, but alas it misses an important lake. We might see
more in another blog, for example showing the countries around the
Caspian sea, or the countries in the former republic of Yugoslavia.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
I think a good and free shapefile of the world is still&amp;nbsp;welcome.&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-3960748557494857137?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/3960748557494857137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/free-shapefiles-of-of-world-2.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/3960748557494857137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/3960748557494857137'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/free-shapefiles-of-of-world-2.html' title='Free Shapefiles of&amp;nbsp;Countries of the World (2)'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_6zrdK5O_LIg/TP_-RX4aJJI/AAAAAAAABYE/5FHuyXjoJSI/s72-c/world1.gif' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-8784335683923097047</id><published>2010-12-02T23:32:00.001+01:00</published><updated>2011-01-04T18:21:06.442+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='world'/><category scheme='http://www.blogger.com/atom/ns#' term='WKT'/><category scheme='http://www.blogger.com/atom/ns#' term='countries'/><category scheme='http://www.blogger.com/atom/ns#' term='shapefile'/><title type='text'>Free Shapefile of Countries of the World</title><content type='html'>&lt;br&gt;

&lt;h1&gt;Free Shapefile of&amp;nbsp;Countries of the World&lt;/h1&gt;
&lt;br&gt;
&lt;i&gt;Note: read also &lt;a href="/2010/12/free-shapefiles-of-of-world-2.html"&gt;part 2&lt;/a&gt; and &lt;a href="/2010/12/free-shapefiles-of-of-world-3.html"&gt;part 3&lt;/a&gt; of this blog.&lt;/i&gt;
&lt;br&gt;&lt;br&gt;

I'm always surprised that it is hard to find a good shapefile with
world countries. I need country vector data for Boost.Geometry sample
data. There is some there but I want to have another set. I want to
have it as WKT (Well-Known Text) and I can use a shapefile as input.&lt;br&gt;
&lt;br&gt;
Asking Google for "free world map shapefile"&amp;nbsp;you get:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.aprsworld.net/gisdata/world/"&gt;aprs&lt;/a&gt;
(1), with also a modified version&lt;/li&gt;
  &lt;li&gt;&lt;a
 href="http://www.bluemarblegeo.com/products/worldmapdata.php?op=download"&gt;blue
marble&lt;/a&gt;&amp;nbsp;requires registration, but (probably) the
same set can be downloaded from the next entry&lt;/li&gt;
  &lt;li&gt;&lt;a
 href="http://www.brothersoft.com/world-map-data-97757.html"&gt;brothersoft&lt;/a&gt;,
serving blue marble data (2)&lt;/li&gt;
  &lt;li&gt;&lt;a
 href="http://www.mapcruzin.com/free-world-country-arcgis-maps-shapefiles.htm"&gt;mapcruzin&lt;/a&gt;
(leading to &lt;span style="font-weight: bold;"&gt;no&lt;/span&gt;
countries but several interesting other shapefiles)&lt;/li&gt;
&lt;/ul&gt;
Via my company, &lt;a href="http://www.geodan.com"&gt;Geodan&lt;/a&gt;,
you can also download a worldmap, &lt;a
 href="http://www.geodan.com/no_cache/products/geographic-data-catalogue/products/achtergrondinfo-dataproducten/download/"&gt;here&lt;/a&gt;
(requiring mailing your contact information) (3)&lt;br&gt;
&lt;br&gt;
Via free gis data, &lt;a
 href="http://freegis.org/database/?cat=1&amp;amp;_ZopeId=34937845A4qWRfhvgwA"&gt;here&lt;/a&gt;,
there is a hit on ESRI, leading to this &lt;a
 href="http://www.esri.com/data/free-data/index.html"&gt;site&lt;/a&gt;,
leading to annual subscriptions etc.. I skipped this one.&lt;br&gt;
&lt;br&gt;
Via similar terms ("countries") we also find:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.mappinghacks.com/data/"&gt;mapping
hacks&lt;/a&gt;, serving three world files (4)&lt;/li&gt;
  &lt;li&gt;actually originating from this &lt;a
 href="http://thematicmapping.org/downloads/world_borders.php"&gt;site&lt;/a&gt;,
which has a more actual version (5)&lt;/li&gt;
  &lt;li&gt;a file from openmap &lt;a
 href="http://openmap.bbn.com/data/shape/"&gt;here&lt;/a&gt;,
called cntry02 (6)&lt;/li&gt;
  &lt;li&gt;and finally (via "cntry08") we find ESRI data&amp;nbsp;&lt;a
 href="http://www.baruch.cuny.edu/geoportal/data/esri/esri_intl.htm"&gt;here&lt;/a&gt;
(7)&lt;/li&gt;
&lt;/ul&gt;
I've downloaded these shapefiles. It gives me (file dates):&lt;br&gt;
&lt;ol&gt;
  &lt;li&gt;is from 2002, modified in 2009 for Antarctica&lt;/li&gt;
  &lt;li&gt;is from 1996&lt;/li&gt;
  &lt;li&gt;is from 2003&lt;/li&gt;
  &lt;li&gt;is from 2004&lt;/li&gt;
  &lt;li&gt;is from 2008&lt;/li&gt;
  &lt;li&gt;is from 2002&lt;/li&gt;
  &lt;li&gt;is from 2008&lt;/li&gt;
&lt;/ol&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;The Netherlands&lt;/span&gt;&lt;br&gt;
Let's first show&amp;nbsp;my country, the Netherlands:&lt;br&gt;
&lt;img style="width: 500px; height: 364px;" alt="netherlands"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TPgcsguh6SI/AAAAAAAABRY/MKePgtQY2gI/nl.png"&gt;&lt;br&gt;
&lt;br&gt;
All borders through each other look quite messy... But let's
concentrate on the data.&lt;br&gt;
&lt;a href="http://en.wikipedia.org/wiki/Flevoland"&gt;Southern
Flevoland&lt;/a&gt;,
a polder, already existing since 1968, is still not there on
maps from 1 (aprsworld, green) and 2 (blue marble, so blue). Of course
it is present on the map of my company 3 (geodan, red), because Geodan
of course takes care for its own country. Southern Flevoland is also
present on all newer maps (5, pink, 6 orange, 7 gray). But on 5
and&amp;nbsp;6 it has a planned but not realized polder (Markerwaard)
included. So best
for the Netherlands are 3 and 7.&lt;br&gt;
&lt;br&gt;
Of
the five inhabited islands along the Waddenzee, 7 depicts only two. So
here 3 is the best choice (of course, it is our country, and note that
for the rest this
is not a commercial talk)&lt;br&gt;
&lt;br&gt;
For the whole world, 6 and 7 are quite similar in nearly all aspects&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Uruguay&lt;/span&gt;&lt;br&gt;
Let's now look at a country not part of Europe or US. I select Uruguay:&lt;br&gt;
&lt;img style="width: 500px; height: 439px;" alt="Uruguay"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TPgcstHNMXI/AAAAAAAABRc/a6adGUt5XnI/uruguay.png"&gt;&lt;br&gt;
&lt;br&gt;
The blue vectors are quite rough and shifted to the west and north.
Green lines are looking nice for a map on this scale, but deviate a bit
from all other maps.&lt;br&gt;
&lt;br&gt;
Let's now take a look in Google Earth. For this, we need to create a
KML file... &amp;nbsp;hmm, shp2kml cannot be downloaded (blank website
saying &lt;span style="font-weight: bold;"&gt;Missing ID&lt;/span&gt;).
OK, we use PostGIS then, it can create KML and WKT (we need it below).&lt;br&gt;
&lt;span style="font-style: italic; font-weight: bold;"&gt;&lt;br&gt;
shp2pgsql -s4326 world.shp world1 &amp;gt; world1.sql&lt;/span&gt;&lt;br&gt;
etc&lt;br&gt;
&lt;br&gt;
So I created a database called &lt;span style="font-weight: bold;"&gt;blog&lt;/span&gt;
and executed these SQL files.&lt;br&gt;
Five minutes later (PostGIS is great) I do:&lt;br&gt;
&lt;span style="font-weight: bold; font-style: italic;"&gt;psql
"-F " -A -n -t -q -Upostgres -dblog "-cselect
'&amp;lt;Placemark&amp;gt;',ST_AsKml(the_geom),'&amp;lt;/Placemark&amp;gt;'
from world2 where name='Uruguay'" -otworld2.kml &lt;br&gt;
&amp;nbsp;&lt;/span&gt;&lt;br
 style="font-weight: bold; font-style: italic;"&gt;
Doing this for all tables and reworking the KML's &amp;nbsp;a bit
(adding
headers etc) gives me:&lt;br&gt;
&lt;img style="width: 672px; height: 734px;"
 alt="Uruguay with Google Maps"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TPgcs5boZAI/AAAAAAAABRg/wZ0PmIyjGbg/s640/uruguay_gm.png"&gt;&lt;br&gt;
&lt;br&gt;
Considering Google Maps as our Single Point of Truth, we can
discard the blue lines from Blue Marble, and might think that the green
lines are also wrong. The rest is following the borders more or less
but we need to zoom in to judge it better.&lt;br&gt;
&lt;br&gt;
This is the new detail on a border:&lt;br&gt;
&lt;img style="width: 500px; height: 504px;"
 alt="Uruguay Google Detailed"
 src="http://lh5.ggpht.com/_6zrdK5O_LIg/TPgcxzNV9QI/AAAAAAAABRk/YXRrFMzvnvw/uruguay_gm1.png"&gt;&lt;br&gt;
&lt;br&gt;
The
Yellow line is Google's line. The red line is following it, probably a
bit too much. For a global scale, the other ones (4,5,6,7) are doing
well here. &lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Caspian Sea&lt;/span&gt;&lt;br&gt;
Looking
at global level, we see immediately one thing, on which we zoom in
here:&amp;nbsp;it is&amp;nbsp;surprising that the Caspian sea is not
included
in map 6 and 7. So the country borders are just across the sea... Not
so good.&lt;br&gt;
&lt;img style="width: 534px; height: 726px;" alt="Caspian see"
 src="http://lh4.ggpht.com/_6zrdK5O_LIg/TPgcrbo6B_I/AAAAAAAABRQ/EnWwn1J1NJ8/s640/caspian.png"&gt;&lt;br&gt;
&lt;br&gt;
Not
so good. So let's discard 6 and 7. We also see that the red lines (3)
are too detailed, also here. Discard 3. Blue (2) and green (1) was
already discarded before. So we keep 4 and 5, which are roughly the
same. So I decide to keep the more actualy one: 5.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Decision&lt;/span&gt;&lt;br&gt;
So
we conclude, based on a few samples (and some more but not described
here), that the file TM_WORLD_BORDERS-0.3.zip &amp;nbsp;from&amp;nbsp;&lt;a
 href="http://thematicmapping.org/downloads/world_borders.php"&gt;Thematic
Mapping&lt;/a&gt; is the best shapefile to use for worldscale countries
(even though it contains the Markerwaard).&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Country number and
validity&lt;/span&gt;&lt;br&gt;
We did not consider attributes, and our research was
still&amp;nbsp;rough.&lt;br&gt;
&lt;br&gt;
An important aspect we want to consider is geometric validity. And,
even more important, the number of countries, it can differ over years,
but the differences are sometimes still surprising.&lt;br&gt;
&lt;table style="text-align: left; width: 100%;" border="1"
 cellpadding="2" cellspacing="2"&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Dataset&lt;/td&gt;
      &lt;td&gt;Invalid (SQL Server)&lt;/td&gt;
      &lt;td&gt;Invalid (PostGIS)&lt;/td&gt;
      &lt;td&gt;#Countries&lt;/td&gt;
      &lt;td&gt;Year&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;244&lt;/td&gt;
      &lt;td&gt;2002 / 2009&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;239&lt;/td&gt;
      &lt;td&gt;1996&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;34&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;253&lt;/td&gt;
      &lt;td&gt;2003&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;6 polygons&lt;/td&gt;
      &lt;td&gt;251 (3784 polygons (this dataset
contains&amp;nbsp;polygonsp; not multi-polygons)&lt;/td&gt;
      &lt;td&gt;2004&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;246&lt;/td&gt;
      &lt;td&gt;2008&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;251&lt;/td&gt;
      &lt;td&gt;2002&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;249&lt;/td&gt;
      &lt;td&gt;2008&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
About
the&amp;nbsp;countries themselves, I just glanced through the
differences
using a query, comparing ISO3 country codes, getting this table:&lt;br&gt;
&lt;img style="width: 445px; height: 492px;"
 alt="Compare 5 and 7"
 src="http://lh6.ggpht.com/_6zrdK5O_LIg/TPgcshLzy-I/AAAAAAAABRU/4OyB5FslWHM/compare_5_7.png"&gt;&lt;br&gt;
&lt;br&gt;
We see some inconsistent and some missing ISO codes, and some countries
not in the one but in the other, and vice versa.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
I think a good and free shapefile of the world is still&amp;nbsp;
welcome.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-8784335683923097047?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/8784335683923097047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/free-shapefile-of-countries-of-world.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/8784335683923097047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/8784335683923097047'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/12/free-shapefile-of-countries-of-world.html' title='Free Shapefile of Countries of the World'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_6zrdK5O_LIg/TPgcsguh6SI/AAAAAAAABRY/MKePgtQY2gI/s72-c/nl.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-3417848162638333354</id><published>2010-11-16T13:56:00.001+01:00</published><updated>2010-12-20T22:45:57.923+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='delphi'/><title type='text'>Delphi TDateTimePicker with WeekNumber</title><content type='html'>&lt;br&gt;
This is not about C++ or C# or Geometry but about Delphi.
&lt;br/&gt;&lt;br/&gt;

I used to have a TDateTimePicker in my app showing the week number. This trick is described on several places, e.g. &lt;a href="http://www.scalabium.com/faq/dct0164.htm"&gt;here&lt;/a&gt;


and (in Dutch) &lt;a href="http://www.nldelphi.com/forum/showthread.php?t=15661"&gt;here&lt;/a&gt;
&lt;br/&gt;&lt;br/&gt;



However, since Windows 7 (or probably since Windows Vista) this behaves differently, resulting in an ugly calendar where the right side  is cut off :-(

&lt;br/&gt;&lt;br/&gt;
&lt;img src="http://lh4.ggpht.com/_6zrdK5O_LIg/TOJ8zSrUBFI/AAAAAAAABPo/rlTmlskU-ZM/tdatetimepicker_win7.png"&gt;&lt;br/&gt;

&lt;br&gt;&lt;br&gt;
The problem was that the actual control (SysMonthCal32) is, since Windows 7, put inside another control (DropDown), which has the same size as the month calendar. So you can enlarge the month calendar, but it only results in things not being displayed. So the parent control (DropDown) should be resized here...&lt;br/&gt;&lt;br/&gt;

Getting the parent is easy with Windows (GetParent), but it should still work using XP of course. So we check if the parent is really a "DropDown". There might be other ways to do it, but I'm using GetClassName now and that works.&lt;br/&gt;&lt;br/&gt;

So the adapted solution is here:&lt;br/&gt;&lt;br/&gt;

&lt;pre&gt;&lt;font color="black"&gt;
procedure TMyForm.BeginDateTimePickerDropDown(Sender: TObject);
const
  MCM_GETMAXTODAYWIDTH  = MCM_FIRST + 21;
var
  Style: LongInt;
  hDTP: THandle;
  r: TRect;
  intTodayWidth: Integer;

  cname: array[0..256] of Char;
begin
  //to get a handle of calendar
  hDTP := DateTime_GetMonthCal((sender as TDateTimePicker).Handle);

  //change a style
  Style := GetWindowLong(hDTP, GWL_STYLE);
  SetWindowLong(hDTP,  GWL_STYLE, Style or MCS_WEEKNUMBERS);

  //now we must change the width for calendar because week numbers shifted all strings
  //1. to get the required rect
  r := Rect(0, 0, 0, 0);
  SendMessage(hDTP, MCM_GETMINREQRECT, 0, Longint(@r));

  //2. to get the maximum width of the "today" string
  intTodayWidth := SendMessage(hDTP, MCM_GETMAXTODAYWIDTH, 0, 0);

  //3. adjust rect width to fit the "today" string
  if intTodayWidth &gt; r.Right then
    r.Right := intTodayWidth;

  // For Win7, the window (class=SysMonthCal32) is automatically inside
  // a parent-window (class=DropDown). Check this. If so, take the parent window.
  // If not so (class=TMainForm), take this window (for XP and lower)
  GetClassName(GetParent(hDtp), cname, sizeof(cname));
  if AnsiSameText(cname, 'DropDown') then
  begin
    hDTP := GetParent(hDTP);

    // To get it perfect (on my machines) is adding this code:
    inc(r.Right, 6);
    inc(r.Bottom, 6);
  end;

  //4. to set new the height and width
  MoveWindow(hDTP, r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top, true);
end;

&lt;/font&gt;&lt;/pre&gt;

&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-3417848162638333354?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/3417848162638333354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/11/delphi-tdatetimepicker-with-weeknumber.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/3417848162638333354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/3417848162638333354'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/11/delphi-tdatetimepicker-with-weeknumber.html' title='Delphi TDateTimePicker with WeekNumber'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_6zrdK5O_LIg/TOJ8zSrUBFI/AAAAAAAABPo/rlTmlskU-ZM/s72-c/tdatetimepicker_win7.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-4231044633743046216</id><published>2010-10-26T23:25:00.000+02:00</published><updated>2010-10-26T23:40:59.092+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='svg'/><category scheme='http://www.blogger.com/atom/ns#' term='union'/><category scheme='http://www.blogger.com/atom/ns#' term='boost'/><category scheme='http://www.blogger.com/atom/ns#' term='geometry'/><title type='text'>Union, Tangencies and Colors</title><content type='html'>&lt;br&gt;
&lt;h1&gt;Union, Tangencies and Colors&lt;/h1&gt;
&lt;p&gt;I like the picture below very much.&lt;/p&gt;
&lt;br&gt;
&lt;embed src="http://www.xs4all.nl/%7Ebarend/blogs/box_union1.svg"
 type="image/svg+xml"
 pluginspage="http://www.adobe.com/svg/viewer/install/"
 height="500" width="500"&gt;&lt;/embed&gt;&lt;br&gt;
&lt;p&gt;What you see here are, more or less, pink, green and blue. The
colors are
chosen as such
that they always form distinct colors, regardless of how you combine
them. There are of course other combinations with these properties,
but... this is at least one of them.&lt;/p&gt;
&lt;p&gt;When the pink layer is slightly moved to the right, you see
better how the image is constructed:&lt;/p&gt;
&lt;br&gt;
&lt;embed src="http://www.xs4all.nl/%7Ebarend/blogs/box_union2.svg"
 type="image/svg+xml"
 pluginspage="http://www.adobe.com/svg/viewer/install/"
 height="600" width="600"&gt;&lt;/embed&gt;&lt;br&gt;

&lt;p&gt;The pink (transparent) layer is the &lt;span
 style="font-weight: bold;"&gt;union&lt;/span&gt; of the two
underlying (multi-)polygons, the green one and the blue one. It has one
hole, one kind of indentation and for the rest it is square. The
underlying multi-polygons are better seen if the pink one is removed:&lt;/p&gt;
&lt;br&gt;
&lt;embed src="http://www.xs4all.nl/%7Ebarend/blogs/box_union3.svg"
 type="image/svg+xml"
 pluginspage="http://www.adobe.com/svg/viewer/install/"
 height="500" width="500"&gt;&lt;/embed&gt;&lt;br&gt;
&lt;p&gt;So this is clear: there are two multi-polygons here, complete
with
holes and self-tangencies. These multi-polygons have overlap in some
places, no overlap in other places. They nearly fill the area, there
are only three "boxes" free. The blue and green colors nicely mix into
blue-green. The colors and transparencies are selected for that. SVG
definitions are:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Green: &lt;/span&gt;style="fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:3"&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Blue&lt;/span&gt;:
style="fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:3"&lt;/p&gt;
&lt;p&gt;I like this combination.&lt;/p&gt;
And with the pink style on top of it...&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Pink&lt;/span&gt;:
style="fill-opacity:0.2;stroke-opacity:0.4;fill:rgb(255,0,0);stroke:rgb(255,0,255);stroke-width:8"&lt;br&gt;
&lt;br&gt;
...all colors change, however, they are still clearly distinct.
Yellow-orange like for green+pink; lila for blue+pink; and brown for
the blue+green+pink. So we have seven unique distinct colors now, which
happens to be the ideal number of colors for a map.&lt;br&gt;
&lt;br&gt;
By the way, this image is created using Boost.Geometry. Boost.Geometry
can easily create SVG images. And Boost.Geometry can overlay
multi-polygons (already possible for a long time) having all kinds of
self-tangencies (new!). A self-tangency in a multi-polygon is a place
where two
polygon-members touch each other (orange dots in the map below), or
where a&amp;nbsp;polygon touches itself (the red dot in the map).&lt;br&gt;
&lt;br&gt;
&lt;embed src="http://www.xs4all.nl/%7Ebarend/blogs/box_union4.svg"
 type="image/svg+xml"
 pluginspage="http://www.adobe.com/svg/viewer/install/"
 height="500" width="500"&gt;&lt;/embed&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;Actually... this could also be a polygon, having five interior rings (holes) which might be mutually tangent and tangent to they exterior ring.&lt;/p&gt;

&lt;br&gt;&lt;p&gt;OK, one more image...&lt;/p&gt;&lt;br&gt;
&lt;embed src="http://www.xs4all.nl/%7Ebarend/blogs/box_union5.svg"
 type="image/svg+xml"
 pluginspage="http://www.adobe.com/svg/viewer/install/"
 height="600" width="600"&gt;&lt;/embed&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-4231044633743046216?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/4231044633743046216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/10/box-union-and-colors.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/4231044633743046216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/4231044633743046216'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/10/box-union-and-colors.html' title='Union, Tangencies and Colors'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-7947577473113748922</id><published>2010-10-19T19:24:00.000+02:00</published><updated>2010-10-19T20:08:45.233+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tag dispatching'/><category scheme='http://www.blogger.com/atom/ns#' term='boost'/><category scheme='http://www.blogger.com/atom/ns#' term='geometry'/><title type='text'>Tag Dispatching and Inheritance</title><content type='html'>&lt;h1&gt;Tag Dispatching and Inheritance&lt;/h1&gt;
&lt;br&gt;
In the previous &lt;a
 href="/2010/10/tag-dispatching-by-type-tag-dispatching.html"&gt;blog&lt;/a&gt;
we described Tag Dispatching by Type. &lt;br&gt;
&lt;br&gt;
Though very convenient, when many classes (tagged by as many
tags) share the same implementation, we get as many dispatch structs
with
the same implementation (or, better, forwarding to the same struct).
This
can be avoided by using similarities between classes, or between tags.
In
Boost.Geometry, for example, some geometries are &lt;span
 style="font-weight: bold;"&gt;single&lt;/span&gt; while others
are &lt;span style="font-weight: bold;"&gt;multi&lt;/span&gt;.
That multi-ness can be recognized by the metafunction &lt;span
 style="font-weight: bold;"&gt;is_multi&lt;/span&gt; which
results in &lt;span style="font-weight: bold;"&gt;true&lt;/span&gt;
for a multi-polygon and in &lt;span style="font-weight: bold;"&gt;false&lt;/span&gt;
for a single polygon. We can include an IsMulti boolean template
parameter in the dispatch structure, so that it is selected not only on
tag dispatching, but also in &lt;span style="font-weight: bold;"&gt;is_multi&lt;/span&gt;.&lt;br&gt;
&lt;br&gt;
This similarity can also be implemented using a &lt;span
 style="font-weight: bold;"&gt;tag hierarchy&lt;/span&gt; and &lt;span
 style="font-weight: bold;"&gt;inheritance.&lt;/span&gt; &lt;br&gt;
&lt;br&gt;
Let's go back to the fruit example. All citrus fruit species have pulp
vesicles. There
are many &lt;a href="http://species.wikimedia.org/wiki/Citrus"&gt;citrus
fruits species&lt;/a&gt;. And, of course, we &lt;span
 style="font-weight: bold;"&gt;don't want&lt;/span&gt; to repeat
the dispatch structure &lt;span style="font-weight: bold;"&gt;has_vesicles&lt;/span&gt;
so many times. So we try to define our tag hierarchy:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; citrus_tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; pome_tag {};&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; apple_tag : pome_tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; pear_tag : pome_tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;&lt;br&gt;struct&lt;/span&gt; banana_tag {};&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; orange_tag : citrus_tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; lemon_tag : citrus_tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; lime_tag : citrus_tag {};&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
And then we couple the tags, like we did in previous blog:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; T&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; tag&amp;lt;apple&amp;gt; { &lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; apple_tag type; };&lt;br&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; tag&amp;lt;pear&amp;gt; { &lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; pear_tag type; };&lt;br&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; tag&amp;lt;orange&amp;gt; { &lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; orange_tag type; };&lt;br&gt;&lt;span
 style="color: Blue;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span
 style="color: Black;"&gt;&lt;span style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; tag&amp;lt;lime&amp;gt; { &lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; lime_tag type; };&lt;br&gt;&lt;/span&gt;&lt;span
 style="color: Black;"&gt;&lt;span style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; tag&amp;lt;banana&amp;gt; { &lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; banana_tag type; };&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
The new thing, besides the inheritance in the tags above, is that we
now define a &lt;span style="font-weight: bold;"&gt;tag_cast&lt;/span&gt;
metafunction:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt;&lt;br&gt;&amp;lt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; Tag, &lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; BaseTag,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; BT2 = &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; BT3 = &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; BT4 = &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; BT5 = &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; BT6 = &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; BT7 = &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;&lt;br&gt;&amp;gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; tag_cast&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; boost::mpl::if_&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; boost::is_base_of&amp;lt;BaseTag, Tag&amp;gt;::type,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BaseTag,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// Try next one in line:&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; tag_cast&amp;lt;Tag, BT2, BT3, BT4, BT5, BT6, BT7, &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;&amp;gt;::type&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;gt;::type type;&lt;br&gt;};&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; Tag&amp;gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; tag_cast&amp;lt;Tag, &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt;&amp;gt;&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// If not found, take specified tag, so do not cast&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; Tag type;&lt;br&gt;};&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
We can now check if a tag &lt;span style="font-weight: bold;"&gt;is
a &lt;/span&gt;citrus tag, by calling defining a new tag as
tag_cast&amp;lt;tag, citrus_tag&amp;gt;::type. This new tag is either a
citrus tag, or it is the tag it already was.&lt;br&gt;
&lt;br&gt;
And we can dispatch by this tag as well. So it looks like:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;namespace&lt;/span&gt; dispatch&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; T&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; has_vesicles : boost::false_type {};&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; has_vesicles&amp;lt;citrus_tag&amp;gt; : boost::true_type {};&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; Fruit&amp;gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; has_vesicles(Fruit &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; fruit)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (Potentially) go up in hierachy: take tag corresponding to Fruit,&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// downcast to citrus_tag if possible&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; tag_cast&amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; tag&amp;lt;Fruit&amp;gt;::type, citrus_tag&amp;gt;::type tag;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt;(&lt;span
 style="color: Maroon;"&gt;"has vesicles: "&lt;/span&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ (dispatch::has_vesicles&amp;lt;tag&amp;gt;::value ? &lt;span
 style="color: Maroon;"&gt;"true"&lt;/span&gt; : &lt;span
 style="color: Maroon;"&gt;"false"&lt;/span&gt;);&lt;br&gt;}&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
This tag_cast, as proposed above, can not only cast to one base-class,
but also to a range
of base-classes. The definition&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt; &lt;span
 style="color: Blue;"&gt;typedef&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; tag_cast&amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; tag&amp;lt;Fruit&amp;gt;::type, citrus_tag, pome_tag&amp;gt;::type tag;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
will result in a citrus_tag if it is a citrus, a pome_tag if it is a
pome, and otherwise it results in the input tag. Besides this, it also
walks through a tag
hierarchy, so if citrus_tag and pome_tag were both derived from, e.g.,
a &lt;a href="http://species.wikimedia.org/wiki/Rosids"&gt;rosid_tag&lt;/a&gt;,
and rosid_tag was specified in this call, it would result in a
rosid_tag. &lt;br&gt;
&lt;br&gt;
The&amp;nbsp;sample program &lt;a href="http://codepad.org/CYmgggw5"&gt;here&lt;/a&gt;
shows two base classes, not listed here.&lt;br&gt;
&lt;br&gt;
Our main program now displays correctly if the specific fruits have
vesicles or not&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; main()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;namespace&lt;/span&gt; fruit;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;apple a(&lt;span
 style="color: Maroon;"&gt;"my apple"&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pear p(&lt;span
 style="color: Maroon;"&gt;"my pear"&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;orange o(&lt;span
 style="color: Maroon;"&gt;"my orange"&lt;/span&gt;);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; has_vesicles(a) &amp;lt;&amp;lt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;endl&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; has_vesicles(p) &amp;lt;&amp;lt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;endl&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; has_vesicles(o) &amp;lt;&amp;lt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;endl&lt;/span&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;;&lt;br&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
Back to Boost.Geometry. Until now it is not done, but we might
depricate
the is_multi meta-function and replace it by this:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; multi_tag;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; multi_point_tag : multi_tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; multi_linestring_tag : multi_tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; multi_polygon_tag : multi_tag {};&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
And instead of calling is_multi, we call tag_cast&amp;lt;tag,
multi_tag&amp;gt;. We then know if it is a multi and can dispatch on
it. The same for linear. This will probably be very convenient, it has
to be worked out a little more.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Casting and (multiple)
inheritance&lt;/span&gt;&lt;br&gt;
The tag_cast as implemented above&amp;nbsp;casts to&amp;nbsp;&lt;span
 style="font-weight: bold;"&gt;&lt;span
 style="font-weight: bold;"&gt;specified&lt;/span&gt;&lt;/span&gt;
tags. We can not just call the parent-tag. One of the reasons for this
is multiple inheritance.&lt;br&gt;
Tag inheritance can be multiple. This is convenient because, of course,
there can be different tag classifications for the same set of tags.
For example: if a geometry
contains segments, or is linear, or is areal. So we might get:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; multi_tag;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; multi_point_tag : multi_tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; multi_linestring_tag : multi_tag, linear_tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; multi_polygon_tag : multi_tag, areal_tag {};&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
When calling tag_cast, the results depends on the order of the
specified base tags. And so does the dispatching.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-7947577473113748922?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/7947577473113748922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/10/tag-dispatching-and-inheritance.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/7947577473113748922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/7947577473113748922'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/10/tag-dispatching-and-inheritance.html' title='Tag Dispatching and Inheritance'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-8367164280005849432</id><published>2010-10-19T17:32:00.000+02:00</published><updated>2010-10-19T19:32:36.088+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tag dispatching'/><category scheme='http://www.blogger.com/atom/ns#' term='boost'/><category scheme='http://www.blogger.com/atom/ns#' term='geometry'/><title type='text'>Tag Dispatching by Type</title><content type='html'>&lt;h1&gt;Tag Dispatching by Type&lt;/h1&gt;
&lt;br&gt;
Tag Dispatching (TD) is a Generic Programming (GP) technique for C++.
It is well
explained in this &lt;a
 href="http://cplusplus.co.il/2010/01/03/tag-dispatching/"&gt;blog&lt;/a&gt;.
Google Hit Number one (GH#1) is&amp;nbsp;&lt;a
 href="http://www.boost.org/community/generic_programming.html#tag_dispatching"&gt;this
site&lt;/a&gt;, where the&amp;nbsp;example of the STL function &lt;span
 style="font-weight: bold;"&gt;advance&lt;/span&gt; is given.
Tag Dispatching is not
described a lot;&amp;nbsp;GH#7 is from ggl (= Boost.Geometry), as
is&amp;nbsp;GH#8..&lt;br&gt;
&lt;br&gt;
Nearly all TD descriptions I know of use the example
of STL-advance. But in Boost.Geometry TD is done in another
way:&amp;nbsp;not&amp;nbsp;&lt;span style="font-weight: bold;"&gt;by
instance&lt;/span&gt;, but &lt;span style="font-weight: bold;"&gt;by
type&lt;/span&gt;. The difference is explained in this blog.&lt;br&gt;
&lt;br&gt;
Suppose you make a generic program
doing something with fruit. An apple is normally being eaten
differently than a banana or an orange. So if we program a generic
function &lt;span style="font-weight: bold;"&gt;eat&lt;/span&gt;,
giving it any type of fruit, it should redirect this to an
implementation specific to that kind of fruit, so for apple differently
than for a banana.&lt;br&gt;
&lt;br&gt;
We first implement the tags. Tags are completely empty structures. But
(of course) not completely useless.&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; apple_tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; banana_tag {};&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; orange_tag {};&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
We then create some sample implementations. Most properties are not
used, it is just to show there are (sometimes completely) different
classes which can be handled genericly.
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; apple&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; radius;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; name;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;apple(&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; n) : name(n) {}&lt;br&gt;};&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; banana&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; length;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; name;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;banana(&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; n) : name(n) {}&lt;br&gt;};&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
All this is quite simple C++ code, though you have to understand
templates (generics) and specialization.&lt;br&gt;
&lt;br&gt;
OK, now we implement&amp;nbsp;&lt;span style="font-weight: bold;"&gt;Tag
Dispatching by Instance:&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;namespace&lt;/span&gt; dispatch&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; eat(apple &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; a, apple_tag)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span
 style="color: Maroon;"&gt;"bite"&lt;/span&gt; &amp;lt;&amp;lt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;endl&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; eat(banana &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; b, banana_tag)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span
 style="color: Maroon;"&gt;"peel"&lt;/span&gt; &amp;lt;&amp;lt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;endl&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; T&amp;gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; eat(T &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; fruit)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; tag&amp;lt;T&amp;gt;::type the_tag;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dispatch::eat(fruit, the_tag);&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
The function &lt;span style="font-weight: bold;"&gt;eat&lt;/span&gt;
at the bottom
first declares an instance of the tag. If an apple is entered in this
function, it will be an instance of the apple_tag. If a banana is
entered, it is a banana_tag. Then it forwards its call to the eat
function in the namespace dispatch. There are two versions (overloads)
there, one specified with an apple_tag, one with a banana_tag. The
compiler selects, based on the tag
the right function. Quite easy, and quite powerful,
this tag dispatching system.&lt;br&gt;
&lt;br&gt;
As said, within Boost.Geometry it is not applied like this. One of the
reasons is that the instance of the tag is not necessary at all. If the
dispatch::eat function would be implemented within a struct, as a
static method, the tag dispatching can be done &lt;span
 style="font-weight: bold;"&gt;by type&lt;/span&gt; and not &lt;span
 style="font-weight: bold;"&gt;by instance&lt;/span&gt;. This is
still tag dispatching!&lt;br&gt;
&lt;br&gt;
So the piece above can be replaced by this &lt;span
 style="font-weight: bold;"&gt;Tag Dispatching by Type&lt;/span&gt;:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;namespace&lt;/span&gt; dispatch&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; Tag&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; eat {};&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; eat&amp;lt;apple_tag&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; apply(apple &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; a)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span
 style="color: Maroon;"&gt;"bite"&lt;/span&gt; &amp;lt;&amp;lt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;endl&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; eat&amp;lt;banana_tag&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; apply(banana &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; b)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span
 style="color: Maroon;"&gt;"peel"&lt;/span&gt; &amp;lt;&amp;lt; &lt;span
 style="color: Blue;"&gt;std&lt;/span&gt;::&lt;span
 style="color: Blue;"&gt;endl&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; T&amp;gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; eat(T &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt;&amp;amp; fruit)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dispatch::eat&amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; tag&amp;lt;T&amp;gt;::type&amp;gt;::apply(fruit);&lt;br&gt;}&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
So no instance at all, type only. Boost.Geometry has this structure
everywhere, and all static dispatching methods are called &lt;span
 style="font-weight: bold;"&gt;apply&lt;/span&gt;.&lt;br&gt;
&lt;br&gt;
For completeness we list the main program as well here:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; main()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;apple a(&lt;span
 style="color: Maroon;"&gt;"my apple"&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;banana b(&lt;span
 style="color: Maroon;"&gt;"my banana"&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;eat(a);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;eat(b);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;;&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
It is the same for the instance-version and the type-version.&lt;br&gt;
&lt;br&gt;
More advantages of the &lt;span style="font-weight: bold;"&gt;Tag
Dispatching by Type&lt;/span&gt; approach are that arguments
can be reversed, so you can call distance(point, polygon) and
distance(polygon, point) but there is only one implementation with
point_tag, polygon_tag necessary. With instances (and function
overloads) this is not possible, or at least not that easy.
Furthermore, tag dispatching by type can be used to define types, or
define constants, as well. Suppose you need to define a constant value
dependant on a type. We approach geometry now and want to define if a
specific fruit-type is spherical or not. So we define this structure,
specialized by tag:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; Tag&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; spherical {};&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; spherical&amp;lt;apple_tag&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;bool&lt;/span&gt; value = true;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&amp;gt; &lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; spherical&amp;lt;banana_tag&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;bool&lt;/span&gt; value = false;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
We can create a generic structure, which calls this dispatch, just like
the free function eat, but now with a struct (or meta-function):&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black;"&gt;&lt;span
 style="color: Blue;"&gt;template&lt;/span&gt; &amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; T&amp;gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;struct&lt;/span&gt; spherical&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;const&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;bool&lt;/span&gt; value = dispatch::spherical&amp;lt;&lt;span
 style="color: Blue;"&gt;typename&lt;/span&gt; tag&amp;lt;T&amp;gt;::type&amp;gt;::value;&lt;br&gt;};&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;br&gt;
Next blog will handle &lt;a href="/2010/10/tag-dispatching-and-inheritance.html"&gt;Tag Dispatching and
Inheritance&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-8367164280005849432?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/8367164280005849432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/10/tag-dispatching-by-type-tag-dispatching.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/8367164280005849432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/8367164280005849432'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/10/tag-dispatching-by-type-tag-dispatching.html' title='Tag Dispatching by Type'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-4180954160200305475</id><published>2010-07-26T22:00:00.000+02:00</published><updated>2010-07-27T18:40:56.105+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='distance'/><category scheme='http://www.blogger.com/atom/ns#' term='generics'/><category scheme='http://www.blogger.com/atom/ns#' term='specialization'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='traits'/><title type='text'>C# Specializations by Traits IV</title><content type='html'>&lt;br&gt;
&lt;h1&gt;C# Specializations by Traits IV&lt;/h1&gt;
&lt;h3&gt;&lt;br&gt;
&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;&lt;span style="font-style: italic;"&gt;Geometry&lt;/span&gt;&lt;/h3&gt;
In last three &lt;a href="/2010/07/c-specializations-by-traits-iii.html"&gt;blogs&lt;/a&gt;
(I'm productive these days in blogs, instead of
klocs) I explained how to to specializations in C#. This blog only
explains how it begon, give different possibilities to design things,
and wraps it up.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Towards specializations&lt;/h2&gt;
Developing Boost.Geometry, in C++, and doing some more C# this year as
well, I wondered how a generic geometry library in C# would look like.
Ideally it would be as Boost.Geometry, of course... But
Boost.Geometry is based on traits and C++ specializations, partial
specializations, tag dispatching. All modern C++ generic programming
stuff. Not easily doable in C#.&lt;br&gt;
&lt;br&gt;
Calculating the distance between
two arbitrary point types would already be something. I tried many
methods, and discussed them with my collegue Paul den Dulk, and he
helped me, suggesting more methods and some essential pieces. Putting
it together, adding the
dictionary as the runtime register instead of the compiletime C++
specializations, the point distance function&amp;nbsp;is looking
exactly the same as Boost.Geometry now!&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Some notes&lt;/h2&gt;
There are still many differences from this system with C++
specializations, of course.&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;in C++ it is compile-time and checked at compile-time&lt;/li&gt;
  &lt;li&gt;therefore in C++ it is very fast&lt;/li&gt;
  &lt;li&gt;in C# the dictionary is runtime and checked at runtime&lt;/li&gt;
  &lt;li&gt;because the dictionary lookup and necesary cast it is
slower in C#&lt;/li&gt;
  &lt;li&gt;C++ has partial specializations, don't know (yet) how to do
that in C#&lt;/li&gt;
  &lt;li&gt;C++ has type calculations, the whole template
metaprogramming is based on that.&amp;nbsp;&lt;/li&gt;
  &lt;li&gt;in C# it is only the methods&lt;/li&gt;
  &lt;li&gt;because in C# it is runtime, it gives some advantages as
well: you can register different traits classes when needed&lt;/li&gt;
  &lt;li&gt;and so, e.g. the ORM can handle the same model in different
ways&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Timings&lt;/h2&gt;
As said the dictionary consultation, together with the cast, take some
time. Using the geometry case &lt;span style="font-style: italic;"&gt;distance&lt;/span&gt;,
I timed it and it is certainly measurable.&lt;br&gt;
&lt;br&gt;
Ten million distance calculations on my computer:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;Using interfaces: 0.10 seconds&lt;/li&gt;
  &lt;li&gt;Using delegates: 0.15 seconds&lt;/li&gt;
  &lt;li&gt;Using traits: 0.13 seconds&lt;/li&gt;
  &lt;li&gt;Using a register: 0.42 seconds&lt;/li&gt;
&lt;/ul&gt;
So, in fact 4 times slower. It is much in this case, but this is
compared to a small calculation (Pythagoras). If applied using GUI,
database, disk io, or occasionally (and not 10 million times), the
lookup will probably fall away.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Complete program&lt;/h2&gt;
The program to research, with 10 possible implementations, with
interfaces, wrappers, delegates, traits, registers and lambdas, is
shown below.&lt;br&gt;
&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;span style="color: Blue;"&gt;using&lt;/span&gt; System;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Diagnostics;&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;namespace&lt;/span&gt; GenericGeometry&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;interface&lt;/span&gt; IPoint&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; x();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; y();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; increase();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;delegate&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; get_x&amp;lt;Point&amp;gt;(Point p);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;delegate&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; get_y&amp;lt;Point&amp;gt;(Point p);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;interface&lt;/span&gt; ITraitsBase {}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;interface&lt;/span&gt; ITraits&amp;lt;Point&amp;gt; : ITraitsBase&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; get_x(Point p);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; get_y(Point p);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; TraitsRegister&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; IDictionary&amp;lt;Type, ITraitsBase&amp;gt; register;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; Register&amp;lt;PointType&amp;gt;(ITraits&amp;lt;PointType&amp;gt; t)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;if&lt;/span&gt; (register == &lt;span
 style="color: Blue;"&gt;null&lt;/span&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;register = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Dictionary&amp;lt;Type, ITraitsBase&amp;gt;();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;register[&lt;span
 style="color: Blue;"&gt;typeof&lt;/span&gt;(PointType)] = t;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; LambdaRegister&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; IDictionary&amp;lt;Type, Tuple&amp;lt;&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;&amp;gt;&amp;gt; register;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; Register&amp;lt;Point&amp;gt;(get_x&amp;lt;Point&amp;gt; gx, get_y&amp;lt;Point&amp;gt; gy)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;if&lt;/span&gt; (register == &lt;span
 style="color: Blue;"&gt;null&lt;/span&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;register = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Dictionary&amp;lt;Type, Tuple&amp;lt;&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;&amp;gt;&amp;gt;();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;register[&lt;span
 style="color: Blue;"&gt;typeof&lt;/span&gt;(Point)] = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Tuple&amp;lt;&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;&amp;gt;(gx, gy);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// The generic library, with functions as "Distance", working on IPoint or on any point&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; Algorithm&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (1) Using an interface to access coordinates&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; Distance(IPoint p1, IPoint p2)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; dx = p1.x() - p2.x();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; dy = p1.y() - p2.y();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; Math.Sqrt(dx * dx + dy * dy);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (7) use delegates to access coordinates of not interfaced point type&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; Distance&amp;lt;Point&amp;gt;(Point p1, Point p2, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get_x&amp;lt;Point&amp;gt; gx, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get_y&amp;lt;Point&amp;gt; gy)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; dx = gx(p1) - gx(p2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; dy = gy(p1) - gy(p2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; Math.Sqrt(dx * dx + dy * dy);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (8) use traits/accessor to access coordinates of not interfaced point type&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; Distance&amp;lt;Point&amp;gt;(Point p1, Point p2, ITraits&amp;lt;Point&amp;gt; traits)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; dx = traits.get_x(p1) - traits.get_x(p2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; dy = traits.get_y(p1) - traits.get_y(p2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; Math.Sqrt(dx * dx + dy * dy);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (9) use traits/REGISTER accessor to access coordinates of not interfaced point type&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; DistanceTR&amp;lt;Point&amp;gt;(Point p1, Point p2)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ITraits&amp;lt;Point&amp;gt; traits = TraitsRegister.register[&lt;span
 style="color: Blue;"&gt;typeof&lt;/span&gt;(Point)] &lt;span
 style="color: Blue;"&gt;as&lt;/span&gt; ITraits&amp;lt;Point&amp;gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; dx = traits.get_x(p1) - traits.get_x(p2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; dy = traits.get_y(p1) - traits.get_y(p2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; Math.Sqrt(dx * dx + dy * dy);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (10) use (tupled) lambda/REGISTER accessor to access coordinates of not interfaced point type&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; DistanceLR&amp;lt;Point&amp;gt;(Point p1, Point p2)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var pair = LambdaRegister.register[&lt;span
 style="color: Blue;"&gt;typeof&lt;/span&gt;(Point)] &lt;span
 style="color: Blue;"&gt;as&lt;/span&gt; Tuple&amp;lt;&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;&amp;gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get_x&amp;lt;Point&amp;gt; gx = pair.Item1 &lt;span
 style="color: Blue;"&gt;as&lt;/span&gt; get_x&amp;lt;Point&amp;gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get_y&amp;lt;Point&amp;gt; gy = pair.Item2 &lt;span
 style="color: Blue;"&gt;as&lt;/span&gt; get_y&amp;lt;Point&amp;gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; dx = gx(p1) - gx(p2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; dy = gy(p1) - gy(p2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; Math.Sqrt(dx * dx + dy * dy);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (1) implement IPoint&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; MyPoint1 : IPoint&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; m_x, m_y;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; MyPoint1(&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; x, &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; y)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_x = x;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_y = y;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; x() { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; m_x; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; y() { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; m_y; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Non-interfaced class...&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; MyPoint2&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; x { &lt;span
 style="color: Blue;"&gt;get&lt;/span&gt;; &lt;span
 style="color: Blue;"&gt;set&lt;/span&gt;; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; y { &lt;span
 style="color: Blue;"&gt;get&lt;/span&gt;; &lt;span
 style="color: Blue;"&gt;set&lt;/span&gt;; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (2) Create a wrapper (implementing IPoint)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; PointWrapper : IPoint&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyPoint2 m_point;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; PointWrapper(MyPoint2 p)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_point = p;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; x() { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; m_point.x; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; y() { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; m_point.y; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (3) Create a generic wrapper using delegates, implementing IPoint&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; DelPointWrapper&amp;lt;Point&amp;gt; : IPoint&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Point m_point;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get_x&amp;lt;Point&amp;gt; m_gx;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get_y&amp;lt;Point&amp;gt; m_gy;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; DelPointWrapper(Point p, get_x&amp;lt;Point&amp;gt; gx, get_y&amp;lt;Point&amp;gt; gy)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_point = p;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_gx = gx;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_gy = gy;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; x() { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; m_gx(m_point); }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; y() { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; m_gy(m_point); }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; increase()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;//m_x += 0.000001;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;//m_y += 0.000001;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (7) define delegates in a static class&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; Accessor&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; get_x&amp;lt;MyPoint2&amp;gt; getX = p =&amp;gt; p.x;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; get_y&amp;lt;MyPoint2&amp;gt; getY = p =&amp;gt; p.y;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (8,9) use a sort of Traits class&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; Traits : ITraits&amp;lt;MyPoint2&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; get_x(MyPoint2 p)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; p.x;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; get_y(MyPoint2 p)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; p.y;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; Program&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;const&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; n = &lt;span
 style="color: Maroon;"&gt;10000000&lt;/span&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; Timed&amp;lt;Point&amp;gt;(String header, Point a, Point b) where Point : IPoint&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; d = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;&lt;span
 style="color: Maroon;"&gt;.0&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Stopwatch st = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Stopwatch();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;st.Start();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;for&lt;/span&gt; (&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; i = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;; i &amp;lt; n; i++)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;d += Algorithm.Distance(a, b);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;st.Stop();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.WriteLine(header + &lt;span
 style="color: Maroon;"&gt;" "&lt;/span&gt; + d + &lt;span
 style="color: Maroon;"&gt;" "&lt;/span&gt; + st.Elapsed.ToString());&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Threading.Thread.Sleep(&lt;span
 style="color: Maroon;"&gt;500&lt;/span&gt;);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Creating the delegates&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; point_get_x(MyPoint2 p)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; p.x;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; point_get_y(MyPoint2 p)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; p.y;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; Main(&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt;[] args)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; option = args.Length &amp;gt; &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt; ? Int32.Parse(args[&lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;]) : &lt;span
 style="color: Maroon;"&gt;10&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.Write(&lt;span
 style="color: Maroon;"&gt;"{0} "&lt;/span&gt;, option);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Point without interface&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyPoint2 p1 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; MyPoint2();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p1.x = &lt;span
 style="color: Maroon;"&gt;3&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p1.y = &lt;span
 style="color: Maroon;"&gt;5&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyPoint2 p2 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; MyPoint2();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p2.x = &lt;span
 style="color: Maroon;"&gt;6&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p2.y = &lt;span
 style="color: Maroon;"&gt;9&lt;/span&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;switch&lt;/span&gt; (option)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;case&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;1&lt;/span&gt;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// Option 1, point with interface&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MyPoint1 ip1 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; MyPoint1(&lt;span
 style="color: Maroon;"&gt;3&lt;/span&gt;, &lt;span
 style="color: Maroon;"&gt;5&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MyPoint1 ip2 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; MyPoint1(&lt;span
 style="color: Maroon;"&gt;6&lt;/span&gt;, &lt;span
 style="color: Maroon;"&gt;9&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Timed(&lt;span
 style="color: Maroon;"&gt;"Using interface"&lt;/span&gt;, ip1, ip2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;span
 style="color: Blue;"&gt;break&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;case&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;2&lt;/span&gt;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// Option 2a:&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PointWrapper pw1 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; PointWrapper(p1);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PointWrapper pw2 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; PointWrapper(p2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Timed(&lt;span
 style="color: Maroon;"&gt;"Using wrapper"&lt;/span&gt;, pw1, pw2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;span
 style="color: Blue;"&gt;break&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;case&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;3&lt;/span&gt;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// Option 2b:&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DelPointWrapper&amp;lt;MyPoint2&amp;gt; dpw1 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; DelPointWrapper&amp;lt;MyPoint2&amp;gt;(p1, point_get_x, point_get_y);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DelPointWrapper&amp;lt;MyPoint2&amp;gt; dpw2 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; DelPointWrapper&amp;lt;MyPoint2&amp;gt;(p2, point_get_x, point_get_y);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Timed(&lt;span
 style="color: Maroon;"&gt;"Using delegate-wrapper"&lt;/span&gt;, dpw1, dpw2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;span
 style="color: Blue;"&gt;break&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;case&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;4&lt;/span&gt;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Green;"&gt;// Option 2c: with inline delegates&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DelPointWrapper&amp;lt;MyPoint2&amp;gt; idpw1 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; DelPointWrapper&amp;lt;MyPoint2&amp;gt;(p1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , &lt;span
 style="color: Blue;"&gt;delegate&lt;/span&gt;(MyPoint2 p) { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; p.x; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , &lt;span
 style="color: Blue;"&gt;delegate&lt;/span&gt;(MyPoint2 p) { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; p.y; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DelPointWrapper&amp;lt;MyPoint2&amp;gt; idpw2 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; DelPointWrapper&amp;lt;MyPoint2&amp;gt;(p2&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , &lt;span
 style="color: Blue;"&gt;delegate&lt;/span&gt;(MyPoint2 p) { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; p.x; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , &lt;span
 style="color: Blue;"&gt;delegate&lt;/span&gt;(MyPoint2 p) { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; p.y; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Timed(&lt;span
 style="color: Maroon;"&gt;"Using inline delegate-wrapper"&lt;/span&gt;, idpw1, idpw2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;span
 style="color: Blue;"&gt;break&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;case&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;5&lt;/span&gt;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DelPointWrapper&amp;lt;MyPoint2&amp;gt; ldpw1 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; DelPointWrapper&amp;lt;MyPoint2&amp;gt;(p1, p =&amp;gt; p.x, p =&amp;gt; p.y);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DelPointWrapper&amp;lt;MyPoint2&amp;gt; ldpw2 = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; DelPointWrapper&amp;lt;MyPoint2&amp;gt;(p2, p =&amp;gt; p.x, p =&amp;gt; p.y);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Timed(&lt;span
 style="color: Maroon;"&gt;"Using lambda-wrapper"&lt;/span&gt;, ldpw1, ldpw2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;span
 style="color: Blue;"&gt;break&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;case&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;6&lt;/span&gt;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; d = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;&lt;span
 style="color: Maroon;"&gt;.0&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Stopwatch st = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Stopwatch();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; st.Start();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;for&lt;/span&gt; (&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; i = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;; i &amp;lt; n; i++)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; d += Algorithm.Distance(p1, p2, p =&amp;gt; p.x, p =&amp;gt; p.y);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; st.Stop();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine(&lt;span
 style="color: Maroon;"&gt;"Using delegate-algorithm+lambda "&lt;/span&gt; + d + &lt;span
 style="color: Maroon;"&gt;" "&lt;/span&gt; + st.Elapsed.ToString());&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;span
 style="color: Blue;"&gt;break&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;case&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;7&lt;/span&gt;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; d = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;&lt;span
 style="color: Maroon;"&gt;.0&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Stopwatch st = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Stopwatch();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; st.Start();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;for&lt;/span&gt; (&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; i = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;; i &amp;lt; n; i++)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; d += Algorithm.Distance(p1, p2, Accessor.getX, Accessor.getY);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; st.Stop();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine(&lt;span
 style="color: Maroon;"&gt;"Using accessor met static delegates "&lt;/span&gt; + d + &lt;span
 style="color: Maroon;"&gt;" "&lt;/span&gt; + st.Elapsed.ToString());&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;span
 style="color: Blue;"&gt;break&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;case&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;8&lt;/span&gt;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Traits traits = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Traits();&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; d = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;&lt;span
 style="color: Maroon;"&gt;.0&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Stopwatch st = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Stopwatch();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; st.Start();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;for&lt;/span&gt; (&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; i = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;; i &amp;lt; n; i++)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; d += Algorithm.Distance(p1, p2, traits);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; st.Stop();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine(&lt;span
 style="color: Maroon;"&gt;"Using traits "&lt;/span&gt; + d + &lt;span
 style="color: Maroon;"&gt;" "&lt;/span&gt; + st.Elapsed.ToString());&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;span
 style="color: Blue;"&gt;break&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;case&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;9&lt;/span&gt;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Traits traits = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Traits();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TraitsRegister.Register&amp;lt;MyPoint2&amp;gt;(traits);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; d = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;&lt;span
 style="color: Maroon;"&gt;.0&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Stopwatch st = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Stopwatch();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; st.Start();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;for&lt;/span&gt; (&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; i = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;; i &amp;lt; n; i++)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; d += Algorithm.DistanceTR(p1, p2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; st.Stop();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine(&lt;span
 style="color: Maroon;"&gt;"Using traits/register "&lt;/span&gt; + d + &lt;span
 style="color: Maroon;"&gt;" "&lt;/span&gt; + st.Elapsed.ToString());&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;span
 style="color: Blue;"&gt;break&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;case&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;10&lt;/span&gt;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LambdaRegister.Register&amp;lt;MyPoint2&amp;gt;(p =&amp;gt; p.x, p =&amp;gt; p.y);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;double&lt;/span&gt; d = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;&lt;span
 style="color: Maroon;"&gt;.0&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Stopwatch st = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Stopwatch();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; st.Start();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span
 style="color: Blue;"&gt;for&lt;/span&gt; (&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; i = &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;; i &amp;lt; n; i++)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; d += Algorithm.DistanceLR(p1, p2);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; st.Stop();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine(&lt;span
 style="color: Maroon;"&gt;"Using lamba/register "&lt;/span&gt; + d + &lt;span
 style="color: Maroon;"&gt;" "&lt;/span&gt; + st.Elapsed.ToString());&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;span
 style="color: Blue;"&gt;break&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.WriteLine(&lt;span
 style="color: Maroon;"&gt;""&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
And here are the complete timings (for each the smallest of 5 runs):
&lt;pre&gt;1 Using interface 50000000 00:00:00.1000114&lt;br&gt;2 Using wrapper 50000000 00:00:00.1055539&lt;br&gt;3 Using delegate-wrapper 50000000 00:00:00.1812642&lt;br&gt;4 Using inline delegate-wrapper 50000000 00:00:00.1843941&lt;br&gt;5 Using lambda-wrapper 50000000 00:00:00.1810666&lt;br&gt;6 Using delegate-algorithm+lambda 50000000 00:00:00.1509385&lt;br&gt;7 Using accessor met static delegates 50000000 00:00:00.1274787&lt;br&gt;8 Using traits 50000000 00:00:00.1327729&lt;br&gt;9 Using traits/register 50000000 00:00:00.4192440&lt;br&gt;10 Using lamba/register 50000000 00:00:00.4194542&lt;br&gt;&lt;/pre&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
Are already done. &lt;span style="font-weight: bold;"&gt;Specializations
in C# are possible. &lt;/span&gt;Use them, it makes C# and generics
more fun.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-4180954160200305475?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/4180954160200305475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/07/c-specializations-by-traits-iv-geometry.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/4180954160200305475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/4180954160200305475'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/07/c-specializations-by-traits-iv-geometry.html' title='C# Specializations by Traits IV'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-6468116161242874157</id><published>2010-07-25T21:28:00.001+02:00</published><updated>2010-07-27T18:38:21.360+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='orm'/><category scheme='http://www.blogger.com/atom/ns#' term='generics'/><category scheme='http://www.blogger.com/atom/ns#' term='specialization'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='traits'/><title type='text'>C# Specializations by Traits III</title><content type='html'>&lt;br&gt;
&lt;h1&gt;C# Specializations by Traits III&lt;/h1&gt;
&lt;br&gt;
&lt;h3&gt;&lt;span style="font-style: italic;"&gt;Stormy:
Specializations by Traits - Object Relational Model&lt;/span&gt;&lt;/h3&gt;
I like &lt;a href="http://soci.sourceforge.net/"&gt;SOCI&lt;/a&gt;
very much. It is a C++ &lt;a
 href="http://en.wikipedia.org/wiki/Object-relational_mapping"&gt;ORM&lt;/a&gt;.
Especially the way to go from SQL to model, the &lt;a
 href="http://soci.sourceforge.net/doc/exchange.html#object_relational"&gt;object-relational
mapping&lt;/a&gt;, is very convenient. It is based on specializations.&lt;br&gt;
&lt;br&gt;
In the earlier &lt;a
 href="/2010/07/c-specializations-by-traits-ii.html"&gt;Blogs&lt;/a&gt;
of this series I have shown that it is possible to do real
specializations in C#. This is possible using the combination of
traits, a dictionary, and (if necessary) extension methods. This is all
explained in previous blogs and I will not explain it again. I will
only show how this system is really convenient in Object Relational
Mapping (ORM). A hundred-lines prototype is developed. Called Stormy
(storm was already occupied).&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Use case&lt;/h2&gt;
In ORM the database (relational) is mapped to objects (models, C#
classes). So by nature there are many classes all handled the same way
(from SQL to the class instance).&lt;br&gt;
&lt;br&gt;
Instead of using the ADO.NET SqlDataReader (delivering just abstract
fields and not a model), we want to do things like this:&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;IEnumerable&amp;lt;Cat&amp;gt; cats = connection.Select&amp;lt;Cat&amp;gt;(&lt;span
 style="color: Maroon;"&gt;"select * from cat"&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
where&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;Cat is our model, shown below&lt;/li&gt;
  &lt;li&gt;connection is any connection to a database&lt;/li&gt;
  &lt;li&gt;the SQL statement is shown, literally. I like that.&lt;/li&gt;
  &lt;li&gt;so it returns a generic collection of our model&lt;/li&gt;
&lt;/ul&gt;
In C# it is not trivial to specialize the Select method per model. But
with traits and a register it can be solved.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;The model Cat&lt;/h2&gt;
The model Cat is borrowed from &lt;a
 href="http://www.nhforge.org/doc/nh/en/index.html#quickstart-persistentclass"&gt;nHibernate&lt;/a&gt;&amp;nbsp;&lt;span
 style="font-style: italic;"&gt;(I know nHibernate
-&amp;nbsp;it
will not map the class below - it wants method to
be virtual&lt;/span&gt;). Slightly modified (I like this way of
specifying
attributes):
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;br&gt;&lt;span style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; Cat&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; Guid Id { &lt;span
 style="color: Blue;"&gt;get&lt;/span&gt;; &lt;span
 style="color: Blue;"&gt;set&lt;/span&gt;; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; Name { &lt;span
 style="color: Blue;"&gt;get&lt;/span&gt;; &lt;span
 style="color: Blue;"&gt;set&lt;/span&gt;; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;char&lt;/span&gt; Sex { &lt;span
 style="color: Blue;"&gt;get&lt;/span&gt;; &lt;span
 style="color: Blue;"&gt;set&lt;/span&gt;; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;float&lt;/span&gt; Weight { &lt;span
 style="color: Blue;"&gt;get&lt;/span&gt;; &lt;span
 style="color: Blue;"&gt;set&lt;/span&gt;; }&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;h2&gt;The Object Relational mapping&lt;/h2&gt;
The ORM is done entirely in code, the way SOCI does it. No XML mappings
here.
We stay with C#. We show here the implementations Map the Cat from
(relational) Database to Object, and vice versa.&lt;br&gt;
&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;br&gt;&lt;span style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; CatConverter : ITypeConversion&amp;lt;Cat&amp;gt;&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; Cat fromSql(SqlDataReader reader)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Cat cat = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Cat();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cat.Id = (Guid)reader[&lt;span
 style="color: Maroon;"&gt;"CatId"&lt;/span&gt;];&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cat.Name = (&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt;)reader[&lt;span
 style="color: Maroon;"&gt;"name"&lt;/span&gt;];&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cat.Sex = (((&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt;)reader[&lt;span
 style="color: Maroon;"&gt;"sex"&lt;/span&gt;]) + &lt;span
 style="color: Maroon;"&gt;" "&lt;/span&gt;)[&lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;];&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cat.Weight = (&lt;span
 style="color: Blue;"&gt;float&lt;/span&gt;)reader[&lt;span
 style="color: Maroon;"&gt;"weight"&lt;/span&gt;];&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; cat;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; fillParameters(Cat cat, SqlCommand command)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;command.Parameters.Add(&lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; SqlParameter(&lt;span
 style="color: Maroon;"&gt;"@name"&lt;/span&gt;, cat.Name));&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;command.Parameters.Add(&lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; SqlParameter(&lt;span
 style="color: Maroon;"&gt;"@sex"&lt;/span&gt;, cat.Sex));&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;command.Parameters.Add(&lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; SqlParameter(&lt;span
 style="color: Maroon;"&gt;"@weight"&lt;/span&gt;, cat.Weight));&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
Note that it is mapped using SqlDataReader. It can be made more
convenient (eliminating casts) of course, but this is how it is done
with
SqlDataReader, normally.&lt;br&gt;
&lt;br&gt;
That SOCI-like type-converter (I renamed the methods &lt;span
 style="font-style: italic;"&gt;from_base&lt;/span&gt; to
&lt;span style="font-style: italic;"&gt;fromSQL&lt;/span&gt; and&lt;span
 style="font-style: italic;"&gt; to_base&lt;/span&gt; to &lt;span
 style="font-style: italic;"&gt;fillParameters&lt;/span&gt;) is
an interface
ITypeConversion&amp;lt;T&amp;gt;, and is registered (normally) once per
model:&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;Orm.Register&amp;lt;Cat&amp;gt;(&lt;span style="color: Blue;"&gt;new&lt;/span&gt; CatConverter());&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Main program&lt;/h2&gt;
We can implement our scenario, converting from
database to Cat and vice
versa, using generic programming. Our program:&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;span style="color: Blue;"&gt;class&lt;/span&gt; Program&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; Main(&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt;[] args)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Orm.Register&amp;lt;Cat&amp;gt;(&lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; CatConverter());&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Connection connection = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Connection(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Maroon;"&gt;@"&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Data Source=localhost\SQLEXPRESS;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MultipleActiveResultSets=True; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Initial Catalog=stormy;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Integrated Security=SSPI;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"&lt;/span&gt;);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var cats = connection.Select&amp;lt;Cat&amp;gt;(&lt;span
 style="color: Maroon;"&gt;"select * from cat"&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;foreach&lt;/span&gt;(Cat cat &lt;span
 style="color: Blue;"&gt;in&lt;/span&gt; cats)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.WriteLine(&lt;span
 style="color: Maroon;"&gt;"Cat {0} named {1}"&lt;/span&gt;, cat.Id, cat.Name);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// Create subselection using linq (not related to SpecializationbyTraits)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var toms = from cat &lt;span
 style="color: Blue;"&gt;in&lt;/span&gt; cats where cat.Name == &lt;span
 style="color: Maroon;"&gt;"Tom"&lt;/span&gt; select cat;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;if&lt;/span&gt; (toms.Count() &amp;gt; &lt;span
 style="color: Maroon;"&gt;0&lt;/span&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Cat tom = toms.First();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.WriteLine(&lt;span
 style="color: Maroon;"&gt;"Tom found, ID={0}"&lt;/span&gt;, tom.Id);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;else&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Cat tom = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Cat();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tom.Name = &lt;span
 style="color: Maroon;"&gt;"Tom"&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tom.Sex = &lt;span
 style="color: Maroon;"&gt;'m'&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tom.Weight = &lt;span
 style="color: Maroon;"&gt;5&lt;/span&gt;&lt;span
 style="color: Maroon;"&gt;.2F&lt;/span&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;connection.Execute(CatConverter.InsertSql(), tom);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
We first register our type conversion specialization. We create a
connection to the database (hard coded - alternatively you might
get it from e.g. appSettings). We can use any SQL statement
to fill any list with any (registered) model. For fun we use LINQ here
to do a subselection.
We can execute SQL to insert, update or delete things. That
InsertSql is specified (&lt;span style="font-style: italic;"&gt;for
convenience, I prefer it close to its parameters&lt;/span&gt;) within
the converter as well, it can be anywhere,&amp;nbsp;up to you.&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;span style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; InsertSql()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; &lt;span
 style="color: Maroon;"&gt;"insert into Cat(CatId, Name, Sex, Weight) values(NEWID(), @name, @sex, @weight)"&lt;/span&gt;;&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Stormy ORM - wrapping it up&lt;/h2&gt;
&lt;br&gt;
Great isn't it? The Stormy code is about hundred lines now. Of course
it is not a full-featured ORM as others are, but in many
cases more convenient, more simple to understand, it does not create
shadow classes, and it does
not&amp;nbsp;force you to learn a new criteria language. If you know
SQL, you will like it!&lt;br&gt;
&lt;br&gt;
The project including sample can be downloaded &lt;a
 href="http://stormy.codeplex.com"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
We're nearly done with C# Specializations. It is really useful. Can be
used everywhere. Makes C# closer to C++.&lt;br&gt;
&lt;br&gt;
Next:&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a
 href="/2010/07/c-specializations-by-traits-iv-geometry.html"&gt;geometry&lt;/a&gt;...&lt;/li&gt;
&lt;/ul&gt;
Stay tuned!&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1218157414905973664-6468116161242874157?l=barendgehrels.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barendgehrels.blogspot.com/feeds/6468116161242874157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://barendgehrels.blogspot.com/2010/07/c-specializations-by-traits-iii.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/6468116161242874157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1218157414905973664/posts/default/6468116161242874157'/><link rel='alternate' type='text/html' href='http://barendgehrels.blogspot.com/2010/07/c-specializations-by-traits-iii.html' title='C# Specializations by Traits III'/><author><name>Barend</name><uri>http://www.blogger.com/profile/09980486851496193008</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1218157414905973664.post-7854452911889000561</id><published>2010-07-23T22:05:00.000+02:00</published><updated>2010-07-24T13:44:33.695+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='generics'/><category scheme='http://www.blogger.com/atom/ns#' term='extension methods'/><category scheme='http://www.blogger.com/atom/ns#' term='specialization'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='traits'/><title type='text'>C# Specializations by Traits II</title><content type='html'>&lt;br&gt;
&lt;h1&gt;C# Specializations by Traits II&lt;/h1&gt;
&lt;br&gt;
&lt;h2&gt;&lt;span style="font-style: italic;"&gt;Cat and Mouse
populate a Silverlight&amp;nbsp;Listbox&lt;/span&gt;&lt;/h2&gt;
In my previous &lt;a href="/2010/07/c-specializations-by-traits-i.html"&gt;blog&lt;/a&gt;
we saw that you seriously can do specialization in C#, using
traits classes, extension methods and a directionary. The
use case was a bit centered on class (method) specialization.&lt;br&gt;
&lt;br&gt;
In this blog we will see that it is equally possible, and probably even
more useful, to
specialize a generic method for different classes. The system is the
same, the samples are more useful.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Use case&lt;/h2&gt;
Imagine two models (classes), a Cat and a Mouse. They are
different,
not sharing an interface and not inheriting from a common base class.
They
are kept simple, just name and ID. On purpose attributes are named
differently for Cat
and Mouse.&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; Cat&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; Cat(&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; i, &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; n)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Id = i;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Name = n;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; Id { &lt;span
 style="color: Blue;"&gt;get&lt;/span&gt;; &lt;span
 style="color: Blue;"&gt;set&lt;/span&gt;; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; Name { &lt;span
 style="color: Blue;"&gt;get&lt;/span&gt;; &lt;span
 style="color: Blue;"&gt;set&lt;/span&gt;; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; Mouse&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; Mouse(&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; i, &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; n)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseId = i;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseName = n;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; MouseId { &lt;span
 style="color: Blue;"&gt;get&lt;/span&gt;; &lt;span
 style="color: Blue;"&gt;set&lt;/span&gt;; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; MouseName { &lt;span
 style="color: Blue;"&gt;get&lt;/span&gt;; &lt;span
 style="color: Blue;"&gt;set&lt;/span&gt;; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
We have two generic collections of them: a List&amp;lt;Cat&amp;gt; and
a List&amp;lt;Mouse&amp;gt;. I like the generic collections! We want to
add both collections to a
Silverlight listbox... of course in a generic way. That is not trivial,
but with help of previous blog, or more specificly with help of our new
"Specialization by Traits" system, we can do it. Note that this example
(filling a list box) is a
bit inspired on this &lt;a
 href="http://stackoverflow.com/questions/893196/generic-combobox-with-automatically-named-properties"&gt;page&lt;/a&gt;
where a dropdown should be specific for a model.&lt;br&gt;
&lt;br&gt;
We will use the&amp;nbsp;traits system which helped us so
much&amp;nbsp;in previous blog to reach our goal. And there are
more traits-ways to do it.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Traits 1: Common Interface&lt;/h2&gt;
First we create a traits class which tries to create a common
interface, getting the &lt;span style="font-style: italic;"&gt;Id
&lt;/span&gt;and the &lt;span style="font-style: italic;"&gt;Name&lt;/span&gt;
for both classes in the same way.&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;br&gt;&lt;span style="color: Blue;"&gt;namespace&lt;/span&gt; Traits&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;interface&lt;/span&gt; AnimalTraits&amp;lt;T&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; GetId(T obj);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; GetName(T obj);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; CatTraits : AnimalTraits&amp;lt;Models.Cat&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; GetId(Models.Cat cat) { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; cat.Id; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; GetName(Models.Cat cat) { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; cat.Name; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; MouseTraits : AnimalTraits&amp;lt;Models.Mouse&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; GetId(Models.Mouse mouse) { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; mouse.MouseId; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; GetName(Models.Mouse mouse) { &lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; mouse.MouseName; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; AnimalRegister&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; IDictionary&amp;lt;System.Type, &lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;&amp;gt; register;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; Register&amp;lt;T&amp;gt;(AnimalTraits&amp;lt;T&amp;gt; traits)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;if&lt;/span&gt; (register == &lt;span
 style="color: Blue;"&gt;null&lt;/span&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;register = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Dictionary&amp;lt;System.Type, &lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;&amp;gt;();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;register[&lt;span
 style="color: Blue;"&gt;typeof&lt;/span&gt;(T)] = traits;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; AnimalTraits&amp;lt;T&amp;gt; Get&amp;lt;T&amp;gt;()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;return&lt;/span&gt; register[&lt;span
 style="color: Blue;"&gt;typeof&lt;/span&gt;(T)] &lt;span
 style="color: Blue;"&gt;as&lt;/span&gt; AnimalTraits&amp;lt;T&amp;gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;
Once we have those classes, we can fill the list using them, using the
common interface. For Cats we take the CatTraits, for the Mice the
MouseTraits, of course. Or we can let the compiler take them
automagically using that traits-register, the Dictionary&amp;lt;Type,
object&amp;gt; which can be approached by the typeof function.&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; fillGeneric1&amp;lt;T&amp;gt;(ListBox lb, IEnumerable&amp;lt;T&amp;gt; animals)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AnimalTraits&amp;lt;T&amp;gt; traits = AnimalRegister.Get&amp;lt;T&amp;gt;();&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;foreach&lt;/span&gt; (T animal &lt;span
 style="color: Blue;"&gt;in&lt;/span&gt; animals)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ListBoxItem item = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; ListBoxItem();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item.Content = traits.GetName(animal);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item.Tag = traits.GetId(animal);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;animalListBox.Items.Add(item);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; button1_Click(&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Green;"&gt;// (Re)fillGeneric1 our list using the generic way&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;animalListBox.Items.Clear();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fillGeneric1(animalListBox, cats);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fillGeneric1(animalListBox, mice);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
We see that we can fill the listbox easily like this. The fillGeneric1
method is generic! It is specialized per animal. &lt;br&gt;
&lt;br&gt;
However, if we
want to do anything different for the Cats class&amp;nbsp;than we do
for Mice (besides getting ID and name), we have to solve it
differently. This is in Traits 3 below. First Lambda.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;"Traits 2": Lambda Register&lt;/h2&gt;
Is this still&amp;nbsp;traits... No traits involved, only lambda. They
play the role of the traits. The architecture is similar.&lt;br&gt;
&lt;br&gt;
We define a delegate type and create (usually in a singleton) a
dictionary&amp;nbsp;delegate-by-type. In this
use case we need two delegates (one for ID, one for name) but that is
flexible of
course. We select here&amp;nbsp;a dictionary of pairs.&lt;br&gt;
&lt;br&gt;
We have the same
directionary as in the previous examples as a register, mapping from
Type to any object (now a delegate-pair). We add
a convenience method to register lambda's and to retrieve them using
Get&amp;lt;&amp;gt;&lt;br&gt;
&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;br&gt;&lt;span style="color: Blue;"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;delegate&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;int&lt;/span&gt; get_id&amp;lt;Animal&amp;gt;(Animal a);&lt;br&gt;&lt;span
 style="color: Blue;"&gt;delegate&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;string&lt;/span&gt; get_name&amp;lt;Animal&amp;gt;(Animal a);&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;class&lt;/span&gt; LambdaRegister&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; IDictionary&amp;lt;System.Type, KeyValuePair&amp;lt;&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;&amp;gt;&amp;gt; register;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; Register&amp;lt;Animal&amp;gt;(get_id&amp;lt;Animal&amp;gt; gi, get_name&amp;lt;Animal&amp;gt; gn)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;if&lt;/span&gt; (register == &lt;span
 style="color: Blue;"&gt;null&lt;/span&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;register = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; Dictionary&amp;lt;System.Type, KeyValuePair&amp;lt;&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;,&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;&amp;gt;&amp;gt;();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;register[&lt;span
 style="color: Blue;"&gt;typeof&lt;/span&gt;(Animal)] = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; KeyValuePair&amp;lt;&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;,&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;&amp;gt;(gi, gn);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;static&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; Get&amp;lt;Animal&amp;gt;(&lt;span
 style="color: Blue;"&gt;out&lt;/span&gt; get_id&amp;lt;Animal&amp;gt; gi, &lt;span
 style="color: Blue;"&gt;out&lt;/span&gt; get_name&amp;lt;Animal&amp;gt; gn)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;KeyValuePair&amp;lt;&lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;, &lt;span
 style="color: Blue;"&gt;object&lt;/span&gt;&amp;gt; pair = register[&lt;span
 style="color: Blue;"&gt;typeof&lt;/span&gt;(Animal)];&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gi = pair.Key &lt;span
 style="color: Blue;"&gt;as&lt;/span&gt; get_id&amp;lt;Animal&amp;gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gn = pair.Value &lt;span
 style="color: Blue;"&gt;as&lt;/span&gt; get_name&amp;lt;Animal&amp;gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
The register can be initialized, once, like this:&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LambdaRegister.Register&amp;lt;Models.Cat&amp;gt;(p =&amp;gt; p.Id, p =&amp;gt; p.Name);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LambdaRegister.Register&amp;lt;Models.Mouse&amp;gt;(p =&amp;gt; p.MouseId, p =&amp;gt; p.MouseName);&lt;br&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
We see: we created the register in the same way. But, again, we &lt;b&gt;don't
need any traits &lt;/b&gt;here.
Then we populate our listbox using the lambda-register
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;private&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;void&lt;/span&gt; fillGeneric3&amp;lt;T&amp;gt;(ListBox lb, IEnumerable&amp;lt;T&amp;gt; animals)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get_id&amp;lt;T&amp;gt; gi;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get_name&amp;lt;T&amp;gt; gn;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LambdaRegister.Get&amp;lt;T&amp;gt;(&lt;span
 style="color: Blue;"&gt;out&lt;/span&gt; gi, &lt;span
 style="color: Blue;"&gt;out&lt;/span&gt; gn);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;foreach&lt;/span&gt; (T animal &lt;span
 style="color: Blue;"&gt;in&lt;/span&gt; animals)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ListBoxItem item = &lt;span
 style="color: Blue;"&gt;new&lt;/span&gt; ListBoxItem();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item.Tag = gi(animal);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item.Content = &lt;span
 style="color: Maroon;"&gt;"L "&lt;/span&gt; + gn(animal);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;animalListBox.Items.Add(item);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Traits 3: Specific Goal&lt;/h2&gt;
We can also create a traits interface&amp;nbsp;which is designed to
fill a listbox. It then has a method called (e.g.) Apply, which takes a
listbox and adds an item. Or which returns an item. Anyway, the traits
classes which (also here) are specific for Cat and Mouse have full
access to these classes, and can call any method. In this way they
assign the ListBoxItem and return it.&lt;br&gt;
&lt;div style="overflow: scroll;"&gt;
&lt;pre&gt;&lt;br&gt;&lt;span style="color: Blue;"&gt;using&lt;/span&gt; System;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Windows;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;using&lt;/span&gt; System.Windows.Controls;&lt;br&gt;&lt;br&gt;&lt;span
 style="color: Blue;"&gt;namespace&lt;/span&gt; Traits&lt;br&gt;{&lt;br&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span
 style="color: Blue;"&gt;public&lt;/span&gt; &lt;span
 style="color: Blue;"&gt;interface&lt;/span&gt; FillAnimalTraits&amp;lt;T&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nb
