Monday, July 2, 2012

Use gvSIG to create Voronoi or Thiessen polygons

A GIS software such as gvSIG can help marketers to create polygons representing regional areas of coverage for their companies' branch offices if none are available. All that is required are the points representing the offices and perhaps a polygon representing the overall area of coverage e.g. the State boundary.

The basic steps to create the regional areas are simply the following:

  1. Generate Voronoi or Thiessen polygons from the points
  2. Mask away the extra parts of the Voronoi polygons from the area of coverage polygon

For a detailed explanation of Voronoi or Thiessen polygons, visit the Wikipedia site http://en.wikipedia.org/wiki/Voronoi_diagram.

The example below illustrates how to generate the Voronoi polygons of cities in the state of Montana.

  1. Start gvSIG OADE. Load and display the cities and the state boundary polygon in a map view.


  2. Select View | Geoprocessing tools.

    The Geoprocessing tools dialog box appears.

  3. Expand the Geoprocessing tools | Analysis | Computational geometry nodes. Double click Voronoi/Delaunay.

    The Analysis tools dialog box appears.

  4. In the Input layer field, choose the points layer e.g. cities_in_montana.shp.
  5. Toggle on Voronoi(Thiessen) polygons.
  6. In the Output layer field, click Choose. In the Save dialog, type in the output layer name e.g. c:\temp\voronoi.shp. Click Save. Click OK.

    The polygons are generated.
     
  7. If the Geoprocessing tools dialog box is closed, select View | Geoprocessing tools.


  8. Expand the Geoprocessing tools | Analysis | Overlay nodes. Double click on Intersection.

    The Analysis tools dialog box appears.

  9. In the Input layer field, choose the newly created Voronoi polygons layer e.g. voronoi.shp.
  10. In the Overlay layer field, choose the overall area of coverage polygon layer e.g. montana.shp.
  11. In the Output layer field, click Choose. In the Save dialog box, type in the output layer name e.g. c:\temp\cities_coverage_pol.shp. Click Save.
  12. Click Ok.

    The final regional area polygons are created and nicely masked.

Monday, June 25, 2012

Google Mapplet for creating persistent point markers

This Google Mapplet can be used to create persistent markers on Google Maps that will still be there when you close and reopen the web page. The markers will remain until they are explicitly deleted. The mapplet makes use of the IndexDB feature of the HTML5 specifications to persist the markers in the browser. This means that only modern Internet browsers such as Chrome, Firefox, and the upcoming Internet Explorer 10 will be able persist the markers. The mapplet can function in older browsers such as Internet Explorer 8 or 9 but the markers will not be retained on the next visit to the page.

To run this mapplet, click on the link http://dominoc925-pages.appspot.com/mapplets/plpoint.html.

Choice of markers
You can choose the type of marker to be pinned on to the map e.g. green, orange etc. Once placed, the markers can be dragged to another location, deleted, and labelled.

Export Points
The markers can be exported out as KML or comma-separated-values (CSV) format. This can be done by clicking the Export button in the side bar.

The Export Points dialog box is shown below.


Export Points example

  1. In the Output format drop down  box, choose the output format, e.g. KML.

    The Coordinate system type drop down box is enabled for CSV and disabled for KML.
  2. If necessary, in the Coordinate system type field, make a choice e.g. Projected.

    The Projection drop down box is enabled.
  3. If necessary, in the Projection field, choose a suitable destination projection for the output e.g. UTM 48N.
  4. If necessary, in the Geodetic datum field, choose a suitable destination datum e.g. WGS84.
  5. Click Start Export.

    The markers are exported to the destination format. The results are displayed in the Results box.


  6. Click the Results text. Press CTRL+C.
  7. In Notepad, press CTRL+V.

    The results are pasted into Notepad.


  8. Close and save the results into a *.csv file.


 An example of the results of a KML output displayed in Google Earth is shown below.


Monday, June 18, 2012

Stop the click event from propagating from the Google Maps marker InfoWindow

