OpenWaterFoundation / owf-app-infomapper-ng

Open Water Foundation InfoMapper web application for menu-driven maps and visualizations, using Angular
GNU General Public License v3.0
1 stars 2 forks source link

Implement graduated classification for vector layer #373

Open smalers opened 3 years ago

smalers commented 3 years ago

Support for graduated classification was added for raster layers in issue #349 but has not been added for vector layers. There is an urgent need to implement graduated classification for polygon layers for SNODAS data visualization. Because polygons and lines are similar in handling in Leaflet symbolization, it should be possible to implement graduated classification for polygons and lines. See the Map Configuration documentation for the specification.

Graduated symbols for point layers are more complicated because there are more properties to control the symbol, including whether using shape or image, built-in or custom image, etc. It would be possible to use a csv file with columns named for all of the combined properties, but this could lead to a complex csv file with many empty slots. Maybe support using shape with csv since it has fewer properties and only a few new properties beyond what polygon and line use? Defaults should be implemented in case a value in a csv is not specified.

Later, we can evaluate implementing graduated symbol for points using images, either by extending this issue or adding another issue specific to graduated point image symbols.

smalers commented 3 years ago

To test on a line layer, I recommend editing a stream reaches layer GeoJSON file (such as a snippet of the larger stream reaches layer) and manually adding properties for "stream_order", which would be an integer value 1+. See the following for explanation. Then make the order correspond to width and other attributes for testing.

https://usgs-mrs.cr.usgs.gov/NHDHelp/WebHelp/NHD_Help/Introduction_to_the_NHD/Feature_Attribution/Stream_Order.htm

smalers commented 3 years ago

Need Josh to confirm which properties are used for the different layer types, which can be added as columns in the classification file, and what the defaults are, for polygon, line, and point geometry types. I updated the GeoProcessor 1.5.0 map configuration file documentation for polygon and need to do for the other types when I have used the new features with working example.

Nightsphere commented 2 years ago

Testing a Point Layer

The graduated classification for vector layers has been implemented. It is using the same code as a raster layer, so the same instructions apply here like in issue #349. Below are examples of a map config file (the geoLayerView only), classification file, layer geoJson file (shortened), and what the map and side bar will display.

NOTE: The names of each of the files in each header below are for my use in my app/ folder, and won't be in the GitHub repo.

Layer geoJson File (Colorado-Municipal-Water-Providers.geojson)

The following is merely an excerpt from the geojson file containing the Colorado water providers. This is to help visualize where the graduated classification attribute comes from, and is not a complete representation of the file or feature.

{
  "type": "Feature",
  "bbox": [1, 2, 3, 4],
  "properties": {
    "WaterProviderName": "Alma, Town of",
    "Latitude": 39.2859447431895,
    "Longitude": -106.067034409302
  }
}

Map Config File (point-geometry-map.json)

There are 3 important values here for creating a graduated layer on the map:

  1. classificationType: This must be set to Graduated.
  2. classificationAttribute: This is the property from the geoJson file of the desired attribute to base the coloring on. For this example, we are separating by a providers latitude.
  3. classificationFile: The relative path from the map config file to the classification file.
{
  "geoLayerViewId": "water-providers-layer-view",
  "name": "Water Providers",
  "description": "Water Providers around Colorado",
  "geoLayerId": "water-providers-point-layer",
  "properties": {
    "refreshInterval": "",
    "selectedInitial": "true"
  },
  "geoLayerSymbol": {
    "name": "Water Providers Single Symbol",
    "description": "The symbol metadata for the water providers layer view",
    "classificationType": "Graduated",
    "classificationAttribute": "Latitude",
    "properties": {
      "classificationFile": "../../data-maps/map-classification-files/water-provider-classify.csv"
    }
  },
  "eventHandlers": []
}

Map Classification File (water-provider-classify-csv)

As with a classification file from a raster layer, the mandatory headers for a graduated layer are:

Both valueMin and valueMax can contain operators with no spaces like in this example, or with spaces. Property notation for both can also be used under the label header, in case custom side bar labels are desired.

