Search This Blog

Sunday, May 25, 2008

GPS Art

A briefcase + GPS + many batteries + DHL + the World = self portrait

http://biggestdrawingintheworld.com/drawing.aspx


Tuesday, May 20, 2008

Population movement tracking in malls

Using people's phones as a way to track movements.

http://technology.timesonline.co.uk/tol/news/tech_and_web/article3945496.ece

Here the IMEI numbers unique to each phone are determined from shoppers so that the number of shoppers, country the phone is registered, and length of time spent in the mall can be stored. The trends can be used to extend shopping hours, or change the language of signs if it's found one nation is well represented in a shopping mall.

Monday, April 28, 2008

TCPIP sockets in c#

Many great working examples on TCPIP sockets... in C#


http://www.java2s.com/Code/CSharp/Network/AsyncTcpServer.htm

- - -
/*C# Network Programming by Richard BlumPublisher: Sybex ISBN: 0782141765*/
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class FixedTcpSrvr
{
private static int SendData(Socket s, byte[] data)
{
int total = 0;
int size = data.Length;
int dataleft = size;
int sent;
while (total < size)
{
sent = s.Send(data, total, dataleft, SocketFlags.None);
total += sent;
dataleft -= sent;
}
return total;
}
private static byte[] ReceiveData(Socket s, int size)
{
int total = 0;
int dataleft = size;
byte[] data = new byte[size];
int recv;
while (total < size)
{
recv = s.Receive(data, total, dataleft, 0);
if (recv == 0)
{
data = Encoding.ASCII.GetBytes("exit ");
break;
}
total += recv;
dataleft -= recv;
}
return data;
}
public static void Main()
{
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 12008);
Socket newsock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
newsock.Bind(ipep);
newsock.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = newsock.Accept();
IPEndPoint newclient = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}",
newclient.Address, newclient.Port);
string welcome = "Welcome to my test server";
data = Encoding.ASCII.GetBytes(welcome);
int sent = SendData(client, data);
for (int i = 0; i < 5; i++)
{
data = ReceiveData(client, 9);
Console.WriteLine(Encoding.ASCII.GetString(data));
}
Console.WriteLine("Disconnected from {0}", newclient.Address);
client.Close();
newsock.Close();
}
}

Tuesday, April 1, 2008

My Location - Google Mobile Maps

So you don't have GPS but your phone can run JAVA apps... or Python apps..

Google Maps for mobiles can use the GSM tower (cell) id to look up roughly where you are... it plots you on Google Map (for mobile) to within a few km (at worst).

So if Google have access to some database of Cell Tower ID - Lat/Long can we access that data too?

Well.. you can buy it.. or try to use Google's dataset.

In the background the Google maps application uses this website to post your Cell ID

http://www.google.com/glm/mmap

Neil Young written a demo C# app to make use of this to get a lat/long for a given Cell id.
(copy of source at end of this article)
http://maps.alphadex.de/datafiles/fct0e1b11782832f02.cs

Excellent article on his webstie: http://maps.alphadex.de/index.php?section=mylocation

- - - - - -

Yahoo have something similar but no where near as populated or dense cell data.
http://developer.yahoo.com/yrb/zonetag/locatecell.html