I was writing Google Maps Javascript code to delete a marker already placed on the map by clicking a 'delete' link on the marker's InfoWindow. However, a new marker kept getting placed at the location of the delete link. The problem is illustrated in the before and after screenshots below.

After reading up, I figured out that the click event on the InfoWindow link was being propagated down to the map's onclick event listener. To prevent this from happening, the click event must be stopped from being propagated down.

The following code snippet illustrates how to stop the propagation.
//Create a new marker on this map
var mkr = new google.maps.Marker({
    icon: icon,
    shadow: shadow,
    position: point, 
    id: id, 
    desc: desc,
    title: desc,
    map: this.map
});

//Now create the infowindow object that will be attached to the marker
var contentString;
//Create a div element with an ID to contain the info window contents
contentString = '<div id="infoDiv" >';
contentString += "<textarea rows='3' cols='25' onclick='this.select();'>";
contentString += desc;
contentString += "</textarea>" + "<br />";
contentString += "<a href='#' onclick='onMkrInfoDeleteClick()'>Delete</a>|";
contentString += "<a href='#' onclick='onMkrInfoOkClick()'>Ok</a>";
contentString += '</div>';
var infoWnd = new google.maps.InfoWindow({content: contentString});
google.maps.event.addListener(mkr,'click',
    function(evt){
        infoWnd.open(this.map,mkr);
    }
);
//call this function when the InfoWindow's Delete link is clicked    
function onMkrInfoDeleteClick(){
    //get the pointer to the InfoWindow div element
    var div = document.getElementById('infoDiv');
    if (div)
        //cancel the click event so that it doesn't propagate to the map object below the InfoWindow
        google.maps.event.addDomListener(div, 'click', 
            function (evt){
                evt.cancelBubble = true;
                if (evt.stopPropagation)
                    evt.stopPropagation();
            }        
        );
    // Erase the clicked marker 
    mkr.setMap(null);
};

Monday, June 11, 2012

Use HTML5 IndexedDB cursors to update existing records

The HTML5 IndexedDB is still in the working draft stage and not fully implemented in major Internet browsers yet. Nevertheless, I tried to use its asynchronous API to develop a Google Maps application. It took me a little while to figure out how to update an existing record in the IndexedDB database store. This can be done by opening a read-write cursor to the record to be updated. Then call the cursor update method to replace it with the new record.

An example Javascript code snippet is shown below.


try {
var objDb;    //the database to update
var store = 'myStore';    //the database store to update
var key = 88;    //the key of the existing record to update
var newRec = 'hello world';    //the new record


var objStore = null;
var objTrans = null;
var objCursor = null;
var objKeyRange = null;
 
//...etc...open the database....etc...


//open a read-write transaction
objTrans = objDb.transaction(store,_IDBTransaction.READ_WRITE);


//get the store
objStore = objTrans.objectStore(store);


//create a range from the key
objKeyRange = _IDBKeyRange.only(key);


//open a cursor of only the record to update
objCursor = objStore.openCursor(objKeyRange);


objCursor.onsuccess = function(evt){

  var cursor = evt.target.result;

  //do the update
  var objRequest = cursor.update(newRec);

  objRequest.onsuccess = function(ev){
    console.log('Success in updating record 88');
    };
  objRequest.onerror = function(ev){
    console.log('Error in updating record 88');
    };
  };
  objCursor.onerror = function(evt){
    console.log('Error in retrieving record 88');
  };
}
catch (e){
  console.log('Exception:'+e.message);
}

Monday, June 4, 2012

Create a camera calibration chess board pattern PDF file

For calibrating a camera to calculate its intrinsic parameters e.g. focal length, principal point and distortion, some camera calibration toolboxes make use of images of chessboard patterns taken with the camera. One such toolbox is this open-source software from this site http://graphics.cs.msu.ru/en. To create this calibration chess board pattern, there are a variety of methods that can be employed to generate it.


