vega / vega-lite

A concise grammar of interactive graphics, built on Vega.
https://vega.github.io/vega-lite/
BSD 3-Clause "New" or "Revised" License
4.69k stars 612 forks source link

Overwriting heigth and width values in concat operators #9316

Open ebocher opened 7 months ago

ebocher commented 7 months ago

Manage width/heigth with concatenation operators

It seems that vega doesn't owerwrite the width/heigth properties specificied in the concatenation element.

Bellow a spec to draw OSM tiles.

{    
  "height": 200,
  "width": 200,
  "layer": [
    {
      "data": {
        "sequence": {"start": 0, "stop": 4, "as": "a"},
        "name": "tile_list"
      },
      "mark": {
        "type": "image",
        "clip": true,
        "height": {"expr": "256"},
        "width": {"expr": "256"}
      },
      "encoding": {
        "url": {"field": "url", "type": "nominal"},
        "x": {"field": "x", "scale": null, "type": "quantitative"},
        "y": {"field": "y", "scale": null, "type": "quantitative"}
      },
      "transform": [
        {"calculate": "sequence(0, 4)", "as": "b"},
        {"flatten": ["b"]},
        {
          "calculate": "'https://tile.opentopomap.org/' + 17 + '/' + (datum.a + floor((invert('projection', [0, 0])[0] + 180) / 360 * pow(2, 17)) + pow(2, 17)) % pow(2, 17) + '/' + ((datum.b + floor((1 - log(tan(invert('projection', [0, 0])[1] * PI / 180) + 1 / cos(invert('projection', [0, 0])[1] * PI / 180)) / PI) / 2 * (pow(2, 17))))) + '.png'",
          "as": "url"
        },
        {
          "calculate": "(datum.a * 256  + round((floor((invert('projection', [0, 0])[0] + 180) / 360 * pow(2, 17)) - (invert('projection', [0, 0])[0] + 180) / 360 * pow(2, 17)) * 256)) + (256  / 2)",
          "as": "x"
        },
        {
          "calculate": "(datum.b * 256  + round((floor((1 - log(tan(invert('projection', [0, 0])[1] * PI / 180) + 1 / cos(invert('projection', [0, 0])[1] * PI / 180)) / PI) / 2 * (pow(2, 17)))-(1 - log(tan(invert('projection', [0, 0])[1] * PI / 180) + 1 / cos(invert('projection', [0, 0])[1] * PI / 180)) / PI) / 2 * (pow(2, 17))) * 256 )) + (256  / 2)",
          "as": "y"
        }
      ]
    },
    {
      "mark": {
        "type": "geoshape"
      },
      "projection": {
        "center": { "expr": "[-2.079943,47.654317]"},
        "rotate": {"expr": "[0, 0, 0]"},
        "scale": {"expr": "256 * pow(2, 17) / (2 * PI)"},
        "translate": {"expr": "[width / 2, height / 2]"},
        "type": "mercator"
      }
    }
  ]
}

It returns the expected OSM tiles.

image

But in the following spec the height and width values do not match the values specified in "layer"


{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "hconcat": [
    {
      "width": 300,
      "height": 300,
      "data": {
        "values": [
          {"a": "A", "b": 28},
          {"a": "B", "b": 55},
          {"a": "C", "b": 43},
          {"a": "D", "b": 91},
          {"a": "E", "b": 81},
          {"a": "F", "b": 53},
          {"a": "G", "b": 19},
          {"a": "H", "b": 87},
          {"a": "I", "b": 52}
        ]
      },
      "mark": "bar",
      "encoding": {
        "x": {"field": "a", "type": "nominal", "axis": null},
        "y": {"field": "b", "type": "quantitative", "axis": null}
      }
    },
    {
      "width": 200,
      "height": 200,
      "layer": [
        {
          "data": {
            "sequence": {"start": 0, "stop": 4, "as": "a"},
            "name": "tile_list"
          },
          "mark": {
            "type": "image",
            "clip": true,
            "height": {"expr": "256 *  pow(2, 17 - ceil(17))"},
            "width": {"expr": "256 *  pow(2, 17 - ceil(17))"}
          },
          "encoding": {
            "url": {"field": "url", "type": "nominal"},
            "x": {"field": "x", "scale": null, "type": "quantitative"},
            "y": {"field": "y", "scale": null, "type": "quantitative"}
          },
          "transform": [
            {"calculate": "sequence(0, 4)", "as": "b"},
            {"flatten": ["b"]},
            {
              "calculate": "'https://tile.opentopomap.org/' + ceil(17) + '/' + (datum.a + floor((invert('projection', [0, 0])[0] + 180) / 360 * pow(2, ceil(17))) + pow(2, ceil(17))) % pow(2, ceil(17)) + '/' + ((datum.b + floor((1 - log(tan(invert('projection', [0, 0])[1] * PI / 180) + 1 / cos(invert('projection', [0, 0])[1] * PI / 180)) / PI) / 2 * (pow(2, ceil(17)))))) + '.png'",
              "as": "url"
            },
            {
              "calculate": "(datum.a * 256 *  pow(2, 17 - ceil(17)) + round((floor((invert('projection', [0, 0])[0] + 180) / 360 * pow(2, ceil(17))) - (invert('projection', [0, 0])[0] + 180) / 360 * pow(2, ceil(17))) * (256 * pow(2, 17 - ceil(17))))) + (256 *  pow(2, 17 - ceil(17)) / 2)",
              "as": "x"
            },
            {
              "calculate": "(datum.b * 256 *  pow(2, 17 - ceil(17)) + round((floor((1 - log(tan(invert('projection', [0, 0])[1] * PI / 180) + 1 / cos(invert('projection', [0, 0])[1] * PI / 180)) / PI) / 2 * (pow(2, ceil(17))))-(1 - log(tan(invert('projection', [0, 0])[1] * PI / 180) + 1 / cos(invert('projection', [0, 0])[1] * PI / 180)) / PI) / 2 * (pow(2, ceil(17)))) * (256 * pow(2, 17 - ceil(17))))) + (256 *  pow(2, 17 - ceil(17)) / 2)",
              "as": "y"
            }
          ]
        },
        {
          "mark": {"type": "geoshape"},
          "projection": {
            "center": {"expr": "[-2.079942,47.654317]"},
            "rotate": {"expr": "[0, 0, 0]"},
            "scale": {"expr": "256 * pow(2, 17) / (2 * PI)"},
            "translate": {"expr": "[width / 2, height / 2]"},
            "type": "mercator"
          }
        }
      ]
    }
  ]
}

