How do I draw a simple heading arrow in the centre of the screen?

I’m been using tskf’s offline gps map for a while and I think it’s a brilliant data field but I would like to see if I could add a heading arrow (the code is open source) as I feel it would be perfect for me then.

The datafield does show your position as a red dot in the middle of the screen and appears to be generated simply by just these bits of code in the function onUpdate(dc) part of the lone MC file.

dc.setColor(0xFF0000, -1);

dc.fillRectangle(x-2, y-2, 4,4);

Not being a coder (although I have tried scratch) I have no idea if that is the case but I was wondering if it would be possible to replace that with a small heading arrow instead in the same position and if so how? I’d be very grateful for some help.

P.S: Just in case you think I might be being lazy asking like this I have tried to do it myself for a few days by looking at the samples and documentation then typing stuff out on eclipse but I can’t find myself understanding it very well. 

P.P.S: I would ask tskf themselves but I don’t want to bother them seeing as the field doesn’t appear to have been updated for over a year now.

  • Sorry for not getting back to you, I’ve managed to produce something that looks like a compass needle and it appears to follow compass heading (sometimes) until you turn on gps at which point it goes funny. I’m not sure how you find a direction in monkey c (i’m not very good at coding). My device is a vivoactive 3 if that helps.

    Also here is the source code. https://github.com/tskf/MapOfflineGPS/blob/master/map.mc

    Thanks

  • I have failed to fully reverse engineer your code, but it seems you're using Activity.getActivityInfo().currentLocation, which returns your current position (latitude, longitude), which I can't visualise as a compass needle. 

    you're asking for a "direction", but given the preceding discussion, It's not clear which direction you are after.

    If you want direction of travel, then you should be using Position:info:Heading

    If you're after the orientation of the device to Magnetic North, you need to use Sensor.Info.mag to get the magnetometer readings for each of the devices axes of the device and then use  Sensor.Info.accel to determine the orientation of the device. 

  • I have failed to fully reverse engineer your code, but it seems you're using Activity.getActivityInfo().currentLocation, which returns your current position (latitude, longitude), which I can't visualise as a compass needle. 

    Yes, it seems that the previous code posted here was closer to the right track:

    https://forums.garmin.com/developer/connect-iq/f/discussion/279455/how-do-i-draw-a-simple-heading-arrow-in-the-centre-of-the-screen/1340504#1340504

    function onUpdate(dc)

        { var g = Activity.getActivityInfo().currentLocation;

            var width;

            var height;

            var screenWidth = dc.getWidth();

            var heading = Activity.getActivityInfo().currentHeading;

    ...

    minuteHandAngle = (heading / 1.0) * Math.PI * 2;

    If you want direction of travel, then you should be using Position:info:Heading

    If it's a data field, you could also use ActivityInfo.currentHeading.

  • I did use activityinfo.currentHeading. Sorry if that wasn’t too clear. Activity.getactivityinfo().current location at the fop is actually fir a different part if the code to do with the map tskf implemented.

  • I did use activityinfo.currentHeading. Sorry if that wasn’t too clear. Activity.getactivityinfo().current location at the fop is actually fir a different part if the code to do with the map tskf implemented.

    I get that, but:

    You make it sound like that's the code you want us to look at at, but of course, that's the code that your code is *based* on, which has no reference to ActivityInfo.currentHeading.

    Also, I'm not sure about this code that you posted:

    minuteHandAngle = (heading / 1.0) * Math.PI * 2;

            targetDc.fillPolygon(generateHandCoordinates(screenCenterPoint, minuteHandAngle, 70, 0, 2));

    generateHandCoordinates looks like this:

        function generateHandCoordinates(centerPoint, angle, handLength, tailLength, width) {

            // Map out the coordinates of the watch hand

            var coords = [[-(width / 1), tailLength], [-(width / 4), -handLength], [width / 5, -handLength], [width / 1, tailLength]];

            var result = new [4];

            var cos = Math.cos(angle);

            var sin = Math.sin(angle);

    Given that currentHeading is already in radians, and Math.cos() / Math.sin() take an angle in radians, why multiply by 2 pi?

    Maybe try changing your code to this:

    minuteHandAngle = heading;

    EDIT: or, more likely:

    minuteHandleAngle = heading + Math.PI;

    See forums.garmin.com/.../1342361

    EDIT: after further reflection, I think it should actually be:

    minuteHandAngle = heading;

  • Okay, looking at the Analog sample, I see why you multiplied by 2 pi:

            var minuteHandAngle = (clockTime.min / 60.0) * Math.PI * 2;

    But you have to realize that currentHeading is already an angle in radians. The code in the analog sample is doing something which is unrelated to your task: converting the position of an analog clock's minute hand into an angle in radians.

  • Maybe try changing your code to this:

    minuteHandAngle = heading;

    The only thing to note here is that currentHeading ranges from -pi and pi radians (sadly not documented), whereas the Analog sample takes an angle which ranges from 0 to 2 pi.

    So you may have to adjust the code slightly:

    minuteHandleAngle = heading + Math.PI;

    I haven't really looked at the Analog sample in depth, but it seems like you'd have to make that adjustment to make currentHeading work with the code you used from the sample.

  • Thats helpful! I’ll try it tomorrow. Thankyou

  • So this is what I did, at first I tried what you said

    minuteHandAngle = heading + Math.PI

    It kept returning an error until I realised I need curved brackets like this (heading + Math.PI.)

    The next problem I ran into was the arrow was pointing South when facing North so I just added a minus sign in front of the number that controls the height of the arrow. Now all I got to do is test with gps, hopefully it works. Pleased so far though.

    Edit: Removed the word prime.

  • I'm glad it's working for you, but I'm not sure I understand this:

    So this is what I did, at first I tried what you said

    minuteHandAngle = heading + Math.PI

    It kept returning an error until I realised I need curved brackets like this (heading + Math.PI.)Prime

    I did have a typo where I typed "Math.Pi" instead of "Math.PI".

    I'm not sure how "(heading + Math.PI.)Prime" would work. That doesn't look like valid code.