In this post, I shall use the free and open-source vector illustration software Inkscape to create an A4 sized 8x3cm by 6x3cm tiles calibration pattern. Inkscape can be downloaded from this site http://inkscape.org.

  1. Start Inkscape.

  2. Select File | Document Properties.

    The Document Properties dialog box appears.
  3. In the Page Size list box, select A4. In the Default Units field, choose cm. Close the Document Properties dialog box.
  4. In the toolbox, click the Create rectangles and squares icon.
  5. Click and drag out a rectangle on the page.

  6. In the Change W and H fields, type in 3.
  7. In the toolbox, click the Select and transform objects icon.

  8. Select Edit | Copy.
  9. Select Edit | Paste. Repeat to paste the square two more times.

  10. Change the fill color of two squares to black. Change the fill color of two squares to white.

  11. Click the Select and transform objects icon and select all squares.
  12. Select Object | Rows and Columns.

    The Rows and Columns pane appears.
  13. Ensure the Rows and Columns are set to 2. Ensure the Set spacing is 0. Click Arrange.

    The squares are rearranged.
  14. Ensure all the squares are selected. Select Object | Group.

    All the squares are grouped as a single object.
  15. Select Edit | Copy.
  16. Select Edit | Paste. Repeat 10 more times to place a total of 48 (3x4x4) tiles.
  17. Press CTRL-A.

    All the tiles are selected.
  18. Select Object | Rows and Columns if the Rows and Columns pane is not displayed.

    The Rows and Columns pane is displayed.
  19. In the Rows field, type in 4. In the Columns field, type in 3. Click Arrange.

    The calibration chess board pattern is complete.
  20. Select File | Save As.

    The Select file to save to dialog box appears.
  21. In the Save as type field, choose Portable Document Format (*.pdf). Browse and type in a file name e.g. calib.pdf. Click Save.

    The file is saved.

Monday, May 28, 2012

Google Mapplet for showing local coordinates

This Google Mapplet was written to show the local projected coordinates for any clicked point on Google Maps. Run it from this website http://dominoc925-pages.appspot.com/mapplets/cs_readout.html.


The mapplet currently supports only the following projection types: Cassini-Soldner, Mercator, Oblique Mercator and Transverse Mercator. The datum transformation between the WGS84 datum used by Google Maps and the local projection datum is done using the Standard Molodensky transformation. The transformation parameters of the datums and ellipsoid parameters are taken from this University of Colorado site http://www.colorado.edu/geography/gcraft/notes/datum/edlist.html.

Define and save projection parameters
There are probably hundreds of projection parameter sets in use in the world - too many to keep track. A facility has been built in using some HTML5 features to allow projection parameters to be changed, saved and named, and reuse in the current browser.


  1. In the Side bar on the right, click the Projection link.
  2. In the Projection combo box, select any default projection parameter set e.g. British National Grid.
  3. Change any parameters e.g. Longitude of origin.
  4. Click Save projection as.

    A text entry field appears.
  5. Type in a meaningful name e.g. MyProjection. Click Ok.

    The projection parameters are saved and named as MyProjection.

    Simply select the saved projection to use it for the coordinate readout

Monday, May 21, 2012

Adjust brightness and contrast of intensity images using Imagemagick

Sometimes the intensity images generated from LiDAR las files are too dark or too bright. An example of a dark intensity image is shown below.

It is useful to be able to apply some post-processing brightness and contrast adjustments to the images. Photoshop can be used to interactively adjust the brightness and contrast but I like to use the free Imagemagick open source software to process images in batch. Imagemagick has a convert utility which can perform brightness and contrast adjustments on images from the command line.

To make an intensity image brighter, type in the following at the command line prompt with the brightness-contrast option.
c:\> convert -brightness-contrast 50x20 input.tif out_lighter.tif

where the 50 tells the utility to increase the brightness by +50 and 20 is to increase the contrast by 20.



To make an intensity image darker, type in the following at the command line prompt with negative brightness and/or contrast values.
c:\> convert -brightness-contrast -30x10 input.tif out_darker.tif

where -30 is to darken by 30 and +10 is to increase the contrast by 10.

More information about the convert utility is available on this link.