cartocss - уровни отрисовки и проверка числовых значений тега

Товарищи!

Вот есть у меня объекты. Нужно их отрисовывать разными иконками. Нужно, чтобы проблемные объекты рисовались поверх непроблемных.
В mapcss за это отвечал параметр z-index, но в cartocss его нет.

Вот пример mss-стиля:


#tp-quality-power-low[zoom >= 5]{
  marker-allow-overlap: true; 
  // мало:
  marker-file: url('icons/power_tp_quality_red.png');
}
#tp-quality-power-hight[zoom >= 5]{
  marker-allow-overlap: true; 
  // высоко:
  marker-file: url('icons/power_tp_quality_yellow.png');
}
#tp-quality-power-good[zoom >= 5]{
  marker-allow-overlap: true; 
  // норм:
  marker-file: url('icons/power_tp_quality_green.png');
}
#tp-quality-power-no[zoom >= 5]{
  marker-allow-overlap: true; 
  // нет данных:
  marker-file: url('icons/power_tp_quality_magenta.png');
}

Как сделать так, чтобы #tp-quality-power-low всегда рисовались поверх всех остальных? Думал, что будет очерёдность в зависимости от описания: все будут либо красные либо cons/power_tp_quality_magenta.png, но нет - чаще зелёные всех перекрывают. Видать очерёдность работает только в рамках одного правила в {}.

И ещё вопрос п очисловым значениям тега. В mapcss раньше можно было проверять значение числового тега и написать что-то вида:


/* low */
node|z2-[power=sub_station][t1_u_f<=220],
node|z2-[power=sub_station][t2_u_f<=220]
{icon-image:"power_tp_quality_red.png"; z-index:10}

/* hight */
node|z2-[power=sub_station][t1_u_f>=242],
node|z2-[power=sub_station][t2_u_f>=242]
{icon-image:"power_tp_quality_yellow.png"; z-index:14}

/* good */
node|z2-[power=sub_station][t1_u_f<=242][t1_u_f>=220],
node|z2-[power=sub_station][t2_u_f<=242][t2_u_f>=220]
{icon-image:"power_tp_quality_green.png"; z-index:16}

И это работало. В cartocss же теперь не работает. Только сравнение с текстовой строкой вида: [t1_u_f=“220”] срабатывает. Если же писать [t1_u_f>=220] - то не работает. Приходится оформлять в виде sql-запроса:


  - id: drsk-tp-quality-power-low
    geometry: point
    <<: *extents
    Datasource:
      <<: *osm2pgsql
      table: |-
        (SELECT
            way,
            power,
            COALESCE(name, alt_name, ref) AS name,
            operator,
            t1_u_f,
            t2_u_f
        FROM planet_osm_point
        WHERE power IN ('substation', 'sub_station')
        AND (t1_u_f::numeric <= 220 or t2_u_f::numeric <= 220)
        ) AS drsk_tp_quality_power_low
    properties:
      minzoom: 5

  - id: drsk-tp-quality-power-hight
    geometry: point
    <<: *extents
    Datasource:
      <<: *osm2pgsql
      table: |-
        (SELECT
            way,
            power,
            COALESCE(name, alt_name, ref) AS name,
            operator,
            t1_u_f,
            t2_u_f
        FROM planet_osm_point
        WHERE power IN ('substation', 'sub_station')
        AND (t1_u_f::numeric >= 242 or t2_u_f::numeric >= 242)
        ) AS drsk_tp_quality_power_hight
    properties:
      minzoom: 5

  - id: drsk-tp-quality-power-good
    geometry: point
    <<: *extents
    Datasource:
      <<: *osm2pgsql
      table: |-
        (SELECT
            way,
            power,
            COALESCE(name, alt_name, ref) AS name,
            operator,
            t1_u_f,
            t2_u_f
        FROM planet_osm_point
        WHERE power IN ('substation', 'sub_station')
        AND (
          (t1_u_f::numeric <= 242 AND t1_u_f::numeric >= 220)
          OR (t2_u_f::numeric <= 242 AND t2_u_f::numeric >= 220)
          )
        ) AS drsk_tp_quality_power_good
    properties:
      minzoom: 5

Скажем так - негибко.
Может быть я чего-то не понимаю?

Очерёдностью рулят из базы данных, в каком порядки элементы приходят, так они и наслаиваются. osm2pgsql например даже на этапе импорта позволяет манипулировать колонкой z_order.

Вот про сортировку от мапбокса, но я думаю ты и сам это должен был найти.
https://tilemill-project.github.io/tilemill/docs/guides/symbol-drawing-order/

