<?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-4113082053753185517</id><updated>2012-02-01T20:17:24.520+01:00</updated><category term='uDig'/><category term='node.js'/><category term='Python'/><category term='logging'/><category term='Rtree'/><category term='javascript'/><category term='roslyn'/><category term='DatagridView'/><category term='WKT'/><category term='GeometryVisualizer'/><category term='youtube'/><category term='anti-rdbms'/><category term='shell'/><category term='Jython'/><category term='projections'/><category term='MongoDb'/><category term='spatial index'/><category term='csv'/><category term='OpenLayers'/><category term='WinForms'/><category term='featureclass'/><category term='code publishing'/><category term='Cursors'/><category term='ogr'/><category term='table'/><category term='esri rest specification'/><category term='document database'/><category term='gvSIG'/><category term='PostGIS'/><category term='ArcGIS'/><category term='DragDrop'/><category term='shortest path'/><category term='syntax highlighting'/><category term='GeoJSON'/><category term='Psyco'/><category term='checked'/><category term='C#'/><category term='Python Toolbox'/><category term='PostgreSQL'/><category term='Tokyo Cabinet'/><category term='Ruby'/><category term='ArcObjects'/><category term='unchecked'/><category term='spatial filter'/><category term='Quantum GIS'/><category term='Ubuntu'/><category term='geoprocessing'/><category term='PyPy'/><category term='duplicate code'/><category term='NetworkX'/><category term='Clone Digger'/><category term='pyproj'/><category term='REPL'/><category term='similar code'/><category term='.NET'/><category term='transformations'/><title type='text'>GIS Solved</title><subtitle type='html'>Solving GIS and other programming problems</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>31</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-4266732842447580212</id><published>2012-01-25T20:35:00.000+01:00</published><updated>2012-01-26T10:20:03.247+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenLayers'/><category scheme='http://www.blogger.com/atom/ns#' term='WKT'/><category scheme='http://www.blogger.com/atom/ns#' term='GeoJSON'/><category scheme='http://www.blogger.com/atom/ns#' term='GeometryVisualizer'/><category scheme='http://www.blogger.com/atom/ns#' term='esri rest specification'/><title type='text'>Visualizing Geometries</title><content type='html'>&lt;p&gt;In this post I'm going to give some more information about the &lt;a href="http://gissolved.blogspot.com/p/geometry-visualizer.html"&gt;GeometryVisualizer&lt;/a&gt; that I created recently.&lt;/p&gt;

&lt;p&gt;The goal of the GeometryVisualizer is to be able to quickly visualize a GeoJson, WKT or ESRI JSON geometry. I created this to be able to quickly see how some ESRI JSON and WKT geometries looked like and visually verify some geometry conversion code I'm writing for my &lt;a href="http://gissolved.blogspot.com/2011/12/creating-nodejs-geometryservice-part-1.html"&gt;GeometryService in node.js&lt;/a&gt;. You can also use this to visualize the WKT or GeoJSON output of a PostGIS geometry query.&lt;/p&gt;

&lt;p&gt;The ESRI JSON geometries are rendered with the &lt;a href="http://help.arcgis.com/en/webapi/javascript/arcgis/"&gt;ArcGIS JavaScript API&lt;/a&gt;. The WKT and GeoJSON geometries are rendered with &lt;a href="http://openlayers.org"&gt;OpenLayers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;
&lt;h3&gt;Some code&lt;/h3&gt;
In this section I'll show some parts of the code that made this web application possible and compare the ArcGIS JavaScript API with the OpenLayers API. First we'll take a look at the initialization of the map. The most notable facts about the initialization are that we need to add a layer before we are able to add graphics and that disabling the zoomwheel is less straight forward with the OpenLayers API.&lt;/p&gt;

&lt;p&gt;ESRI JavaScript API map initialization:&lt;/p&gt;

&lt;!-- HTML generated using hilite.me --&gt;&lt;div style="background: #ffffff; overflow:auto;width:auto;color:black;background:white;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"&gt;&lt;pre style="margin: 0; line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; map &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; esri.Map(&lt;span style="background-color: #fff0f0"&gt;&amp;quot;esriJsonMap&amp;quot;&lt;/span&gt;);
map.disableScrollWheelZoom();

&lt;span style="color: #808080"&gt;// add a layer and directly hide it because otherwise we can&amp;#39;t create graphics&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; basemapURL&lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;quot;http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer&amp;quot;&lt;/span&gt;

&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; basemap &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; esri.layers.ArcGISDynamicMapServiceLayer(basemapURL);
map.addLayer(basemap);
basemap.visible &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;false&lt;/span&gt;;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;OpenLayers map initialization:&lt;/p&gt;

&lt;!-- HTML generated using hilite.me --&gt;&lt;div style="background: #ffffff; overflow:auto;width:auto;color:black;background:white;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"&gt;&lt;pre style="margin: 0; line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; map &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; OpenLayers.Map(&lt;span style="background-color: #fff0f0"&gt;&amp;quot;openLayersMap&amp;quot;&lt;/span&gt;);

&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; controls &lt;span style="color: #303030"&gt;=&lt;/span&gt; map.getControlsByClass(&lt;span style="background-color: #fff0f0"&gt;&amp;#39;OpenLayers.Control.Navigation&amp;#39;&lt;/span&gt;); 
&lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt;(&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; i &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="color: #0000D0; font-weight: bold"&gt;0&lt;/span&gt;; i&lt;span style="color: #303030"&gt;&amp;lt;&lt;/span&gt;controls.length; &lt;span style="color: #303030"&gt;++&lt;/span&gt;i){ 
    controls[i].disableZoomWheel(); 
}

&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; layer &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; OpenLayers.Layer.ArcGIS93Rest( &lt;span style="background-color: #fff0f0"&gt;&amp;quot;ArcGIS World Street Map&amp;quot;&lt;/span&gt;, 
                &lt;span style="background-color: #fff0f0"&gt;&amp;quot;http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer&amp;quot;&lt;/span&gt;,
                {layers&lt;span style="color: #303030"&gt;:&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;} );
map.addLayer(layer);
layer.setVisibility(&lt;span style="color: #008000; font-weight: bold"&gt;false&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
To be able to render an ESRI JSON geometry string with the ArcGIS JavaScript API you have to do some specific steps :
&lt;ul&gt;
&lt;li&gt;Clear the graphics&lt;/li&gt;
&lt;li&gt;Parse the geometry string representation&lt;/li&gt;
&lt;li&gt;Create a graphic and set its symbol according to the geometry type.&lt;/li&gt;
&lt;li&gt;Update the extent of the map&lt;/li&gt;
&lt;/ul&gt; 
Not that for updating the extent, I had to access an undocumented property of the graphics object and for point graphics the extent had to be enlarged. 
&lt;/p&gt;

&lt;!-- HTML generated using hilite.me --&gt;&lt;div style="background: #ffffff; overflow:auto;width:auto;color:black;background:white;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"&gt;&lt;pre style="margin: 0; line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; addGeometry(geometryText) {
    
    &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt;(map.graphics &lt;span style="color: #303030"&gt;===&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;null&lt;/span&gt;) &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt;; &lt;span style="color: #808080"&gt;// map not loaded yet or something else is wrong&lt;/span&gt;
            
    map.graphics.clear();

    &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; geometryJson &lt;span style="color: #303030"&gt;=&lt;/span&gt; JSON.parse(geometryText);
    &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; graphic &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; esri.Graphic(geometryJson);

    &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; (&lt;span style="color: #303030"&gt;!&lt;/span&gt;graphic.symbol){
      &lt;span style="color: #008000; font-weight: bold"&gt;switch&lt;/span&gt;(graphic.geometry.type){
        &lt;span style="color: #008000; font-weight: bold"&gt;case&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;quot;point&amp;quot;&lt;/span&gt;&lt;span style="color: #303030"&gt;:&lt;/span&gt;
        &lt;span style="color: #008000; font-weight: bold"&gt;case&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;quot;multipoint&amp;quot;&lt;/span&gt;&lt;span style="color: #303030"&gt;:&lt;/span&gt;
          graphic.setSymbol(&lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; esri.symbol.SimpleMarkerSymbol());
          &lt;span style="color: #008000; font-weight: bold"&gt;break&lt;/span&gt;;
        &lt;span style="color: #008000; font-weight: bold"&gt;case&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;quot;polyline&amp;quot;&lt;/span&gt;&lt;span style="color: #303030"&gt;:&lt;/span&gt;
          graphic.setSymbol(&lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; esri.symbol.SimpleLineSymbol());
          &lt;span style="color: #008000; font-weight: bold"&gt;break&lt;/span&gt;;
        &lt;span style="color: #008000; font-weight: bold"&gt;default&lt;/span&gt;&lt;span style="color: #303030"&gt;:&lt;/span&gt;
          graphic.setSymbol(&lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; esri.symbol.SimpleFillSymbol());
          &lt;span style="color: #008000; font-weight: bold"&gt;break&lt;/span&gt;;
      }
    }

    map.graphics.add(graphic);
    &lt;span style="color: #808080"&gt;// use undocumented object&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; ext &lt;span style="color: #303030"&gt;=&lt;/span&gt; graphic._extent;
    &lt;span style="color: #808080"&gt;// if point expand the extent&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt;(ext.getWidth() &lt;span style="color: #303030"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color: #6000E0; font-weight: bold"&gt;0.00000001&lt;/span&gt; &lt;span style="color: #303030"&gt;||&lt;/span&gt; ext.getHeight() &lt;span style="color: #303030"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color: #6000E0; font-weight: bold"&gt;0.00000001&lt;/span&gt;){
      &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; factor &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="color: #0000D0; font-weight: bold"&gt;1&lt;/span&gt;;
      ext.update(ext.xmin &lt;span style="color: #303030"&gt;-&lt;/span&gt; factor, ext.ymin &lt;span style="color: #303030"&gt;-&lt;/span&gt; factor, ext.xmax &lt;span style="color: #303030"&gt;+&lt;/span&gt; factor, ext.ymax &lt;span style="color: #303030"&gt;+&lt;/span&gt; factor, ext.spatialReference);
    }

    map.setExtent(ext.expand(&lt;span style="color: #0000D0; font-weight: bold"&gt;2&lt;/span&gt;));
}
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The process of adding WKT and GeoJSON geometries was very similar.
&lt;ul&gt;
&lt;li&gt;Remove all features&lt;/li&gt;
&lt;li&gt;Parse the geometry string representation with a predefined formatter (OpenLayers.Format.WKT or OpenLayers.Format.GeoJSON)&lt;/li&gt;
&lt;li&gt;Update the extent of the map.&lt;/li&gt;
&lt;/ul&gt;
Note that I didn't had to specify the symbology and zooming to the extent of the feature was easier. 
The WKT parsing was very straight forward. For the GeoJSON parsing I had to add two things. First I had to ensure that the parsed JSON had a property "type" with as value "Feature" and the parsed object returned a feature collection with one feature instead of directly returning the feature.
&lt;/p&gt;

&lt;!-- HTML generated using hilite.me --&gt;&lt;div style="background: #ffffff; overflow:auto;width:auto;color:black;background:white;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"&gt;&lt;pre style="margin: 0; line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; addGeometry(geometryInput, parser, type){
  vectorLayer.removeAllFeatures();
  &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; feature &lt;span style="color: #303030"&gt;=&lt;/span&gt; parser.read(geometryInput);
  vectorLayer.addFeatures(feature);
  &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt;(dojo.isArray(feature)){
    feature &lt;span style="color: #303030"&gt;=&lt;/span&gt; feature[&lt;span style="color: #0000D0; font-weight: bold"&gt;0&lt;/span&gt;];
  }
  &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; bounds &lt;span style="color: #303030"&gt;=&lt;/span&gt; feature.geometry.getBounds();
  bounds = bounds.scale(1.1);
  map.zoomToExtent(bounds);  
}

&lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; addWkt(geometryText) {
  &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; wktFormat &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; OpenLayers.Format.WKT();
  addGeometry(geometryText, wktFormat);
}

&lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; addGeoJson(geometryText) {
  &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; geoJsonFormat &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; OpenLayers.Format.GeoJSON();
  &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; geometry &lt;span style="color: #303030"&gt;=&lt;/span&gt; JSON.parse(geometryText);
  geometry[&lt;span style="background-color: #fff0f0"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;] &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;quot;Feature&amp;quot;&lt;/span&gt;;
  addGeometry(geometry, geoJsonFormat);
}
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This are the most interesting parts of the code. The full source code is in the &lt;a href="http://gissolved.blogspot.com/p/geometry-visualizer.html"&gt;GeometryVisualizer&lt;/a&gt;.
&lt;p&gt;Any questions/remarks/improvements ? Let me know !&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-4266732842447580212?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/4266732842447580212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2012/01/visualizing-geometries.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/4266732842447580212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/4266732842447580212'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2012/01/visualizing-geometries.html' title='Visualizing Geometries'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-1358890831265359342</id><published>2011-12-15T21:38:00.016+01:00</published><updated>2012-01-25T12:34:36.252+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><category scheme='http://www.blogger.com/atom/ns#' term='esri rest specification'/><title type='text'>Creating a node.js GeometryService : part 2</title><content type='html'>&lt;p&gt;This is my second post on what I learned from creating an implementation of the  geometryservice specification in node.js. The first post can be found &lt;a href="http://gissolved.blogspot.com/2011/12/creating-nodejs-geometryservice-part-1.html"&gt;here&lt;/a&gt;.  &lt;p&gt;By default node.js doesn't reload your files when they have changed but while developing this can be very handy. The most easy to use tool for node.js on windows that monitors your files for changes, with an easy way to set the node.js debugging flag, is nodemonw. You can download nodemonw at &lt;a href="https://github.com/cenanozen/nodemonw"&gt;https://github.com/cenanozen/nodemonw&lt;/a&gt;. Once you've downloaded the executable I suggest to copy it to your %Appdata%\npm directory or another directory thats in your path. To start nodemonw I now run the following command &lt;code&gt;nodemonw --debug index.js&lt;/code&gt;. In the next section it will become clear why I added the --debug flag. &lt;/p&gt;&lt;p&gt;To be able to debug my node.js application I installed &lt;a href="https://github.com/dannycoates/node-inspector"&gt;node-inspector&lt;/a&gt; (&lt;code&gt;npm install -g node-inspector&lt;/code&gt;). As you can read in the readme of node-inspector it is really easy to get started with node-inspector. You just have to start node-inspector and then open &lt;a href="http://127.0.0.1:8080/debug?port=5858"&gt;http://127.0.0.1:8080/debug?port=5858&lt;/a&gt; in your favorite WebKit based browser. On Wikipedia I found this list of &lt;a href="http://en.wikipedia.org/wiki/List_of_web_browsers#WebKit-based"&gt;WebKit based browsers&lt;/a&gt;. The most well known ones for Windows are &lt;a href="https://www.google.com/chrome/?brand=ECSB&amp;installdataindex=no-apps-no-promo"&gt;Google Chrome&lt;/a&gt; and &lt;a href="http://www.apple.com/safari/download/"&gt;Safari&lt;/a&gt;. A screencast on node-inspector can be found &lt;a href="http://howtonode.org/debugging-with-node-inspector"&gt;here&lt;/a&gt;. There is also a &lt;a href="http://www.youtube.com/view_play_list?p=A5216AC29A41EFA8"&gt;node-inspector playlist&lt;/a&gt; on YouTube. &lt;/p&gt;&lt;p&gt;To be able to test parts of my GeometryService I used vows (&lt;code&gt;npm install -g vows&lt;/code&gt;). Vows is an asynchronous behavior driven development framework. More info about it can be found on &lt;a href="http://vowsjs.org/"&gt;http://vowsjs.org/&lt;/a&gt;. I am now going to show a small part of the code from my GeometryService and some tests I wrote for this code. My directory structure for the code I'll show looks like this: &lt;code&gt; lib/&lt;br /&gt;
-- datatransformer.js&lt;br /&gt;
test/&lt;br /&gt;
-- datatransformers.test.js&lt;br /&gt;
&lt;/code&gt; In datatransformer.js I started a function to convert an ESRI geometry JSON object to wkt based on its geometry type.&lt;/p&gt;&lt;div style="background: #ffffff; overflow:auto;width:auto;color:black;background:white;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"&gt;&lt;pre style="margin: 0; line-height: 125%"&gt;exports.esriGeoJsonToWKT &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; esriGeoJsonToWKT (geometryType, geometry) {
  &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt;(geometryType &lt;span style="color: #303030"&gt;===&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;quot;esriGeometryPoint&amp;quot;&lt;/span&gt;) {
    &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;quot;POINT(&amp;quot;&lt;/span&gt; &lt;span style="color: #303030"&gt;+&lt;/span&gt; geometry.x &lt;span style="color: #303030"&gt;+&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span style="color: #303030"&gt;+&lt;/span&gt; geometry.y &lt;span style="color: #303030"&gt;+&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;quot;)&amp;quot;&lt;/span&gt;;
  }
}
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the content of datatransformer.test.js is:&lt;/p&gt;&lt;!-- HTML generated using hilite.me --&gt;&lt;div style="background: #ffffff; overflow:auto;width:auto;color:black;background:white;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"&gt;&lt;pre style="margin: 0; line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; dt &lt;span style="color: #303030"&gt;=&lt;/span&gt; require(&lt;span style="background-color: #fff0f0"&gt;&amp;quot;../lib/datatransformer&amp;quot;&lt;/span&gt;);
&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; vows &lt;span style="color: #303030"&gt;=&lt;/span&gt; require(&lt;span style="background-color: #fff0f0"&gt;&amp;#39;vows&amp;#39;&lt;/span&gt;);
&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; assert &lt;span style="color: #303030"&gt;=&lt;/span&gt; require(&lt;span style="background-color: #fff0f0"&gt;&amp;#39;assert&amp;#39;&lt;/span&gt;);

vows.describe(&lt;span style="background-color: #fff0f0"&gt;&amp;#39;Esri geometry JSON to WKT&amp;#39;&lt;/span&gt;).addBatch({
  &lt;span style="background-color: #fff0f0"&gt;&amp;#39;when converting esriGeometryPoint {&amp;quot;x&amp;quot;:-117,&amp;quot;y&amp;quot;:34}&amp;#39;&lt;/span&gt;&lt;span style="color: #303030"&gt;:&lt;/span&gt;{
    topic&lt;span style="color: #303030"&gt;:&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt;(){ 
      &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; geomType &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;#39;esriGeometryPoint&amp;#39;&lt;/span&gt;;
      &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; p &lt;span style="color: #303030"&gt;=&lt;/span&gt; JSON.parse(&lt;span style="background-color: #fff0f0"&gt;&amp;#39;{&amp;quot;x&amp;quot;:-117,&amp;quot;y&amp;quot;:34}&amp;#39;&lt;/span&gt;);
      &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; dt.esriGeoJsonToWKT(geomType, p);
    },
    &lt;span style="background-color: #fff0f0"&gt;&amp;#39;we get &amp;quot;POINT(-117 34)&amp;quot;&amp;#39;&lt;/span&gt;&lt;span style="color: #303030"&gt;:&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt;(topic){
      assert.equal(topic, &lt;span style="background-color: #fff0f0"&gt;&amp;quot;POINT(-117 34)&amp;quot;&lt;/span&gt;);
    }
  },
  &lt;span style="background-color: #fff0f0"&gt;&amp;#39;but when converting esriGeometryPoint {&amp;quot;x&amp;quot;:-117.01,&amp;quot;y&amp;quot;:34.02}&amp;#39;&lt;/span&gt;&lt;span style="color: #303030"&gt;:&lt;/span&gt;{
    topic&lt;span style="color: #303030"&gt;:&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt;(){ 
      &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; geomType &lt;span style="color: #303030"&gt;=&lt;/span&gt; &lt;span style="background-color: #fff0f0"&gt;&amp;#39;esriGeometryPoint&amp;#39;&lt;/span&gt;;
      &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; p &lt;span style="color: #303030"&gt;=&lt;/span&gt; JSON.parse(&lt;span style="background-color: #fff0f0"&gt;&amp;#39;{&amp;quot;x&amp;quot;:-117.01,&amp;quot;y&amp;quot;:34.02}&amp;#39;&lt;/span&gt;);
      &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; dt.esriGeoJsonToWKT(geomType, p);
    },
    &lt;span style="background-color: #fff0f0"&gt;&amp;#39;we get &amp;quot;POINT(-117.01 34.02)&amp;quot;&amp;#39;&lt;/span&gt;&lt;span style="color: #303030"&gt;:&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt;(topic){
      assert.equal(topic, &lt;span style="background-color: #fff0f0"&gt;&amp;quot;POINT(-117.01 34.02)&amp;quot;&lt;/span&gt;);
    }
  }
}).exportTo(module);
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see I created two tests for converting point geometries from ESRI JSON to wkt. One for integer coordinates and one for decimal coordinates. The easiest way to run this tests with vows on windows was opening a commandline in the root directory of my node.js project and type &lt;code&gt;vows --spec&lt;/code&gt;. This will run the tests it finds in the test and spec directories of your project. My output looks like this :&lt;/p&gt;&lt;code&gt;  ? Esri geometry JSON to WKT&lt;br /&gt;
&lt;br /&gt;
when converting esriGeometryPoint {"x":-117,"y":34}&lt;br /&gt;
V we get "POINT(-117 "4)"&lt;br /&gt;
but when converting esriGeometryPoint {"x":-117.01,"y":34.02}&lt;br /&gt;
V we get "POINT(-117.01 34.02)"&lt;br /&gt;
&lt;br /&gt;
V OK » 2 honored (0.007s)&lt;br /&gt;
&lt;/code&gt;  &lt;p&gt;On a side note if you ever encounter that node can't find any of your globally installed packages then it might help to add a new User Variable called NODE_PATH with as value %AppData%\npm\node_modules. That was it for this post more posts on this project will follow.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-1358890831265359342?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/1358890831265359342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2011/12/creating-nodejs-geometryservice-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/1358890831265359342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/1358890831265359342'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2011/12/creating-nodejs-geometryservice-part-2.html' title='Creating a node.js GeometryService : part 2'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-8155082192735650069</id><published>2011-12-15T21:00:00.000+01:00</published><updated>2011-12-15T21:37:47.208+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><category scheme='http://www.blogger.com/atom/ns#' term='esri rest specification'/><title type='text'>Creating a node.js GeometryService : part 1</title><content type='html'>&lt;p&gt;Ever since I encountered the &lt;a href="http://www.esri.com/library/whitepapers/pdfs/geoservices-rest-spec.pdf"&gt;geoservices-rest-specification (pdf)&lt;/a&gt; I've been thinking about creating my own implementation. I also wanted wanted to try out &lt;a href="http://nodejs.org/"&gt;node.js&lt;/a&gt; so I combined both ideas and started implementing a GeometryService in node.js. If you've never heard of node.js, this is the short introduction from the homepage of node.js:&lt;br /&gt;&lt;q&gt;Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.&lt;/q&gt; The GeometryService is a web service that contains GIS related utility methods like project, intersect, buffer,... A sample server can be found here &lt;a href="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer"&gt;http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I first downloaded and installed the windows installer of node.js version 0.65. After a reboot all locations where added to my path so that I can now start a new cmd window and type node. Note that when you install packages globally with the node package manager called npm (&lt;code&gt;npm install &amp;lt;package&amp;gt; -g&lt;/code&gt;) npm (the node package manager) then the packages are installed in Windows 7 under %AppData%\npm (C:\Users\&amp;lt;username&amp;gt;\AppData\Roaming\npm). The full list of packages is located here &lt;a href="http://search.npmjs.org/"&gt;search.npmjs.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To get started learning node I first read the node.js tutorial at &lt;a href="http://www.nodebeginner.org/"&gt;nodebeginner.com&lt;/a&gt;. By following this tutorial I got a great insight in how to create your own webserver. At this moment I'm continuing to build my webservice based on this code but I plan to use some framework like &lt;a href="http://expressjs.com/"&gt;express&lt;/a&gt; or &lt;a href="https://github.com/cloudhead/journey/"&gt;journey&lt;/a&gt; in a later stage. This is not very urgent because I'll first focus on the JSON output of the GeometryService and thus won't need to output any html.&lt;/p&gt;