- - -

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Diagnostics;
/*
* Sample code to obtain geo codes from a cell info
* "GSM/UMTS" setting revealed by smuraro, thanks!
*/
/* (c) "Neil Young" (neil.young@freenet.de)
*
* This script/program is provided "as is".
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* GNU General Public License, see .
*/
namespace GMM {
class Program {
static byte[] PostData(int MCC, int MNC, int LAC, int CID, bool shortCID) {
/* The shortCID parameter follows heuristic experiences:
* Sometimes UMTS CIDs are build up from the original GSM CID (lower 4 hex digits)
* and the RNC-ID left shifted into the upper 4 digits.
*/
byte[] pd = new byte[] {
0x00, 0x0e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x1b,
0x00, 0x00, 0x00, 0x00, // Offset 0x11
0x00, 0x00, 0x00, 0x00, // Offset 0x15
0x00, 0x00, 0x00, 0x00, // Offset 0x19
0x00, 0x00,
0x00, 0x00, 0x00, 0x00, // Offset 0x1f
0x00, 0x00, 0x00, 0x00, // Offset 0x23
0x00, 0x00, 0x00, 0x00, // Offset 0x27
0x00, 0x00, 0x00, 0x00, // Offset 0x2b
0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00
};
bool isUMTSCell = ((Int64)CID > 65535);
if (isUMTSCell)
Console.WriteLine("UMTS CID. {0}", shortCID ? "Using short CID to resolve." : "");
else
Console.WriteLine("GSM CID given.");
if (shortCID)
CID &= 0xFFFF; /* Attempt to resolve the cell using the GSM CID part */
if ((Int64)CID > 65536) /* GSM: 4 hex digits, UTMS: 6 hex digits */
pd[0x1c] = 5;
else
pd[0x1c] = 3;
pd[0x11] = (byte)((MNC >> 24) & 0xFF);
pd[0x12] = (byte)((MNC >> 16) & 0xFF);
pd[0x13] = (byte)((MNC >> 8) & 0xFF);
pd[0x14] = (byte)((MNC >> 0) & 0xFF);
pd[0x15] = (byte)((MCC >> 24) & 0xFF);
pd[0x16] = (byte)((MCC >> 16) & 0xFF);
pd[0x17] = (byte)((MCC >> 8) & 0xFF);
pd[0x18] = (byte)((MCC >> 0) & 0xFF);
pd[0x27] = (byte)((MNC >> 24) & 0xFF);
pd[0x28] = (byte)((MNC >> 16) & 0xFF);
pd[0x29] = (byte)((MNC >> 8) & 0xFF);
pd[0x2a] = (byte)((MNC >> 0) & 0xFF);
pd[0x2b] = (byte)((MCC >> 24) & 0xFF);
pd[0x2c] = (byte)((MCC >> 16) & 0xFF);
pd[0x2d] = (byte)((MCC >> 8) & 0xFF);
pd[0x2e] = (byte)((MCC >> 0) & 0xFF);
pd[0x1f] = (byte)((CID >> 24) & 0xFF);
pd[0x20] = (byte)((CID >> 16) & 0xFF);
pd[0x21] = (byte)((CID >> 8) & 0xFF);
pd[0x22] = (byte)((CID >> 0) & 0xFF);
pd[0x23] = (byte)((LAC >> 24) & 0xFF);
pd[0x24] = (byte)((LAC >> 16) & 0xFF);
pd[0x25] = (byte)((LAC >> 8) & 0xFF);
pd[0x26] = (byte)((LAC >> 0) & 0xFF);
return pd;
}
static void Main(string[] args) {
if (args.Length < 4) {
Console.WriteLine("Usage: gmm MCC MNC LAC CID [\"shortcid\"]");
return;
}
string shortCID = ""; /* Default, no change at all */
if (args.Length == 5)
shortCID = args[4].ToLower();
try {
String url = "http://www.google.com/glm/mmap";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(new Uri(url));
req.Method = "POST";

int MCC = Convert.ToInt32(args[0]);
int MNC = Convert.ToInt32(args[1]);
int LAC = Convert.ToInt32(args[2]);
int CID = Convert.ToInt32(args[3]);
byte[] pd = PostData(MCC, MNC, LAC, CID, shortCID == "shortcid");
req.ContentLength = pd.Length;
req.ContentType = "application/binary";
Stream outputStream = req.GetRequestStream();
outputStream.Write(pd, 0, pd.Length);
outputStream.Close();
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
byte[] ps = new byte[res.ContentLength];
int totalBytesRead = 0;
while (totalBytesRead < ps.Length) {
totalBytesRead += res.GetResponseStream().Read(ps, totalBytesRead, ps.Length - totalBytesRead);
}
if (res.StatusCode == HttpStatusCode.OK) {
short opcode1 = (short)(ps[0] << 8 ps[1]);
byte opcode2 = ps[2];
System.Diagnostics.Debug.Assert(opcode1 == 0x0e);
System.Diagnostics.Debug.Assert(opcode2 == 0x1b);
int ret_code = (int)((ps[3] << 24) (ps[4] << 16) (ps[5] << 8) (ps[6]));

if (ret_code == 0) {
double lat = ((double)((ps[7] << 24) (ps[8] << 16) (ps[9] << 8) (ps[10]))) / 1000000;
double lon = ((double)((ps[11] << 24) (ps[12] << 16) (ps[13] << 8) (ps[14]))) / 1000000;
Console.WriteLine("Latitude: {0}, Longitude: {1}", lat, lon);

Process p = new Process();
p.StartInfo.FileName = "iexplore";
Console.WriteLine("\nClose map window to exit\n");
p.StartInfo.Arguments = String.Format(
"http://maps.google.de/maps?f=q&hl=de&q={0},{1}&ie=UTF8&z=15",
lat.ToString().Replace(',','.'), lon.ToString().Replace(',','.'));
p.Start();
p.WaitForExit();
}
else
Console.WriteLine("Error {0}", ret_code);
}
else
Console.WriteLine("HTTP Status {0} {1}", res.StatusCode, res.StatusDescription);
}
catch (Exception) {
throw;
}
}
}
}

