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.

  • Prime is an autocorrect mistake I forgot to delete when typing the comment, oops. 

    I’ve removed the word prime from my comment.

  • I still feel like I'm missing some context here. Are you literally saying that the following doesn't work:

    minuteHandAngle = heading + Math.PI;

    But the following does work?

    minuteHandAngle = (heading + Math.PI);

    That doesn't make a whole lot of sense to me. Can you share what error you were getting and exactly what code you had? (And exactly what code you have now?) Just the one line would be enough.

    I'm just super curious as to what happened.

  • Also, I think I gave bad advice once again (sorry).

    If heading ranges from -pi to pi, that must mean that 0 is north and -pi/pi is south.

    So adding pi to heading doesn't make a whole lot of sense :/, if you want to map it to 0 to 2pi, where 0/2pi is north. That actually explains why north and south were flipped in your results.

    I thought about a bit more, and I'm gonna go back to my original recommendation of:

    minuteHandAngle = heading;

    I mean, when using sin and cos on an angle, it shouldn't matter whether it ranges from -pi to pi or 0 to 2pi, as long as 0 is north / up.

    For example: sin 270 degrees = sin -90 degrees.

    Or equivalently, sin (3/2) pi = sin (-1/2) pi

    My bad.

  • current code

    width = targetDc.getWidth();

    height = targetDc.getHeight();

    targetDc.setColor(Graphics.COLOR_RED, Graphics.COLOR_TRANSPARENT);

    minuteHandAngle = (heading + Math.PI);

    targetDc.fillPolygon(generateHandCoordinates(screenCenterPoint, minuteHandAngle, -22, 0, 8));

    Previous code

    width = targetDc.getWidth();

    height = targetDc.getHeight();

    targetDc.setColor(Graphics.COLOR_RED, Graphics.COLOR_TRANSPARENT);

    minuteHandAngle = heading + Math.PI;

    targetDc.fillPolygon(generateHandCoordinates(screenCenterPoint, minuteHandAngle, -22, 0, 8));

    I think it may have also been cos I was using Position.Info as it kept returning something about not being able to find symbol Info. But I don't know really, I don't really have a clue what I'm doing.

  • I don't see why you would've needed parentheses around "heading + Math.PI", but in any case, I think the correct code is actually "minuteHandAngle = heading;". If you use that code, you won't have to add a minus sign to the angle, to correct it. Sorry about the bad advice haha.

    I think it may have also been cos I was using Position.Info as it kept returning something about not being able to find symbol Info.

    Yeah, you can't access Position.Info directly like that -- you would have to call Position.getInfo() instead. Position.Info is the name of a class, but what you need is an instance of the class (an object that has values.) But you don't need to do that as using ActivityInfo.heading is simpler anyway.

  • Well i’ve changed it to just heading and removed the brackets and it still works so perhaps it was only just me trying to use position info instead of activity info.

    Anyway now that that its all done I can focus on finding or creating my own equarectangular mercator map (or whatever its called) of europe and some of its roads. It seems the projection I was using before wasn’t working with the code.

    I do have one last question unrelated to the arrow however. Hypothetically would it be possible to calculate what motorway you were on and what junction would be upcoming using both your location and heading? I imagine it would require a lot of “If such and such then return such n such text”

  • can I have a working code for that red triangle in the screenshot you have posted
    that screenshot is exactly what I need for my App
    drawing a triangle in a position on the dial

  • As I said the basics can be found in the analog sample in the SDK, as the logic is close to drawing watch hands.

    You want to calculate the three corners of the triangle (the right and left hands would be a few degrees different than the center, and the length of those is also shorter.  Then use fillPolygon with those 3 corners

  • FWIW, here's the function that I use to draw a nice arrow pointing in a particular direction. 

     function drawMarkArrow(dc){ // Arrow icon, no lay-lines - VA-HR only
    		var offsetX = 0, offsetY=0;
    		var transformedCoords = [[0,0],[0,0],[0,0]];
    		var i;
    		offsetX = screenWidth/6; //44; // from earlier... needs scaling for venusq
    		offsetY = screenHeight/2; //135;
    		for (var sideIndex = 0; sideIndex<=1; sideIndex++){
    			var arrowImagePoints = (sideIndex==0?leftArrowImagePoints:rightArrowImagePoints);
    			for (i =0; i<=2; i++){ // three points of the arrow
    				var r = arrowImagePoints[i][0]; // dist from centre of arrow
    				var theta = arrowImagePoints[i][1] + Math.toRadians(unSmoothedMarkBearingToCourse.toFloat()); 
    				var rotatedCoordsX =  r * Math.sin(theta);
    				var rotatedCoordsY =  -r * Math.cos(theta);
    				transformedCoords [i][0] = rotatedCoordsX + offsetX;
    				transformedCoords [i][1] = rotatedCoordsY + offsetY;		
    			}	
    			dc.setColor(sideIndex==0?0xFFFF00:Graphics.COLOR_YELLOW, Graphics.COLOR_TRANSPARENT); //color for yellow left hand side			
    			dc.fillPolygon(transformedCoords);	
    		}

  • Thank you jim_m_58 and Alan.raceQs for the answers
    @Alan.raceQs can you please give me more explanation about these undeclared variables in your code: unSmoothedMarkBearingToCourse, rightArrowImagePoints, leftArrowImagePoints ?