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.