ossw/ossw-firmware-s120

Analog watchfaces

Opened this issue · 3 comments

Add support for analog watchfaces

vaspa commented

I was also thinking about the way to define analog watch faces and I see at least 3 options (in my opinion the first category is the most relevant):

  1. use polar coordinates with graphics primitives like: line segment, point, [filled] circle and circular segment of different style (and their combinations). Suitable for the following watch faces:
    image image image image image image
  2. use predefined set of bitmaps for each watch hand, need 8 bitmaps for 60 positions (for symmetrical hands), like:
    image image
  3. particular styles where special rendering is needed (or a set of 60 images), like:
    image image

First group looks the best and will not take too much space, the question is how to describe it in json :)

vaspa commented

OK, here we go. Extending the set of controls.
The most useful is the radial line segment, sufficient to make a classic dial. We need a pole (center), angle, radius and optional line width (line styles could be added afterwards). I propose using 360 degrees starting from the upper point (12 o'clock).
Simple example of an analog watch dial. Need a scale ratio = 30 for hours to go from 12 hours to 360 degrees. For minutes and second ratio = 6.

{ "type": "radial-line",
"pole": {"x": 72, "y": 72}, "angle": {"type": "internal", "value": "hour", "ratio": 30}, "radius": 50,
"style": {"width": 5} },
{ "type": "radial-line",
"pole": {"x": 72, "y": 72}, "angle": {"type": "internal", "value": "minutes", "ratio": 6}, "radius": 60,
"style": {"width": 3} },
{ "type": "radial-line",
"pole": {"x": 72, "y": 72}, "angle": {"type": "internal", "value": "seconds", "ratio": 6}, "radius": 70,
"tail": 20,
"style": {"width": 1} },

To generalize, I also propose to define a common way to draw any simple graphical object (lines, points, circles and also images maybe) using position with both Cartesian (by default) or polar coordinates ;-)
For scaling from internal properties to the screen coordinates we have to use affine transformation (x' = ratio * x + shift).
Let's start from from drawing two circles going clockwise for hours and minutes.

{ "type": "filled-circle",
"position": {"type": "polar", "pole": {"x": 72, "y": 72}, "angle": {"type": "internal", "value": "hours", "ratio": 30}, "radius": {"type": "constant", "value": 50}},
"size": {"type": "constant", "value": 5} },
{ "type": "circle",
"position": {"type": "polar", "pole": {"x": 72, "y": 72}, "angle": {"type": "internal", "value": "minutes", "ratio": 6}, "radius": {"type": "constant", "value": 60}},
"size": {"type": "constant", "value": 5},
},

Here is an image which goes with seconds around the center like a satellite:

{ "type": "image",
"position": {"type": "polar", "pole": {"x": 72, "y": 72}, "angle": {"type": "internal", "value": "seconds", "ratio": 6}, "radius": {"type": "constant", "value": 60}},
"image": {"type": "resource", "id": "satellite"} }

Here is a line from hours hand to minutes hand. Need to define A position and B position.

{ "type": "line",
"a": {"type": "polar", "pole": {"x": 72, "y": 72}, "angle": {"type": "internal", "value": "hour", "ratio": 30},
"radius": {"type": "constant", "value": 50}},
"b": {"type": "polar", "pole": {"x": 72, "y": 72}, "angle": {"type": "internal", "value": "minutes", "ratio": 6},
"radius": {"type": "constant", "value": 70}},
"style": {"width": 5} }

Final example is a donut segment. Analogous to rectangle in Cartesian coordinates it can be defined via two points A and B. Here we have the same pole and only polar coordinates are useful.

{ "type": "donut",
"pole": {"x": 72, "y": 72},
"a": {"angle": {"type": "constant", "value": "0"}, "radius": {"type": "constant", "value": 60}},
"b": {"angle": {"type": "internal", "value": "minutes", "ratio": 6}, "radius": {"type": "constant", "value": 70}} }

Therefore, on the lower level we need drawing for:

  • Lines with given width;
  • Circles;
  • Filled circles;
  • Donut segments.