Yet Another GIS Blog
GIS, Geography, Programming, and Neogeography

ASP.NET MVC

Monday, 7 June 2010 11:27 by boxshapedwo
I started to look at creating a plugin for a web-based application as related to some potential project work.  It once again through me into a world I never heard of and knew nothing about.  Do you know what MVC is?  No, then we are on the same level.  MVC stands for Model View Controller and it is a way to build web applications.  If you'd like a quick, but good, introduction into MVC specifically for ASP.NET, then I recommend this video.  Not for the faint of heart, or those not familiar with a little web programming.
Categories:   Programming
Actions:   E-mail | del.icio.us | Permalink | Comments (7) | Comment RSSRSS comment feed

Why every GISer should learn Python

Monday, 8 March 2010 12:16 by boxshapedwo

What the hell is Python?  You may or may not be asking.  Well, it is a "high-level programming language" according to wikipedia.  Not so long ago, to me it was just some other thing that ESRI was installing on my machine in an already excruciatingly long process.  Then I actually tried to use it for some geoprocessing in ArcToolbox, and actually have found it quite a valuable skill to have.  I do find the syntax to be cumbersome to use, but my programming started with Visual Basic, so it is much more concise than VB.  Anyway, here are my reasons.

  1.  ESRI ArcGIS is using it for a lot of their ArcTools.  They seem to be supporting it at least for the next few versions, unlike VBA. (Keep reading as I discuss nonESRI reasons further down)
  2. You can do a lot with Python outside of the ESRI environment too.
  3. You don't need ArcGIS in order to do geoprocessing with it.
  4. You get to use cool libraries like matplotlib to create your charts instead of Excel.
  5. It is used in a lot of web programming, like MapServer.

Why am I recommending getting started with Python, when I invested time and effort in creating VBA tutorials (as yet unfinished).  VBA is still useful as the syntax is similar to VB.NET.  But VB.NET has a bigger learning curve.  Python will be supported for a while, and you can get started with it while staying within the ArcGIS environment.

How should I get started then?  Assuming you are using ArcGIS 9.3.  You should install PythonWin as well as that came on the installation disc separately.  If you don't have access to that disc, or admin privledges, I'll describe this using something else.  Pick a task that you use ArcToolbox for often.  Let's use Clipping as an example that should be available to anyone with any license.  Add two generic polygon layers to work with.  Add ArcToolbox if you don't have it open already, right click and create new toolbox.  Right click on your new toolbox and add a new model. Drag the Analysis Tools -> Extract -> clip tool to the model and you should see a square and oval.  Double click on Clip and fill out the form as you normally would.  Click ok and you should see two blue ovals added.  Go to Model --> Export --> To Script --> Python.  Call it what you want.  Discard the model.  Go to where you saved the file with a .py extension.  Right-click on it and select edit with IDLE.  Two windows open.  A note here.  Version 9.3 of Arc uses version 2.5 ofPython, and only 2.5.  Version9.2 uses only 2.4.  You can't use a different version of Python with a different version of Arc.  Python will install multiple versions rather than overwrite existing ones.  It is possible that you still have 2.4 from arcgis 9.2 still installed.  Or another program might have put 2.6 on.  Look at the window opened that is called Python Shell and it will tell you what version.  If it opened with the wrong version  Go to Start -->  All programs -->  Python 2.5 --> IDLE.  When that opens got to File--> Open and open up the Python file that way.  It is really important that you get the version right, or else your tool will just crash.  Now you have your first bit of code.  I suggest you go through it line by line to understand what is happening:

 # ---------------------------------------------------------------------------
# clip_example.py
# Created on: Tue Mar 09 2010 12:06:20 PM
#   (generated by ArcGIS/ModelBuilder)
# ---------------------------------------------------------------------------

# Import system modules
import sys, string, os, arcgisscripting

# Create the Geoprocessor object
gp = arcgisscripting.create()

# Load required toolboxes...
gp.AddToolbox("C:/Program Files/ArcGIS/ArcToolbox/Toolboxes/Analysis Tools.tbx")


# Local variables...
statesp020_Clip_shp = "C:\\WorkSpace\\FlowMap\\statesp020_Clip.shp"
statesp020 = "statesp020"
statesp020_Project = "statesp020_Project"