Result : image

Expected : image

Checklist

ebocher commented 7 months ago

Not sure if it's related to the same issue but combined a geoshape with the OSM tiles chart returns a blank chart.

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "hconcat": [
    {
      "width": 300,
      "height": 300,
      "data": {
        "values": [
          {
            "type": "Feature",
            "geometry": {
              "type": "Polygon",
              "coordinates": [
                [
                  [-0.67541641, 47.366634369],
                  [-0.67541641, 47.530906677],
                  [-0.431031048, 47.530906677],
                  [-0.431031048, 47.366634369],
                  [-0.67541641, 47.366634369]
                ]
              ]
            },
            "properties": {"ID_ZONE": 1}
          }
        ]
      },
      "projection": {"type": "mercator"},
      "mark": {"type": "geoshape"}
    },
    {
      "height": 200,
      "width": 200,
      "layer": [
        {
          "data": {
            "sequence": {"start": 0, "stop": 4, "as": "a"},
            "name": "tile_list"
          },
          "mark": {
            "type": "image",
            "clip": true,
            "height": {"expr": "256"},
            "width": {"expr": "256"}
          },
          "encoding": {
            "url": {"field": "url", "type": "nominal"},
            "x": {"field": "x", "scale": null, "type": "quantitative"},
            "y": {"field": "y", "scale": null, "type": "quantitative"}
          },
          "transform": [
            {"calculate": "sequence(0, 4)", "as": "b"},
            {"flatten": ["b"]},
            {
              "calculate": "'https://tile.opentopomap.org/' + 17 + '/' + (datum.a + floor((invert('projection', [0, 0])[0] + 180) / 360 * pow(2, 17)) + pow(2, 17)) % pow(2, 17) + '/' + ((datum.b + floor((1 - log(tan(invert('projection', [0, 0])[1] * PI / 180) + 1 / cos(invert('projection', [0, 0])[1] * PI / 180)) / PI) / 2 * (pow(2, 17))))) + '.png'",
              "as": "url"
            },
            {
              "calculate": "(datum.a * 256  + round((floor((invert('projection', [0, 0])[0] + 180) / 360 * pow(2, 17)) - (invert('projection', [0, 0])[0] + 180) / 360 * pow(2, 17)) * 256)) + (256  / 2)",
              "as": "x"
            },
            {
              "calculate": "(datum.b * 256  + round((floor((1 - log(tan(invert('projection', [0, 0])[1] * PI / 180) + 1 / cos(invert('projection', [0, 0])[1] * PI / 180)) / PI) / 2 * (pow(2, 17)))-(1 - log(tan(invert('projection', [0, 0])[1] * PI / 180) + 1 / cos(invert('projection', [0, 0])[1] * PI / 180)) / PI) / 2 * (pow(2, 17))) * 256 )) + (256  / 2)",
              "as": "y"
            }
          ]
        },
        {
          "mark": {"type": "geoshape"},
          "projection": {
            "center": {"expr": "[-2.079943,47.654317]"},
            "rotate": {"expr": "[0, 0, 0]"},
            "scale": {"expr": "256 * pow(2, 17) / (2 * PI)"},
            "translate": {"expr": "[width / 2, height / 2]"},
            "type": "mercator"
          }
        }
      ]
    }
  ]
}
ebocher commented 6 months ago

Dear all,

any comments or ideas to solve this issue ?

Thanks