Monday, September 26, 2011

Create a thematic map with gvSIG

Creating thematic maps based on one or more attribute fields of a geographical feature is a fairly typical GIS task. The free and open source software gvSIG has the tools to quickly generate a thematic map of a geographical layer. The example below shows the procedure to color the thematic map according to unique attribute field values.

  1.  Open up gvSIG OADE and display a polygon layer e.g. States.shp.

  2. In the legend, press a mouse right click on the States.shp layer.

    A pop up menu appears.
  3. Choose Properties.

    The Layer properties dialog box appears.
  4. Select the Symbology tab.

  5. Expand the Categories tree node. Choose Unique values.
  6. In the Classification field, choose the field to style with e.g. STATE_NAME.
  7. In the Color ramp field, choose a suitable color table.
  8. Click Add All.

    The colors are assigned to each unique field value.
  9. Click OK.

    The thematic map is generated.

Monday, September 19, 2011

Convert local date time to GPS week, seconds of week Google Gadget


Note: A WebApp version of this Google Gadget is available at https://dominoc925-pages.appspot.com/webapp/calc_timegps/

This Google Gadget calculator can convert the local date time values into the equivalent GPS week and seconds of week format. The GPS leap seconds from 1980 till 2012 are taken into account in the conversion now.  This came about since I found that in some situations, I need to find out the equivalent GPS week and seconds of week for a given local date time. So I wrote this gadget to do the job. 

To use this calculator, 
  1. Simply select your time zone.
  2. Then type in the local date time.

    Note: The time should be entered in 24HR form. It is not necessary to fill in all local date time fields - the calculator will use zero values in place of blank fields.
  3. Then click the Convert to GPS time button.

    If the keyed in local date time values do not represent a valid date time string, then the calculator will simply display an error 'Invalid date time' message. Otherwise, the GPS week and seconds of week values will be shown in the GPS Time field.

Monday, September 12, 2011

Passing structures between C# and C/C++

Data structures can be passed between managed C# code and unmanaged C/C++ dynamic link libraries but it can be a little complicated. The trick is to define structures that match between the two different languages; and perhaps write wrapper functions that hide away the complexity of the memory marshaling code. I will show a couple of simple examples of passing a system time data structure from C/C++ to C# and vice versa here.

The C/C++ definition of the system time structure is as follows:

