mon, 01-mar-2010, 18:24

Who owns it?

Updated web app
http://swingleydev.com/gis/loc.html
(for GPS enabled phones within the Fairbanks North Star Borough)

Now that my two year web hosting contract with BlueHost is coming up, I’ve decided to migrate over to Linode. It’s about twice as expensive, but you get your own Xen virtual machine to do with as you want. With BlueHost I wound up needing to compile a whole bunch of software packages (gnuplot, remind, spatialite, a variety of Python modules, etc.) just to get my site to work. And I couldn’t upgrade PostgreSQL, which left me unable to use PostGIS. With my Linode, I put the latest Ubuntu on it, and was able to install all the software I need.

As mentioned, PostGIS is one of the benefits of this. Instead of loading the Fairbanks North Star Borough tax parcel database into spatialite and using a CGI program to extract data, I’m able to query the same data in PostGIS directly from PHP. That means I can do all sorts of cool stuff with the data I’m extracting.

Here, I am using the Google Maps API to draw the property polygon and put a marker at the location from the iPhone’s GPS. You can see the result on the right, taken while eating lunch at the office. If you’ve got a GPS-enabled smart device and you’re in the Fairbanks North Star Borough, the link is http://swingleydev.com/gis/loc.html.

The code that drives the map is at the bottom of this post. The complicated query in the middle of it gets the outermost ring from the polygon, and dumps each vertex as a separate row. This section is in the middle of the Google Maps JavaScript that builds the overlay polygon. Note that this doesn’t handle the few properties in the database that have multiple polygons in their geometry, and it ignores the holes that might be present (if a small chunk out of the middle of a property was sold, for example). I expect these cases are pretty infrequent.

One enhancement would be to include a circular buffer around the point marker so you could get a sense of where the GPS accuracy places you on the map. This is complicated with Google because of the custom projection they’re using. I think it’s called “Google Mercator,” but spatialreference.org lists several projections that look like they might be compatible. I’ll have to give those projections a try to see if I can make a projected circular buffer that looks like a circle. It would also be nice to set the map extent to match the extent of the parcel you’re inside. I don’t know if that’s part of the Google Maps API or not.

Here’s the code:

<script type="text/javascript">
function initialize() {
  if (GBrowserIsCompatible()) {
      var map = new GMap2(document.getElementById("map_canvas"));
      var mapControl = new GMapTypeControl();
      map.addControl(mapControl);
      map.setCenter(new GLatLng(<?php echo $lat; ?>, <?php echo $lon; ?>), 14);
      var polygon = new GPolygon([
        <?php
            $query = "
SELECT
    ST_X(ST_PointN(ST_ExteriorRing(ST_GeometryN(wkb_geometry, 1)),
        generate_series(1, ST_NPoints(ST_ExteriorRing(ST_GeometryN(wkb_geometry, 1))))))
        AS x,
    ST_Y(ST_PointN(ST_ExteriorRing(ST_GeometryN(wkb_geometry, 1)),
        generate_series(1, ST_NPoints(ST_ExteriorRing(ST_GeometryN(wkb_geometry, 1))))))
        AS y
FROM tax_parcels
WHERE ST_Intersects(wkb_geometry, ST_SetSRID(ST_MakePoint($lon, $lat), 4326));";
            $result = pg_query($query);
            $num_rows = pg_num_rows($result);
            for ($i = 0; $i < $num_rows - 1; $i++) {
                $row = pg_fetch_row($result);
                list($vlon, $vlat) = $row;
                echo "new GLatLng($vlat, $vlon),";
            }
            $row = pg_fetch_row($result);
            list($vlon, $vlat) = $row;
            echo "new GLatLng($vlat, $vlon)";
            pg_free_result($result);
        ?>
      ], "#f33f00", 2, 1, "#ff0000", 0.2);
    map.addOverlay(polygon);
    var point = new GLatLng(<?php echo $lat; ?>, <?php echo $lon; ?>);
    map.addOverlay(new GMarker(point));
  }
}
</script>

tags: GIS  GPS  iPhone 
mon, 01-mar-2010, 17:16

Caslon, Tallys and Jenson

Tallys, Caslon, and Jenson

I took Friday off from work and brewed my first batch of beer in quite a long time. It’s a brown porter named Crazy Kittens Porter. As should be obvious, it’s named after our three crazy kittens Caslon, Tallys and Jenson, pictured on the right. This time around I developed the recipe using the BrewPal iPhone app, trusting all the measurements and temperatures to the app. We’ll see how well it does. My favorite part of the app is the “style” tab, which shows you what styles your recipe conforms to and to what degree.