&lt;p&gt;For my first version of the GeometryService I decided to use &lt;a href="http://postgis.refractions.net/"&gt;PostGIS&lt;/a&gt; as my geometry processor. I know this introduces an extra overhead. But I think this is the easiest way to get something up and running in a short period of time. If you don't want to bother with installing PostgreSQL and PostGIS I suggest you to &lt;a href="http://opengeo.org/technology/suite/download/"&gt;download&lt;/a&gt; the Community edition of the &lt;a href="http://opengeo.org/"&gt;Open Geo Suite&lt;/a&gt;. To be able to connect to the database I installed &lt;a href="https://github.com/brianc/node-postgres"&gt;node-postgres&lt;/a&gt; with following command line: &lt;code&gt;npm install pg -g&lt;/code&gt;. If you're on windows and get build errors you might try to add a file called true.cmd to the directory where node.exe resides (e.g. C:\Program Files (x86)\nodejs) with as content &lt;code&gt;exit 0&lt;/code&gt;. Below is a short snippet on how I connect to the database. Make sure to replace all placeholders in the connection string.&lt;br /&gt;

&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;var&lt;/span&gt; pg &lt;span style='color:#808030; '&gt;=&lt;/span&gt; require&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;pg&lt;/span&gt;&lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;

&lt;span style='color:#800000; font-weight:bold; '&gt;function&lt;/span&gt; executeSQL&lt;span style='color:#808030; '&gt;(&lt;/span&gt;sql&lt;span style='color:#808030; '&gt;,&lt;/span&gt; parameters&lt;span style='color:#808030; '&gt;,&lt;/span&gt; resultCallback&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;{&lt;/span&gt;
  &lt;span style='color:#800000; font-weight:bold; '&gt;var&lt;/span&gt; connectionString &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;pg://username:password@host:port/databasename&lt;/span&gt;&lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
  pg&lt;span style='color:#808030; '&gt;.&lt;/span&gt;connect&lt;span style='color:#808030; '&gt;(&lt;/span&gt;connectionString&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;function&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;err&lt;span style='color:#808030; '&gt;,&lt;/span&gt; client&lt;span style='color:#808030; '&gt;)&lt;/span&gt; &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
    client&lt;span style='color:#808030; '&gt;.&lt;/span&gt;query&lt;span style='color:#808030; '&gt;(&lt;/span&gt;sql&lt;span style='color:#808030; '&gt;,&lt;/span&gt;parameters&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;function&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;err&lt;span style='color:#808030; '&gt;,&lt;/span&gt; result&lt;span style='color:#808030; '&gt;)&lt;/span&gt; &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
      &lt;span style='color:#696969; '&gt;// TODO add error handling&lt;/span&gt;
      console&lt;span style='color:#808030; '&gt;.&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;log&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;result&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
      resultCallback&lt;span style='color:#808030; '&gt;(&lt;/span&gt;result&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
    &lt;span style='color:#800080; '&gt;}&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
  &lt;span style='color:#800080; '&gt;}&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
&lt;span style='color:#800080; '&gt;}&lt;/span&gt;
&lt;/pre&gt;

&lt;/p&gt;

&lt;p&gt;That was it for today. In the next part of the series I'll write about debugging node.js and about my progress on the GeometryService.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-8155082192735650069?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/8155082192735650069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2011/12/creating-nodejs-geometryservice-part-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/8155082192735650069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/8155082192735650069'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2011/12/creating-nodejs-geometryservice-part-1.html' title='Creating a node.js GeometryService : part 1'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-2031030966136785562</id><published>2011-12-03T06:07:00.004+01:00</published><updated>2011-12-03T10:16:17.001+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='REPL'/><category scheme='http://www.blogger.com/atom/ns#' term='roslyn'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>C# REPL</title><content type='html'>&lt;p&gt;Until recently when you wanted to test small snippets of C# code you had to create a small console application or use the immediate window while debugging or use something like LinqPad.&lt;/p&gt;