# A testing Graduated classification table for Water Providers.
#
# The value from attribute is compared as follows to determine symbol:
#  value > valueMin
#  value <= valueMax
valueMin,valueMax,color,opacity,fillColor,fillOpacity,weight,symbolShape,symbolSize,label
>=40.63,Infinity,#000000,1,#dc050c,0.8,1,"square",7,> ${valueMin}
>=40.33,<40.63,#000000,1,#e8601c,0.8,1,"square",7,${valueMin} - ${valueMax}
>=40.03,<40.33,#000000,1,#f1932d,0.8,1,"square",7,${valueMin} - ${valueMax}
>=39.73,<40.03,#000000,1,#f6c141,0.8,1,"square",7,${valueMin} - ${valueMax}
>=39.43,<39.73,#000000,1,#f7f056,0.8,1,"square",7,${valueMin} - ${valueMax}
>=39.13,<39.43,#000000,1,#cae0ab,0.8,1,"square",7,${valueMin} - ${valueMax}
>=38.83,<39.13,#000000,1,#90c987,0.8,1,"square",7,${valueMin} - ${valueMax}
>=38.53,<38.83,#000000,1,#4eb265,0.8,1,"square",7,${valueMin} - ${valueMax}
>=38.23,<38.53,#000000,1,#7bafde,0.8,1,"square",7,${valueMin} - ${valueMax}
>=37.93,<38.23,#000000,1,#5289c7,0.8,1,"square",7,${valueMin} - ${valueMax}
>=37.63,<37.93,#000000,1,#1965b0,0.8,1,"square",7,${valueMin} - ${valueMax}
>=37.33,<37.63,#000000,1,#882e72,0.8,1,"square",7,${valueMin} - ${valueMax}
-Infinity,<37.33,#000000,1,#ae76a3,0.8,1,"square",7,< ${valueMax}
# Use black for NoData
NoData,NoData,#000000,1,#000000,0.8,1,"square",7,${valueMin}

Graduated Layer on the Map

The above files will display the following in the InfoMapper.

image

Nightsphere commented 2 years ago

Testing a Line Layer

This section briefly lists the differences between testing point layer and a line layer with weights.

Layer geoJson File (swrf-district.geojson)

Like the above comment suggested, I manually created the stream_order feature property and added it to the geoJson file of the layer. The features property array looked like this (obviously shortened for this example):

{
  "features": [
    {
      "type": "Feature",
      "properties": {
        "stream_order": 2
      }
    }
  ]
}

Map Config File (line-geometry-map.json)

The only difference between this geoLayerView and the one from the example above is the setting of the classificationAttribute, which has been changed to stream_order.

Map Classification File (swrf-stream-order-classify.csv)

Note either valueMin or valueMax can be used for the NoData field, as both will just display "NoData". Also note the differences in line weight for each range, listed as following since it's difficult to tell in the CSV text below:

valueMin valueMax weight
>=3.5 Infinity 6
>=2.5 <3.5 4
>=1.5 <2.5 3
-Infinity <1.5 2
NoData NoData 3
# A testing Graduated classification table for Water Providers.
#
# The value from attribute is compared as follows to determine symbol:
#  value > valueMin
#  value <= valueMax
valueMin,valueMax,color,opacity,fillColor,fillOpacity,weight,label
>=3.5,Infinity,#ff0000,1,#ff0000,0.8,6,> ${valueMin}
>=2.5,<3.5,#ffa500,1,#ffa500,0.8,4,${valueMin} - ${valueMax}
>=1.5,<2.5,#ffff00,1,#ffff00,0.8,3,${valueMin} - ${valueMax}
-Infinity,<1.5,#008000,1,#008000,0.8,2,< ${valueMax}
# Use black for NoData
NoData,NoData,#000000,1,#000000,0.8,3,${valueMin}

Graduated Layer on Map

Here is what the above files will produce. Click on the image for an easier time of seeing the line weights.

image