Monday, March 10, 2008

Sunday, March 9, 2008

Monday, February 25, 2008

NZMG - WGS84 Projections

NZMG was the official New Zealand mapping projection until 2001.

From the LINZ website (NZ mapping body):

"NZMG is not based on a geometric projection (transverse Mercator is based on a cylinder). Instead it uses a complex-number polynomial expansion. This has the advantage of exhibiting minimal scale distortion over New Zealand; however it is a projection unique to New Zealand and so can be difficult to use or program into computer software or positioning devices. "

In packages such as ESRI ArcGIS you can reproject data easily...... however if you're writting your own software you need to find some libraries to do this.

PROJ4 is one such library. It can be downloaded with GDAL / OGR as part of FW TOOLS.
http://fwtools.maptools.org/

Here there are 2 tools to assist in transformations... PROJ and CS2CS.
CS2CS caters with changes in DATUM.

To convert from NZMG to WGS84 requires a change in datum.

There are 3 methods to do this...

a) 3 parameter shift
b) 7 parameter shift
c) grid (NTv2)

a) is only good to the nearest 100m or so...
b) is only good to 5m or so..
c) uses a look up grid and should be good to nearest few cm

The look up grid can be downloaded from here: ftp://ftp.remotesensing.org/proj

Syntax to convert a user entered co-ordinate from WGS84 lat/long to NZMG x,y (m):


C:\Program Files\FWTools2.1.0\bin>cs2cs +proj=latlong +datum=WGS84 +to +proj=nzmg +datum=nzgd49 +nadgrids=o:/nzgd2kgrid0005.gsb

170 -43 [enter]
2265438.60 5796423.71 0.00
[ctrl+z]

This should give you metre accuracte conversions.

_____

To carry out from C# using FW TOOLS... you will need to check the C# example from Tamas Szekeres. This can be found in the FWTOOLS / csharp /apps folder.. and is entitled OSRTransform.cs.

A few modifications are required to work with NZMG and WGS84... as follows:


OSGeo.OSR.SpatialReference src = new OSGeo.OSR.SpatialReference("");

src.ImportFromProj4("+proj=latlong +datum=WGS84");

OSGeo.OSR.SpatialReference dst = new OSGeo.OSR.SpatialReference("");

dst.ImportFromProj4("+proj=nzmg +x_0=25100000.0000000000 +y_0=6023150.0000000000 +datum=nzgd49 +nadgrids='o:\nzgd2kgrid0005.gsb'");

CoordinateTransformation ct = new OSGeo.OSR.CoordinateTransformation(src, dst);

double[] p = new double[3];

p[0] = 172.585303;

p[1] = -43.510183;

p[2]=0; //needed even if 0 value

ct.TransformPoint(p); Console.WriteLine("x:" + p[0] + " y:" + p[1]) ;

___
This should give you results accurate to a few metres.