&lt;p&gt;But a few weeks ago Microsoft finally announced a solution for this called Roslyn. The goal of Roslyn is to provide an API for the compiler. This is still just a CTP but it is very promising. One of the features of Roslyn is an interactive window for C# also called a REPL (read eval print loop). Note that some C# features like Linq query expressions, events and the dynamic and async keywords have not been implemented yet. More information on the Roslyn CTP can be found here 
&lt;a href="http://blogs.msdn.com/b/visualstudio/archive/2011/10/19/introducing-the-microsoft-roslyn-ctp.aspx"&gt;Introducing the Roslyn CTP&lt;/a&gt; and here &lt;a href="http://msdn.com/roslyn"&gt;http://msdn.com/roslyn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tip of the day:&lt;br /&gt;
When you want to reevaluate or edit a previous entry then use ALT+Up and ALT+Down.&lt;/p&gt;
&lt;p&gt;Bonus tip:&lt;br /&gt;
You might also wanna try out &lt;a href="http://billyreisinger.com/jash/"&gt;Jash&lt;/a&gt;. This is a javascript shell that can be opened on any website with a bookmarklet. It  features some code completion and is very practical for trying out things you`re unsure about.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-2031030966136785562?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/2031030966136785562/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2011/12/c-repl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/2031030966136785562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/2031030966136785562'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2011/12/c-repl.html' title='C# REPL'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-964099810531455907</id><published>2011-11-07T22:16:00.006+01:00</published><updated>2011-12-03T10:36:28.027+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='unchecked'/><category scheme='http://www.blogger.com/atom/ns#' term='checked'/><title type='text'>Performance of Checked vs Unchecked</title><content type='html'>&lt;p&gt;If you're ever in doubt on using the checked keyword in C# or the /checked compiler directive because it might hurt your performance then don't worry anymore.&lt;/p&gt;
&lt;p&gt;I did some integer additions on my portable in a checked and unchecked context and the performance decrease was only about &lt;b&gt;3-5%&lt;/b&gt; on operations of about 5 seconds. Don't forget that checked and unchecked only have an effect on integers. Float and double never check for overflows and the decimal always does. More info on this feature can be found on &lt;a href="http://msdn.microsoft.com/en-us/library/khy08726(v=vs.80).aspx"&gt;msdn&lt;/a&gt; and in this &lt;a href="http://www.codeproject.com/KB/cs/overflow_checking.aspx"&gt;Code Project article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the code I used to benchmark the performance of a checked vs unchecked context. I also tested subtraction, multiplication and division with similar results. Pay great attention when using the checked context. Only inline operations are checked/unchecked, code in function calls and anonymous functions isn't.&lt;/p&gt;

&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;using&lt;/span&gt; System&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
&lt;span style='color:#800000; font-weight:bold; '&gt;using&lt;/span&gt; System&lt;span style='color:#808030; '&gt;.&lt;/span&gt;Diagnostics&lt;span style='color:#800080; '&gt;;&lt;/span&gt;

&lt;span style='color:#800000; font-weight:bold; '&gt;namespace&lt;/span&gt; GISSolved&lt;span style='color:#808030; '&gt;.&lt;/span&gt;TestConsole
&lt;span style='color:#800080; '&gt;{&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;class&lt;/span&gt; Program
    &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;static&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;void&lt;/span&gt; Main&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;string&lt;/span&gt;&lt;span style='color:#808030; '&gt;[&lt;/span&gt;&lt;span style='color:#808030; '&gt;]&lt;/span&gt; args&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
            GC&lt;span style='color:#808030; '&gt;.&lt;/span&gt;Collect&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#008c00; '&gt;3&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; GCCollectionMode&lt;span style='color:#808030; '&gt;.&lt;/span&gt;Forced&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
            var checkedResult &lt;span style='color:#808030; '&gt;=&lt;/span&gt; TimeIt&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;true&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
            Console&lt;span style='color:#808030; '&gt;.&lt;/span&gt;WriteLine&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Checked : {0}&lt;/span&gt;&lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; checkedResult&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
            GC&lt;span style='color:#808030; '&gt;.&lt;/span&gt;Collect&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#008c00; '&gt;3&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; GCCollectionMode&lt;span style='color:#808030; '&gt;.&lt;/span&gt;Forced&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
            var uncheckedResult &lt;span style='color:#808030; '&gt;=&lt;/span&gt; TimeIt&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;false&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
            Console&lt;span style='color:#808030; '&gt;.&lt;/span&gt;WriteLine&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Unchecked : {0}&lt;/span&gt;&lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; uncheckedResult&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
            Console&lt;span style='color:#808030; '&gt;.&lt;/span&gt;WriteLine&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Difference : {0:0}%&lt;/span&gt;&lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#008c00; '&gt;1&lt;/span&gt; &lt;span style='color:#808030; '&gt;-&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;double&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;checkedResult &lt;span style='color:#808030; '&gt;/&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;double&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;uncheckedResult&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt; &lt;span style='color:#808030; '&gt;*&lt;/span&gt; &lt;span style='color:#008c00; '&gt;100&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
            Console&lt;span style='color:#808030; '&gt;.&lt;/span&gt;ReadLine&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
        &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
        
        &lt;span style='color:#800000; font-weight:bold; '&gt;static&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;long&lt;/span&gt; TimeIt&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;bool&lt;/span&gt; isCheckedCalculation&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
            var s &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;new&lt;/span&gt; Stopwatch&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
            s&lt;span style='color:#808030; '&gt;.&lt;/span&gt;Start&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;

            Int32 a &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;123&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; b &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;123&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
            &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;isCheckedCalculation&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
            &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
                &lt;span style='color:#800000; font-weight:bold; '&gt;checked&lt;/span&gt;
                &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
                    &lt;span style='color:#800000; font-weight:bold; '&gt;for&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;int&lt;/span&gt; i &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;0&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt; i &lt;span style='color:#808030; '&gt;&amp;lt;&lt;/span&gt; &lt;span style='color:#008c00; '&gt;900000000&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt; i&lt;span style='color:#808030; '&gt;+&lt;/span&gt;&lt;span style='color:#808030; '&gt;+&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
                    &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
                        a &lt;span style='color:#808030; '&gt;=&lt;/span&gt; i &lt;span style='color:#808030; '&gt;+&lt;/span&gt; b &lt;span style='color:#808030; '&gt;+&lt;/span&gt; a&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
                        a &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;125&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
                    &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
                    &lt;span style='color:#696969; '&gt;// extra check to make sure that overflow exceptions are thrown&lt;/span&gt;
                    &lt;span style='color:#800000; font-weight:bold; '&gt;try&lt;/span&gt;
                    &lt;span style='color:#800080; '&gt;{&lt;/span&gt;   
                        Int32 x &lt;span style='color:#808030; '&gt;=&lt;/span&gt; a &lt;span style='color:#808030; '&gt;+&lt;/span&gt; Int32&lt;span style='color:#808030; '&gt;.&lt;/span&gt;MaxValue&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
                    &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
                    &lt;span style='color:#800000; font-weight:bold; '&gt;catch&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;OverflowException&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
                    &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
                        Console&lt;span style='color:#808030; '&gt;.&lt;/span&gt;WriteLine&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Int32 Overflow&lt;/span&gt;&lt;span style='color:#800000; '&gt;"&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
                    &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
                &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
            &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
            &lt;span style='color:#800000; font-weight:bold; '&gt;else&lt;/span&gt; 
            &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
                &lt;span style='color:#800000; font-weight:bold; '&gt;unchecked&lt;/span&gt;
                &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
                    &lt;span style='color:#800000; font-weight:bold; '&gt;for&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;int&lt;/span&gt; i &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;0&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt; i &lt;span style='color:#808030; '&gt;&amp;lt;&lt;/span&gt; &lt;span style='color:#008c00; '&gt;900000000&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt; i&lt;span style='color:#808030; '&gt;+&lt;/span&gt;&lt;span style='color:#808030; '&gt;+&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
                    &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
                        a &lt;span style='color:#808030; '&gt;=&lt;/span&gt; i &lt;span style='color:#808030; '&gt;+&lt;/span&gt; b &lt;span style='color:#808030; '&gt;+&lt;/span&gt; a&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
                        a &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;125&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
                    &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
                    Int32 x &lt;span style='color:#808030; '&gt;=&lt;/span&gt; a &lt;span style='color:#808030; '&gt;+&lt;/span&gt; Int32&lt;span style='color:#808030; '&gt;.&lt;/span&gt;MaxValue&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
                &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
            &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
            s&lt;span style='color:#808030; '&gt;.&lt;/span&gt;Stop&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
            &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; s&lt;span style='color:#808030; '&gt;.&lt;/span&gt;ElapsedMilliseconds&lt;span style='color:#800080; '&gt;;&lt;/span&gt;
        &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
    &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
&lt;span style='color:#800080; '&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-964099810531455907?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/964099810531455907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2011/11/checked-vs-unchecked-in-c.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/964099810531455907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/964099810531455907'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2011/11/checked-vs-unchecked-in-c.html' title='Performance of Checked vs Unchecked'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-1230325856045734193</id><published>2010-06-16T12:51:00.003+02:00</published><updated>2011-12-23T07:06:43.464+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spatial index'/><category scheme='http://www.blogger.com/atom/ns#' term='MongoDb'/><title type='text'>MongoDB : Geospatial Indexing</title><content type='html'>&lt;p&gt;Just a short note to let you know that &lt;a href="http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html"&gt; this post&lt;/a&gt; has become outdated because MongoDB supports native two dimensional geospatial indexing. More information can be found &lt;a href="http://www.mongodb.org/display/DOCS/Geospatial+Indexing"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-1230325856045734193?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/1230325856045734193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2010/06/mongodb-geospatial-indexing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/1230325856045734193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/1230325856045734193'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2010/06/mongodb-geospatial-indexing.html' title='MongoDB : Geospatial Indexing'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-3959823362329284584</id><published>2010-06-01T08:33:00.008+02:00</published><updated>2010-06-07T16:36:02.897+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NetworkX'/><category scheme='http://www.blogger.com/atom/ns#' term='PyPy'/><category scheme='http://www.blogger.com/atom/ns#' term='Psyco'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='shortest path'/><title type='text'>2 Possible Ways To Speed Up NetworkX (and Python)</title><content type='html'>&lt;p&gt;I'm in the process of looking for a way to run the shortest path algorithms of &lt;a href="http://networkx.lanl.gov/"&gt;NetworkX&lt;/a&gt; in a faster way. At this moment I tried &lt;a href="http://psyco.sourceforge.net/"&gt;psyco&lt;/a&gt; and &lt;a href="http://pypy.org/"&gt;PyPy&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Psyco&lt;/h4&gt;

&lt;p&gt;Using &lt;a href="http://psyco.sourceforge.net/"&gt;psyco&lt;/a&gt; is really easy. After installing it you only have to write the following two lines.&lt;/p&gt;
&lt;q&gt;import psyco&lt;/q&gt;
&lt;q&gt;psyco.full()&lt;/q&gt;

&lt;p&gt;Psyco didn't speedup my shortest path calculations.&lt;/p&gt;

&lt;p&gt;If you want to know more about psyco I suggest you to read &lt;a href="http://psyco.sourceforge.net/psycoguide/index.html"&gt;the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;PyPy&lt;/h4&gt;

&lt;p&gt;In order to test &lt;a href="http://pypy.org/"&gt;PyPy&lt;/a&gt; I downloaded the latest windows binary and ran my code against PyPy instead of CPython by invoking my script on the command line with pypy.exe.&lt;/p&gt; 

&lt;p&gt;The startup time is a lot longer for PyPy but if you don't take this startup cost into account then the speedup on my machine is in the range of 10-20% for shortest path routing with NetworkX.&lt;/p&gt;

&lt;p&gt;So far my tests. Any suggestions ?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-3959823362329284584?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/3959823362329284584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2010/06/speed-up-python.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/3959823362329284584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/3959823362329284584'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2010/06/speed-up-python.html' title='2 Possible Ways To Speed Up NetworkX (and Python)'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-3665682487335768038</id><published>2010-05-31T21:56:00.004+02:00</published><updated>2010-06-01T09:23:33.953+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NetworkX'/><category scheme='http://www.blogger.com/atom/ns#' term='Jython'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='shortest path'/><title type='text'>Using NetworkX with Jython</title><content type='html'>&lt;p&gt;Just a quick note to let you know that the Python graph library &lt;a href="http://networkx.lanl.gov/"&gt;NetworkX&lt;/a&gt; (version 1.1), which by the way is really good, can be ported to Jython with some minor modifications. Sadly enough you loose some performance in the process.&lt;/p&gt;&lt;p&gt;The two changes I made to get it running where :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Because numpy doesn't exist for Jython you can't use the current_flow_closeness_centrality function in current_flow_closeness.py. I moved the &lt;q&gt;import numpy as np&lt;/q&gt; statement at the top to the _compute_C function at the bottom.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;In the __init__.py file under generators I commented &lt;q&gt;from atlas import *&lt;/q&gt; out.&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;In the following weeks I will try to port a small subset off NetworkX to Java or Scala. Hopefully I'll be able to outperform the Jython and CPython version.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-3665682487335768038?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/3665682487335768038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2010/05/using-networkx-with-jython.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/3665682487335768038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/3665682487335768038'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2010/05/using-networkx-with-jython.html' title='Using NetworkX with Jython'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-9046988078175261918</id><published>2010-05-27T21:36:00.001+02:00</published><updated>2010-06-01T09:24:00.145+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='youtube'/><title type='text'>Arithmetic, Population, and Energy.</title><content type='html'>&lt;p&gt;Just watched Dr. Albert A. Bartlett's presentation on "Arithmetic, Population, and Energy." on youtube. It's really good and entertaining. It's in 8 parts and I encourage you to watch them all.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The url of part 1 is : &lt;a href="http://www.youtube.com/watch?v=F-QA2rkpBSY"&gt;http://www.youtube.com/watch?v=F-QA2rkpBSY&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-9046988078175261918?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/9046988078175261918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2010/05/arithmetic-population-and-energy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/9046988078175261918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/9046988078175261918'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2010/05/arithmetic-population-and-energy.html' title='Arithmetic, Population, and Energy.'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-4466918726169092553</id><published>2009-10-29T21:26:00.003+01:00</published><updated>2009-10-29T21:30:07.748+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='featureclass'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Cursors'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcObjects'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><title type='text'>Using yield to create an iterator</title><content type='html'>&lt;p&gt;Not so long ago I blogged about &lt;a href="http://gissolved.blogspot.com/2009/09/using-foreach-with-icursor.html"&gt;using the foreach statement with an ICursor&lt;/a&gt;. I achieved this by inheriting from IEnumerator&lt;IRow&gt; and IEnumerable&lt;IRow&gt;.&lt;/p&gt;

&lt;p&gt;But by using the yield statement we can achieve a similar effect with much less code. The generator function looks like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IFeature&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IFeatureCursor&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;IFeature&lt;/span&gt; &lt;span class="n"&gt;feat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;feat&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NextFeature&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;feat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can use this method like below.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;IFeatureClass&lt;/span&gt; &lt;span class="n"&gt;featureClass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;// initialize feature class&lt;/span&gt;
&lt;span class="n"&gt;IQueryFilter&lt;/span&gt; &lt;span class="n"&gt;queryFilter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;QueryFilterClass&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;queryFilter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WhereClause&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="n"&gt;your&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="n"&gt;clause&lt;/span&gt; &lt;span class="n"&gt;here&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;recycling&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IFeature&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;featureClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queryFilter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recycling&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IFeature&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="n"&gt;your&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;here&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you're running .NET 3.0 or more you can create the following extension method in an extension class. This method adds the SearchIter method to the IFeatureClass interface which replaces the Search method.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Extensions&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IFeature&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SearchIter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;IFeatureClass&lt;/span&gt; &lt;span class="n"&gt;featureClass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IQueryFilter&lt;/span&gt; &lt;span class="n"&gt;queryFilter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;recycling&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;IFeatureCursor&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;featureClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queryFilter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recycling&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;IFeature&lt;/span&gt; &lt;span class="n"&gt;feat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;feat&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NextFeature&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;feat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The usage of the extension method is similar to the usage of the Iter method but you can replace&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IFeature&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;featureClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queryFilter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recycling&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;with this&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IFeature&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;featureClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SearchIter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queryFilter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recycling&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So this was it. I hope you learned something and feel free to leave a comment.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related posts&lt;/b&gt;&lt;br /&gt;
&lt;a hef="http://gissolved.blogspot.com/2009/10/editing-with-arcobjects.html"&gt;Disposable Editing&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/drag-drop-from-arccatalog.html"&gt;Drag Drop from ArcCatalog&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/09/inserting-features-and-rows.html"&gt;Inserting Features and Rows&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-4466918726169092553?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/4466918726169092553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/10/using-yield-to-create-iterator.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/4466918726169092553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/4466918726169092553'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/10/using-yield-to-create-iterator.html' title='Using yield to create an iterator'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-466070987894016672</id><published>2009-10-29T20:42:00.005+01:00</published><updated>2009-11-18T10:30:19.601+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='geoprocessing'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><title type='text'>Looping over a Workspace</title><content type='html'>&lt;p&gt;Ever wanted to execute a function on all the tables and/or featureclasses in a workspace then the following code is something for you.
What it basically does is first loop over all the featureclasses that are in featuredatasets. Then loop over all the other featureclasses and finally loop over all the tables in the provided workspace.&lt;/p&gt;

&lt;p&gt;To achieve this and still be able to retrieve the result of each function execution on the tables and featureclasses I created a generator function. I did this by using the yield statement. In order to avoid duplicate code I also created a nested function for looping over the featureclasses.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;executeiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;featclassfunction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tablefunction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
    
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;loopfcs&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;fcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listfeatureclasses&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fcs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;featclassfunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    
    &lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;featclassfunction&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdatasets&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;datasetworkspace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datasetworkspace&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;loopfcs&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
                &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

        &lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;loopfcs&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
            
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tablefunction&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;tables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listtables&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;tablefunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you don't need the result of the function you can call the following function. It takes the same arguments as the executeiter function but its a regular function instead of a generator.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;featclassfunction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tablefunction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;executeiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;featclassfunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tablefunction&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To demonstrate the usage of my code I first initialized a geoprocessing object and a workspace variable. Then I used the executeiter method to make it return the uppercase version of the name of the tables and featureclasses in my workspace. I could also have passed for example the describe or the listfields method of the geoprocessing object or a custom function. When you want to pass a function that doesn't return a result like the deleterows or deletefeatures function its more convenient to call the execute function.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;arcgisscripting&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;string&lt;/span&gt;

&lt;span class="n"&gt;gp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arcgisscripting&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;workspace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;r&amp;#39;D:\temp\temp.gdb&amp;#39;&lt;/span&gt; &lt;span class="c"&gt;# path to your workspace&lt;/span&gt;

&lt;span class="c"&gt;# print the uppercase names of all the tables and featureclasses&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;uppername&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;executeiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;uppername&lt;/span&gt;

&lt;span class="c"&gt;# delete all rows of all the tables and featureclasses&lt;/span&gt;
&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deletefeatures&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deleterows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I've come to the end of this post. Did I miss something ? Know a Python idiom I really should start using ? Feel free to comment.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/09/inserting-features-and-rows.html"&gt;Inserting features and rows&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/04/table-to-csv.html"&gt;Export a table to a csv&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-466070987894016672?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/466070987894016672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/10/looping-over-workspace.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/466070987894016672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/466070987894016672'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/10/looping-over-workspace.html' title='Looping over a Workspace'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-1760387821837706403</id><published>2009-10-13T21:24:00.003+02:00</published><updated>2009-10-13T21:28:30.220+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcObjects'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><title type='text'>Editing with ArcObjects</title><content type='html'>&lt;p&gt;Recently I found myself rewriting a lot of code which started and stopped edit sessions to decorate it with try ... finally blocks to make sure that every started edit session closes even when an error occurs. The code I wrote looked like below.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;saveEdits&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;StartEditing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="n"&gt;edit&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;featureclass&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;saveEdits&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;StopEditing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;saveEdits&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I thought that there had to be a cleaner way to achieve the same functionality. Here comes the &lt;a href="http://msdn.microsoft.com/en-us/library/yh598w02.aspx"&gt;using statement&lt;/a&gt; to the rescue. To be able to use the using statement with a class it has to implement the &lt;a href="http://msdn.microsoft.com/en-us/library/system.idisposable.aspx"&gt;IDisposable&lt;/a&gt; interface. So I wrote the following wrapper class for starting and stopping edit sessions.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EditSession&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDisposable&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;IWorkspaceEdit&lt;/span&gt; &lt;span class="n"&gt;_workspaceEdit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IWorkspaceEdit&lt;/span&gt; &lt;span class="n"&gt;WorkspaceEdit&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="k"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_workspaceEdit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="k"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_workspaceEdit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;EditSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IWorkspace&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;withUndoRedo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_workspaceEdit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IWorkspaceEdit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;EditSession&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IWorkspace&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;withUndoRedo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;EditSession&lt;/span&gt; &lt;span class="n"&gt;editSession&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;EditSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;withUndoRedo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;editSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withUndoRedo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;editSession&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;withUndoRedo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_workspaceEdit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsBeingEdited&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_workspaceEdit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartEditing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withUndoRedo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;_workspaceEdit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartEditOperation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SaveAndStop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_workspaceEdit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsBeingEdited&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_workspaceEdit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StopEditOperation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;_workspaceEdit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StopEditing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;

    &lt;span class="cp"&gt;#region IDisposable Members&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_workspaceEdit&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;_workspaceEdit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsBeingEdited&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;

    &lt;span class="cp"&gt;#endregion&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can use the EditSession class like this.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EditSession&lt;/span&gt; &lt;span class="n"&gt;editSession&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EditSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="n"&gt;edit&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;featureclass&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;editSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SaveAndStop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you're using .NET 3.0 or a later version you can use the following class which creates an &lt;a href="http://msdn.microsoft.com/en-us/library/bb383977.aspx"&gt;extension method&lt;/a&gt; for the IWorkspace.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Extensions&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;EditSession&lt;/span&gt; &lt;span class="nf"&gt;StartEditing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;IWorkspace&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;withUndoRedo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;EditSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;withUndoRedo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the extension method you can directly call StartEditing on a workspace.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EditSession&lt;/span&gt; &lt;span class="n"&gt;editSession&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartEditing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="n"&gt;edit&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;featureclass&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;editSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SaveAndStop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Related posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/drag-drop-from-arccatalog.html"&gt;Drag Drop from ArcCatalog&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/09/using-foreach-with-icursor.html"&gt;Using foreach with ICursor&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/09/inserting-features-and-rows.html"&gt;Inserting Features and Rows&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-1760387821837706403?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/1760387821837706403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/10/editing-with-arcobjects.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/1760387821837706403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/1760387821837706403'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/10/editing-with-arcobjects.html' title='Editing with ArcObjects'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-1275139815917820748</id><published>2009-09-27T11:59:00.006+02:00</published><updated>2009-09-27T13:23:35.388+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='featureclass'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcObjects'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><title type='text'>Inserting Features and Rows</title><content type='html'>&lt;p&gt;Recently I was inserting features in a feature class but my code was rather slow so I looked around for another method and the following is what I found.&lt;/p&gt;
&lt;p&gt;First you need to start an edit session and then you can use the code below. This is just a short body of code to give you an idea on how to use the different objects.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;IFeatureCursor&lt;/span&gt; &lt;span class="n"&gt;insertFeatCursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;outputFeatClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;featureToInsert&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;featuresToInsert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;IFeatureBuffer&lt;/span&gt; &lt;span class="n"&gt;outputFeatBuffer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;outputFeatClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateFeatureBuffer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c"&gt;// set the shape&lt;/span&gt;
    &lt;span class="n"&gt;outputFeatBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="c"&gt;// set the different values&lt;/span&gt;
    &lt;span class="n"&gt;outputFeatBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fieldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c"&gt;// insert the feature buffer&lt;/span&gt;
    &lt;span class="n"&gt;insertFeatCursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InsertFeature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outputFeatBuffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;insertFeatCursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flush&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you now save and close your edit session the features are inserted. The code for inserting rows in a table is very similar.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;ITable&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;ICursor&lt;/span&gt; &lt;span class="n"&gt;insertCursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;IRowBuffer&lt;/span&gt; &lt;span class="n"&gt;rowBuffer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateRowBuffer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;rowBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fieldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;insertCursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InsertRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rowBuffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;insertCursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flush&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you have any comments or questions, let me know !!!&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/09/using-foreach-with-icursor.html"&gt;Using foreach with the ICursor&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/drag-drop-from-arccatalog.html"&gt;Drag Drop from ArcCatalog&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html"&gt;Pythonnet (call .NET from Python)&lt;/a&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-1275139815917820748?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/1275139815917820748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/09/inserting-features-and-rows.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/1275139815917820748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/1275139815917820748'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/09/inserting-features-and-rows.html' title='Inserting Features and Rows'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-6116249359442830593</id><published>2009-09-19T14:02:00.005+02:00</published><updated>2009-09-19T14:11:49.478+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gvSIG'/><category scheme='http://www.blogger.com/atom/ns#' term='uDig'/><category scheme='http://www.blogger.com/atom/ns#' term='Quantum GIS'/><category scheme='http://www.blogger.com/atom/ns#' term='geoprocessing'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><title type='text'>Geoprocessing 1 : Intersect</title><content type='html'>&lt;p&gt;The intersect operation is one of the many overlay operations. When intersecting layer A with a layer B the result will include all those parts that occur in both A and B. In this post I'm going to compare the results of the ArcGIS Intersect tool with the corresponding operation in 3 other GIS packages. The reason why did this was that I noticed that the output from ArcGIS contains more features then I expected when dealing with overlapping geometries. This is usually not a problem but it becomes one when you have lots of overlapping geometries.&lt;/p&gt;

&lt;p&gt;The GIS tools I used to compare the result of ArcGIS with were : &lt;a href="http://udig.refractions.net/"&gt;uDig&lt;/a&gt;, &lt;a href="http://www.qgis.org/"&gt;Quantum GIS&lt;/a&gt; and  &lt;a href="http://www.gvsig.gva.es/"&gt;gvSIG&lt;/a&gt;. All these and some more can be found on &lt;a href="http://www.archaeogeek.com/download.php"&gt;Portable GIS&lt;/a&gt;. Portable GIS brings open source GIS to your usb.&lt;/p&gt;

&lt;p&gt;To test the code I prepared 2 shapefiles. One with a long small polygon and the other one with 3 overlapping rectangles (see image below).&lt;/p&gt;

&lt;a target="_blank" href="http://h.imagehost.org/view/0599/intersect_situation"&gt;&lt;img src="http://h.imagehost.org/0599/intersect_situation.jpg" border="0" width="369" height="286" alt="ImageHost.org" /&gt;&lt;/a&gt;

&lt;p&gt;When intersecting with ArcGIS (version 9.2 and 9.3 tested) the output looks like below. As you can see in the attribute table the result contains 9 polygons.&lt;/p&gt;

&lt;a target="_blank" href="http://h.imagehost.org/view/0713/intersect_1_2_ArcMap"&gt;&lt;img src="http://h.imagehost.org/0713/intersect_1_2_ArcMap.jpg" border="0" width="552" height="253" alt="ImageHost.org" /&gt;&lt;/a&gt;

&lt;p&gt;To be able to do the intersect operation with uDig I had to install the &lt;a href="http://www.axios.es/"&gt;Axios&lt;/a&gt; Spatial Operations Extension. You can install this extension by clicking Help -&gt; Find and install from the menubar. With Quantum GIS I needed to enable the &lt;a href="http://www.ftools.ca/"&gt;ftools&lt;/a&gt; plugin to enable the geoprocessing functionality. The results of the 3 used open source GIS packages where the same. Only 3 features where created in the output shapefile. For completeness I added the screenshots of the results.&lt;/p&gt;

&lt;p&gt;uDig :&lt;/p&gt;
&lt;a target="_blank" href="http://h.imagehost.org/view/0292/intersect_1_2_uDig"&gt;&lt;img src="http://h.imagehost.org/t/0292/intersect_1_2_uDig.jpg" border="0" width="122" height="150" alt="intersect_1_2_uDig.jpg (28 KB)" /&gt;&lt;/a&gt;
&lt;p&gt;Quantum GIS :&lt;/p&gt;
&lt;a target="_blank" href="http://h.imagehost.org/view/0402/intersect_1_2_QGIS"&gt;&lt;img src="http://h.imagehost.org/t/0402/intersect_1_2_QGIS.jpg" border="0" width="150" height="146" alt="intersect_1_2_QGIS.jpg (41 KB)" /&gt;&lt;/a&gt;
&lt;p&gt;gvSIG :&lt;/p&gt;
&lt;a target="_blank" href="http://h.imagehost.org/view/0499/intersect_1_2_gvSIG"&gt;&lt;img src="http://h.imagehost.org/t/0499/intersect_1_2_gvSIG.jpg" border="0" width="150" height="123" alt="intersect_1_2_gvSIG.jpg (19 KB)" /&gt;&lt;/a&gt;

&lt;p&gt;Have any comments or questions ? Let me know !&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/04/table-to-csv.html"&gt;Exporting an ArcGIS table to a text file&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/04/projections-and-transformations-with.html"&gt;Projections and Transformations with pe.dll&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html"&gt;Accessing a .NET dll from within Python&lt;/a&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-6116249359442830593?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/6116249359442830593/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/09/geoprocessing-1-intersect.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/6116249359442830593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/6116249359442830593'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/09/geoprocessing-1-intersect.html' title='Geoprocessing 1 : Intersect'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-2007000677903054748</id><published>2009-09-08T21:47:00.004+02:00</published><updated>2009-09-27T12:05:31.628+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Cursors'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcObjects'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><title type='text'>Using foreach with the ICursor</title><content type='html'>&lt;p&gt;My &lt;a href="http://gissolved.blogspot.com/2009/04/using-for-loops-for-cursors.html"&gt;first post&lt;/a&gt; on this blog was about how to loop over an ESRI cursor in Python with the for statement instead of the while statement. The same problem exists in .NET when using the various cursor objects like ICursor and IFeatureCursor. Normally you would code something like this :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;ICursor&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;IRow&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NextRow&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// some code&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;ICursor&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;IRow&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NextRow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// some code&lt;/span&gt;
    &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NextRow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And I want to replace it with the following.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;ITable&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;// get table from somewhere&lt;/span&gt;
&lt;span class="n"&gt;IQueryFilter&lt;/span&gt; &lt;span class="n"&gt;queryFilter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;// create QueryFilter or leave it null&lt;/span&gt;
&lt;span class="n"&gt;CursorGS&lt;/span&gt; &lt;span class="n"&gt;cursorGS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;CursorGS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;queryFilter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IRow&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cursorGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// ... insert your code here&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To make a class usable in a foreach statement you need to implement the IEnumerable and IEnumerator interfaces. I found a good introduction to making class usable in a foreach statement in this &lt;a href="http://support.microsoft.com/kb/322022"&gt;Microsoft article&lt;/a&gt;. So what I did was creating a class that inherited from IEnumerator&amp;lt;IRow&amp;gt; and IEnumerable&amp;lt;IRow&amp;gt; and implement all the needed properties and methods. For IEnumerator these where Current, MoveNext, Reset and Dispose and for IEnumerable only the method GetEnumerator was needed. The biggest problem was the Reset method because an ICursor doesn't have a reset method. I decided to set the cursor null and the recreated at the moment that MoveNext is called. This also makes sure the ICursor is only created when we really need it. Below you can find my full class&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;ESRI.ArcGIS.Geodatabase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;GisSolved.GeoDiff.Esri&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CursorGS&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IEnumerator&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IRow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IRow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ITable&lt;/span&gt; &lt;span class="n"&gt;_table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;IQueryFilter&lt;/span&gt; &lt;span class="n"&gt;_queryFilter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;ESRI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArcGIS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ADF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ComReleaser&lt;/span&gt; &lt;span class="n"&gt;_comReleaser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;IRow&lt;/span&gt; &lt;span class="n"&gt;_currentRow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;ICursor&lt;/span&gt; &lt;span class="n"&gt;_cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CursorGS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ITable&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IQueryFilter&lt;/span&gt; &lt;span class="n"&gt;queryFilter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_table&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;_queryFilter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;queryFilter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;_comReleaser&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ESRI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArcGIS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ADF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ComReleaser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;

        &lt;span class="cp"&gt;#region IEnumerator&amp;lt;IRow&amp;gt; Members&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IRow&lt;/span&gt; &lt;span class="n"&gt;Current&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="k"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_currentRow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;

        &lt;span class="cp"&gt;#endregion&lt;/span&gt;

        &lt;span class="cp"&gt;#region IEnumerator Members&lt;/span&gt;

        &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IEnumerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="k"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_currentRow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;MoveNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_cursor&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// initialize the cursor&lt;/span&gt;
            &lt;span class="k"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;_cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_queryFilter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;_comReleaser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ManageLifetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_cursor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;_currentRow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NextRow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_currentRow&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;

        &lt;span class="cp"&gt;#endregion&lt;/span&gt;

        &lt;span class="cp"&gt;#region IEnumerable&amp;lt;IRow&amp;gt; Members&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEnumerator&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IRow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;GetEnumerator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IEnumerator&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IRow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;

        &lt;span class="cp"&gt;#endregion&lt;/span&gt;

        &lt;span class="cp"&gt;#region IEnumerable Members&lt;/span&gt;

        &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IEnumerator&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetEnumerator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IEnumerator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;

        &lt;span class="cp"&gt;#endregion&lt;/span&gt;

        &lt;span class="cp"&gt;#region IDisposable Members&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_comReleaser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;

        &lt;span class="cp"&gt;#endregion&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see I used the ESRI &lt;a href="http://edndoc.esri.com/arcobjects/9.2/NET/fe9f7423-2100-4c70-8bd6-f4f16d5ce8c0.htm"&gt;ComReleaser object&lt;/a&gt; to make sure that the ICursor references get released properly.&lt;/p&gt;

&lt;p&gt;So now you know how to create a wrapper around the ICursor you can start creating other wrappers for often used cursors like the IFeatureCursor, IFields, ... and I can go to my bed. Success and feel free to post any comments or your implementation !!!&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/09/inserting-features-and-rows.html"&gt;Inserting Features and Rows&lt;/a&gt;
&lt;a href="http://gissolved.blogspot.com/2009/04/using-for-loops-for-cursors.html"&gt;Using for-loops for cursors (Python)&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/drag-drop-from-arccatalog.html"&gt;Drag Drop from ArcCatalog&lt;/a&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-2007000677903054748?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/2007000677903054748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/09/using-foreach-with-icursor.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/2007000677903054748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/2007000677903054748'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/09/using-foreach-with-icursor.html' title='Using foreach with the ICursor'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-2956304473643772384</id><published>2009-08-03T21:13:00.005+02:00</published><updated>2009-08-03T21:27:33.083+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='DatagridView'/><category scheme='http://www.blogger.com/atom/ns#' term='WinForms'/><title type='text'>DatagridView Tricks</title><content type='html'>&lt;p&gt;This post will entirely be about the .NET DatagridView control. I will show you how to synchronize the scrolling of two Datagridviews, disable column sorting, disable cell selection and focus cues.&lt;/p&gt;

&lt;p&gt;To synchronize the scrolling of two DatagridViews you should subscribe to the Scroll event of the two Datagridviews and add the following code. What it does is equalizing the first row index and the scrolled horizontal offset. I did set the FirstDisplayedScrollingRowIndex because the VerticalScrollingOffset is a readonly property.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;dataGridViewA_Scroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ScrollEventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;dataGridViewB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstDisplayedScrollingRowIndex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dataGridViewA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstDisplayedScrollingRowIndex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;dataGridViewB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HorizontalScrollingOffset&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dataGridViewA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HorizontalScrollingOffset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;dataGridViewB_Scroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ScrollEventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;dataGridViewA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstDisplayedScrollingRowIndex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dataGridViewB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstDisplayedScrollingRowIndex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;dataGridViewA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HorizontalScrollingOffset&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dataGridViewB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HorizontalScrollingOffset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For the following tricks I created a custom control called DatagridViewGS that derives from the DatagridView control.&lt;p&gt;

&lt;p&gt;Disabling column sorting for all columns is done by setting the SortMode to NotSortable for every column of the DatagridView. In order to do that I subscribed the DataBindingComplete event and added the following code to it&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;DatagridViewGS_DataBindingComplete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DataGridViewBindingCompleteEventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DataGridViewColumn&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SortMode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DataGridViewColumnSortMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NotSortable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Cell selection is disabled by subscribing to the CellStateChanged event and setting the Selected property of the cell whose state changed to false. I've also set the SelectionMode of the DataGridView to DataGridViewSelectionMode.CellSelect and the MultiSelect property to false.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;DatagridViewGS_CellStateChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DataGridViewCellStateChangedEventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StateChanged&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;DataGridViewElementStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Selected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Selected&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After disabling cell selection there where still focus cues. These are the small dotted lines around the selected elements. To hide these I needed to override ShowFocusCues property of the DataGridView and make it always return false.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;ShowFocusCues&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;get&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The full code of my custom DatagridView looked like this :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Windows.Forms&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Drawing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;GisSolved.GUI&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DatagridViewGS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;DataGridView&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;DatagridViewGS&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;MultiSelect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;SelectionMode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DataGridViewSelectionMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CellSelect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;CellStateChanged&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DataGridViewCellStateChangedEventHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DatagridViewGS_CellStateChanged&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            
            &lt;span class="n"&gt;DataBindingComplete&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DataGridViewBindingCompleteEventHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DatagridViewGS_DataBindingComplete&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;
        
        &lt;span class="c"&gt;// Disable column sorting&lt;/span&gt;
        &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;DatagridViewGS_DataBindingComplete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DataGridViewBindingCompleteEventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DataGridViewColumn&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SortMode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DataGridViewColumnSortMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NotSortable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;
        &lt;span class="c"&gt;// Disable cell selection&lt;/span&gt;
        &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;DatagridViewGS_CellStateChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DataGridViewCellStateChangedEventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StateChanged&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;DataGridViewElementStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Selected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Selected&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;
        &lt;span class="c"&gt;// Disable focus cues&lt;/span&gt;
        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;ShowFocusCues&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;get&lt;/span&gt;
            &lt;span class="k"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Do you know other useful tricks with DatagridViews or other .NET controls ? Feel free to write them down in the comments section !&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/drag-drop-from-arccatalog.html"&gt;Drag and drop from ArcCatalog to a .NET form.&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html"&gt; Calling .NET code from Python&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-2956304473643772384?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/2956304473643772384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/08/datagridview-tricks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/2956304473643772384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/2956304473643772384'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/08/datagridview-tricks.html' title='DatagridView Tricks'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-1887239811920309482</id><published>2009-07-27T20:53:00.000+02:00</published><updated>2009-07-27T20:56:21.461+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rtree'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Building and Installing Spatial Index on Ubuntu</title><content type='html'>&lt;p&gt;This is a short post about installing Spatial Index on Ubuntu. First download the &lt;a href="http://trac.gispython.org/spatialindex/wiki/Releases"&gt;latest release&lt;/a&gt;. At the moment it's version 3.2 and cd to the location of your download. Then issue the following commands :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;tar xzvf spatialindex-1.3.2.tar.gz
&lt;span class="nb"&gt;cd &lt;/span&gt;spatialindex-1.3.2
./configure
sudo make install
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you want to configure your install you should take a look at the installation notes. You can find more information about Spatial Index at the projects &lt;a href="http://trac.gispython.org/spatialindex/"&gt;trac&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related Posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/07/installating-tokyo-cabinet-and-ruby-on.html"&gt;Installing Tokyo Cabinet and Ruby on Ubuntu&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html"&gt;Rtree and MongoDB&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-1887239811920309482?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/1887239811920309482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/07/building-and-installing-spatial-index.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/1887239811920309482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/1887239811920309482'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/07/building-and-installing-spatial-index.html' title='Building and Installing Spatial Index on Ubuntu'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-8032790868644847596</id><published>2009-07-16T21:48:00.006+02:00</published><updated>2009-07-20T21:00:55.622+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tokyo Cabinet'/><category scheme='http://www.blogger.com/atom/ns#' term='anti-rdbms'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ogr'/><title type='text'>Tokyo Cabinet 2 : Loading and querying point data</title><content type='html'>&lt;p&gt;After &lt;a href="http://gissolved.blogspot.com/2009/07/installating-tokyo-cabinet-and-ruby-on.html"&gt;setting up Tokyo Cabinet and Ruby&lt;/a&gt; its time to use it. As with my post about MongoDB I'm going to load 500.000 POIs in a database and query them with a bounding box query. I will use the table database from Tokyo Cabinet because it supports the most querying facilities. With a table database you can query numbers with full matched and range queries and for strings you can do full matching, forward matching, regular expression matching,...&lt;/p&gt;

&lt;p&gt;To load the data in my database I will need to read my shapefile with POIs with Ruby and write the attributes to a new database. First we create the database with the following code.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;tokyocabinet&amp;#39;&lt;/span&gt;
&lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;TokyoCabinet&lt;/span&gt;

&lt;span class="c1"&gt;# create the object&lt;/span&gt;
&lt;span class="n"&gt;tdb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TDB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kp"&gt;new&lt;/span&gt;

&lt;span class="c1"&gt;# open or create  the database&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;poi_db.tct&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;TDB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;OWRITER&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;TDB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;OCREAT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;STDERR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;open error: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ecode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To read the features in my shapefile I am going to use the Ruby bindings for GDAL/OGR. Because I installed Tokyo Cabinet on &lt;a href="http://www.gisvm.com/"&gt;GISVM&lt;/a&gt; I already had &lt;a href="http://fwtools.maptools.org/"&gt;FWTools&lt;/a&gt; installed but I still needed to install the Ruby bindings for it. I did this with the following command.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;sudo apt-get install libgdal-ruby
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we are going to read a shapefile with 500.000 point features and write the records to the database. First we open the shapefile and get the layer. Then we loop over the features, create a new record and fill the record with the x,y information and the other fields when they aren't empty. The values need to be converted to strings otherwise the record can't be saved. Then we put the record in the database.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;gdal/ogr&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# open my shapefile&lt;/span&gt;
&lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Gdal&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Ogr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;poi_500000.shp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="n"&gt;feature_defn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_layer_defn&lt;/span&gt;

&lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_feature_count&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
 &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="c1"&gt;# create new record&lt;/span&gt;
    &lt;span class="n"&gt;feature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_feature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="n"&gt;geom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_geometry_ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;geom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;geom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_y&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="n"&gt;pkey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;genuid&lt;/span&gt; &lt;span class="c1"&gt;# init primary key&lt;/span&gt;
 &lt;span class="n"&gt;feature_defn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_field_count&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;field_defn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feature_defn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_field_defn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;fieldname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;field_defn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_name_ref&lt;/span&gt;
  &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_field_as_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nil?&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;field_defn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_name_ref&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;ID&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;pkey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
   &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fieldname&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
 &lt;span class="k"&gt;end&lt;/span&gt;
 &lt;span class="c1"&gt;# store the record in Tokyo Cabinet&lt;/span&gt;
 &lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To add indexes on the x and y field we call the following code. This creates two supplementary files called poi_db.tct.idx.x.dec and poi_db.tct.idx.y.dec.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# add index on x and y&lt;/span&gt;
&lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;TDB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ITDECIMAL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;TDB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ITDECIMAL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To query the POIs in the database I created a function to query the POIs for a given bounding box and then I benchmarked it. I used the same bounding box as in my previous posts about &lt;a href="http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html"&gt;MongoDB&lt;/a&gt;, &lt;a href="http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html"&gt;Rtree&lt;/a&gt;, &lt;a href="http://gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html"&gt;Pythonnet&lt;/a&gt; and &lt;a href="http://gissolved.blogspot.com/2009/06/postgis-loading-and-querying-data.html"&gt;PostGIS&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# query POIs by bounding box&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;miny&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="n"&gt;qry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TDBQRY&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kp"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="n"&gt;qry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addcond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;TDBQRY&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;QCNUMGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
 &lt;span class="n"&gt;qry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addcond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;TDBQRY&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;QCNUMLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
 &lt;span class="n"&gt;qry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addcond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;y&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;TDBQRY&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;QCNUMGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;miny&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
 &lt;span class="n"&gt;qry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addcond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;y&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;TDBQRY&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;QCNUMLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
 &lt;span class="n"&gt;qry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setorder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;TDBQRY&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;QONUMASC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

 &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;
 &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="c1"&gt;# number of results found&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;benchmark&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;Benchmark&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;measure&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The query returned 98000 POIs. I ran the benchmark 12 times and this where the results :&lt;/p&gt;
&lt;div&gt;&lt;pre&gt;  1.620000   0.190000   1.810000 (  1.866339)
  1.570000   0.030000   1.600000 (  1.625303)
  1.640000   0.030000   1.670000 (  1.668573)
  1.650000   0.000000   1.650000 (  1.664806)
  1.650000   0.020000   1.670000 (  1.708228)
  1.730000   0.010000   1.740000 (  1.744645)
  1.410000   0.310000   1.720000 (  1.749268)
  1.620000   0.050000   1.670000 (  1.724199)
  1.610000   0.010000   1.620000 (  1.657794)
  1.660000   0.020000   1.680000 (  1.680383)
  1.710000   0.020000   1.730000 (  1.767141)
  1.720000   0.010000   1.730000 (  1.809114)&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;According to the Ruby documentation the benchmark outputs the user CPU time, the system CPU time, the sum of the user and system CPU times, and the elapsed real time. So this means that the query took between 1.65 and 1.87 seconds to get a list of 98000 POIs within the given bounding box. This is a nice indication of the speed of Tokyo Cabinet.&lt;/p&gt;

&lt;p&gt;To demonstrate how you can access the attribute I created the following code. It loops over the first 100 found POIs and prints the ID and the x- and y-coordinate.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# print the first hundred found POIs&lt;/span&gt;
&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rkey&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
 &lt;span class="n"&gt;rcols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rkey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;rcols&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rcols&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rcols&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
  &lt;span class="k"&gt;break&lt;/span&gt;
 &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we are ready to close the database. I hope you enjoyed this post and as always I welcome any comments.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# close the database&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
 &lt;span class="n"&gt;ecode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ecode&lt;/span&gt;
 &lt;span class="no"&gt;STDERR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;close error: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ecode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Related Posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/07/installating-tokyo-cabinet-and-ruby-on.html"&gt;Installing Tokyo Cabinet and Ruby on Ubuntu&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html"&gt;Populating a MongoDb with POIs&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html"&gt;Spatial indexing a MongoDb with Rtree&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/postgis-loading-and-querying-data.html"&gt;PostGIS : Loading and querying data&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-8032790868644847596?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/8032790868644847596/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/07/tokyo-cabinet-2-loading-and-querying.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/8032790868644847596'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/8032790868644847596'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/07/tokyo-cabinet-2-loading-and-querying.html' title='Tokyo Cabinet 2 : Loading and querying point data'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-3471997680361475944</id><published>2009-07-07T20:45:00.005+02:00</published><updated>2009-07-27T20:56:38.446+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tokyo Cabinet'/><category scheme='http://www.blogger.com/atom/ns#' term='anti-rdbms'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Installing Tokyo Cabinet and Ruby on Ubuntu</title><content type='html'>&lt;p&gt;After &lt;a href="http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html"&gt;MongoDB&lt;/a&gt; its time for another alternative to relational databases called Tokyo Cabinet. Tokyo Cabinet is a library of routines for managing a file based key-value store. It's a high performing database and it can be accessed over a network with Tokyo Tyrant. In this post I install Tokyo Cabinet, Ruby and the Ruby bindings for Tokyo Cabinet. But there will be a follow up post where I load and query POIs like I did with &lt;a href="http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html"&gt;MongoDB&lt;/a&gt; and &lt;a href="http://gissolved.blogspot.com/2009/06/postgis-loading-and-querying-data.html"&gt;PostgreSQL/PostGIS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tokyo Cabinet only works on Linux so I installed it in on an Ubuntu virtual machine. It took me some time to figure everything out but if I can do it you can too. First you need to download the latest version of Tokyo Cabinet from the &lt;a href="http://tokyocabinet.sourceforge.net/"&gt;project site&lt;/a&gt;. Once downloaded you open a terminal window, navigate to the download location and issue the following commands.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;tar xzvf tokyocabinet-1.4.20.tar.gz
&lt;span class="nb"&gt;cd &lt;/span&gt;tokyo-cabinet/
&lt;span class="c"&gt;# install dependencies&lt;/span&gt;
sudo apt-get install checkinstall build-essential libbz2-dev
&lt;span class="c"&gt;# now compile&lt;/span&gt;
./configure --prefix&lt;span class="o"&gt;=&lt;/span&gt;/usr
make clean
make
&lt;span class="c"&gt;# creates and installs a Debian package&lt;/span&gt;
sudo checkinstall -D 
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I decided to use the Ruby bindings so if you don't have it you can install it with the below command. This installs Ruby, an interactive shell, an interactive reference, the Ruby documentation and the dev part of the Ruby Standard Library. We will need the ruby-dev package for building the Ruby bindings of Tokyo Cabinet.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;sudo apt-get install ruby irb ri rdoc ruby1.8-dev
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After downloading the Ruby bindings for Tokyo Cabinet from the &lt;a href="http://tokyocabinet.sourceforge.net/"&gt;project site&lt;/a&gt;, I installed them with the following commands.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;tar xzvf tokyocabinet-ruby-1.26.tar.gz
&lt;span class="nb"&gt;cd &lt;/span&gt;tokyocabinet-ruby-1.26
ruby extconf.rb
make
sudo make install
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the &lt;a href="http://tokyocabinet.sourceforge.net/spex-en.html"&gt;specifications document&lt;/a&gt; you can find a lot of information about Tokyo Cabinet and the underlying concepts. As you can read there are four types of databases : a hash database, a B+ tree database, a fixed-length database and a table database. In the examples directory of the Ruby bindings you will find some samples that create and use these four database. There is also a sample that uses the abstract database API with which you can communicate to the four database types. For more info on the Ruby bindings you can read the &lt;a href="http://tokyocabinet.sourceforge.net/rubydoc/"&gt;docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Problems with the installation ? Here are the sources that helped me with the installation process or post a comment and maybe I can help out.&lt;br /&gt;
&lt;a href="http://openwferu.rubyforge.org/tokyo.html"&gt;http://openwferu.rubyforge.org/tokyo.html&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://oui.com.br/blog/nando-en/post/installing-tokyo-cabinet"&gt;http://oui.com.br/blog/nando-en/post/installing-tokyo-cabinet&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://www.ubuntugeek.com/how-to-install-ruby-on-rails-ror-in-ubuntu.html"&gt;http://www.ubuntugeek.com/how-to-install-ruby-on-rails-ror-in-ubuntu.html&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://blogs.law.harvard.edu/hoanga/2006/10/27/fixing-mkmf-load-error-ruby-in-ubuntu/"&gt;http://blogs.law.harvard.edu/hoanga/2006/10/27/fixing-mkmf-load-error-ruby-in-ubuntu/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/07/tokyo-cabinet-2-loading-and-querying.html"&gt;Tokyo Cabinet 2 : Loading and querying points&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html"&gt;Populating a MongoDb with POIs&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html"&gt;Spatial indexing a MongoDb with Rtree&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/postgis-loading-and-querying-data.html"&gt;PostGIS : Loading and querying data&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-3471997680361475944?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/3471997680361475944/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/07/installating-tokyo-cabinet-and-ruby-on.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/3471997680361475944'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/3471997680361475944'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/07/installating-tokyo-cabinet-and-ruby-on.html' title='Installing Tokyo Cabinet and Ruby on Ubuntu'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-6130247787353159763</id><published>2009-06-30T21:25:00.011+02:00</published><updated>2009-09-27T12:06:16.071+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='featureclass'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='DragDrop'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcObjects'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><title type='text'>Drag Drop from ArcCatalog</title><content type='html'>&lt;p&gt;As you probably already noticed you can drag drop items within ArcGIS. For example you can drag a feature class from ArcCatalog to ArcMap or from ArcMap or ArcCatalog to a geoprocessing form. In this post I'm going to show you what has to be done to enable drag drop behavior from ArcCatalog and Windows Explorer to a textbox.&lt;/p&gt;

&lt;p&gt;To enable drag drop on a textbox I added event handlers for DragEnter, DragOver and DragDrop for my textbox called textBoxPath. In the DragEnter and DragOver handlers I check whether the dragged object is valid. If this is the case the drag drop effect is set to &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.dragdropeffects.aspx"&gt;All&lt;/a&gt;. This is a combination of the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.dragdropeffects.aspx"&gt;Copy, Move, and Scroll&lt;/a&gt; effect. But its in the DragDrop event handler and more precisely in the helper function GetPaths that the most import stuff happens. As you can see the Data property of the DragEventArgs is processed by the GetPaths method and if any paths to feature classes or tables are found the first path is shown. After that I added a small hack to put the cursor at the end of the text in the textbox.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TextBoxPath_DragEnter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DragEventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EsriDragDrop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;DragDropEffects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DragDropEffects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TextBoxPath_DragOver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DragEventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EsriDragDrop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;DragDropEffects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DragDropEffects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TextBoxPath_DragDrop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DragEventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;paths&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EsriDragDrop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetPaths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="n"&gt;TextBox&lt;/span&gt; &lt;span class="n"&gt;txtBoxPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TextBox&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="k"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// set value of textbox to the first found path&lt;/span&gt;
  &lt;span class="n"&gt;txtBoxPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;esriDragDrop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Paths&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="c"&gt;// place cursor at the end of the textbox&lt;/span&gt;
  &lt;span class="n"&gt;txtBoxPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SelectionStart&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;txtBoxPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TextLength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the below EsriDragDrop class I placed the IsValid and GetPaths methods. The IsValid method checks whether the IDataObject coming from the drag event contains any valid objects. The GetPaths method retrieves those valid objects and returns the paths to the found feature classes and tables. It uses the IDataObjectHelper interface and its GetNames and GetFiles methods to access the objects in the IDataObject. Note that only feature classes and tables will be returned by my code but this constraint can easily be removed by not checking the Type of the datasetName. I didn't add any functionality to check whether the file path dragged from a Windows Explorer to the textbox was valid but you can implement this by using the &lt;a href="http://webhelp.esri.com/arcgisdesktop/9.3/index.cfm?TopicName=Geoprocessor_object"&gt;Geoprocessor object&lt;/a&gt; and its &lt;a href="http://webhelp.esri.com/arcgisdesktop/9.3/index.cfm?TopicName=Exists_method"&gt;Exists&lt;/a&gt; and &lt;a href="http://webhelp.esri.com/arcgisdesktop/9.3/index.cfm?TopicName=Describe_method"&gt;Describe&lt;/a&gt; methods or by &lt;a href="http://forums.esri.com/Thread.asp?c=93&amp;f=1170&amp;t=203270#609558"&gt;trying to open the table or feature class&lt;/a&gt;.&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Windows.Forms&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;ESRI.ArcGIS.esriSystem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;ESRI.ArcGIS.Geodatabase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;ESRI.ArcGIS.SystemUI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;GisSolved.DragDrop&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EsriDragDrop&lt;/span&gt;
 &lt;span class="k"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;DATAOBJECT_ESRINAMES&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;ESRI Names&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDataObject&lt;/span&gt; &lt;span class="n"&gt;dataObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dataObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetDataPresent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DATAOBJECT_ESRINAMES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt;
    &lt;span class="n"&gt;dataObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetDataPresent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Windows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Forms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFormats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FileDrop&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;GetPaths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDataObject&lt;/span&gt; &lt;span class="n"&gt;dataObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foundPaths&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
   &lt;span class="n"&gt;IDataObjectHelper&lt;/span&gt; &lt;span class="n"&gt;dataObjectHelper&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DataObjectHelperClass&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;dataObjectHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InternalObject&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;dataObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataObjectHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CanGetNames&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
   &lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;IEnumName&lt;/span&gt; &lt;span class="n"&gt;enumNames&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dataObjectHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNames&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;IName&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enumNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;IDatasetName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="k"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;IDatasetName&lt;/span&gt; &lt;span class="n"&gt;datasetName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDatasetName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c"&gt;// only accept feature classes and tables&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datasetName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;esriDatasetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;esriDTFeatureClass&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt;
       &lt;span class="n"&gt;datasetName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;esriDatasetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;esriDTTable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;{&lt;/span&gt;
       &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datasetName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WorkspaceName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PathName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datasetName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="n"&gt;foundPaths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataObjectHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CanGetFiles&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
   &lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;paths&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;&lt;span class="n"&gt;dataObjectHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetFiles&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;
     &lt;span class="c"&gt;// TODO : Add code here to check if the file path is a valid path&lt;/span&gt;
     &lt;span class="n"&gt;foundPaths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;foundPaths&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;}&lt;/span&gt;
 &lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is all you need to implement drag drop behavior from ArcCatalog or Windows Explorer to your textbox. If you want to implement drag drop from ArcMap to your form I suggest you to read &lt;a href="http://mrrichie.spaces.live.com/blog/cns!DD16C3F34F4D913E!599.entry"&gt;this&lt;/a&gt; and &lt;a href="http://mrrichie.spaces.live.com/blog/cns!DD16C3F34F4D913E!1741.entry"&gt;this&lt;/a&gt;. Any comments or suggestions ? Let me know.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/08/datagridview-tricks.html"&gt;DatagridView Tricks&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html"&gt; Calling .NET from Python to execute spatial queries&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/04/projections-and-transformations-with.html"&gt;Projecting coordinates with Python and the ArcGIS Projection Engine&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-6130247787353159763?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/6130247787353159763/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/06/drag-drop-from-arccatalog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/6130247787353159763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/6130247787353159763'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/06/drag-drop-from-arccatalog.html' title='Drag Drop from ArcCatalog'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-2784385595857794455</id><published>2009-06-25T20:35:00.006+02:00</published><updated>2009-06-30T21:25:09.471+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='similar code'/><category scheme='http://www.blogger.com/atom/ns#' term='Clone Digger'/><category scheme='http://www.blogger.com/atom/ns#' term='Python Toolbox'/><category scheme='http://www.blogger.com/atom/ns#' term='duplicate code'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Toolbox 4 : Clone Digger</title><content type='html'>&lt;p&gt;Looking for duplicate code or opportunities to refactor, let me introduce you to a great Python tool called &lt;a href="http://clonedigger.sourceforge.net/"&gt;Clone Digger&lt;/a&gt;. As the &lt;a href="http://clonedigger.sourceforge.net/"&gt;projects page&lt;/a&gt; says
&lt;blockquote&gt;Clone Digger aimed to detect similar code in Python and Java programs. The synonyms for the term "similar code" are "clone" and "duplicate code".&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;Once &lt;a href="http://clonedigger.sourceforge.net/download.html"&gt;installed&lt;/a&gt; you call the clonedigger.py file with as arguments the path for the output html and the path to a folder or code file to analyze. If you call it with the parameter -h it outputs the different commandline options. To show the power of Clone Digger I used the following extract from actual code.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;arcgisscripting&lt;/span&gt;

&lt;span class="n"&gt;gp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arcgisscripting&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createobject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Point&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;createPolygon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xMin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xMax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yMin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yMax&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;polygon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createobject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;array&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;##Add the first point&lt;/span&gt;
    &lt;span class="n"&gt;newPoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xMin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yMin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;polygon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;##Add the second point&lt;/span&gt;
    &lt;span class="n"&gt;newPoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xMin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yMax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;polygon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;##Add the third point&lt;/span&gt;
    &lt;span class="n"&gt;newPoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xMax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yMax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;polygon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;##Add the fourth point&lt;/span&gt;
    &lt;span class="n"&gt;newPoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xMax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yMin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;polygon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;##Close the polygon&lt;/span&gt;
    &lt;span class="n"&gt;newPoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xMin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yMin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;#polygon.Add(newPoint)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;polygon&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To run Clone Digger on this file all you have to is issue the below command. Make sure that your shell finds the file clonedigger.py by adding to your path variables or by navigating to its folder.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;python clonedigger.py -o D:\output.html D:\CodeTest.py
&lt;/pre&gt;&lt;/div&gt;&lt;br/&gt;

&lt;p&gt;The output first shows some summary values from the code analysis. Then it shows the different code blocks where duplicate or similar code where found. This is how the output looks like for my short Python code.&lt;/p&gt;

&lt;div class="highlight"&gt;
    &lt;P&gt;Source files: 1&lt;/P&gt;
 &lt;P&gt;Clones detected: 2&lt;/P&gt;
 &lt;P&gt;9 of 17 lines are duplicates (52.94%) &lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Parameters&lt;BR&gt; &lt;/B&gt;

clustering_threshold = 10&lt;BR&gt;
distance_threshold = 5&lt;BR&gt;
size_threshold = 5&lt;BR&gt;
hashing_depth = 1&lt;BR&gt;
clusterize_using_hash = False&lt;BR&gt;
clusterize_using_dcup = False&lt;BR&gt;
&lt;/P&gt; 
 
    &lt;B&gt;Time elapsed&lt;/B&gt;&lt;BR&gt;Construction of AST : 0.00 seconds&lt;BR&gt;
Building statement hash : 0.00 seconds&lt;BR&gt;

Building patterns : 0.00 seconds&lt;BR&gt;
Marking similar statements : 0.02 seconds&lt;BR&gt;
Finding similar sequences of statements : 0.00 seconds&lt;BR&gt;
Refining candidates : 0.02 seconds&lt;BR&gt;
 Total time: 0.03&lt;BR&gt;
 Started at: Wed Jun 24 21:05:15 2009&lt;BR&gt;
 Finished at: Wed Jun 24 21:05:15 2009
    &lt;P&gt;&lt;B&gt;Clone # 1&lt;/B&gt;&lt;BR&gt;Distance between two fragments = 4 &lt;BR&gt;Clone size = 7&lt;TABLE NOWRAP WIDTH=100% BORDER=1&gt;&lt;TD&gt;Source file "D:\CodeToTest.py"&lt;BR&gt;The first line is 16&lt;/TD&gt;&lt;TD&gt;&lt;/TD&gt;&lt;TD&gt;Source file "D:\CodeToTest.py"&lt;BR&gt;The first line is 13&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;

&lt;TD&gt;
newPoint = createPoint(xMin, &lt;span style="color: rgb(255, 0, 0);"&gt;yMax&lt;/span&gt;)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=RED&gt; &lt;/TD&gt;&lt;TD&gt;
newPoint = createPoint(xMin, &lt;span style="color: rgb(255, 0, 0);"&gt;yMin&lt;/span&gt;)&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
polygon.Add(newPoint)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=AQUA&gt; &lt;/TD&gt;&lt;TD&gt;

polygon.Add(newPoint)&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
newPoint = createPoint(&lt;span style="color: rgb(255, 0, 0);"&gt;xMax&lt;/span&gt;, yMax)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=RED&gt; &lt;/TD&gt;&lt;TD&gt;
newPoint = createPoint(&lt;span style="color: rgb(255, 0, 0);"&gt;xMin&lt;/span&gt;, &lt;span style="color: rgb(255, 0, 0);"&gt;yMax&lt;/span&gt;)&lt;/TD&gt;

&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
polygon.Add(newPoint)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=AQUA&gt; &lt;/TD&gt;&lt;TD&gt;
polygon.Add(newPoint)&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
newPoint = createPoint(xMax, &lt;span style="color: rgb(255, 0, 0);"&gt;yMin&lt;/span&gt;)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=RED&gt; &lt;/TD&gt;&lt;TD&gt;

newPoint = createPoint(&lt;span style="color: rgb(255, 0, 0);"&gt;xMax&lt;/span&gt;, &lt;span style="color: rgb(255, 0, 0);"&gt;yMax&lt;/span&gt;)&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
polygon.Add(newPoint)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=AQUA&gt; &lt;/TD&gt;&lt;TD&gt;
polygon.Add(newPoint)&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;

&lt;TD&gt;
newPoint = createPoint(&lt;span style="color: rgb(255, 0, 0);"&gt;xMin&lt;/span&gt;, yMin)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=RED&gt; &lt;/TD&gt;&lt;TD&gt;
newPoint = createPoint(&lt;span style="color: rgb(255, 0, 0);"&gt;xMax&lt;/span&gt;, &lt;span style="color: rgb(255, 0, 0);"&gt;yMin&lt;/span&gt;)&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TABLE&gt; &lt;/P&gt; &lt;HR&gt;&lt;BR&gt;

&lt;P&gt;&lt;B&gt;Clone # 2&lt;/B&gt;&lt;BR&gt;Distance between two fragments = 4 &lt;BR&gt;Clone size = 5&lt;TABLE NOWRAP WIDTH=100% BORDER=1&gt;&lt;TD&gt;Source file "D:\CodeToTest.py"&lt;BR&gt;The first line is 19&lt;/TD&gt;&lt;TD&gt;&lt;/TD&gt;&lt;TD&gt;Source file "D:\CodeToTest.py"&lt;BR&gt;The first line is 13&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;
&lt;TD&gt;
newPoint = createPoint(&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;xMax&lt;/span&gt;&lt;/span&gt;, &lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;yMax&lt;/span&gt;&lt;/span&gt;)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=RED&gt; &lt;/TD&gt;&lt;TD&gt;

newPoint = createPoint(&lt;span style="color: rgb(255, 0, 0);"&gt;xMin&lt;/span&gt;, &lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;yMin&lt;/span&gt;&lt;/span&gt;)&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
polygon.Add(newPoint)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=AQUA&gt; &lt;/TD&gt;&lt;TD&gt;
polygon.Add(newPoint)&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;

&lt;TD&gt;
newPoint = createPoint(&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;xMax&lt;/span&gt;&lt;/span&gt;, &lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;yMin&lt;/span&gt;&lt;/span&gt;)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=RED&gt; &lt;/TD&gt;&lt;TD&gt;
newPoint = createPoint(&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;xMin&lt;/span&gt;&lt;/span&gt;, &lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;yMax&lt;/span&gt;&lt;/span&gt;)&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;

&lt;TD&gt;
polygon.Add(newPoint)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=AQUA&gt; &lt;/TD&gt;&lt;TD&gt;
polygon.Add(newPoint)&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
newPoint = createPoint(&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;xMin&lt;/span&gt;&lt;/span&gt;, &lt;span style="color: rgb(255, 0, 0);"&gt;yMin&lt;/span&gt;)&lt;/TD&gt;
&lt;TD style="width: 10px;" BGCOLOR=RED&gt; &lt;/TD&gt;&lt;TD&gt;

newPoint = createPoint(&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;xMax&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;yMax&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TABLE&gt; &lt;/P&gt; &lt;HR&gt;
    
    
    &lt;HR&gt;
    Clone Digger is aimed to find software clones in Python and Java programs. It is provided under the GPL license and can be downloaded from the site &lt;a href="http://clonedigger.sourceforge.net"&gt;http://clonedigger.sourceforge.net&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;I would not try remove all the duplicates or similarities found by Clone Digger. But I think it's a great tool to find code that can be improved. The degree to which you refactor depends greatly on the goal of your code and your time restrictions. Clone Digger is also be useful when working with multiple people on a project or when having to improve some legacy code.&lt;br /&gt;
Have any comments ? Any tools you can't live without ? Any suggestions for me ? Feel free to let me know.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html"&gt;Pythonnet (call .NET from Python)&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/05/python-toolbox-2-pygments.html"&gt;Pygments (syntax highlighter)&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/05/python-toolbox-1-logging.html"&gt;Logging&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-2784385595857794455?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/2784385595857794455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/06/python-toolbox-4-clone-digger.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/2784385595857794455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/2784385595857794455'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/06/python-toolbox-4-clone-digger.html' title='Python Toolbox 4 : Clone Digger'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-7970578413082183301</id><published>2009-06-21T22:11:00.004+02:00</published><updated>2009-06-24T15:18:34.125+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PostGIS'/><category scheme='http://www.blogger.com/atom/ns#' term='PostgreSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='spatial filter'/><title type='text'>PostGIS : Loading and querying data</title><content type='html'>&lt;p&gt;Today I'm going to load some POIs (points of interest) in a PostGIS database and query them back. 
To do this you'll first need an installed version of PostgreSQL with PostGIS. I suggest to first &lt;a href="http://www.postgresql.org/download/"&gt;download&lt;/a&gt; and  &lt;a href="http://www.postgresql.org/docs/8.3/interactive/admin.html"&gt;install PostgreSQL&lt;/a&gt; and then &lt;a href="http://postgis.refractions.net/documentation/manual-1.3/ch02.html"&gt;install PostGIS&lt;/a&gt; with the &lt;a href="http://postgis.refractions.net/download/"&gt;latest version&lt;/a&gt;. Then you should &lt;a href="http://postgis.refractions.net/documentation/manual-1.3/ch02.html#templatepostgis"&gt;create a spatially enabled database&lt;/a&gt;. I called mine pois_db.&lt;/p&gt;

&lt;p&gt;Now we are ready to import the POIs. I first extracted 500.000 POIs from a file geodatabase into a shapefile with the ArcGIS Select tool. Then I used the PostGIS shp2pgsql tool which is located in your bin folder of your PostgreSQL installation to create a text file. This file can then be used to import the data in your database with the PostgreSQL psql tool.
My commandline looked like below.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;rem -s : srid (spatial reference id)&lt;/span&gt;
&lt;span class="c"&gt;rem -c : creates a new table and populates it&lt;/span&gt;
&lt;span class="c"&gt;rem -D : use PostgreSQL dump format&lt;/span&gt;
&lt;span class="c"&gt;rem -i create a GiST index on the geometry column&lt;/span&gt;
&lt;span class="s2"&gt;&amp;quot;C:\Program Files\PostgreSQL\8.3\bin\shp2pgsql.exe&amp;quot;&lt;/span&gt; -s &lt;span class="m"&gt;4326&lt;/span&gt; -c -D -i poi_&lt;span class="m"&gt;500000&lt;/span&gt;.shp pois_db &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pois&lt;/span&gt;.sql
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;More information about the usage of shp2pgsql can be found &lt;a href="http://postgis.refractions.net/documentation/manual-1.3/ch04.html#id2571948"&gt;here&lt;/a&gt;. Note that I set the srid to 4326 which stands for WGS84. On &lt;a href="http://spatialreference.org/"&gt;spatialreference.org&lt;/a&gt; you can find a list of spatial reference ids or you can take a look at the &lt;a href="http://postgis.refractions.net/documentation/manual-1.3/ch04.html#id2571306"&gt;spatial_ref_sys table&lt;/a&gt; in your database.&lt;br /&gt;
Next thing we are going to is load the pois.sql in the pois_db with the following command line.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="s2"&gt;&amp;quot;C:\Program Files\PostgreSQL\8.3\bin\psql&amp;quot;&lt;/span&gt; -d pois_db -f pois.sql
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To query the POIs we issue the following sql command. 
This query checks whether the bounding box of the point intersects with the bounding box of a &lt;a href="http://en.wikipedia.org/wiki/Well-known_text"&gt;created rectangle polygon&lt;/a&gt;.
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;pois&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;the_geom&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;GeomFromText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;POLYGON((4.5 50.5, 5.0 50.5, 5.0 51.0, 4.5 51.0, 4.5 50.5))&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4326&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This query takes in pgAdmin III with a gist index on the geometry column only 515 ms for more then 4000 found POIs. If I only ask the ids the query is down to 67 ms which is slightly slower then &lt;a href="http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html"&gt;with Rtree&lt;/a&gt; but faster then with &lt;a href="http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html"&gt;MongoDb&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've come to the end of this post. I hope you liked it and leave a comment if you want to.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related Posts&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html"&gt;Pythonnet&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html"&gt;MongoDB&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html"&gt;Rtree&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-7970578413082183301?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/7970578413082183301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/06/postgis-loading-and-querying-data.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/7970578413082183301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/7970578413082183301'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/06/postgis-loading-and-querying-data.html' title='PostGIS : Loading and querying data'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-3312630258065768305</id><published>2009-06-14T21:50:00.009+02:00</published><updated>2009-06-30T21:51:32.696+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='geoprocessing'/><category scheme='http://www.blogger.com/atom/ns#' term='Python Toolbox'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><category scheme='http://www.blogger.com/atom/ns#' term='spatial filter'/><title type='text'>Python Toolbox 3 : Pythonnet</title><content type='html'>&lt;p&gt;After &lt;a href="http://gissolved.blogspot.com/2009/05/python-toolbox-1-logging.html"&gt;logging&lt;/a&gt; and &lt;a href="http://gissolved.blogspot.com/2009/05/python-toolbox-2-pygments.html"&gt;Pygments&lt;/a&gt; I want to uncover another useful Python tool called &lt;a href="http://pythonnet.sourceforge.net"&gt;pythonnet&lt;/a&gt;. Pythonnet provides a way to call .NET assemblies from within Python. Its usage is very similar to that of &lt;a href="http://ironpython.codeplex.com/"&gt;IronPython&lt;/a&gt; and also comparable to that of &lt;a href="http://python.net/crew/theller/ctypes"&gt;ctypes&lt;/a&gt; which I used in my &lt;a href="http://gissolved.blogspot.com/2009/04/projections-and-transformations-with.html"&gt;post&lt;/a&gt; about using the ArcGIS projection engine dll (pe.dll) to project coordinates.&lt;/p&gt;

&lt;p&gt;To get working binaries for this project you need to make your hands a little bit dirty but with some small effort you're good to go. And although the last release is rather old I've read about people using it on Python 2.6 with .NET 3.5. Before anything I suggest you to read the &lt;a href="http://pythonnet.sourceforge.net/readme.html"&gt;readme&lt;/a&gt; because this will explain and clarify a lot of things. What I did is download the project from &lt;a href="http://pythonnet.sourceforge.net/"&gt;sourceforge&lt;/a&gt; and open the visual studio solution. Then I applied the patch described &lt;a href="http://mail.python.org/pipermail/pythondotnet/2008-January/000771.html"&gt;here&lt;/a&gt;. For more information about this patch and sample code to test whether the patch was applied successfully I suggest you to read &lt;a href="http://feihonghsu.blogspot.com/2008/02/pythonnet-20-for-net-sp1_15.html"&gt;this&lt;/a&gt;. Finally you have to build the solution and copiy the clr.pyd and Python.Runtime.dll to the root of your Python installation. In my case this is C:\Python24.&lt;br /&gt;
To test if everything went fine you can take a look at the demo directory in the pythonnet folder. I had to add import clr before the other import statements to make the samples work. This is not a bug but merely due to the fact that I used the standard Python executable.&lt;/p&gt;

&lt;p&gt;One of the possible uses of pythonnet in a GIS context is when you're creating some arcgisscripting code but want to do things that can't be done with the Python bindings of ArcGIS. One of those things is a spatial filter although you can create a workaround with an extra query layer and the SelectLayerByLocation tool. I first created a static method called Hello to test if pythonnet worked with my dll. Then I created the CreateLayerFromSpatialIntersect method. The goal of this method is to do a bounding box query and export the queried features. This method takes input the path to a shapefile, a destination folder and name and the minimum and maximum values of x and y. The found features are exported to a new shapefile. I also added a helper method to get an IFeatureClass object from the shapefile. I also used the LicenseInitializer class. This class is part of the ArcGIS Console application template and has the sole purpose of getting and releasing an ArcGIS license.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;ESRI.ArcGIS.Geodatabase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;ESRI.ArcGIS.Geometry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;ESRI.ArcGIS.GeoDatabaseUI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;ESRI.ArcGIS.esriSystem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;ESRI.ArcGIS.DataSourcesFile&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;GisSolved.SpatialQueryTool&lt;/span&gt;
&lt;span class="k"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SpatialQueryTool&lt;/span&gt;
    &lt;span class="k"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Hello !!!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;CreateLayerFromSpatialIntersect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;shapeSourcePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;destinationFolder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;destinationName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;xMin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;xMax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;yMin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;yMax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;LicenseInitializer&lt;/span&gt; &lt;span class="n"&gt;licenseInitializer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;LicenseInitializer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;licenseInitializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InitializeApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;esriLicenseProductCode&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="k"&gt;{&lt;/span&gt; &lt;span class="n"&gt;esriLicenseProductCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;esriLicenseProductCodeArcView&lt;/span&gt; &lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;esriLicenseExtensionCode&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="k"&gt;{&lt;/span&gt; &lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;IFeatureClass&lt;/span&gt; &lt;span class="n"&gt;sourceFeatureClass&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetShapeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shapeSourcePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c"&gt;// create  the spatial filter&lt;/span&gt;
            &lt;span class="n"&gt;ISpatialFilter&lt;/span&gt; &lt;span class="n"&gt;spatialFilter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;SpatialFilterClass&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;spatialFilter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SpatialRel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;esriSpatialRelEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;esriSpatialRelIntersects&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;IEnvelope&lt;/span&gt; &lt;span class="n"&gt;boundingBox&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;EnvelopeClass&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;boundingBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XMax&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xMax&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;boundingBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XMin&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xMin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;boundingBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;YMax&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yMax&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;boundingBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;YMin&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yMin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;spatialFilter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Geometry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IGeometry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;boundingBox&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c"&gt;// create other parameters for the export operation&lt;/span&gt;
            &lt;span class="n"&gt;IDataset&lt;/span&gt; &lt;span class="n"&gt;sourceDataset&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDataset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;sourceFeatureClass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;IDatasetName&lt;/span&gt; &lt;span class="n"&gt;sourceDatasetName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDatasetName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;sourceDataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;IFeatureClassName&lt;/span&gt; &lt;span class="n"&gt;destinationClassName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;FeatureClassNameClass&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;IDatasetName&lt;/span&gt; &lt;span class="n"&gt;destinationDatasetName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDatasetName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;destinationClassName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;destinationDatasetName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;destinationName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;IWorkspaceName&lt;/span&gt; &lt;span class="n"&gt;destinationWorkspaceName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;WorkspaceNameClass&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;destinationWorkspaceName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PathName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;destinationFolder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;destinationWorkspaceName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WorkspaceFactoryProgID&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;esriDataSourcesFile.ShapefileWorkspaceFactory&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;destinationDatasetName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WorkspaceName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;destinationWorkspaceName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c"&gt;// do the actual export&lt;/span&gt;
            &lt;span class="n"&gt;IExportOperation&lt;/span&gt; &lt;span class="n"&gt;exportOp&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ExportOperationClass&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;exportOp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExportFeatureClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sourceDatasetName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IQueryFilter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;spatialFilter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destinationClassName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;licenseInitializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShutdownApplication&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IFeatureClass&lt;/span&gt; &lt;span class="nf"&gt;GetShapeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;workspacePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetDirectoryName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetFileName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;IWorkspaceFactory&lt;/span&gt; &lt;span class="n"&gt;shapefileWorkspaceFactory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ShapefileWorkspaceFactoryClass&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;IFeatureWorkspace&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IFeatureWorkspace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;shapefileWorkspaceFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenFromFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workspacePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenFeatureClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It's easy to use this code from pythhonnet. The first step is to build the .NET project and copy the resulting dll to the same directory as your Python code. Then you need to import clr and add a reference to the dll. Next thing to do is import the desired class from your assembly. Now you can use your class like you would do in IronPython. To test my code I exported 500.000 POIs to a shapefile which I then queried with the same bounding box as in my two previous posts about &lt;a href="http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html"&gt;MongoDb&lt;/a&gt; and &lt;a href="http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html"&gt;Rtree&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;clr&lt;/span&gt;
&lt;span class="n"&gt;clr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;SpatialQueryTool&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;GisSolved.SpatialQueryTool&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SpatialQueryTool&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;SpatialQueryTool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;r&amp;quot;D:\source\poi_500000.shp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;destinationFolder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;r&amp;quot;D:\destination&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;destinationName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;poi_45_50_505_510_2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;SpatialQueryTool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateLayerFromSpatialIntersect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destinationFolder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destinationName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;50.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;51.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I hope that this post was useful to you and as always I welcome any comments.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-3312630258065768305?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/3312630258065768305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/3312630258065768305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/3312630258065768305'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html' title='Python Toolbox 3 : Pythonnet'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-5080851236954716621</id><published>2009-06-06T18:29:00.009+02:00</published><updated>2010-06-16T12:56:05.986+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spatial index'/><category scheme='http://www.blogger.com/atom/ns#' term='MongoDb'/><category scheme='http://www.blogger.com/atom/ns#' term='Rtree'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Spatial indexing a MongoDb with Rtree</title><content type='html'>&lt;p&gt;&lt;i&gt;Update : recent versions of MongoDB support native &lt;a href="http://www.mongodb.org/display/DOCS/Geospatial+Indexing"&gt;geospatial indexing&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;In my &lt;a href="http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html"&gt;previous post&lt;/a&gt; about populating a MongoDb I mentioned the existence of the &lt;a href="http://pypi.python.org/pypi/Rtree"&gt;Rtree package&lt;/a&gt; as a solution to the lack of a spatial index  mechanism in MongoDb. In this post 'm going to try this out. &lt;a href="http://pypi.python.org/pypi/Rtree"&gt;Rtree&lt;/a&gt; is a Python package with the sole purpose of creating spatial indexes. To install Rtree I downloaded the Windows installer and ran the installer.&lt;/p&gt;

&lt;p&gt;To test Rtree I decided to create a spatial index for my &lt;a href="http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html"&gt;previously created&lt;/a&gt; POI database in MongoDb. To do this I first connect to my running MongoDb instance. Then I create an Rtree disk index in the same directory as my script called poi_index. This creates two files (poi_index.dat and poi_index.idx) who will contain the index. Finally I loop over all the POIs in the database and add the x and y values to the index with as reference the id of the POI.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pymongo.connection&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Connection&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rtree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Rtree&lt;/span&gt;

&lt;span class="n"&gt;mongo_conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;27017&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;poidb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mongo_conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;poidb&lt;/span&gt;
&lt;span class="n"&gt;pois&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;poidb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pois&lt;/span&gt;

&lt;span class="n"&gt;poi_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Rtree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;poi_index&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;poi&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pois&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;poi_index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poi&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ID&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poi&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;poi&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;y&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we have created an index for the 500.002 POIs in my database. The file size of this index is 350 mb which is more than I expected it to be when compared my Mongo POI database which has a total file size of 460 mb. Querying this index is very easy and very fast. To time my query I added a &lt;a href="http://www.daniweb.com/code/snippet368.html"&gt;handy wrapper function&lt;/a&gt;. Essentially to query the index the only thing you need to do is create a bounding box and call the intersection method of the index. This returns the ids of the intersecting points.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_timing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;t2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; took &lt;/span&gt;&lt;span class="si"&gt;%0.0f&lt;/span&gt;&lt;span class="s"&gt; ms&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;1000.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="n"&gt;minx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;
&lt;span class="n"&gt;miny&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;50.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;51.0&lt;/span&gt;
&lt;span class="n"&gt;bbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;minx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;miny&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxy&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@print_timing&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;intersect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bbox&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bbox&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;hits&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;intersect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poi_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bbox&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On my machine this bounding box query took 265 ms on the MongoDb and only 15 ms with Rtree. This is a great improvement for my query. But the disadvantage is that I still need to query my POIs out of the MongoDb with the ids I got from Rtree. Sadly enough this doesn't go very fast so the total improvement is very small and with lots of points even negative. Strange thing is that when I do an IN query on MongoDb the result is always slower than querying the pois one by one by ID. My temporary conclusion is that Rtree is really fast but you only get the ids. The best solution would be that MongoDb could natively use the Rtree index or another spatial index. A small downside of Rtree is that the id can only be an integer value. So you can't store strings as ids. We have come to the end of my small exploration of Rtree as a mean to add a spatial index to MongoDb. I hope you liked it and I still welcome any comments/suggestions.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Related Posts&lt;/b&gt;&lt;br&gt;
&lt;a href="http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html"&gt;Populating a MongoDB with POIs&lt;/a&gt;&lt;br&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/postgis-loading-and-querying-data.html"&gt;PostGIS Loading and querying data&lt;/a&gt;&lt;br&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html"&gt;Spatial queries with Pythonnet&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-5080851236954716621?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/5080851236954716621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/5080851236954716621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/5080851236954716621'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html' title='Spatial indexing a MongoDb with Rtree'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-2691936102340155271</id><published>2009-05-31T11:37:00.014+02:00</published><updated>2009-07-07T20:57:20.419+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MongoDb'/><category scheme='http://www.blogger.com/atom/ns#' term='anti-rdbms'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><category scheme='http://www.blogger.com/atom/ns#' term='document database'/><title type='text'>Populating a MongoDb with POIs</title><content type='html'>&lt;p&gt;I have been looking at the alternatives for relational databases for a while now and this week I came across &lt;a href="http://www.mongodb.org/display/DOCS/Home"&gt;MongoDB&lt;/a&gt;. MongoDB is a &lt;a href="http://en.wikipedia.org/wiki/Document-oriented_database"&gt;documented-oriented database&lt;/a&gt; which tries to bridge the gap between key/value stores and relational databases. In this post I'm going to install MongoDb and populate it with 500.000 POIs from &lt;a href="www.teleatlas.com"&gt;Tele Atlas&lt;/a&gt;. &lt;p&gt;To install MongoDb I only needed to download the Windows binaries and that's it. Then I followed the guidelines in the &lt;a href="http://www.mongodb.org/display/DOCS/Quickstart"&gt;Quickstart&lt;/a&gt; to start the database. As the default datapath for MongoDb on Windows is c:\data\db I specified a custom datapath.&lt;/p&gt;

&lt;div class="highlight"&gt;
&gt; mongod.exe --dbpath "D:\mongodb\data" run
&lt;/div&gt;

&lt;p&gt;Once I got MongoDb up and running I downloaded and installed the Python bindings named &lt;a href="http://pypi.python.org/pypi/pymongo"&gt;PyMongo&lt;/a&gt;. This also went very smoothly. On the MongoDb website there is a great &lt;a href="http://www.mongodb.org/display/DOCS/Python+Tutorial"&gt;introductory tutorial&lt;/a&gt; for PyMongo.&lt;/p&gt;

&lt;p&gt;To populate the MongoDb I wrote a Python program that loops over the POIs in a layer, creates a dictionary with its properties and coordinates. Then the POI dictionary is inserted in the pois collection in the poi database.&lt;br /&gt;
First I connect to my running MongoDb and create a reference to a new database called poidb. Then I create a new collection called pois.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;arcgisscripting&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pymongo.connection&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Connection&lt;/span&gt;

&lt;span class="n"&gt;mongo_conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;27017&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;poidb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mongo_conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;poidb&lt;/span&gt;
&lt;span class="n"&gt;pois&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;poidb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pois&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then comes some code that uses ESRI functions to create a list with the fields in the POI layer and a featurecursor for the POIs. I removed the SHAPE field from this list because this will be treated separately.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;gp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arcgisscripting&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;poi_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;r&amp;#39;D:\ta.gdb\eureur_____pi&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listfields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poi_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;SHAPE&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;searchcursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poi_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the next part we loop over the POIs in the cursor. For each poi we extract the x and y coordinate and save them in the poi dictionary. For all the fields we fetch the value and put the none empty values in the dictionary. The strings are stored as unicode. Finally we insert the poi dictionary in the poi collection of the poidb. The script stops when more then 500.000 POIs have been inserted (500.002 to be exact).&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feat&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="n"&gt;poi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getpart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;poi&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="n"&gt;poi&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;            
        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getvalue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;unicode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;latin-1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;poi&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;

    &lt;span class="n"&gt;pois&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;500000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To count the pois you only need to call the count method of the pois collection object.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;pois&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Before querying this data I'am going to create ascending indexes for the x and y fields. It would be better if spatial indexes where supported but with reasonably sized datasets a double index is sufficient for doing bounding box queries. I also could try the &lt;a href="http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html"&gt;RTree package&lt;/a&gt; but that will be for another time. At the end the information about the indexes is printed.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pymongo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ASCENDING&lt;/span&gt;
&lt;span class="n"&gt;poi_db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pois&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ensure_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ASCENDING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;poi_db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pois&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ensure_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ASCENDING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;pois&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index_information&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Query parameters are passed to MongoDb in a nested directory structure. So defining a bounding box query is an straightforward task. The $gt character means bigger then and $lt means smaller then. In this query I search for all the POIs with a longitude larger then 4.5 and smaller then 5.0 and a latitude larger then 50.5 and smaller then 51.0. Then I print the result count, the number of milliseconds that the query took and the first resulting document.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;query_pois&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pois&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;$gt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;$lt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;y&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;$gt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;50.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;$lt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;51.0&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;query_pois&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;query_pois&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;explain&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;millis&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;query_pois&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The result looks like this :&lt;/p&gt;
&lt;div class="highlight"&gt;
4585&lt;br /&gt;
265&lt;br /&gt;
SON([(u'HSNUM', u'173'), (u'MUNCD', u'23062'), (u'MUNID', 10560032003493.0), (u'x', 4.5000037996786091), (u'NAME', u'Shell Overijse Frans Verbeekstraat'), (u'OBJECTID', 134471), (u'TELNUM', u'+(32)-(2)-6573607'), (u'STNAME', u'Frans Verbeekstraat'), (u'FEATTYP', 7311), (u'ADDRPID', 10560000020526.0), (u'RELPOS', 75), (u'POSTCODE', u'3090'), (u'STNAMELC', u'DUT'), (u'ARNAMELC', u'DUT'), (u'y', 50.769815399855986), (u'IMPORT', 2), (u'MUNNAME', u'Overijse'), (u'_id', ObjectId('YB\xd6l\x99\xe0$U\x8f\t&gt;\xc3')), (u'CLTRPELID', 10560001815786.0), (u'ID', 10560300013584.0), (u'BUANAME', u'Hoeilaart')])&lt;/div&gt;&lt;p&gt;
So it took 265 milliseconds to query 4585 POIs from a collection 500.002 POIs with two range query parameters. If you need to optimize a query you can take a look at &lt;a href="http://www.mongodb.org/display/DOCS/Optimizing+Mongo+Performance"&gt;MongoDb Site&lt;/a&gt; for some tips and tricks.&lt;/p&gt;

&lt;p&gt;We have come to the end of my first exploration of MongoDb. What I especially liked is the flexibility you get from this kind of databases and the ease of installation and use. The downside for geographic applications is that at the moment there is no built-in support for geometries. I hope you enjoyed this post and I welcome any comments and suggestions.&lt;p/&gt;

&lt;p&gt;&lt;b&gt;Related Posts&lt;/b&gt;&lt;br&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/spatial-indexing-mongodb-with-rtree.html"&gt;Spatial indexing a MongoDB&lt;/a&gt;&lt;br&gt;
&lt;a href="http://gissolved.blogspot.com/2009/06/postgis-loading-and-querying-data.html"&gt;PostGIS Loading and querying data&lt;/a&gt;&lt;br&gt;
&lt;a href="http://gissolved.blogspot.com/2009/07/installating-tokyo-cabinet-and-ruby-on.html"&gt;Installing Tokyo Cabinet and Ruby&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-2691936102340155271?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/2691936102340155271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/2691936102340155271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/2691936102340155271'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/05/populating-mongodb-with-pois.html' title='Populating a MongoDb with POIs'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-8818282215216436302</id><published>2009-05-19T22:29:00.004+02:00</published><updated>2009-06-24T15:17:59.710+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='syntax highlighting'/><category scheme='http://www.blogger.com/atom/ns#' term='code publishing'/><category scheme='http://www.blogger.com/atom/ns#' term='Python Toolbox'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Toolbox 2 : Pygments</title><content type='html'>&lt;p&gt;This is the second post in my series about Python tools and I'm going to talk about &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt;. Pygments is a generic syntax highlighter implemented in Python. I started using it to able to show the code samples on this blog in a decent way.&lt;/p&gt;

&lt;p&gt;Pygments can highlight a very large &lt;a href="http://pygments.org/languages"&gt;list&lt;/a&gt; of programming languages, template languages and other sources like config files, shell scripts, css and many more. The markup of your sources can then be exported to multiple output formats like HTML, GIF or BMP image, Latex, rtf, svg, Bulletin bord code and terminal. More info about the formatters can be found &lt;a href="http://pygments.org/docs/formatters/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once &lt;a href="http://pygments.org/docs/installation/"&gt;installed&lt;/a&gt; you can call this library from within Python or you can call the provided executable from the commandline. The &lt;a href="http://pygments.org/docs/"&gt;documentation&lt;/a&gt; for Pygmentize is very clear and extensive so I won't reproduce it here but I'll show you some small samples.&lt;/p&gt;

&lt;p&gt;Below is a sample commandline usage. The first command outputs a file with your code wrapped in a div and span elements with css class attributes. The second command creates the stylesheet for your code.&lt;p&gt;
&lt;div class="highlight"&gt;
pygmentize -o test.html test.py
pygmentize -S default -f html &gt; style.css
&lt;/div&gt;
&lt;p&gt;If you want to create a full html file from your code with the styles included then all you need is the following command :&lt;p&gt;
&lt;div class="highlight"&gt;
pygmentize -O full=true -o test.html test.py
&lt;/div&gt;

&lt;p&gt;For the code in my blog I use the following simple Python script that converts the scripts in a folder to a html files. I also added the styles to the css of my blog.&lt;br /&gt;First I import the relevant namespaces from pygments and the os namespace. And then create a basic HtmlFormatter&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pygments&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;highlight&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pygments.lexers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PythonLexer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pygments.formatters&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HtmlFormatter&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HtmlFormatter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If you want a printout of all the different classes the only thing you need is the following line. I ran this once and copied to my style definitions on my blog.&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_style_defs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.highlight&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The following code converts all the python files in a directory to html files with the same name. We loop over the elements in the folder, read the python files, create a highlight of them and then write this to a new file.&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre&gt;&lt;span class="n"&gt;indir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;r&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indir&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.py&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;infile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;outfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;infile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.py&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;infile&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PythonLexer&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;finished :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-8818282215216436302?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/8818282215216436302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/05/python-toolbox-2-pygments.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/8818282215216436302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/8818282215216436302'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/05/python-toolbox-2-pygments.html' title='Python Toolbox 2 : Pygments'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-4552221595147229269</id><published>2009-05-12T21:12:00.012+02:00</published><updated>2009-06-24T15:17:59.711+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='projections'/><category scheme='http://www.blogger.com/atom/ns#' term='pyproj'/><category scheme='http://www.blogger.com/atom/ns#' term='transformations'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='ogr'/><title type='text'>Projections and transformation (2)</title><content type='html'>&lt;p&gt;In a comment on my previous post about &lt;a href="http://gissolved.blogspot.com/2009/04/projections-and-transformations-with.html"&gt;projections and transformations&lt;/a&gt; &lt;a href="http://www.blogger.com/profile/08561219259741483130"&gt;Gene&lt;/a&gt; pointed out that I could use Ogr with it its Python bindings. I already used the C# bindings from Ogr in the past but I thought it would be a nice exercise to use Ogr from Python.&lt;/p&gt;

&lt;p&gt;If you are on windows and need to install gdal/ogr and its Python bindings I suggest you to use the following &lt;a href="http://www.gis.usu.edu/~chrisg/python/2009/docs/gdal_win.pdf"&gt;installation guideline&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Below is the short code I came up with but there are numerous other samples on the web &lt;a href="http://pastebin.com/f686f8e69"&gt;sample 1&lt;/a&gt; &lt;a href="http://hackmap.blogspot.com/2008/03/ogr-python-projection.html"&gt;sample 2&lt;/a&gt; and off course the documentation on the &lt;a href="http://www.gdal.org/ogr/osr_tutorial.html"&gt;gdal site&lt;/a&gt;. Attention I got an error when trying to use the TransformPoints method.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;osgeo&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; osr

&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;get_spatialref&lt;/span&gt;(epsg_code):
    spatialref &lt;span style="color: #666666"&gt;=&lt;/span&gt; osr&lt;span style="color: #666666"&gt;.&lt;/span&gt;SpatialReference()
    spatialref&lt;span style="color: #666666"&gt;.&lt;/span&gt;ImportFromEPSG(epsg_code)
    &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; spatialref

lambert72_spatialref &lt;span style="color: #666666"&gt;=&lt;/span&gt; get_spatialref(&lt;span style="color: #666666"&gt;31300&lt;/span&gt;)
etrs89_spatialref &lt;span style="color: #666666"&gt;=&lt;/span&gt; get_spatialref(&lt;span style="color: #666666"&gt;4258&lt;/span&gt;)

coordinate_transformation &lt;span style="color: #666666"&gt;=&lt;/span&gt; osr&lt;span style="color: #666666"&gt;.&lt;/span&gt;CoordinateTransformation(lambert72_spatialref, etrs89_spatialref)

&lt;span style="color: #408080; font-style: italic"&gt;## start location : random point in Belgium&lt;/span&gt;
x &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #666666"&gt;155335.20410&lt;/span&gt;
y &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #666666"&gt;166096.08270&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; coordinate_transformation&lt;span style="color: #666666"&gt;.&lt;/span&gt;TransformPoint(x, y)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Another solution is to install and use the &lt;a href="http://code.google.com/p/pyproj/"&gt;Python bindings&lt;/a&gt; for the &lt;a href="http://trac.osgeo.org/proj/"&gt;Proj4 library&lt;/a&gt;.&lt;br /&gt;
The following sample code comes from its &lt;a href="http://pyproj.googlecode.com/svn/trunk/README.html"&gt;documentation&lt;/a&gt;.
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;pyproj&lt;/span&gt;

&lt;span style="color: #408080; font-style: italic"&gt;# projection 1: UTM zone 15, grs80 ellipse, NAD83 datum&lt;/span&gt;
&lt;span style="color: #408080; font-style: italic"&gt;# (defined by epsg code 26915)&lt;/span&gt;
p1 &lt;span style="color: #666666"&gt;=&lt;/span&gt; pyproj&lt;span style="color: #666666"&gt;.&lt;/span&gt;Proj(init&lt;span style="color: #666666"&gt;=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;#39;epsg:26915&amp;#39;&lt;/span&gt;)
p1_2 &lt;span style="color: #666666"&gt;=&lt;/span&gt; get_spatialref(&lt;span style="color: #666666"&gt;26915&lt;/span&gt;)
&lt;span style="color: #408080; font-style: italic"&gt;# projection 2: UTM zone 15, clrk66 ellipse, NAD27 datum&lt;/span&gt;
p2 &lt;span style="color: #666666"&gt;=&lt;/span&gt; pyproj&lt;span style="color: #666666"&gt;.&lt;/span&gt;Proj(init&lt;span style="color: #666666"&gt;=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;#39;epsg:26715&amp;#39;&lt;/span&gt;)
p2_2 &lt;span style="color: #666666"&gt;=&lt;/span&gt; get_spatialref(&lt;span style="color: #666666"&gt;26715&lt;/span&gt;)
&lt;span style="color: #408080; font-style: italic"&gt;# find x,y of Jefferson City, MO.&lt;/span&gt;
x1, y1 &lt;span style="color: #666666"&gt;=&lt;/span&gt; p1(&lt;span style="color: #666666"&gt;-92.199881&lt;/span&gt;,&lt;span style="color: #666666"&gt;38.56694&lt;/span&gt;)
&lt;span style="color: #408080; font-style: italic"&gt;# transform this point to projection 2 coordinates.&lt;/span&gt;
x2, y2 &lt;span style="color: #666666"&gt;=&lt;/span&gt; pyproj&lt;span style="color: #666666"&gt;.&lt;/span&gt;transform(p1,p2,x1,y1)
&lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; x2, y2
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt; If you need to look up a spatial reference you might wanna take a look at &lt;a href="http://spatialreference.org"&gt;spatialreference.org&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Succes !&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-4552221595147229269?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/4552221595147229269/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/05/projections-and-transformation-2.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/4552221595147229269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/4552221595147229269'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/05/projections-and-transformation-2.html' title='Projections and transformation (2)'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-7307172743522068404</id><published>2009-05-04T10:07:00.032+02:00</published><updated>2009-06-24T15:17:59.711+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='logging'/><category scheme='http://www.blogger.com/atom/ns#' term='Python Toolbox'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Toolbox 1 : Logging</title><content type='html'>&lt;p&gt;This is the first post in a series about internal and external Python modules.
Today I am going to give a brief overview of the built in &lt;a href="http://www.python.org/doc/2.5/lib/module-logging.html"&gt;logging&lt;/a&gt; module.&lt;p&gt;&lt;/p&gt;
The logging module is a core python module that was introduced in Python 2.3. There are 6 different logging levels (debug, info, warning, error, critical and fatal). You can also log an exception wich outputs a nice traceback. There are numerous output possibilities defined as handlers. The log information can for example be send to a file, an http server, the windows event log, an e-mail address, a stream and more. The logger can also be configured to log to a different output depending on the logging level. You could for example log to a file when the level is debug but you might want to receive an e-mail when a critical or fatal error occurs. In this post we will use a basic file logger and then create a rotating file logger. The rotating file logger will make a back-up of the logfile when it reaches a predefined maximum size.&lt;/p&gt;&lt;p&gt;As the following code shows, basic logging is easy to set up. In short it first imports the &lt;a href="http://www.python.org/doc/2.5/lib/module-logging.html"&gt;logging&lt;/a&gt; module. Then it intialize this module by calling the &lt;i&gt;basicConfig&lt;/i&gt; method. According to the help the input parameters for this method are :
&lt;/p&gt;&lt;pre&gt;&lt;i&gt;filename  Specifies that a FileHandler be created, using the specified filename,
          rather than a StreamHandler.
filemode  Specifies the mode to open the file, if filename is specified
          (if filemode is unspecified, it defaults to "a").
format    Use the specified format string for the handler.
datefmt   Use the specified date/time format.
level     Set the root logger level to the specified level.
stream    Use the specified stream to initialize the StreamHandler. Note that
          this argument is incompatible with 'filename' - if both are present,
          'stream' is ignored.&lt;/i&gt;&lt;/pre&gt;Then we test the different logging level and also deliberately throw an error to test the exception logging.
At the end I added some clean up code because the logging module doesn't get unloaded between to test runs in some IDE's.&lt;/p&gt;
&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;logging&lt;/span&gt;

logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;basicConfig(filename&lt;span style="color: #666666"&gt;=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;#39;gissolved.log&amp;#39;&lt;/span&gt;,
                    level&lt;span style="color: #666666"&gt;=&lt;/span&gt;logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;DEBUG,
                    format&lt;span style="color: #666666"&gt;=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(asctime)s&lt;/span&gt;&lt;span style="color: #BA2121"&gt; &lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(levelname)s&lt;/span&gt;&lt;span style="color: #BA2121"&gt; : &lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(message)s&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;#39;&lt;/span&gt;)

&lt;span style="color: #008000; font-weight: bold"&gt;try&lt;/span&gt;:
    logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;debug(&lt;span style="color: #BA2121"&gt;&amp;#39;debug&amp;#39;&lt;/span&gt;)
    logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;info(&lt;span style="color: #BA2121"&gt;&amp;#39;info&amp;#39;&lt;/span&gt;)
    logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;warning(&lt;span style="color: #BA2121"&gt;&amp;#39;warning&amp;#39;&lt;/span&gt;)
    logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;error(&lt;span style="color: #BA2121"&gt;&amp;#39;error&amp;#39;&lt;/span&gt;)
    logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;critical(&lt;span style="color: #BA2121"&gt;&amp;#39;critical&amp;#39;&lt;/span&gt;)
    logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;fatal(&lt;span style="color: #BA2121"&gt;&amp;#39;fatal&amp;#39;&lt;/span&gt;)
    &lt;span style="color: #008000; font-weight: bold"&gt;try&lt;/span&gt;:
        &lt;span style="color: #008000; font-weight: bold"&gt;raise&lt;/span&gt; &lt;span style="color: #D2413A; font-weight: bold"&gt;TypeError&lt;/span&gt;, &lt;span style="color: #BA2121"&gt;&amp;#39;Demo error&amp;#39;&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;except&lt;/span&gt; &lt;span style="color: #D2413A; font-weight: bold"&gt;TypeError&lt;/span&gt;:
        logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;exception(&lt;span style="color: #BA2121"&gt;&amp;#39;exception&amp;#39;&lt;/span&gt;)
&lt;span style="color: #008000; font-weight: bold"&gt;finally&lt;/span&gt;: &lt;span style="color: #408080; font-style: italic"&gt;## close logger properly&lt;/span&gt;
    logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;shutdown()
    logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;getLogger(&lt;span style="color: #008000"&gt;None&lt;/span&gt;)&lt;span style="color: #666666"&gt;.&lt;/span&gt;handlers &lt;span style="color: #666666"&gt;=&lt;/span&gt; []&lt;/pre&gt;
&lt;p&gt;Ok now let's create a rotating file logger. To do this we not only import the logging module but also the sub module handlers and the class Formatter. Then we define the log path and create a logger object. Now its time to create the &lt;i&gt;RotatingFileHandler&lt;/i&gt; that is defined in the handlers sub module. The parameters are the &lt;i&gt;filename&lt;/i&gt;, the &lt;i&gt;mode&lt;/i&gt; (defaults to 'a' which means append), &lt;i&gt;maxBytes&lt;/i&gt; (max number of bytes before rollover occurs), &lt;i&gt;backupCount&lt;/i&gt; (number of backup files that will be created as needed). Then we define a format for the handler and add it to the logger object. At last we set the logging level of our logger.&lt;/p&gt;&lt;p&gt;
Now its time to test the logger. I've put the code in a loop in order to log more bytes then the predefined number of maximum bytes per logfile. Internally the rotating file logger first checks whether the max size will be reached by writing the current message to the logfile. If this is the case it closes the current file and adds a suffix to it, a new file with the message is then created. So in this case the first back-up file will be renamed to &lt;q&gt;gissolved_rotate.log.1&lt;/q&gt;. The next back-up will then be named &lt;q&gt;gissolved_rotate.log.2&lt;/q&gt; and so on. Until the maximum number of back-up files is reached and the first back-up files gets overwritten. The file being written to is always the original &lt;q&gt;gissolved_rotate.log&lt;/q&gt;. In the finally block the current handler is removed from our logger and the handler is closed. If you've defined multiple handlers for your logger you could loop over the logger.handlers and call their close method and then set the logger.handlers equal to an empty list like I did in the first example.
&lt;/p&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;logging&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;logging&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; handlers, Formatter

&lt;span style="color: #008000; font-weight: bold"&gt;try&lt;/span&gt;:
    log_path &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;gissolved_rotate.log&amp;#39;&lt;/span&gt;
    logger &lt;span style="color: #666666"&gt;=&lt;/span&gt; logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;getLogger(&lt;span style="color: #BA2121"&gt;&amp;#39;gissolved&amp;#39;&lt;/span&gt;)
    &lt;span style="color: #408080; font-style: italic"&gt;## create a rotating file handler and add it to the logger&lt;/span&gt;
    handler &lt;span style="color: #666666"&gt;=&lt;/span&gt; handlers&lt;span style="color: #666666"&gt;.&lt;/span&gt;RotatingFileHandler(log_path,
                                           maxBytes&lt;span style="color: #666666"&gt;=5000000&lt;/span&gt;,
                                           backupCount&lt;span style="color: #666666"&gt;=4&lt;/span&gt;)
    log_format &lt;span style="color: #666666"&gt;=&lt;/span&gt; Formatter(&lt;span style="color: #BA2121"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(name)s&lt;/span&gt;&lt;span style="color: #BA2121"&gt; &lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(asctime)s&lt;/span&gt;&lt;span style="color: #BA2121"&gt; &lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(levelname)s&lt;/span&gt;&lt;span style="color: #BA2121"&gt; : &lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(message)s&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;&lt;/span&gt;)
    handler&lt;span style="color: #666666"&gt;.&lt;/span&gt;setFormatter(log_format)
    logger&lt;span style="color: #666666"&gt;.&lt;/span&gt;addHandler(handler)
    &lt;span style="color: #408080; font-style: italic"&gt;## set the root logging level&lt;/span&gt;
    logger&lt;span style="color: #666666"&gt;.&lt;/span&gt;setLevel(logging&lt;span style="color: #666666"&gt;.&lt;/span&gt;DEBUG)
    
    &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; i &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; &lt;span style="color: #008000"&gt;range&lt;/span&gt;(&lt;span style="color: #666666"&gt;11000&lt;/span&gt;):
        &lt;span style="color: #408080; font-style: italic"&gt;## write test logging&lt;/span&gt;
        logger&lt;span style="color: #666666"&gt;.&lt;/span&gt;debug(&lt;span style="color: #BA2121"&gt;&amp;#39;debug&amp;#39;&lt;/span&gt;)
        logger&lt;span style="color: #666666"&gt;.&lt;/span&gt;info(&lt;span style="color: #BA2121"&gt;&amp;#39;info&amp;#39;&lt;/span&gt;)
        logger&lt;span style="color: #666666"&gt;.&lt;/span&gt;warning(&lt;span style="color: #BA2121"&gt;&amp;#39;warning&amp;#39;&lt;/span&gt;)
        logger&lt;span style="color: #666666"&gt;.&lt;/span&gt;critical(&lt;span style="color: #BA2121"&gt;&amp;#39;critical&amp;#39;&lt;/span&gt;)
        logger&lt;span style="color: #666666"&gt;.&lt;/span&gt;error(&lt;span style="color: #BA2121"&gt;&amp;#39;error&amp;#39;&lt;/span&gt;)
        logger&lt;span style="color: #666666"&gt;.&lt;/span&gt;fatal(&lt;span style="color: #BA2121"&gt;&amp;#39;fatal&amp;#39;&lt;/span&gt;)
        
        &lt;span style="color: #008000; font-weight: bold"&gt;try&lt;/span&gt;:
            &lt;span style="color: #008000; font-weight: bold"&gt;raise&lt;/span&gt; &lt;span style="color: #D2413A; font-weight: bold"&gt;TypeError&lt;/span&gt;, &lt;span style="color: #BA2121"&gt;&amp;#39;Demo error&amp;#39;&lt;/span&gt;
        &lt;span style="color: #008000; font-weight: bold"&gt;except&lt;/span&gt; &lt;span style="color: #D2413A; font-weight: bold"&gt;TypeError&lt;/span&gt;:
            logger&lt;span style="color: #666666"&gt;.&lt;/span&gt;exception(&lt;span style="color: #BA2121"&gt;&amp;#39;exception&amp;#39;&lt;/span&gt;)

        logger&lt;span style="color: #666666"&gt;.&lt;/span&gt;info(&lt;span style="color: #BA2121"&gt;&amp;#39;next round &amp;#39;&lt;/span&gt; &lt;span style="color: #666666"&gt;+&lt;/span&gt; &lt;span style="color: #008000"&gt;str&lt;/span&gt;(i))

&lt;span style="color: #008000; font-weight: bold"&gt;finally&lt;/span&gt;: &lt;span style="color: #408080; font-style: italic"&gt;## close logger properly&lt;/span&gt;
    logger&lt;span style="color: #666666"&gt;.&lt;/span&gt;removeHandler(handler)
    handler&lt;span style="color: #666666"&gt;.&lt;/span&gt;close()
&lt;/pre&gt;&lt;p&gt;If you've still have some questions, shoot and I'll try to answer them.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-7307172743522068404?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/7307172743522068404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/05/python-toolbox-1-logging.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/7307172743522068404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/7307172743522068404'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/05/python-toolbox-1-logging.html' title='Python Toolbox 1 : Logging'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-6130509911355602478</id><published>2009-04-30T07:38:00.006+02:00</published><updated>2009-11-18T11:38:02.058+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='csv'/><category scheme='http://www.blogger.com/atom/ns#' term='featureclass'/><category scheme='http://www.blogger.com/atom/ns#' term='geoprocessing'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><title type='text'>Table to csv</title><content type='html'>On the ESRI support forum someone asked how to convert an attribute table to a csv file. This can easily be done with a Python script.

First we import arcgisscripting and the &lt;a href="http://gissolved.blogspot.com/2009/04/using-for-loops-for-cursors.html"&gt;CursorIterator&lt;/a&gt; and initialize the geoprocessing object.
&lt;pre&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;arcgisscripting&lt;/span&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;string&lt;/span&gt;
&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;from&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;cursoriterator&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;import&lt;/span&gt; CursorIterator

gp &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; arcgisscripting&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;create()&lt;/pre&gt;The next step is to initialize the different variables for this script. The workspace is the path to the directory, file geodatabase, personal geodatabase, sde,... where the script can find the table or feature class that you want to convert. The table is the name of the table or feature class you want to export. The outputpath is the path to file where you want your export to be written to. Be aware that the output directory should exist. If the file doesn't exist it will be created otherwise it will be overwritten. The csvseparator is the column separator for the output file. It could be anything you want. If you want to use tabs you should set this variable to '\t'. The last variable is ignorefields. If a field name in the table or featureclass  is equal to a string in this list then this field won't be exported. This can be used for excluding the shape field, the objectid field or other fields you don't want to appear in the output file.
&lt;pre&gt;gp&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;workspace &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;r''&lt;/span&gt; &lt;span style="color: rgb(64, 128, 128); font-style: italic;"&gt;## workspace of the table or feature class&lt;/span&gt;
table &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;''&lt;/span&gt; &lt;span style="color: rgb(64, 128, 128); font-style: italic;"&gt;## table or feature class from wich the attributes should be exported&lt;/span&gt;
outputpath &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;r''&lt;/span&gt; &lt;span style="color: rgb(64, 128, 128); font-style: italic;"&gt;## path to the file where the output should be written to&lt;/span&gt;
csvseparator &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;','&lt;/span&gt; &lt;span style="color: rgb(64, 128, 128); font-style: italic;"&gt;## column separator field&lt;/span&gt;
ignorefields &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; [] &lt;span style="color: rgb(64, 128, 128); font-style: italic;"&gt;##list with fields to ignore&lt;/span&gt;&lt;/pre&gt;Then we define a function wich purpose is to create a list of fieldnames that are to be exported to the output file. This is done by iterating over the fields cursor that can be accessed by the gp function listfields. The fields that are in the ignorefields list won't be returned.
&lt;pre&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;get_fieldnames&lt;/span&gt;(fields, ignorefields&lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt;[]):
   ignorefieldsupper &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;map&lt;/span&gt;(string&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;upper, ignorefields)
   fields &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; CursorIterator(fields)
   fields_output &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; []
   &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;for&lt;/span&gt; field &lt;span style="color: rgb(170, 34, 255); font-weight: bold;"&gt;in&lt;/span&gt; fields:
       &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: rgb(170, 34, 255); font-weight: bold;"&gt;not&lt;/span&gt; field&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;name&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;upper() &lt;span style="color: rgb(170, 34, 255); font-weight: bold;"&gt;in&lt;/span&gt; ignorefieldsupper:
           fields_output&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;append(field&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;name)
   &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;return&lt;/span&gt; fields_output


fields &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; gp&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;listfields(table)
fieldnames &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; get_fieldnames(fields)&lt;/pre&gt;Now we are going to iterate over the rows in the table or featureclass and create a list with a string representation of each row. For each field we add the value of a  field to a list. Then we concactenate this values with the chosen separator and add this to the output list.
&lt;pre&gt;rows &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; gp&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;searchcursor(table)
rows &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; CursorIterator(rows)

output &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; []
output&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;append(csvseparator&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;join(fieldnames))
&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;for&lt;/span&gt; row &lt;span style="color: rgb(170, 34, 255); font-weight: bold;"&gt;in&lt;/span&gt; rows:
   outputrow &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; []
   &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;for&lt;/span&gt; fieldname &lt;span style="color: rgb(170, 34, 255); font-weight: bold;"&gt;in&lt;/span&gt; fieldnames:
       outputrow&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;append(&lt;span style="color: rgb(0, 128, 0);"&gt;str&lt;/span&gt;(row&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;getvalue(fieldname)))

   outputrow &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; csvseparator&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;join(outputrow)
   output&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;append(outputrow)&lt;/pre&gt;
Finally we write the outputlist to the defined outputpath.
&lt;pre&gt;f &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;open&lt;/span&gt;(outputpath, &lt;span style="color: rgb(186, 33, 33);"&gt;'w'&lt;/span&gt;)
f&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;write(&lt;span style="color: rgb(186, 33, 33);"&gt;'&lt;/span&gt;&lt;span style="color: rgb(187, 102, 34); font-weight: bold;"&gt;\n&lt;/span&gt;&lt;span style="color: rgb(186, 33, 33);"&gt;'&lt;/span&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;join(output))
f&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;close()&lt;/pre&gt;&lt;p&gt;The full code can be found on the &lt;a href="http://arcscripts.esri.com/details.asp?dbid=16257"&gt;arcscripts site&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-6130509911355602478?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/6130509911355602478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/04/table-to-csv.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/6130509911355602478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/6130509911355602478'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/04/table-to-csv.html' title='Table to csv'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-8817238114951896858</id><published>2009-04-20T21:58:00.035+02:00</published><updated>2009-06-24T15:20:45.794+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='geoprocessing'/><category scheme='http://www.blogger.com/atom/ns#' term='projections'/><category scheme='http://www.blogger.com/atom/ns#' term='transformations'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><title type='text'>Projections and transformation</title><content type='html'>On his blog Richie Carmichael (&lt;a href="http://mrrichie.spaces.live.com/Blog/cns!DD16C3F34F4D913E!806.entry"&gt;First edition&lt;/a&gt; &lt;a href="http://mrrichie.spaces.live.com/Blog/cns!DD16C3F34F4D913E!1807.entry"&gt;Second edition&lt;/a&gt;) showed how to use the ESRI Projection Engine from .NET.
In this article I am going to do the same with Python.
&lt;div&gt;My original problem was that I needed to convert some coordinates from ED50 Projected and ED50 geographic to ETRS89 projected for the UTM zone 31.
&lt;/div&gt;&lt;div&gt;
First of all we will need the pe.dll provided by ESRI which can be found in the BIN folder of the ArcGIS installation. Copy this dll in the same folder as your Python script.&lt;/div&gt;&lt;div&gt;
To use this dll from Python you can use the &lt;a href="http://python.net/crew/theller/ctypes"&gt;ctypes&lt;/a&gt; package. This extension started has a separate project in Python 2.3 but it has been fully incorporated in Python 2.5. So if you're still using Python 2.4 that shipped with ArcGIS 9.2 You will have to download and install ctypes. This extensions creates the possibility to easily use C dll's from within Python.&lt;/div&gt;
&lt;div&gt;Now lets start writing some code. First we import the ctypes package.&lt;/div&gt;

&lt;pre&gt;    &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;ctypes&lt;/span&gt;&lt;/pre&gt;

&lt;div&gt;The pe.dll is accessed in the following way.&lt;/div&gt;

&lt;pre&gt;    pe &lt;span style="color: #666666"&gt;=&lt;/span&gt; ctypes&lt;span style="color: #666666"&gt;.&lt;/span&gt;windll&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe&lt;/pre&gt;

&lt;div&gt;To transform from one projection to another we need to first create a projection object for the input spatial reference and the output spatial reference. Then we also need a geographic transformation object.
We do this by calling the appropriate factory functions which can be found in the &lt;a href="http://edndoc.esri.com/arcsde/9.2/api/capi/geometry/geometry.htm#PE"&gt;SDE C API&lt;/a&gt; documentation on &lt;a href="http://edndoc.esri.com"&gt;EDN&lt;/a&gt;.&lt;/div&gt;

&lt;pre&gt;    input_proj &lt;span style="color: #666666"&gt;=&lt;/span&gt; pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;&lt;a href="http://edndoc.esri.com/arcsde/9.2/api/capi/geometry/coordsys/pefactoryprojcs.htm"&gt;pe_factory_projcs&lt;/a&gt;(input_proj_code)
    transformation &lt;span style="color: #666666"&gt;=&lt;/span&gt; pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;&lt;a href="http://edndoc.esri.com/arcsde/9.2/api/capi/geometry/coordsys/pefactorygeogtran.htm"&gt;pe_factory_geogtran&lt;/a&gt;(transformation_code)
    output_proj &lt;span style="color: #666666"&gt;=&lt;/span&gt; pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;&lt;a href="http://edndoc.esri.com/arcsde/9.2/api/capi/geometry/coordsys/pefactoryprojcs.htm"&gt;pe_factory_projcs&lt;/a&gt;(output_proj_code)&lt;/pre&gt;
&lt;div&gt;    
To lookup the code of your projection you will need to take a look at the following sites&lt;a href="http://edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriGeometry/esriSRProjCSType.htm"&gt; page 1&lt;/a&gt; &lt;a href="http://edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriGeometry/esriSRProjCSType2.htm"&gt;page 2&lt;/a&gt; &lt;a href="http://edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriGeometry/esriSRProjCSType3.htm"&gt;page 3&lt;/a&gt; and &lt;a href="http://edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriGeometry/esriSRProjCSType4.htm"&gt;page 4&lt;/a&gt;. The code of your geographic transformation can be found on the this sites &lt;a href="http://edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriGeometry/esriSRGeoTransformationType.htm"&gt;page 1&lt;/a&gt; &lt;a href="http://edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriGeometry/esriSRGeoTransformationType.htm"&gt;page 2&lt;/a&gt; and &lt;a href="http://edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriGeometry/esriSRGeoTransformationType.htm"&gt;page 3&lt;/a&gt;.
&lt;/div&gt;
&lt;div&gt;To transform points with the projection engine we need to pass the points as a 2 dimensional array of points. In order to do this I created a small Python point class and methods to convert from a list of points to a 2 dimensional C array and back to a list of points. If you want more information about this I suggest you take a look at the ctypes documentation (&lt;a href="http://python.net/crew/theller/ctypes/tutorial.html"&gt;tutorial&lt;/a&gt; &lt;a href="http://python.net/crew/theller/ctypes/reference.html"&gt;reference&lt;/a&gt;) and also have a look at the needed datatypes for the pe functions.&lt;/div&gt;
&lt;pre&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Point&lt;/span&gt;:
        &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;__init__&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, x, y):
            &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;x &lt;span style="color: #666666"&gt;=&lt;/span&gt; x
            &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;y &lt;span style="color: #666666"&gt;=&lt;/span&gt; y
        &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;__str__&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;):
            &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;x : &amp;#39;&lt;/span&gt; &lt;span style="color: #666666"&gt;+&lt;/span&gt; &lt;span style="color: #008000"&gt;str&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;x) &lt;span style="color: #666666"&gt;+&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39; y : &amp;#39;&lt;/span&gt; &lt;span style="color: #666666"&gt;+&lt;/span&gt; &lt;span style="color: #008000"&gt;str&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;y)
    
    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;_ctypes_to_points&lt;/span&gt;(point_array):
        points &lt;span style="color: #666666"&gt;=&lt;/span&gt; []
        &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; point &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; point_array:
            point &lt;span style="color: #666666"&gt;=&lt;/span&gt; Point(point[&lt;span style="color: #666666"&gt;0&lt;/span&gt;], point[&lt;span style="color: #666666"&gt;1&lt;/span&gt;])
            points&lt;span style="color: #666666"&gt;.&lt;/span&gt;append(point)
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; points

    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;_points_to_ctypes&lt;/span&gt;(points):
        array_type &lt;span style="color: #666666"&gt;=&lt;/span&gt; ctypes&lt;span style="color: #666666"&gt;.&lt;/span&gt;ARRAY(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;point_type, &lt;span style="color: #008000"&gt;len&lt;/span&gt;(points))
        ctype_points &lt;span style="color: #666666"&gt;=&lt;/span&gt; []
        &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; point &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; points:
            ctype_point &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;point_type(point&lt;span style="color: #666666"&gt;.&lt;/span&gt;x, point&lt;span style="color: #666666"&gt;.&lt;/span&gt;y)
            ctype_points&lt;span style="color: #666666"&gt;.&lt;/span&gt;append(ctype_point)
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; array_type(&lt;span style="color: #666666"&gt;*&lt;/span&gt;ctype_points)
&lt;/pre&gt;
&lt;div&gt;Now we can create the function for doing the actual transformation from input projected reference system to the output projected reference system. As you can see we first need to convert the projected coordinates to geographic coordinates. Then transform these geographic coordinates with the give transformation. Finally we convert the geographic coordinates back to projected coordinates.&lt;/div&gt;

&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;transform&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, points):
    points_count &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;len&lt;/span&gt;(points)
    point_array &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;_points_to_ctypes(points)
    pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;&lt;a href="http://edndoc.esri.com/arcsde/9.2/api/capi/geometry/coordsys/peprojtogeog.htm"&gt;pe_proj_to_geog&lt;/a&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;input_proj, points_count, 
                       point_array)
    pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;&lt;a href="http://edndoc.esri.com/arcsde/9.2/api/capi/geometry/coordsys/pegeog1togeog2.htm"&gt;pe_geog1_to_geog2&lt;/a&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;transformation, points_count, 
                         point_array, &lt;span style="color: #008000"&gt;None&lt;/span&gt;)
    pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;&lt;a href="http://edndoc.esri.com/arcsde/9.2/api/capi/geometry/coordsys/pegeogtoproj.htm"&gt;pe_geog_to_proj&lt;/a&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;output_proj, points_count, 
                       point_array)
    &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;_ctypes_to_points(point_array)&lt;/pre&gt;

&lt;div&gt;The complete code looks like this. I've put the projection related code in a class and at the bottom I added some test code.&lt;/div&gt;

&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;ctypes&lt;/span&gt;

&lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Point&lt;/span&gt;:
    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;__init__&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, x, y):
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;x &lt;span style="color: #666666"&gt;=&lt;/span&gt; x
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;y &lt;span style="color: #666666"&gt;=&lt;/span&gt; y
    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;__str__&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;):
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;x : &amp;#39;&lt;/span&gt; &lt;span style="color: #666666"&gt;+&lt;/span&gt; &lt;span style="color: #008000"&gt;str&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;x) &lt;span style="color: #666666"&gt;+&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39; y : &amp;#39;&lt;/span&gt; &lt;span style="color: #666666"&gt;+&lt;/span&gt; &lt;span style="color: #008000"&gt;str&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;y)

&lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Proj&lt;/span&gt;:
    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;__init__&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, input_proj_code, transformation_code, 
        output_proj_code):
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe &lt;span style="color: #666666"&gt;=&lt;/span&gt; ctypes&lt;span style="color: #666666"&gt;.&lt;/span&gt;windll&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;input_proj &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe_factory_projcs(input_proj_code)
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;output_proj &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe_factory_projcs(output_proj_code)
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;transformation &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe_factory_geogtran(transformation_code)
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;point_type &lt;span style="color: #666666"&gt;=&lt;/span&gt; ctypes&lt;span style="color: #666666"&gt;.&lt;/span&gt;c_double &lt;span style="color: #666666"&gt;*&lt;/span&gt; &lt;span style="color: #666666"&gt;2&lt;/span&gt;

    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;_points_to_ctypes&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, points):
        array_type &lt;span style="color: #666666"&gt;=&lt;/span&gt; ctypes&lt;span style="color: #666666"&gt;.&lt;/span&gt;ARRAY(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;point_type, &lt;span style="color: #008000"&gt;len&lt;/span&gt;(points))
        ctype_points &lt;span style="color: #666666"&gt;=&lt;/span&gt; []
        &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; point &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; points:
            ctype_point &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;point_type(point&lt;span style="color: #666666"&gt;.&lt;/span&gt;x, point&lt;span style="color: #666666"&gt;.&lt;/span&gt;y)
            ctype_points&lt;span style="color: #666666"&gt;.&lt;/span&gt;append(ctype_point)
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; array_type(&lt;span style="color: #666666"&gt;*&lt;/span&gt;ctype_points)

    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;_ctypes_to_points&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, point_array):
        points &lt;span style="color: #666666"&gt;=&lt;/span&gt; []
        &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; point &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; point_array:
            point &lt;span style="color: #666666"&gt;=&lt;/span&gt; Point(point[&lt;span style="color: #666666"&gt;0&lt;/span&gt;], point[&lt;span style="color: #666666"&gt;1&lt;/span&gt;])
            points&lt;span style="color: #666666"&gt;.&lt;/span&gt;append(point)
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; points

    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;transform&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, points):
        points_count &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;len&lt;/span&gt;(points)
        point_array &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;_points_to_ctypes(points)
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe_proj_to_geog(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;input_proj, points_count, 
                                point_array)
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe_geog1_to_geog2(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;transformation, 
                                  points_count, point_array, &lt;span style="color: #008000"&gt;None&lt;/span&gt;)
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe&lt;span style="color: #666666"&gt;.&lt;/span&gt;pe_geog_to_proj(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;output_proj, points_count, 
                                point_array)
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;_ctypes_to_points(point_array)

&lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; __name__ &lt;span style="color: #666666"&gt;==&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:
    ed50_proj_code &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #666666"&gt;23031&lt;/span&gt;
    ed50_etrs89_transformation &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #666666"&gt;1650&lt;/span&gt;
    etrs89_proj_code &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #666666"&gt;25831&lt;/span&gt;
    proj &lt;span style="color: #666666"&gt;=&lt;/span&gt; Proj(ed50_proj_code, ed50_etrs89_transformation, etrs89_proj_code)
    points &lt;span style="color: #666666"&gt;=&lt;/span&gt; [Point(&lt;span style="color: #666666"&gt;585635&lt;/span&gt;, &lt;span style="color: #666666"&gt;5690770&lt;/span&gt;), Point(&lt;span style="color: #666666"&gt;585654&lt;/span&gt;, &lt;span style="color: #666666"&gt;5690110&lt;/span&gt;)]
    points &lt;span style="color: #666666"&gt;=&lt;/span&gt; proj&lt;span style="color: #666666"&gt;.&lt;/span&gt;transform(points)
    &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; point &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; points:
        &lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; point
&lt;/pre&gt;

&lt;p&gt;I hope you liked this post. Have fun.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4113082053753185517-8817238114951896858?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/8817238114951896858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/04/projections-and-transformations-with.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/8817238114951896858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/8817238114951896858'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/04/projections-and-transformations-with.html' title='Projections and transformation'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4113082053753185517.post-7785188067571575010</id><published>2009-04-16T20:36:00.020+02:00</published><updated>2009-09-08T21:51:50.073+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='geoprocessing'/><category scheme='http://www.blogger.com/atom/ns#' term='Cursors'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='ArcGIS'/><title type='text'>Using for-loops for cursors</title><content type='html'>When writing Python scripts to automate ArcGIS you often encounter all kind of cursors. Cursors are returned mostly returned by the gp object when calling functions like listtables, listfeatureclasses, listrasters, listfields, searchcursor, updatecursor, ...

Usually cursors are used in the following way :
&lt;pre&gt;    &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;arcgisscripting&lt;/span&gt;
    gp &lt;span style="color: #666666"&gt;=&lt;/span&gt; arcgisscripting&lt;span style="color: #666666"&gt;.&lt;/span&gt;create()
    inputFC &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;r&amp;#39;path to a feature class&amp;#39;&lt;/span&gt;

    inRows &lt;span style="color: #666666"&gt;=&lt;/span&gt; gp&lt;span style="color: #666666"&gt;.&lt;/span&gt;searchcursor(inputFC)
    inRow &lt;span style="color: #666666"&gt;=&lt;/span&gt; inRows&lt;span style="color: #666666"&gt;.&lt;/span&gt;next()
    &lt;span style="color: #008000; font-weight: bold"&gt;while&lt;/span&gt; inRow:
        &lt;span style="color: #666666"&gt;...&lt;/span&gt;do something
    inRow &lt;span style="color: #666666"&gt;=&lt;/span&gt; inRows&lt;span style="color: #666666"&gt;.&lt;/span&gt;next()&lt;/pre&gt;This is quiet a verbose way to loop through the rows. Fortunately there is a way to turn the cursor into an iterator that can be used in a for loop. This can be done by adding the following short class to your code.
&lt;pre&gt;    &lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;CursorIterator&lt;/span&gt;(&lt;span style="color: #008000"&gt;object&lt;/span&gt;):
        &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;__init__&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, cursor):
            &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;cursor &lt;span style="color: #666666"&gt;=&lt;/span&gt; cursor
            &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;cursor&lt;span style="color: #666666"&gt;.&lt;/span&gt;reset()
        &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;next&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;):
            n &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;cursor&lt;span style="color: #666666"&gt;.&lt;/span&gt;next()
            &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; n &lt;span style="color: #AA22FF; font-weight: bold"&gt;is&lt;/span&gt; &lt;span style="color: #008000"&gt;None&lt;/span&gt;:
                &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;cursor&lt;span style="color: #666666"&gt;.&lt;/span&gt;reset()
                &lt;span style="color: #008000; font-weight: bold"&gt;raise&lt;/span&gt; &lt;span style="color: #D2413A; font-weight: bold"&gt;StopIteration&lt;/span&gt;
            &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; n
        &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;__iter__&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;):
            &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;/pre&gt;As it is nicely explained in &lt;a href="http://www.amazon.com/gp/product/184719494X?ie=UTF8&amp;tag=giso0d-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=184719494X"&gt;Expert Python Programming by Tarek Ziadé&lt;/a&gt; we just created an iterator class. This is a container class with two methods namely next and __iter__.
Usage of the CursorIterator class looks like this.
&lt;pre&gt;    rows &lt;span style="color: #666666"&gt;=&lt;/span&gt; gp&lt;span style="color: #666666"&gt;.&lt;/span&gt;searchcursor(inputFC)
    rowsIterator &lt;span style="color: #666666"&gt;=&lt;/span&gt; CursorIterator(rows)
    &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; row &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; rowsIterator:
        &lt;span style="color: #666666"&gt;...&lt;/span&gt; do something&lt;/pre&gt;or shorter
&lt;pre&gt;    &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; row &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; CursorIterator(gp&lt;span style="color: #666666"&gt;.&lt;/span&gt;searchcursor(inputFC)):
        &lt;span style="color: #666666"&gt;...&lt;/span&gt; do something&lt;/pre&gt;I hope you enjoyed my first post. Have fun.&lt;br&gt;&lt;br&gt;

&lt;i&gt;Update : &lt;/i&gt;As Jason Schreider points out in his comment the CursorIterator class can be easily replaced by the following :

&lt;pre&gt;    rows &lt;span style="color: #666666"&gt;=&lt;/span&gt; gp&lt;span style="color: #666666"&gt;.&lt;/span&gt;searchcursor(inputFC)
    &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; row &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; &lt;span style="color: #008000"&gt;iter&lt;/span&gt;(rows&lt;span style="color: #666666"&gt;.&lt;/span&gt;next, &lt;span style="color: #008000"&gt;None&lt;/span&gt;):
        &lt;span style="color: #666666"&gt;...&lt;/span&gt; do something
&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/4113082053753185517-7785188067571575010?l=gissolved.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gissolved.blogspot.com/feeds/7785188067571575010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gissolved.blogspot.com/2009/04/using-for-loops-for-cursors.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/7785188067571575010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4113082053753185517/posts/default/7785188067571575010'/><link rel='alternate' type='text/html' href='http://gissolved.blogspot.com/2009/04/using-for-loops-for-cursors.html' title='Using for-loops for cursors'/><author><name>Samuel</name><uri>http://www.blogger.com/profile/00902576471871535529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_ssVmrLrXiIo/SeeJDbpbucI/AAAAAAAAADM/1t_zNJBFF4E/S220/Suisse2008+394+kleiner.jpg'/></author><thr:total>6</thr:total></entry></feed>
