Elijah Robison | GIS Blog

A scrapbook of GIS tricks, with emphasis on FOSS4G.

Archive for the ‘OpenScales’ tag

OpenScales: Coordinate Transformation from Uncommon Projections

without comments

————

UPDATE 2.19.2013:

It turns out you don’t have to rebuild OpenScales to apply uncommon projections, you can just assign the projection directly to ProjProjection.defs. (See Simon L.’s answer here in the OpenScales user group.)

So if I modify my example toward the bottom of the post (at #5), here is how I would apply the alternate, and arguably better, approach.

(Fair warning, I haven’t compiled this and tested it yet, the only difference is the first line), but this is how I expect it should be. If it doesn’t work like this, it’s likely ‘cos an instance of ProjProjection needs to be created first, and the defs property of the instance needs to be appended. In other words, if this doesn’t work, follow the line instantiating moNADProj with moNADProj.defs[‘EPSG:102697’] = “+title…. blah blah”; One of these days I’ll make super-sure this is correct. But I didn’t want to forget where I found this, hence updating the post.)

private function transformCoordinates():void
{
         // This single line is the only difference:
         ProjProjection.defs['EPSG:102697']="+title=NAD_1983_StatePlane_Missouri_Central_FIPS_2402_Feet +proj=tmerc +lat_0=35.83333333333334 +lon_0=-92.5 +k=0.9999333333333333 +x_0=500000.0000000002 +y_0=0 +ellps=GRS80 +datum=NAD83 +to_meter=0.3048006096012192 +no_defs";

         // Source point's projection, called using the KEY defined above..
         var moNADProj:ProjProjection = new ProjProjection("EPSG:102697");

         // Destination projection (WGS84), which is already available in proj4as..
	 var wgs84Proj:ProjProjection = new ProjProjection("EPSG:4326");

         // The source point, instantiated here using its easting (value along X-axis)
         // and northing (value along the Y-axis) parameters..
	 var projPt:ProjPoint = new ProjPoint(easting,northing);

         // The Proj4as.transform() method returns a ProjPoint object in the new
         // coordinate system; in this case, longitude and latitude.
	 var lonLatPt:ProjPoint = Proj4as.transform(moNADProj, wgs84Proj, projPt);
}

————

Original Post:

In short, I wanted to transform projected source coordinates from NAD_1983_StatePlane_Missouri_Central_FIPS_2402_Feet to geodetic coordinates in WGS84. As expected, OpenScales didn’t recognize my relatively uncommon projection, but I had high-hopes I could implement its properties piece-meal, possibly through the ProjParams class, or in some similar fashion.

At first I hoped I would find a static method on ProjProjection like  “ProjProjection.fromProj4Def(String:proj4Def)” which would return an instance of ProjProjection for any valid Proj4 expression, but such a method never emerged from the fog. I did, however, manage to “appened” my rogue projection into the proj4as source code, which ultimately solved my problem —-though admittedly, I still think a method like I described above would be a nice addition. 🙂

So getting to the point, if you need to add an uncommon projection to your OpenScales-derived project, here’s what you can do:

1) Remove openscales-proj4as-1.2.1.swc from your project (alternatively, you could mod these instructions and just recompile the swc) and copy the proj4as source package into your own project’s src directory. In other words, relative to your unpacked OpenScales download, you want to copy in the part I’m emphasizing in bold and underlined:

C:\..\openscales-1.2.1\src\openscales-proj4as\src\main\flex\org\openscales\proj4as\proj

Adding the proj4as Code to your Project

 

2) Now open the file ProjProjection.as and scroll down to about line 20. You should see something like what follows; these are the various projections available through proj4as right out-of-the-box:

static public const defs:Object={
	'EPSG:900913': "+title=Google Mercator EPSG:900913 +proj=merc +ellps=WGS84 +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs",
	'WGS84': "+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees",
	'EPSG:4326': "+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84 +units=degrees",
	'EPSG:4269': "+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees",

	[.. .. expect several lines of these .. ..]

 

3) At this point, you’ll add your projection’s Proj.4 text to the mix. If you don’t know the Proj.4 expression for your projection, drop by http://www.spatialreference.org, look up your projection, and select the Proj4 link. Once it loads just copy the definition text to your clipboard..

Getting the Proj4 Definition Expression for a Projection

 

4) Now, add your projection’s Proj.4 expression to the defs object, shown in bold, below. You will need to add the underlined part yourself, and frankly, these values are somewhat arbitrary. On the left, ‘EPSG:102697’ becomes the KEY you’ll use  to reference the projection later in code; and the title is even less significant. I recommend keeping your entries relatively sane. Basically, “make it look like the neighboring expressions”. Oh.. and you can put it anywhere in the list, separated by line-breaks if you prefer. I put mind right above the OSGB36/British National Grid entry:

static public const defs:Object={
	'EPSG:900913': "+title=Google Mercator EPSG:900913 +proj=merc +ellps=WGS84 +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs",
	'WGS84': "+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees",
	'EPSG:4326': "+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84 +units=degrees",
	'EPSG:4269': "+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees",

	'EPSG:102697': "+title=NAD_1983_StatePlane_Missouri_Central_FIPS_2402_Feet +proj=tmerc +lat_0=35.83333333333334 +lon_0=-92.5 +k=0.9999333333333333 +x_0=500000.0000000002 +y_0=0 +ellps=GRS80 +datum=NAD83 +to_meter=0.3048006096012192 +no_defs",

	[.. .. expect several lines of these .. ..]

 

5) That handles adding your projection to proj4as, assuming you want to consume this somewhere in your Flex/ActionScript application, a function like this one will perform your coordinate transformation (this is just to demonstrate the idea —-I don’t actually recommend instantiating both projections each time you want to do a conversion):

private function transformCoordinates():void
{
         // Source point's projection, called using the KEY defined above..
         var moNADProj:ProjProjection = new ProjProjection("EPSG:102697");

         // Destination projection (WGS84), which is already available in proj4as..
	var wgs84Proj:ProjProjection = new ProjProjection("EPSG:4326");

         // The source point, instantiated here using its easting (value along X-axis)
         // and northing (value along the Y-axis) parameters..
	var projPt:ProjPoint = new ProjPoint(easting,northing);

         // The Proj4as.transform() method returns a ProjPoint object in the new
         // coordinate system; in this case, longitude and latitude. Just to emphasize,
         // longitude is returned as X (i.e. x-intercept) and latitude as Y..
	var lonLatPt:ProjPoint = Proj4as.transform(moNADProj, wgs84Proj, projPt);
}

6) Enfin, and mostly for the sake of proving all this worked, here’s a screenshot of the application I’m working on (an AIR app that will integrate with a USB GPS device) showing the coordinate transformation in action.

The map, which is in Mo State Plane Central, tracks mouse movement as easting/northing values (bottom-center), and at the time, my mouse was hovering over Bass Pro Shops, which is a significant Springfield landmark to say the least. The proj4as-transformed coordinates are at bottom-right:

proj4as Coordinate Transformation in Action

If you want to scruitinize the accuracy of the coordinate transformation, here’s that location in Google Maps: http://maps.google.com/?ll=37.18069720,-93.29592962

And for the curious among you, my USB GPS device (coords at bottom-left) is cranking out quite accurately, too.. but that’s a  post for another day..

Cheers, Elijah

Written by elrobis

November 6th, 2011 at 12:25 pm

Google Maps for Flash/Flex: Dead Man Walking

without comments

“When life gives you lemons..”

Let’s just review the signs:

  • First, the Google Maps Flash/Flex API had not been updated for quite some time.
  • Meanwhile, some developers were sharing a hack to bypass a nasty initialization bottleneck in the Maps Flash/Flex API that stalled map loading in AIR apps.
  • At the other end of the yard, Google lifted its registration key requirement for the Maps JavaScript API V3; yet, the Flash/Flex counterpart remained unchanged in this respect (curiously, it was key-hashing that caused AIR apps to stall).
  • Finally, and though unrelated, Pamela Fox, one of the higher-profile support engineers attached to Maps developer relations, left Google for other pursuits.

In spite of the above indicators, I started an eBook titled: Google Mapping the Shapefile with Flex, PHP, and PostGIS. After four or five chapters, I threw in the towel to enjoy what was left of the summer ..but, maybe that was a good thing, because lo and behold, the Maps Flash/Flex API was a dead man walking. In their defense, Google saw comparatively less consumption of the Flash/Flex API vs the JavaScript flagship, so they pulled the plug on the Flash stuff. It’s an understandable reaction ..but I do wonder if that inertia will eventually affect StreetView, which (I believe) remains in Flash.

I had planned to return to my book over the winter, and I was optimistic about re-approaching O’Reilly with the finished book and a suggestion that it be released as a print title. So clearly I was disappointed by the deprecation announcement. Also, I really like Flex! If I want to make an interactive web map, I’d rather do it with Flex! Where does this leave me?

“..make lemonade.”

That was lemons. But it turns out, there’s a chance to make lemonade. It’s called OpenScales, and it’s a Flex mapping API with some real potential. While investigating OpenScales, I had some difficulty finding examples of raw implementations, where the Flex client UI has a direct line (PHP) to vector GIS data stored on a PostGIS-enabled PostGREsql database. Fortunately it wasn’t difficult to setup. So, rising from the ashes of my failed eBook, and primed by the excitement of finding OpenScales, I decided to start this blog as a place to post OpenScales examples. And that’s exactly what I’ll do.

In the next few months, I’ll post several OpenScales examples here, with the goal of touching upon the following topics:

  • Publish Shapefile or Personal Geodatabase data to an OpenScales map by converting it into usable flatfiles or migrating it into a spatially-aware database and pulling it from there.
  • Load geodata into OpenScales from the following formats: XML, JSON, GML, and KML.
  • Load data faster by enabling AMF support with AMFPHP, et cetera.
  • Pull WMS and WFS data from 3rd-party sources (I’m imagining a weather map).
  • Prepare custom basemap tiles for an OpenScales map and either load raster tiles direct from the filesystem or pull them from a PostGIS database.
  • Publish OpenScales-based applications to Android devices.

If I can do all that in a handful of months, I’ll be a happy camper, and with a little luck, a few people will stumble across this site and they will be too.

Wild! Stallions!

Written by elrobis

October 16th, 2011 at 3:26 pm

Posted in Uncategorized

Tagged with ,