I'm creating a display for a GPS-based embedded system and would like to have an arrow indicating the current bearing. I'd love the arrow to have a 3d appearance by rotating it on a plane tilted up toward the camera, as per these images.

Bearing arrow at 0 degrees and 40 degrees

My original idea was to have an ellipse that represents a circle on the tilted plane and plot the bearing angle as a point on the ellipse (this would be the 'head' of the arrow). The rest of the arrow would be drawn by offsetting the bearing by two fixed angles (say 160 and 200 degrees) to make the two points of the tail, then plotting those on the ellipse. The line connecting these two tail points would have its midpoint moved towards the head point to create the arrow shape.

Drawing the arrow by calculating offset points on a ellipse

As the target is a bitmap display and I would have to do the rendering myself, is there an algorithm for rotating a bitmap on an arbitrary plane given an angle of the plane and the angle of rotation? Or is there a better way to plot the arrow as a 3d shape, then translate to 2d?

  • \$\begingroup\$ What are your available drawing primitives, if any? If it's polygons, then draw everything as polygons including the circle, as a high-N-gon. But put each x,y point first through perspective calculation (omitted here, but it wont be very big) and done! For debugging, don't do the transform... \$\endgroup\$ – david van brink Oct 19 '14 at 0:44
  • \$\begingroup\$ I'm not using a drawing library, so don't really have any primitives available except BitBlt. Any pointers to your omitted perspective calculation? Thanks. \$\endgroup\$ – simonhaines Oct 19 '14 at 3:41
  1. Take an arrow image without any perspective

enter image description here

  1. Rotate the image by the desired amount of degree

enter image description here

  1. Scale the image vertically.

enter image description here

| improve this answer | |
  • \$\begingroup\$ Hey this is not bad. Merely scaling the image vertically doesn't provide any perspective though. But it gives me an idea: scale each row horizontally by a value in the range of something like 0.6 for the top row and 1.0 for the bottom. This way perspective is simulated and it can be done at the same time as the bitmap rotation using something like this. Yeah? \$\endgroup\$ – simonhaines Oct 19 '14 at 3:32
  • \$\begingroup\$ @simonhaines You didn't say what technology you are using, but most graphic APIs support rotation and scaling out-of-the-box. They often also do it GPU accelerated, which is much faster than doing it completely on the CPU like it is done in that article you linked. \$\endgroup\$ – Philipp Oct 19 '14 at 5:13
  • \$\begingroup\$ @simonhaines Your proposed approach of "pinching" the top by 0.6, the middle by 0.8, and the bottom by 1.0 will give you a reasonable trapezoid. You can play with the vertical scale and pinch amounts. This isn't proper perspective. Specifically, a diagonal from top left to bottom right will end up curved. (Really! Try it.) But it is cheap, easy to understand & implement, and depending what you're drawing, might give the desired visual cues. I say, give it a go! \$\endgroup\$ – david van brink Oct 19 '14 at 19:34
  • \$\begingroup\$ @Philipp sorry when I mentioned 'embedded system' I really meant raw access to the graphics framebuffer (no GPU). Tight memory constraints mean no drawing library like cairo either. \$\endgroup\$ – simonhaines Oct 19 '14 at 22:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.