# Process: Clip...
gp.Clip_analysis(statesp020, statesp020_Project, statesp020_Clip_shp, "")

The # is a comment and it is not processed by the compiler.  Import loads different libraries.  ESRI has a special one called arcgisscripting that you use to create a geoprocessing object (gp).  This gives you access to all the ArcTools.  Paths to files use either the forward slash / or double backslash \\ but not a single backslash \.  This is because strings use this slash as a special character and it would confuse python if you did this.  If you change the statesp020 and statesp020_Project (your variable names will be different) to equal their actual path to the file, then, in theory you should just be able to go to Run  --> Run Module and it will perform the operation.

Your next task:  Figure out how to loop through all the feature classes in a folder and clip them.  You already have one important line of code gp.Clip_analysis.  You just need to do the looping bit.  Follow the isntructions on this page for more information.  As always, the ESRI help is quite good and extensive (which does make it difficult to find things).

 

What if I don't use ESRI, and I use MapInfo or Manifold  you are now asking.  Well I'm sorry for you.  Just kidding, those programs have their merits too, no really they do.  :) [Thanks to Brian for pointing out that Manifold does have Python scripting.  I should also note there is Python scripting in QGIS].  Unfortunately, you cant use python with those programs, but there is something called GDAL that is an open source geoprocessing library (and more) that you can use instead.  Here is a lesson on installing  GDAL for python.  And Chris Garrard has been generous in posting his course presentations that show step by step how to work with python and GDAL.  I recommend even for ESRI users giving that a once over.

I hope this has convinced you and given you a start on using Python with GIS.  There are plenty of tutorials that will give you more of the basics of Python Syntax, but I find it better to start with the GIS stuff, which I'm familiar with, and then look up the Python bits I'm less familiar with.

Tags:  
Categories:   Programming
Actions:   E-mail | del.icio.us | Permalink | Comments (36) | Comment RSSRSS comment feed

Movie Links Visualizer

Thursday, 7 January 2010 15:57 by boxshapedwo