Normally I do everything out in the red cabin, but I had the wood stove cranking so I heated the strike and spare water on the wood stove and drained the mash in the kitchen (shown below). It was nice to be able to do that stuff in the house and to avoid burning fossil fuels for the wort production. As usual, I boiled and chilled the wort outside and set the fermenter in the old fridge out in the red cabin. It’s bubbling away now.

I plan to brew another batch of Devil Dog on top of the yeast cake from this batch. This is an excellent way to save some money on yeast, and the second batch normally gets a very explosive start from the massive population of healthy yeast.

Sparging with kittens

Sparging with kittens

sun, 21-feb-2010, 18:45

Back 40

Back lot

Today I went for a walk on the Creek with Nika and Piper and it occurred to me that the iPhone ought to be able to tell me not only where I am (which it does quite well with the Google-driven map application), but on whose property I’m walking through. It took me a little time, but I now have a webapp (http://swingleydev.com/gis/loc.html) that can do this (don't bother clicking on the link unless you're on an iPhone or other GPS-enabled device).

The result is a pair of pages. The first one shows you your current location, speed, and heading. With a press of a button (and a delay while the database finds the property owner) you can see the Borough information on the property you’re currently inside (assuming you’re in the Fairbanks North Star Borough—this page doesn’t do non-Borough residents any good).

Here’s how I set it up:

My web hosting provider doesn’t have a new enough version of PostgreSQL to run PostGIS, which means I need to use the spatially-enabled version of SQLite3, called Spatialite. To get the parcel database from the shapefile to Spatialite requires the following steps. Some parcels are eliminated in this process, but it’s a small fraction of the parcels in the database:

Download the parcels shapefile:

$ wget ftp://co.fairbanks.ak.us/GIS/tax_parcels.zip

Unzip it and insert it into a spatially enabled PostgreSQL database using ogr2ogr. Crash the process immediately:

$ unzip tax_parcels.zip
$ ogr2ogr -f "PostgreSQL"
    -t_srs EPSG:4326
    -overwrite -skipfailures
    PG:"dbname='test'"
    tax_parcels.shp

Fix the column definitions:

sql> DELETE FROM tax_parcels;
sql> ALTER TABLE tax_parcels ALTER COLUMN
    sqft_calc TYPE numeric (22,12);

Re-import the data:

$ ogr2ogr -f "PostgreSQL"
    -t_srs EPSG:4326
    -append -skipfailures
    PG:"dbname='test'"
    tax_parcels.shp

Convert the geometry column to MULTIPOLYGON:

sql> ALTER TABLE tax_parcels DROP CONSTRAINT "enforce_geotype_wkb_geometry";
sql> ALTER TABLE tax_parcels ADD CONSTRAINT "enforce_geotype_wkb_geometry"
     CHECK (geometrytype(wkb_geometry) = 'MULTIPOLYGON'::text OR
            wkb_geometry IS NULL OR
            geometrytype(wkb_geometry) = 'POLYGON'::text);
sql> UPDATE tax_parcels SET wkb_geometry = ST_Multi(wkb_geometry);
sql> ALTER TABLE tax_parcels DROP CONSTRAINT "enforce_geotype_wkb_geometry";
sql> ALTER TABLE tax_parcels ADD CONSTRAINT "enforce_geotype_wkb_geometry"
     CHECK (geometrytype(wkb_geometry) = 'MULTIPOLYGON'::text OR
            wkb_geometry IS NULL);
sql> UPDATE geometry_columns SET type='MULTIPOLYGON'
     WHERE f_table_name='tax_parcels' AND f_geometry_column='wkb_geometry';

Re-import the data (there will be thousands of errors, but this insert should add the MULTIPOLYGON rows that weren’t inserted the first time around):

$ ogr2ogr -f "PostgreSQL"
    -t_srs EPSG:4326
    -append -skipfailures
    PG:"dbname='test'"
    tax_parcels.shp

Get rid of the illegal polygons:

sql> DELETE FROM tax_parcels WHERE NOT ST_IsValid(wkb_geometry);

Convert to spatialite:

$ ogr2ogr -f "SQLite"
    tax_parcels.sqlite
    PG:"dbname='test'"
    -dsco SPATIALITE=YES

With the data in the proper format, I built a mobile web page that can pull location information from the mobile device, display it on the screen, and pass this information to a page that finds and displays the parcel information from the Spatialite database. JavaScript handles gathering the location information, but because I don’t control the web server, I had to write a CGI script to pass a query to spatialite and format the results as a list. This CGI is called by the main page from a <form> element. The spatialite query looks like this:

sqlite> SELECT street_add, owner_firs, owner_last,
           owner1, owner2, owner3, mail_add, ci_st_zip,
           round(acres_calc, 1) as acres, ’$’ || total as total,
           ’$’ || land as land, ’$’ || improvemen as improvements,
           pan, sub, block, lot, road_water, lot_size, units,
           neighborho, primary_us, tax_status, tax_year, mill_rate,
           business, year_built, situs_numb, situs_name
        FROM tax_parcels
        WHERE Intersects(GEOMETRY, SetSRID(MakePoint(lon, lat), 4326));

Again, implementing this would be a lot easier if I could install PostGIS on the server and use PHP to access the data directly. Because I can’t, spatialite and CGI do the trick.

Update: I added a few more steps to convert the initially imported POLYGON layers to MULTIPOLYGON, which then allows us to include the MULTIPOLYGON rows from the shapefile.

tags: app  GPS  iPhone  location  Nika  Piper  property 
sun, 14-feb-2010, 17:02

Drawn bow

Drawing my bow

Today I made a bow from a board. I started with a 1x3 piece of red oak, and ended up with the bow seen in silhouette in the photo on the right. It’s an American flatbow, similar to what many Native American tribes (including some Inuit) used. In mine, the upper and lower limbs don’t have quite the same shape and it has a lower draw weight than I had planned on, but I think it was a good first attempt at bow-making.

The hardest part is finding a board that has straight grain lines running all the way down the face of the board. You cut and smooth the sides first (it’s about 1½” wide at the handle and gently tapers to ½” at the tips) then begin tapering the limbs (full thickness at the handle, gently tapering to ½” at the tips). After each thinning the bow is drawn slightly further up a tillering board (a piece of wood with notches cut into it to hold the string) and the shape is evaluated to make sure it’s bending the way you want. My mistake was in thinning the wrong limb too much without making similar changes to the other half of the bow. Once I realized this, I had to remove a bunch of material off the now-thicker limb and wound up with a bow that is easier to draw than intended. Since I haven’t actually shot an arrow from a bow since high school, a light drawing bow is probably a good idea until I’m ready for something more powerful. This one is reasonably easy for me to pull, and shoots sticks very smoothly.

Tools used: I used a rip saw to cut the board to rough dimension, smoothed the saw cuts with a wooden jack plane, made the initial taper with a drawknife, and did the majority of the remaining adjustments with a coffin smoother, an adjustable mouth block plane and a handled cabinet scraper. Probably should have used the scraper more and the hand planes less. Volumes 1 and 4 of The Traditional Bowyer’s Bible were invaluable, and I think I could have used the other two volumes too, if I’d had them. There’s a ton of information in those books for both the beginner, and advanced bowyer. In addition to volumes 2 and 3, I need some real arrows, a target, and more wood for more bows!

tags: bow  bowyer  woodworking 
sun, 31-jan-2010, 16:41

Utility area doors

Utility area doors

We’ve been wanting to let the kittens into the rest of the house for several weeks now, but when we got close to letting them downstairs we realized they could get into all sorts of trouble in the utility area in the bathroom where the water heater, pump, and washing machine are. Worse, if they got in there, they could climb around behind the shower and tub surround and we’d have no way of getting them out.

So I built the doors you can see in the photo. They’re made from clear pine. I’d originally planned on using “pocket-screw technology,” on the doors, but when driving the pocket screws from the back of the rails into the styles, they cracked the styles. I wound up using glue and dowels instead, and they seem solid. I was a little worried because the doors were so large, but they’re flat and slide easily in the tracks I made.

The image looks a little warped because it's a series of photos that are joined together using the AutoStitch iPhone app. It's a pretty good alternative when you don't have a wide angle lens.

Today was the first day the kittens came downstairs (except once when Jenson escaped), and things seemed to go well. Nika and Piper have been spending nights with all of us, so they’re used to the kittens. Buddy and Deuce mostly seemed afraid. Koidern and Kiva were both very interested, and spent the whole time cautiously following the kittens around. After an hour or so we put the kittens back upstairs to let everyone relax. I opened up the gates again this afternoon and captured this video of Kiva’s interaction with Tallys (and a little of Jenson). Tallys is the one rolling around on the floor in front of the heater, seemingly trying to play with Kiva’s feet.

The music (which was playing on the stereo as I recorded the video on my iPhone) is from Four Tet's latest record.

tags: dogs  Jenson  kittens  Kiva  Tallys 

Meta Photolog Archives