How do I draw multiple points from multiple lat longs pairs?

I have an array in storage called track, it looks a bit like this.

[56.8967, 0.7654, 53,8736, 0.9832, 50,6453, 0,0773….etc]
As you can see, multiple lat and longs, the array is of no fixed size.

Currently I have only managed to draw the first lat lon in the array.

//By transforming them with this:


function TransformCoordinates(lat, lon) {

var Me = [240/2,240/2];

var track = Application.Storage.getValue(“track”);

var pixelsLong = (120 - lon) * (4/screenWidthPixels);

var pixelsLat = (lat - 120) * (4/screenHeightPixels);

var x = Me[1] - pixelsLong;

var y = Me[0] - pixelsLat;

return [x,y]; }

//Then drawing them with this:

function onUpdate(dc) {

var track = [x,y];

dc.setColor(Graphics.COLOR_BLACK, Graphics.COLOR_TRANSPARENT);

for(var i=0; i<track.size();i=i+2){
var pointA=track[i];

var pointB=track[i+1];

dc.setPenWidth(8) 

dc.drawPoint(pointA,pointB);}

Help in drawing all these points is much appreciated.

  • Where it says scale the geographical size to the display size does that mean fitting the whole route scaled down into the screen as opposed to it extending off screen like in a satnav?

    This will fit a given route into the display size. It's a template which you've to adjust to your needs. For clarification I've separated lats and lons to different arrays. If you use another storage scheme than you should adjust it accordingly. Lat/lons are stored internally in semicircles (Lang.Long) and if you convert them to radians or degrees you get double precision (Lang.Double) values because enhanced precision is necessary as the increments are usually 10E-5deg or 10E-9rad. If the app crashes because of type error you've to cast the expression to double using eg. myValue.toDouble() .

    As I said, I'm not sure what you want to display. If you want instant tracking during an activity, the method needs to be adjusted accordingly. You also need to manage the moving lat/lon data vector. These are just my initial thoughts and there is no guarantee for this template to really work and to be accurate. The customization and implementation is your part.

    const EARTHRADIUS = 6371000.0d;  // m
    var scaleDistDeg = (EARTHRADIUS * Math.PI) / 180.0d;  // m/deg
    
    // define maximum trace length in m to display
    // either with hard coding or by user settings
    // this means only the last 1000m are inside the display 
    // the other points are outside and therefore not visible
    const totalTraceLen = 1000.0;
    var totalTraceDeg = traceLen / scaleDistDeg;  // deg/1000m
    
    var lonMax = totalTraceDeg;
    var lonMin = 0.0d;
    var latMax = totalTraceDeg;
    var latMin = 0.0d;
    
    //--- old code equals to last comment ---
    
    // scale the geographical size to the display size
    var scaleX = dc.getWidth() / (lonMax - lonMin);
    var scaleY = dc.getHeight() / (latMax - latMin);
    var scaleXY = (scaleX < scaleY) ? scaleX : scaleY;
    
    for(i=0; i < track.size(), i++) {
        // calculate point locations in pixels
        var pixelsLon = (lon[i+1] - lon[i]) * scaleXY;
        var pixelsLat = (lat[i+1] - lat[i]) * scaleXY;
    
        // adjust point locations to a reference point
        var displayX = pixelsLon + pixelsXRef;
        var displayY = pixelsLat + pixelsYRef;
    
        // draw points
        dc.setColor(...);
    	dc.fillCircle(displayX, displayY, 2);
    }
    
    // add aditional lon/lats and execute the previous for() loop
    ...
    

  • What I am wanting to display is a route to follow that is scaled according to a map on my non map device. I think I can use your code for this but…

    As the app has the functionality to save up to 6 tracks as track1, track2, track3, etc I would like to keep things simple and not have to divide those into tracklat1 and tracklon1 and then load it into the current track as tracklat, tracklon etc, how do I go about doing the below instead?

    Here’s how I’d like to load a route from saves: 

    Choose either track1, track2, track3, track4, track5 or track6 -> track -> separate Lat and Lons -> your transforming and drawing code.

  • Also what does it mean by add additional lon, lats? Do they not all get converted by the one chunk of code already provided?

  • Me again, I got the thing to work, yay! But upon loading a new route while one is active it gets a memory error which I think I can fix, what is weird though is after clearing the app data in the sim it complained of an array out of bounds error, upon checking the storage it didn’t seem to have cleared the storage data. Could that be why I got the out of bounds error?

  • Also what does it mean by add additional lon, lats?

    Sorry, I've missed to define the reference point but it's according to your code

    var Me = [240/2,240/2];

    So my code should read:

        // adjust point locations to a reference point
        // e.g. center of display
        var pixelsXRef = 120;
        var pixelsYRef = 120;
        var displayX = pixelsLon + pixelsXRef;
        var displayY = pixelsLat + pixelsYRef;

  • Thanks for that but of info, would you be willing to provide an example of your code but where the lat longs can be extracted from a single array containing both lat and lon as opposed to separate arrays? I imagine that might help with the memory issue the widget had when loading and storing a track.

  • Thanks for that but of info, would you be willing to provide an example of your code but where the lat longs can be extracted from a single array containing both lat and lon as opposed to separate arrays?

    // using 1-dim array like 
    // track[lat1,lon1,lat2,lon2,lat3,...}
    for(i=0; i < (track.size() - 2), i+=2) {
        // calculate point locations in pixels
        var pixelsLon = (track[i+3] - track[i+1]) * scaleXY;
        var pixelsLat = (track[i+2] - track[i])   * scaleXY;
    
        // adjust point locations to a reference point
        var displayX = pixelsLon + pixelsXRef;
        var displayY = pixelsLat + pixelsYRef;
    
        // draw points
        dc.setColor(...);
    	dc.fillCircle(displayX, displayY, 2);
    }
    ...

    Please note the loop index to prevent a crash due to running out of bounds of the array.

    EDIT: (track.size() - 4) => (track.size() - 2)

  • Thanks, the loop index is the i=0; i < track.size(); i+=2) yes?

    I am still coming to grips with the terms 

  • Typo from me, it should read:

    for(i=0; i < (track.size() - 2), i+=2)

    (track.size() - 2) note that -2 is important to avoid out of bounds error

    Since the refences in the loop are at most [i+3] (=4 values) the loop should end 4 values before the end to not reference an address outside the array bounds.

    For example:

    track[lat1,lon1,lat2,lon2,lat3,lon3,lat4,lon4,lat5,lon5]

    This array has a size of 10 elements. That means the addresses 0 to 9.

    The index gets the values i=0, 2, 4, 6 because the end condition for the loop is i<(track.size()-2), i.e. i<10-2 which is according to the increment i+=2 the address 6 in the array .

    If i=6 then in the loop the address for track[i+3] refers to 9 (lon5) which is the last available address in this array. If you would try to reference the address track[10] then it crashes because this address is outside the array bounds. Keep in mind that an array starts with address 0.

  • Know its been two weeks but I realised I forgot to ask, now that the points are drawn is there a way to draw a line between each point?(basically to connect them up like in a dot to dot).