After spending the last month in java land in a perpetual state of frustration, I needed a break, and went back to the blissful world of Flex.  I even toyed around with JavaFX.  The only reason I can see that taking off, is because of the multitude of open source Java libraries available.  Anyway, this isn't about Java.

 I needed to have a confidence booster and have a little fun, so I decided to take on a little project.  I am a big movie fan, and sometimes I like to find out if an actor (I'm using actor as a gender neutral for both men and women) as acted any movies with another actor.  There wasn't a real easy way to do this on IMDB so I thought why not create my own.  Unfortunately, IMDB does not have an API to pull movie and actor names from, but I did find the free movie database.  It's free for my purposes at least, since this was just a pet project.  To display the links and movies, I used the FLARE library's force directed layout.  I suppose one of the other layouts would also work.  Because of the ease of use of Flare and FLEX I was up and running in a day and half, and most of that half was tweaking to get the different things to work right.  I know the user interface is a bit crappy, but I was mostly interested in the back end and having something work.

Currently under "beta", and perhaps perpetually so.  Here are some quick instructions.

You can search for just one actor to see their movies by just entering the name in the first box and clicking find.  You can search for both actors and find their links and all their movies, or check the checkbox to just see the links.  Double click on the box to get more info about the movie, and double click on the actor to get more info about the actor.  Hover over the items to find the name of the movie or actor.  You can hover over the link to find out what job they had (actor, producer, etc...), but this doesn't list all the jobs, hence why this is still under beta.  Pause and Resume buttons will pause the layout from moving the whole time.

The app is available here, and the source code is available here.  You will need your own API key though.

Tags:   ,
Categories:   Programming | Visualizations
Actions:   E-mail | del.icio.us | Permalink | Comments (25) | Comment RSSRSS comment feed

Set Row Height in MS Publisher

Monday, 9 November 2009 16:54 by boxshapedwo

You might need to know how to do this one day in your life.  I never thought I would.

 There is no easy way to set the row height of a table in MS Publisher.  So it is quite easy to have your rows be set unevenly.  I never found a distribute function either.

 One work around is to set the row height using VBA:

Private Sub changeRows()
  
    Dim i As Integer
    i = 1
    Dim RowHeight As Double
    RowHeight = 15.5 'ThisDocument.Selection.ShapeRange(1).Table.Rows(i).Height
   
    For i = 1 To ThisDocument.Selection.ShapeRange(1).Table.Rows.Count Step 1
        ThisDocument.Selection.ShapeRange(1).Table.Rows(i).Height = RowHeight
    Next
   
End Sub

 

This code only works if you have your row heights selected.  The idea was taken from here, but modified to loop through the rows.

Categories:   Programming
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

SQLite Flare and AIR

Friday, 10 July 2009 18:29 by boxshapedwo

Ok, so displaying data from your database in a table is rather boring don't you think?  I'm working with time series data in this project, and so I'm really interested in being able to quickly display a trend.  This will be particularly useful since data becomes updated once every quarter, so fairly frequently.  I don't have a professional license of Flex Builder which opens up the very simple to use charting features (played around with a demo a while back), so I've had to look for alternatives.  There are two that I came across:  Flare, and Axiis.  The first problem I ran into with both is that my data didn't come in a 'web' format, but as an array from the SQLite question.  The lack of tutorials for both project made it difficult to find out an answer to this question, so I had to play around with both.  The short answer is - yes you can take the SQLResult.Data and apply it directly to both projects.  I ended up using Flare which was actually much much easier to use (for me) compared to Axiis.  I don't find Axiis very intuitive to use.  Which I was really disapointed by, not just because I couldn't figure it out, but because it is based on the excellent Degrafa project.  Which is how it gets such nice looking charts.  It was easy enough, but it took some playing around with, to get the data array to be used by Axiis.  Instead of playing with the dataset class, just set the DataProvider to the array directly.  Here is a tutorial that was useful.  And I was even able to get it to display some bar graphs, which all the tutorials seem to teach.  When I started to try and work with the LineSeriesGroup, I couldn't ever get a series of lines to display.  I found this one really difficult to understand, because I think of data statistically where there is a x and y axis and couldn't grasp how to set this up.  If anyone wants to explain it to me, I would still like to give Axiis a go.

Like I said, I ended up using Flare which I found much easier to work with.  Instead of the mxml base, Flare uses sprites, which is more Flash less Flex, but still useable in Flex.  So after querying and getting my data array, mentioned in a previous post, this is where I start:

A bunch of Imports: 

    import flare.vis.data.Data;
    import flare.vis.data.EdgeSprite;
    import flare.vis.data.NodeSprite;
    import flare.vis.operator.encoder.ColorEncoder;
    import flare.vis.operator.encoder.PropertyEncoder;
    import flare.vis.operator.label.Labeler;
    import flare.vis.operator.layout.AxisLayout;
    import flare.vis.Visualization;
    import flare.scale.ScaleType;
    import flare.vis.controls.AnchorControl;
    import flare.vis.controls.HoverControl;
    import flare.vis.controls.SelectionControl;
    import flare.vis.data.DataSprite;
    import flare.vis.events.SelectionEvent;
    import flare.vis.controls.TooltipControl;
    import flare.vis.events.TooltipEvent;
    import flare.display.TextSprite;
    import flare.util.Strings;
   
    import flash.filters.GlowFilter;
    import flash.display.Sprite;
    import flash.geom.Rectangle;

 

A class that extends Sprite:

 

    public class LineChartExperiment extends Sprite
    {

 

Global variables and the constructor are commented.  The loaddata() function is the key step that takes our data array and puts it in the data format that is used by Flare.  Flare uses a graph data model.  This means everything is stored as a node and an edge.  You see graphs all the time, not line graphs, but real graphs.  Search wikipedia if you want a more in-depth explanation of graph theory.  This makes a lot of sense given what the library is capable of.  If you look at the Flare Demo Page, and select the layout and then force option, this is a visual representation of a graph that is being organized by a force directed method.  In other words it uses physics to place the circles.  The circles are the nodes, and the lines connecting the nodes are the edges.

When you look at the loaddata function, we are actually taking each object in the array and creating a node from this.  Once we exit the loop we can use Flare's createEdges function to generate the edges for us.  It does this based on two inputs, a sort by input and group by input.  So in this example I sort by time, and group by the name.  Another way to think of this is sort is your x axis and group is the series.

 

        //this is the string that will be used for a tooltip that pops up when hovering
        private static const _tipText:String =
            "Venue: {0}<br/>" +
            "Value: {1}<br/>" +
            "Date: {2}";
        //visualization is the component that handles everyting       
        private var vis:Visualization;
        //this holds our data
        private var dataArray:Array;
        //this is passed in when the sprite is created.  I add the sprite to a canvas
        private var _width:Number;
        private var _height:Number;
       
        public function LineChartExperiment(da:Array, width:Number, height:Number)
        {
           
            super();
            this.dataArray = da;
            this._width = width;
            this._height = height;
            //call the load data function
            loadData();
        }
       
        private function loadData():void
        {
           
            var data:Data = new Data();
            for each (var o:Object in dataArray) {
                data.addNode(o);
                //this also works but uses more lines of code
                //data.addNode({
                        //Value: o.Value,
                        //Date: o.Date,
                        //Name: o.Name
                    //});
            }
            //Important Step do not miss this one
            data.createEdges("data.Date", "data.Name");
            createVisualization(data);
        }

 

 

Once the data is loaded we pass it to the createVisualization function.  A lot of this was pulled from the source code of the examples that download with the swc file.

 

        private function createVisualization(data:Data):void
        {

            //This sets up the location and size of the Visualization

            vis = new Visualization(data);
            vis.bounds = new Rectangle(0, 0, _width - 25, _height - 25);
            vis.x = 50;
            vis.y = 0;
            //and is added to the sprite as a child
            addChild(vis);
           

            //I need to look ino these in more depth, but basically they are used to set up the chart, and the colors

           //Date is the xAxis and Value is the y Axis  Note how you are creating symbols for the nodes, and edges.

           //This allows the edges to show as a line in the chart.  You could skip the nodes and just show the lines

            vis.operators.add(new AxisLayout("data.Date", "data.Value"));
            vis.operators.add(new ColorEncoder("data.Name", Data.EDGES, "lineColor", ScaleType.CATEGORIES));
            vis.operators.add(new ColorEncoder("data.Name", Data.NODES, "fillColor", ScaleType.CATEGORIES));
            vis.operators.add(new PropertyEncoder( { lineAlpha: 0, alpha:0.5, buttonMode: false, scaleX: 1, scaleY:1, size:0.5 } ));
            vis.operators.add(new PropertyEncoder( { lineWidth:2 }, Data.EDGES));
           
            vis.data.nodes.setProperties( { fillColor:0, lineWidth:2 } );
           
            // add mouse-over highlight
            vis.controls.add(new HoverControl(NodeSprite, 0,
                // highlight on mouse over
                function(e:SelectionEvent):void {
                    e.item.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
                },
                // remove higlight on mouse out
                function(e:SelectionEvent):void {
                        e.item.filters = null
                }
            ));
           
            // add tooltip showing data values
            vis.controls.add(new TooltipControl(DataSprite, null,
                function(e:TooltipEvent):void {
                    var data:Object = e.node.data;
                    TextSprite(e.tooltip).htmlText = Strings.format(
                        _tipText, data.Name, data.Value, data.Date);
                }
            ));
           
            vis.update();
        }
       

        //I added an eventlistener to the canvas to when it was resized, it then called this function

        //Which resizes the visualization to the canvas' new size   

        public function resize(w:Number, h:Number):void
        {
            var rect:Rectangle = new Rectangle(0, 0, w - 25, h - 25);
            _width = w;
            _height = h;
            vis.bounds = rect.clone();
            vis.update();
        }

 

 

Because we are working with a sprite, when we add this to our Main.mxml, we should first add it to a UIComponent, then add it to the Canvas or else you get an error.  Can is a canvas that is created in another portion of the code.

 

                exp = new LineChartExperiment(rev.dataArray, can.width, can.height);
                exp.width = can.width;
                exp.height = can.height;
                var ui:UIComponent = new UIComponent();
                can.addChild(ui);
                ui.addChild(exp);

 

 

Hopefully that is helpful to those who are starting out with flare too.