Может от движка зависит, я вот быстро попробовал в MapSerfer.NET и там правило отрабатывет корректно


#place-area {
	polygon-fill: #F9E4BE;
 	text-name: [name];
 	text-face-name: 'Arial Regular';	
}

#place-area[population > 0] {
	polygon-fill: #1F7B67;
}

#place-area[population >= 5000] {
	polygon-fill: #E73A95;
}

Хм, попытался выставлять разный z_order руками - не повлияло. Полез посмотрел mml для OSM и увидел, что там просто при выборке SQL-запросом объектов происходит соответствующая сортировка по z_order.
Таким способом в принципе я мог бы и по напряжению в своём случае отсортировать, но… Но это сработает, если будет один запрос по всем подстанциям. А в моём случае я его разделил на три SQL-запроса именно потому, что не получается в mss прописывать условия в зависимости от числовых значений тегов (вторая часть вопроса).

Если бы можно было от числового значения тегов делать условия в mms, то тогда одним sql-запросом можно было бы выбрать все подстанции и отсортировать их по напряжению или по z_order.

Извратился и таки сделал через “виртуальный” тег “level”:
mml:


Layer:
  
  - id: tp-quality-power
    geometry: point
    <<: *extents
    Datasource:
      <<: *osm2pgsql
      table: |-
        (SELECT
            way,
            power,
            z_order,
            COALESCE(name, alt_name, ref) AS name,
            CASE
              WHEN (t1_u_f is null AND t2_u_f is null)
                THEN 'unknown'
              ELSE
                CASE
                  WHEN (t1_u_f::numeric <= 220 OR t2_u_f::numeric <= 220)
                    THEN 'low'
                  ELSE
                    CASE
                      WHEN (t1_u_f::numeric >= 242 OR t2_u_f::numeric >= 242)
                        THEN 'hight'
                      ELSE
                        'normal'
                    END
                END
            END AS level,
            operator,
            t1_u_f,
            t2_u_f
        FROM planet_osm_point
        WHERE power IN ('substation', 'sub_station')
        ORDER BY z_order
        ) AS tp_quality_power
    properties:
      minzoom: 5

ну и mss:


#tp-quality-power[zoom >= 5]{
  marker-allow-overlap: true;
  // нет данных:
  marker-file: url('icons/power_tp_quality_magenta.png');
  [level='low']{marker-file: url('icons/power_tp_quality_red.png');}
  [level='hight']{marker-file: url('icons/power_tp_quality_yellow.png');}
  [level='normal']{marker-file: url('icons/power_tp_quality_green.png');}
}

Ну и соответственно выставил z_order через sql для теста:


update planet_osm_point set z_order=100 WHERE power IN ('substation', 'sub_station') AND ( (t1_u_f::numeric <= 242 AND t1_u_f::numeric >= 220) OR (t2_u_f::numeric <= 242 AND t2_u_f::numeric >= 220) );
update planet_osm_point set z_order=200 WHERE power IN ('substation', 'sub_station') AND (t1_u_f is null and t2_u_f is null);
update planet_osm_point set z_order=300 WHERE power IN ('substation', 'sub_station') AND (t1_u_f::numeric >= 242 or t2_u_f::numeric >= 242);
update planet_osm_point set z_order=400 WHERE power IN ('substation', 'sub_station') AND (t1_u_f::numeric <= 220 or t2_u_f::numeric <= 220);

Сработало как надо, но это какая-то шляпа - делать такую простую вещь через такое место… :frowning:
Почему в mss не отрабатывает простая проверка значения тега как числового значения - мне неведомо…

Да, находил.

пробовал вот так, вроде ведь то же самое… Но не работает:


    #tp-quality-power[zoom >= 5]{
      marker-line-color: black;
      marker-line-width: 1;
      marker-placement: interior;
      marker-width: 15.0;
      marker-height: 15.0;
      marker-fill: green;
      marker-allow-overlap: true;
      // высоко:
      [t1_u_f>=242]{marker-file: url('icons/power_tp_quality_yellow.png');}
      [t2_u_f>=242]{marker-file: url('icons/power_tp_quality_yellow.png');}
      // норм:
      [t1_u_f<=242]{marker-file: url('icons/power_tp_quality_green.png');}
      [t2_u_f<=242]{marker-file: url('icons/power_tp_quality_green.png');}
      // мало:
      [t1_u_f<=220]{marker-file: url('icons/power_tp_quality_red.png');}
      [t2_u_f<=220]{marker-file: url('icons/power_tp_quality_red.png');}
    }

Может действительно просто баг в cartocss или версия старая…

carto -v
1.2.0