DataField Obscurity

I understand I can getObscurityFlags() is available in the DataField class which indicates whether there are obscured portions of the screen.

But how to know what portions of the view are obscured - something like 'isObscured(x,y)' ? If layouts are the answer then doesn't that mean I need a layout for every device to be supported - and I would then also need to know dimensions of each device - is this available?

Thanks in advance for a nudge in the right direction...
  • With the obscurity flag, you can see which edge is obscured. Left, right, top bottom (an "and" with something like OBSCURE_BOTTOM) None of them will be set on rectangular devices.

    As far as the max size of the DF (including parts that could be obscured, you can get that with dc.getWidth() and dc.getHeight(). The info on sizes is also in the UX guide, Appendix C (it's in the SDK).

    As an option to using layouts, you can instead use direct dc calls (if the left is obscured, just shift something towards the right, etc)
  • Thanks - but let me be more specific...If I attempt to drawPoint(0,0) on a fenix - it is obscured and doesn't display. OK makes sense. So what I need to know is which points are obscured - the flags don't help much and knowing the rectangular dimensions doesn't help either.

    As an example assume I'm drawing a horizontal bar graph to span the screen (basically a rectangle oriented horizontally) - it seems I will need to know what the non-obscured upper left and lower right points will be and I don't see how to get that information.

    UPDATE - ok i was excited about the ux guide app C - but that's not quite enough so I'll have to use simulator and trial-and-error for each device.

    UPDATE2 - For a round device, using the parametric equation for a circle and the dimension data in app c, one can derive approximations of the obscurity horizon such as for a fenix 3 (0-217,0-217): x=trunc(109+(109*cos([0..pi)])) and y= trunc(109+(109*sin([0..pi]))) to get the range of x/y's over the lower semi-circle (in increments of 0.02 radians). [note to self - double check orientation of connectiq trig functions].

    So in theory, given the rectangular dimensions of the device one can programmatically determine the obscurity horizon. As a further exercise, one can solve for x given y if that is desired - and vice versa. This is actually a bit easier: y = sqrt(109*109 - x*x) , so at x=169, y=sqrt(109*109-60*60) = 91 => 200 (+109).

    For example at x=217, y=109 (obviously) and for x=200=y=168. Whether the device actually behaves this way is to be determined. I'll continue this later...

    This is the full circle case (obscurity flags=15) ; more on the other cases to follow.

  • OK I decided to try something mainly as an academic exercise to work with DFs in round faces.

    The following code ('onUpdate' and supporting functions) generates a random X within the DF width and draws 2 points at the min/max Y so it is along the arc of the DF (or rectangular edge) - works with rectangular face as well which is the trivial case. It should be device agnostic as it is based on DF dimensions and obscurity flags (tested on fenix sim).

    The attached photo - if you look really closely - shows the red points on the edges/arcs.


    // just invoke the test
    function onUpdate(dc) {
    testArcPoints(dc);
    }

    // clear and draw 2 points (upper and lower Y) at a random X
    function testArcPoints(dc) {
    dc.clear();
    drawYAtX(dc, width, height, getObscurityFlags(), (Math.rand()%width));
    }

    // compute Y given circle radius and x
    function computeY(radius, x) {
    return (Math.sqrt((radius*radius)-((x)*(x))));
    }

    // draw the 2 points
    function drawIt(dc, x, lowerY, upperY) {
    dc.drawPoint(x,lowerY);
    dc.drawPoint(x,upperY);
    }

    // use obscurity flags, width & height and random x and draw upper/lower Y
    function drawYAtX(dc,w,h,o,x) {
    var r = (w/2);
    var y;
    var lowerY;
    var upperY;

    dc.setColor(Graphics.COLOR_RED, Graphics.COLOR_WHITE);
    dc.setPenWidth(4);

    if (o == 0) { // rectangle
    drawIt(dc,x,0,(h-1));
    }

    if (o == 15) { // full-circle (One Data Field : Field One)
    y = computeY(r, (x-r));
    drawIt(dc, x, (y+r),(r-y));
    }

    if (o == 7) { //upper semi-circle
    y = computeY(r, (x-r));
    drawIt(dc, x, h, (r-y));
    }

    if (o == 13) { // lower semi-circle
    // rat=1 for semi-circle and 1.5 for bottom third
    var rat = ((w / h) * 0.5);
    r = (rat * h);

    y = computeY(r, (x-r));
    drawIt(dc, x, (y/rat), 0);
    }

    if (o == 9) { // lower left quarter-circle (layout B 3&4)
    // the radius is actually the full circle (so use width)
    y = computeY(w, (x-w));
    drawIt(dc, x, y, 0);
    }

    if (o == 12) { // lower right quarter-circle (layout B 3&4)
    y = computeY(w, x);
    drawIt(dc, x, y, 0);
    }

    if (o == 3) { // upper left quarter-circle
    y = computeY(w, (w-x));
    drawIt(dc, x, h, (h-y));
    }

    if (o == 6) { // upper right quarter circle
    y = computeY(w, x);
    drawIt(dc, x, h, (h-y));
    }

    if (o == 5) {
    // x:0..w/2 => w/2..0
    // x:w/2 .. w => 0 .. w/2
    y = computeY(r, (x-r));
    lowerY = (h / 2) - y;
    if (lowerY < 0) { lowerY = 0; }
    upperY = (h / 2) + y;
    if (upperY > h) { upperY = h; }
    drawIt(dc, x, lowerY, upperY);
    }

    if (o == 1) {
    // x:0..w => w/2..0
    // x:w/2 .. w => 0 .. w/2
    y = computeY(w, (x-w));
    lowerY = (h / 2) - y;
    upperY = (h / 2) + y;
    drawIt(dc, x, ((lowerY < 0) ? 0 : lowerY), ((upperY > h) ? h : upperY));
    }

    if (o == 4) {
    // x:0..w => w/2..0
    // x:w/2 .. w => 0 .. w/2
    y = computeY(w, x);
    lowerY = (h / 2) - y;
    upperY = (h / 2) + y;
    drawIt(dc, x, ((lowerY < 0) ? 0 : lowerY), ((upperY > h) ? h : upperY));
    }

    }
    community.garmin.com/.../1308097.jpg
  • If you use layouts, or device-specific drawing code, you don't need to know at runtime which pixels are visible. You can check the obscurity flag and dimensions of the draw context to figure out what you need to render. Something like this..

    const OBSCURE_ALL_SIDES = (OBSCURE_TOP | OBSCURE_BOTTOM | OBSCURE_RIGHT | OBSCURE_LEFT);
    const OBSCURE_TOP_HALF = (OBSCURE_TOP | OBSCURE_RIGHT | OBSCURE_LEFT);
    const OBSCURE_BOTTOM_HALF = (OBSCURE_BOTTOM | OBSCURE_RIGHT | OBSCURE_LEFT);

    (:is_round_240x240) function selectLayout(width, height, obscurity)
    {
    var obscurity = getObscurityFlags();

    if (OBSCURE_ALL_SIDES == obscurity) {
    return Rez.Layouts._1_Field;
    }
    else if (OBSCURE_TOP_HALF == obscurity) {
    if (height == 120) {
    return Rez.Layouts._2_Field_Top;
    }
    else (height == 77) {
    return Rez.Layouts._3_Field_A_Top; // or 4 Field A Top
    }
    else (height == 119) {
    return Rez.Layouts._3_Field_B_Top;
    }
    }
    else if (OBSCURE_BOTTOM_HALF == obscurity) {
    if (height == 118) {
    return Rez.Layouts._2_Field_Bottom;
    }

    // ...
    }


    ???????Travis