Sunday, February 15, 2009
additional geowankery
Google Maps can only handle KMLs with points, lines, and polys. Ground overlays are strictly verboten. However, you can overlay images in Google Maps using mapplets. The process is simple and well documented. The basic steps are:
1. write your mapplet, the example below contains all the tags that the example on google doesn't show for your cut-n-paste enjoyment:
<?xml version="1.0" encoding="UTF-8"?>
<module>
<moduleprefs title="1929 Map of San Antonio, Texas" height="300">
<require feature="sharedmap">
</require></moduleprefs>
<content type="html"><![CDATA[
<small>
This is a georeferenced map of San Antonio, Texas in 1929. The original map is at http://www.tsl.state.tx.us/arc/maps/images/map1052a.jpg
</small>
<script>
var map = new GMap2();
map.setCenter(new GLatLng(29.4208378,-98.4938900), 12);
// ground overlay
var boundaries = new GLatLngBounds(new GLatLng(29.3400022,-98.5543116), new GLatLng(29.5016733,-98.4334683))
var oldmap = new GGroundOverlay("http://www.tsl.state.tx.us/arc/maps/images/map1052a.jpg", boundaries)
map.addOverlay(oldmap)
</script>
]]></content>
</module>
2. Upload your code to a server or to Google page creator.
3. Install it on Google Maps directory.
4. Share the map using a long url like this: http://maps.google.com/ig/add?synd=mpl&pid=mpl&moduleurl=http://www.geouptime.com/mapplet_san_antonio_1929.xml
Google will ask you if you want to add it to maps (I assume it means your maps). Clicking on Add it to Maps opens the mapplet.
Voila!
Making historic information more available
I write on another blog documenting the history of my house in San Antonio, Texas. As part of the research we found that there was streetcar service close the house. A quick search turned up a map of the streetcar lines at the Texas Transportation Museum. I thought it would be neat to overlay that map over other map services.
I first tried to georectify the Texas Transportation Museum map using Metacarta Labs Map Rectifier, but the quality of the scan was too poor to successfully add enough ground control points for a good warp. Another search turned up a much better scan of a 1929 map at the University of Texas Perry-Castaneda Library Historic Map collection. This map was scanned at a very high resolution and it was easy to create a sufficient number of ground control points to use a cubic fit georegistration using Metacarta's Map Rectifier. The result was a 215mb tif file which I was able to download. Thanks Metacarta!
The next step was to trace the streetcar lines using uDig. I used version 1.1.1 which is verrrry slooowww when it comes to handling largish tif files. I heard that raster handling is improved in 1.2 beta as well as more digitizing tools, so you might want to use that. Once I figured out the editing tools it was fairly easy to digitize the streetcar lines. Always the critic, I have to say the the editing tools could use some context sensitive menus available through a right click. I saved the streetcar lines as a shape file and I saw that uDig has a number of tools for cleaning up the data and validating the output. Nice.
I converted the shape file kml using ogr2ogr. The first time I tried it ate my shape file, no idea why. I noticed that my gdal install was way out of date (version 1.4), so I installed version 1.6 for OS X from the Kyng Chaos Wiki. Using ogr2ogr was straight forward:
View Larger Map
ogr2ogr -f KML sa_streetcars.km streetcar_lines.shpI tweaked the KML in a text editor so that each streetcar line was a consistent color. Then I uploaded it to myGoogle maps. The 1929 map overlays fairly well but not exactly. I think it was important to use a historic map for digitizing the lines instead of using a modern map such as Open Street Map, Google Maps, or the Census Bureau's TIGER street files because there have been many changes to the street network since the streetcars were in service. The lines may not overlay perfectly, but I think its a better representation. Here's the data and final map:
View Larger Map
Friday, October 17, 2008
orchestra practice
Yesterday was the first practice for my church orchestra. I was wondering who would show up and it turned out to be a diverse group.
- 3 cellos
- 3 violins
- 2 violas
- 1 oboe/english horn
- 1 flute
- 3 clarinets
- 2 alto saxes
Wednesday, October 15, 2008
subtle reminders
I was in Chicago on Tuesday and I stayed at the Kimpton Allegro. Lo and behold there was a picture of what looks like an x-ray of a cello in my room! Just another reminder to get may butt in gear with the Prakticello build.I've found a tail piece on ebay so far, and I'm looking for a neck and fingerboard. Finding a source for spruce is turning out more elusive.
Friday, October 10, 2008
Building a Prakticello: The Plans Arrive
This is a departure from my cheesy java bits, but I'm building a Prakticello; so this will be a build log of sorts.
I travel a bit and I really miss cello practice when I'm out of town. I thought about getting a silent or electric cello but none of them seem to be overhead compartment friendly except the Ned Steinberger electric cellos. The NS cellos look awesome, and in my imaginary world I can see myself playing Bjork or the Clash's "Straight to hell" and becoming a rock star cellist. But I bought a cello over the summer, so I'm just not ready to plunk down $2K for another instrument. Once again cheapness (or more kindly, thrift) crushes my dreams.
Another mitigating factor is that I joined the Christmas orchestra at my church. While the pieces are not particularly difficult, most of the songs are in F major and I'm still kinda banging around C major in the Suzuki 2 pieces. Yeah, I know I should practice my scales more often. Anyway, I don't want to sound like an ass because my extension sucks.
I ordered a set of plans from the inventor of the Prakticello, Mr. Ernest Nussbaum. The plans were written circa 1985 and they have the sort of charm of plans ordered from the back of Popular Mechanics. The plans are hand drawn (as opposed to be done in a CAD package) and the hand lettering is charming, not Leroy lettering but you can see faint lines drawn in to guide the lettering.
The plans come with a 22 page instruction manual written in a Courier font adding a typewritten charm. You can imagine Mr Nussbaum banging away on an IBM Selectric. The plans are actually for a Traviola, which is the electrified version of the Prakticello. They contain the build of materials and general instructions which include building a small amp. For my purposes, I'll stick to the silent cello build for now. There are a couple of photos of the Prakticello in the manual and the website, but they really don't do the Prakticello justice. I found these pics on a discussion board:
Tuesday, September 16, 2008
checking for well formed documents in OS X
I sometimes have to generate XML documents from some random source of data. It's typically a one off task, so I just write a quick program. However, I usually get the format wrong or forget a special character. OS X (and linux) happens to have a neato utility for checking for well formedness called xmlwf
Saturday, July 5, 2008
Making GeoWebCache authenticate to a WMS
GeoWebCache is a java implementation of TileCache. Geowebcache does not connect to secured a WMS, so I added support for it (yay! for open source).
The WMS GetMap requests are in WMSMetaTile.java (../geowebcache-0.8.3/src/main/java/org/geowebcache/layer/wms). I thought that the best place to put the username and password was in the WMS service url, which is set in the properties file for the layer (../geowebcache/WEB-INF). This takes the form of http://username:password@www.mapserver.com/ .
Alternatively you can also put username and password in the vendor parameters, but that could get dodgy if you have other vendor parameters.
From googling RFC 2716 related documents, the username and password has to be sent in the http Authorization request header in the form of username:password encoded in base64. Real secure, huh?
So here's the code:
private void forwardRequest(WMSParameters wmsparams, String backendURL,
WMSLayerProfile profile) throws IOException, ConnectException,
ServiceException {
// extract username and password from service url if there
String encoding = null;
int upTest = backendURL.indexOf("@");
if (upTest>0) {
String[] temp = backendURL.split("@");
backendURL = "http://"+temp[1];
String usernamePassword = temp[0].substring(temp[0].lastIndexOf("/")+1,temp[0].length());
encoding = new sun.misc.BASE64Encoder().encode (usernamePassword.getBytes());
}
//Get user name and password from vendor parameters
//Vendor parameter key is "logon"
//Need to add iterator in case of multiple vendor parameters
/*
if (profile.vendorParameters!=null) {
String[] temp =profile.vendorParameters.split("=");
if (temp[0].equalsIgnoreCase("logon") {
String usernamePassword= temp[1];
//usernamePassword = usernamePassword.substring(usernamePassword.indexOf("=")+1,usernamePassword.length());
String encoding = new sun.misc.BASE64Encoder().encode (usernamePassword.getBytes());
}
}
*/
// Create an outgoing WMS request to the server
Request wmsrequest = new Request(backendURL, wmsparams);
URL wmsBackendUrl = new URL(wmsrequest.toString());
log.info("the request: "+wmsrequest.toString());
URLConnection wmsBackendCon = wmsBackendUrl.openConnection();
//if username and password required set header
if (!(encoding==null)) {
wmsBackendCon.setRequestProperty ("Authorization", "Basic " + encoding);
}
...Tuesday, June 24, 2008
bits and stuff
Some bits I always seem to forget.
Splitting a delimited line of text in bash
line = a|b
first=${line%|*}
second=${line#*|}
echo $first
echo $second
Post in curl (OS X)
curl --data-ascii "var1=one&var2=two" http://server.com/myapp
Sunday, May 18, 2008
in the belly of the beast
Saturday, May 10, 2008
Embedded tomcat and launch4j FTW
I've been meaning to get around to this for years.
Using this example, I compiled it with my webapps and then used lauch4j to create a windows executable wrapper. Throw in a jre and some data and I'm good to go. Now I just give the live demos to the sales people and clients on a USB stick without having to go through the install or setting it up on a web server.
Here's the code example:
import org.apache.catalina.*; import org.apache.catalina.connector.*; import org.apache.catalina.realm.*; import org.apache.catalina.startup.*; public class EmbeddedTomcat { // Instance variables: private String name; private int portNumber; private Embedded embedded; private Engine baseEngine; private Host baseHost; private Connector httpConnector; /** Creates a new instance of EmbeddedTomcat */ public EmbeddedTomcat( String name, int portNumber) { this.name = name; this.portNumber = portNumber; init(); } private void init() { MemoryRealm realm; Context context; String baseEngineName; String hostName; embedded = new Embedded(); // set default logger and realm /* FileLogger fileLog = new FileLogger(); fileLog.setDirectory("."); fileLog.setPrefix(name); fileLog.setSuffix(".log"); fileLog.setTimestamp(true); embedded.setLogger(fileLog); */ realm = new MemoryRealm(); embedded.setRealm(realm); // create an Engine baseEngine = embedded.createEngine(); // set Engine properties baseEngineName = name + "Engine"; hostName = name + "Host"; baseEngine.setName(baseEngineName); baseEngine.setDefaultHost(hostName); baseHost = embedded.createHost(hostName, "webapps"); baseEngine.addChild(baseHost); // RootContext context = addContext("", "ROOT"); // ManagerContext context = addContext("/manager", "manager"); context.setPrivileged(true); /* This is where you add your webapps*/ // GeoBrowserContext context = addContext("/geobrowser", "geobrowser"); context.setPrivileged(true); // add new Engine to set of Engine for embedded server embedded.addEngine(baseEngine); // create Connector httpConnector = embedded.createConnector((java.net.InetAddress) null, portNumber, false); // add new Connector to set of Connectors for embedded server, associated // with Engine embedded.addConnector(httpConnector); } public void start() { // start server try { embedded.start(); } catch (org.apache.catalina.LifecycleException ex) { ex.printStackTrace(); //fileLog.log("Startup failed"); //fileLog.log(ex.getMessage()); } } public void stop() { // start server try { embedded.stop(); } catch (org.apache.catalina.LifecycleException ex) { ex.printStackTrace(); //fileLog.log("Startup failed"); //fileLog.log(ex.getMessage()); } } public Context addContext( String path, String docBase) { Context c; c = embedded.createContext(path, docBase); baseHost.addChild(c); return c; } public static void main(String[] args) { new EmbeddedTomcat("RedSpider", 8080).start(); } }
Subscribe to:
Posts (Atom)