typedef struct _SYSTEMTIME {
    WORD wYear;
    WORD wMonth;
    WORD wDayOfWeek;
    WORD wDay;
    WORD wHour;
    WORD wMinute;
    WORD wSecond;
    WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;

The matching C# equivalent of the system time structure can be defined as shown below.

private struct SYSTEMTIME
{
    public UInt16 wYear;
    public UInt16 wMonth;
    public UInt16 wDayOfWeek;
    public UInt16 wDay;
    public UInt16 wHour;
    public UInt16 wMinute;
    public UInt16 wSecond;
    public UInt16 wMilliseconds;
}

Example 1: Passing a structure from C/C++ to C#
If the C/C++ function has the following signature:

HRESULT GetDateTime( HANDLE hClient, SYSTEMTIME* pSysTime );

Then the following wrapper functions can be used to call the C/C++ function.

[DllImport("MyDynamicLinkLib.dll")]
private static extern int GetDateTime(IntPtr hClient, IntPtr pSysTime);
public static int GetDateTime(IntPtr hClient, out DateTime sysTime)
{
    int hr = 0;
    IntPtr pSysTime = IntPtr.Zero;
    SYSTEMTIME theTime = new SYSTEMTIME();
    sysTime = new DateTime();
    pSysTime = Marshal.AllocHGlobal( Marshal.SizeOf(theTime));
    hr = GetDateTime(hClient, pSysTime);
    theTime = (SYSTEMTIME) Marshal.PtrToStructure(pSysTime, typeof(SYSTEMTIME));
    Marshal.FreeHGlobal(pSysTime);
    sysTime = new DateTime(theTime.wYear, theTime.wMonth, theTime.wDay, theTime.wHour, theTime.wMinute, theTime.wSecond, theTime.wMilliseconds);
    return hr;
}

To use the wrapper functions, simply do something like the following:

IntPtr hClient = IntPtr.Zero;
DateTime dt = new DateTime();
int ret = GetDateTime( hClient, out dt);

Example 2: Passing a structure from C# to C/C++
If the C/C++ function has the following signature,

HRESULT SetDateTime( HANDLE hClient, SYSTEMTIME* pSysTime );

Then the following wrapper functions can be used to call the C/C++ function.

[DllImport("MyDynamicLinkLib.dll")]
private static extern int SetDateTime(IntPtr hClient, IntPtr pSysTime);
public static int SetDateTime(IntPtr hClient, DateTime sysTime)
{
    int hr = 0;
    IntPtr pSysTime = IntPtr.Zero;
    SYSTEMTIME theTime = new SYSTEMTIME();
    theTime.wYear = (ushort) sysTime.Year;
    theTime.wMonth = (ushort) sysTime.Month;
    theTime.wDay = (ushort) sysTime.Day;
    theTime.wDayOfWeek = (ushort) sysTime.DayOfWeek;
    theTime.wHour = (ushort) sysTime.Hour;
    theTime.wMinute = (ushort) sysTime.Minute;
    theTime.wSecond = (ushort) sysTime.Second;
    theTime.wMilliseconds = (ushort) sysTime.Millisecond;
    pSysTime = Marshal.AllocHGlobal(Marshal.SizeOf(theTime));
    hr = SetDateTime(hClient, pSysTime);
    Marshal.FreeHGlobal(pSysTime);
    return hr;
}

Do the following to call the wrapper functions.
DateTime dt = new DateTime();
int hr = SetDateTime(hClient, dt);
 

Monday, September 5, 2011

Google Maps tool for creating air photo frames

In aerial digital photography, the area captured by the camera is dependent on a number of factors including the camera lens and sensor dimensions, the flying speed and height, and the capture interval. For instance, if the capture interval is too slow and the aircraft is flying too fast, the amount of overlap between photo frames could be less and there could be gaps in coverage. The pixel ground resolution is also a consideration. With this tool , it is possible to estimate the coverage, overlap, resolution, given certain input parameters prior to the actual survey mission.

This Google Maps based tool was written partly based on some information about calculating camera field of views from this site http://www.bobatkins.com/photography/technical/field_of_view.html. The tool also use geodetic functions by Chris Veness from www.movable-type.co.uk/scripts/latlong.html.

The command makes a few assumptions:
  1. The camera sensor is a full frame sensor
  2. There is no lens distortion
  3. The ground elevation is flat and is based on the elevation at the center of the frame
  4. The earth is a perfect spheroid
  5. There is no roll and pitch.
The tool makes use of the Google Elevations Service to obtain the ground elevations at the center of the photo frames.

To use this tool,
  1. Click this link http://dominoc925-pages.appspot.com/mapplets/camframes.html.
  2. Fill in the camera focal length e.g. 50
  3. Fill in the camera sensor width e.g. 59.
  4. Fill in the camera sensor height e.g. 36.7.
  5. Fill in the camera sensor horizontal pixel dimensions e.g. 8176.
  6. Fill in the camera sensor vertical pixel dimensions e.g. 6132.
  7. Enter the aircraft altitude e.g. 1080.
  8. Enter the initial latitude and longitude position of the aircraft, e.g. 33.7232 and -100.3347.
  9. Set the capture interval e.g. 6.
  10. Enter the aircraft speed e.g. 33
  11. Enter the aircraft bearing e.g. 10
  12. Enter the number of frames to create e.g. 10.
  13. Click the Create button.

    The frames are created.
 To create a KML file, simply click the KML button. Then click the text area below the settings and press CTRL+C to copy the text to the clipboard. Then open up a text editor and paste the contents inside. Save the file with a .KML extension.

An example of the file in Google Earth is displayed in the screen shot below.