Условный стиль Geotools на основе атрибута

Как по-разному стилизовать разные элементы слоя в зависимости от значения атрибута?

Например, у меня есть данные о часовых поясах, которые включают в себя атрибут, связывающий целое число от 1 до 8 с каждым часовым поясом для раскрашивания часовых поясов на карте. Как связать стиль с каждым значением атрибута и использовать его для окрашивания часовых поясов в разные цвета?


person OpenSauce    schedule 06.12.2013    source источник


Ответы (1)


Этот ответ для Geotools 9.2

Ниже приведен пример, который вы можете использовать. Ниже приведены некоторые идеи, как применить его к вашим требованиям.

Пример касается полигонов. Он имеет разные стили для выбранных и видимых объектов, а также для малых и больших масштабов:

protected final StyleFactory styleFactory =
  CommonFactoryFinder.getStyleFactory(GeoTools.getDefaultHints());
protected final FilterFactory2 filterFactory =
  CommonFactoryFinder.getFilterFactory2();

protected Rule createLayerRule
  ( Color outlineColor
  , float strokeWidth
  , Color fillColor
  , float opacity
  , Filter filter
  , double minScaleDenominator
  , double maxScaleDenominator)
{
  Stroke stroke =
      outlineColor != null
    ? styleFactory.createStroke
       ( filterFactory.literal(outlineColor)
       , filterFactory.literal(strokeWidth)
       , filterFactory.literal(opacity))
    : null;//Stroke.NULL;
  Fill fill = 
      fillColor != null 
    ? styleFactory.createFill
       ( filterFactory.literal(fillColor)
       , filterFactory.literal(opacity))
    : null;//Fill.NULL;

  PolygonSymbolizer symbolizer = 
    styleFactory.createPolygonSymbolizer(stroke, fill, null);

  return createRule(filter, minScaleDenominator, maxScaleDenominator, symbolizer);
}

// IDs of visible features, programmatically updated. 
protected final Set<FeatureId> visibleFeatureIDs = new HashSet<FeatureId>();

// IDs of selected features, programmatically updated. 
protected final Set<FeatureId> selectedFeatureIDs = new HashSet<FeatureId>();

protected Style createLayerStyle()
{
  Filter selectionFilter = filterFactory.id(selectedFeatureIDs);
  Filter visibilityFilter = filterFactory.and
    ( Arrays.asList
        ( filterFactory.not
            (selectionFilter)
        , filterFactory.id(visibleFeatureIDs)
        )
    );
  FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle
    ( new Rule[]
      {
        // hope constants below are self explaining
        createLayerRule
          ( SELECTED_OUTLINE_COLOR 
          , STROKE_WIDTH_LARGE_SCALE
          , SELECTED_FILL_COLOR
          , SELECTED_OPACITY
          , selectionFilter
          , STYLE_SCALE_LIMIT
          , Double.NaN)
      , createLayerRule
          ( UNSELECTED_OUTLINE_COLOR
          , STROKE_WIDTH_LARGE_SCALE
          , UNSELECTED_FILL_COLOR
          , UNSELECTED_OPACITY
          , visibilityFilter
          , STYLE_SCALE_LIMIT
          , Double.NaN)
      , createLayerRule
          ( SELECTED_OUTLINE_COLOR
          , STROKE_WIDTH_SMALL_SCALE
          , SELECTED_FILL_COLOR
          , SELECTED_OPACITY
          , selectionFilter
          , Double.NaN
          , STYLE_SCALE_LIMIT)
      , createLayerRule
          ( UNSELECTED_OUTLINE_COLOR
          , STROKE_WIDTH_SMALL_SCALE
          , UNSELECTED_FILL_COLOR
          , UNSELECTED_OPACITY
          , visibilityFilter
          , Double.NaN
          , STYLE_SCALE_LIMIT)
      }
    );

  Style style = styleFactory.createStyle();
  style.featureTypeStyles().add(fts);

  return style;
}

// layer creation
FeatureLayer someMethode()
{
  ...
  FeatureLayer layer = new FeatureLayer
    ( dataStore.getFeatureSource()
    , createLayerStyle()
    , "Zipcodes"
    );
  ...
  return layer;
}

// style update if visible or selected features have changed
void someOtherMethod(FeatureLayer layer)
{
   ... // update selectedFeatureIDs or visibleFeatureIDs
   layer.setStyle(createLayerStyle());
}

Конечно, оптимизации возможны и приветствуются.

Для вашего требования может помочь следующее:

  1. Вам нужно 8 правил (см. createRule(..) выше), если вы хотите иметь один стиль для всех масштабов (или 16 для малых и больших масштабов).
  2. Определите 8 фильтров, используя FilterFactory.equals(Expression, Expression), где первое выражение имеет тип AttributeExpressionImpl, а второе - тип LiteralExpressionImpl.
  3. Имейте в виду, что в FilterFactory2 есть еще один метод equal (без s).
person Claude    schedule 07.12.2013
comment
Спасибо. Сложный процесс для простой концепции! - person OpenSauce; 09.12.2013
comment
@OpenSauce Немного проще, если у вас одинаковый стиль для всех масштабов. Может быть, есть другой способ сделать это еще проще. Однако в конце вы должны классифицировать свои функции по группам, которые должны быть окрашены по-разному ... и это то, что делают фильтры. - person Claude; 09.12.2013