wkutils/0000755000176200001440000000000013777065112011765 5ustar liggesuserswkutils/NAMESPACE0000644000176200001440000000221313774605367013213 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(coords_linestring_translate_wkb) export(coords_linestring_translate_wkt) export(coords_point_translate_wkb) export(coords_point_translate_wkt) export(coords_polygon_translate_wkb) export(coords_polygon_translate_wkt) export(wk_geometry_type) export(wk_geometry_type_id) export(wkb_coords) export(wkb_debug) export(wkb_draw_lines) export(wkb_draw_points) export(wkb_draw_polypath) export(wkb_feature_ranges) export(wkb_grob) export(wkb_has_missing) export(wkb_is_finite) export(wkb_meta) export(wkb_plot) export(wkb_plot_new) export(wkb_ranges) export(wkb_set_srid) export(wkb_set_z) export(wkb_transform) export(wkb_unnest) export(wkt_coords) export(wkt_debug) export(wkt_draw_lines) export(wkt_draw_points) export(wkt_draw_polypath) export(wkt_feature_ranges) export(wkt_grob) export(wkt_has_missing) export(wkt_is_finite) export(wkt_meta) export(wkt_plot) export(wkt_plot_new) export(wkt_ranges) export(wkt_set_srid) export(wkt_set_z) export(wkt_streamer_debug) export(wkt_streamer_meta) export(wkt_transform) export(wkt_unnest) import(wk) importFrom(Rcpp,sourceCpp) useDynLib(wkutils, .registration = TRUE) wkutils/LICENSE0000644000176200001440000000005613677637256013010 0ustar liggesusersYEAR: 2020 COPYRIGHT HOLDER: Dewey Dunnington wkutils/README.md0000644000176200001440000000467413774415352013261 0ustar liggesusers # wkutils Whereas the [wk package](https://paleolimbot.github.io/wk/) provides headers and class definitions for well-known geometry formats, this package uses those headers to interrogate and transform these vectors. ## Installation You can install the released version of wkutils from [CRAN](https://CRAN.R-project.org) with: ``` r install.packages("wkutils") ``` And the development version from [GitHub](https://github.com/) with: ``` r # install.packages("remotes") remotes::install_github("paleolimbot/wkutils") ``` ## Example The gist of the functions in this package: ``` r library(wkutils) wkt_coords("POINT (30 10)") #> # A tibble: 1 x 7 #> feature_id part_id ring_id x y z m #> #> 1 1 1 0 30 10 NA NA coords_point_translate_wkt(30, 10) #> [1] "POINT (30 10)" wkt_debug("POINT (30 10)") #> nextFeatureStart(0) #> nextGeometryStart(POINT [1], WKReader::PART_ID_NONE) #> nextCoordinate(POINT [1], WKCoord(x = 30, y = 10), 0) #> nextGeometryEnd(POINT [1], WKReader::PART_ID_NONE) #> nextFeatureEnd(0) wkt_set_srid("POINT (30 10)", 1234) #> [1] "SRID=1234;POINT (30 10)" wkt_set_z("POINT (30 10)", 1234) #> [1] "POINT Z (30 10 1234)" wkt_meta("POINT (30 10)") #> # A tibble: 1 x 7 #> feature_id part_id type_id size srid has_z has_m #> #> 1 1 1 1 1 NA FALSE FALSE wkt_ranges("POINT (30 10)") #> # A tibble: 1 x 8 #> xmin ymin zmin mmin xmax ymax zmax mmax #> #> 1 30 10 Inf Inf 30 10 -Inf -Inf ``` The package also contains plot methods for `wk::wkb()` and `wk::wkt()` vectors. These aren’t intended to be high-performance, but are helpful for debugging geometries. ``` r plot(wk::wkt("LINESTRING (1 2, 4 7)")) plot(wk::wkt("POINT (3 4)"), add = T) ``` Finally, the package contains slightly faster functions to send points, lines, and polygons to a graphics device: ``` r nc_sf <- sf::read_sf(system.file("shape/nc.shp", package = "sf")) nc_wkb <- wk::as_wkb(sf::st_as_binary(nc_sf$geometry)) wkb_plot_new(nc_wkb) wkb_draw_polypath(nc_wkb) ``` wkutils/man/0000755000176200001440000000000013774402556012544 5ustar liggesuserswkutils/man/wkt_set_srid.Rd0000644000176200001440000000271113774402552015531 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/filters.R \name{wkt_set_srid} \alias{wkt_set_srid} \alias{wkb_set_srid} \alias{wkt_set_z} \alias{wkb_set_z} \alias{wkt_transform} \alias{wkb_transform} \title{Modify well-known geometries} \usage{ wkt_set_srid(wkt, srid, precision = 16, trim = TRUE) wkb_set_srid(wkb, srid) wkt_set_z(wkt, z, precision = 16, trim = TRUE) wkb_set_z(wkb, z) wkt_transform(wkt, trans, precision = 16, trim = TRUE) wkb_transform(wkb, trans) } \arguments{ \item{wkt}{A character vector containing well-known text.} \item{srid}{An integer spatial reference identifier with a user-defined meaning. Use \code{NA} to unset this value.} \item{precision}{The rounding precision to use when writing (number of decimal places).} \item{trim}{Trim unnecessary zeroes in the output?} \item{wkb}{A \code{list()} of \code{\link[=raw]{raw()}} vectors, such as that returned by \code{sf::st_as_binary()}.} \item{z}{A Z value that will be assigned to every coordinate in each feature. Use \code{NA} to unset this value.} \item{trans}{A 3x3 transformation matrix that will be applied to all coordinates in the input.} } \value{ An unclassed well-known vector with the same type as the input. } \description{ Modify well-known geometries } \examples{ wkt_set_srid("POINT (30 10)", 1234) wkt_set_z("POINT (30 10)", 1234) wkt_transform( "POINT (0 0)", # translation +12 +13 matrix(c(1, 0, 0, 0, 1, 0, 12, 13, 1), ncol = 3) ) } wkutils/man/wkb_draw_points.Rd0000644000176200001440000000401713774377120016227 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/draw.R \name{wkb_draw_points} \alias{wkb_draw_points} \alias{wkt_draw_points} \alias{wkb_draw_lines} \alias{wkt_draw_lines} \alias{wkb_draw_polypath} \alias{wkt_draw_polypath} \alias{wkb_plot_new} \alias{wkt_plot_new} \title{Draw well-known geometries} \usage{ wkb_draw_points(wkb, ...) wkt_draw_points(wkt, ...) wkb_draw_lines(wkb, ...) wkt_draw_lines(wkt, ...) wkb_draw_polypath(wkb, ..., rule = "evenodd") wkt_draw_polypath(wkt, ..., rule = "evenodd") wkb_plot_new( wkb, ..., asp = 1, xlab = "", ylab = "", main = deparse(substitute(wkb)) ) wkt_plot_new( wkt, ..., asp = 1, xlab = "", ylab = "", main = deparse(substitute(wkt)) ) } \arguments{ \item{wkb}{A \code{list()} of \code{\link[=raw]{raw()}} vectors, such as that returned by \code{sf::st_as_binary()}.} \item{...}{Passed to \code{\link[graphics:points]{graphics::points()}}, \code{\link[graphics:lines]{graphics::lines()}}, or \code{\link[graphics:polypath]{graphics::polypath()}}} \item{wkt}{A character vector containing well-known text.} \item{rule}{Passed to \code{\link[graphics:polypath]{graphics::polypath()}}} \item{asp, xlab, ylab, main}{Passed to \code{\link[graphics:plot.default]{graphics::plot()}} to initialize a new plot.} } \value{ The input, invisibly } \description{ These functions send well-known geometry vectors to a graphics device using \code{\link[graphics:points]{graphics::points()}}, \code{\link[graphics:lines]{graphics::lines()}}, and \code{\link[graphics:polypath]{graphics::polypath()}}. These are minimal wrappers aimed at developers who need to visualize test data: they do not check geometry type and are unlikely to work with vectorized graphical parameters in \code{...}. Use the \verb{wk*_plot_new()} functions to initialize a plot using the extent of all coordinates in the vector. } \examples{ x <- "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))" wkt_plot_new(x) wkt_draw_polypath(x, col = "grey90") wkt_draw_lines(x, col = "red") wkt_draw_points(x) } wkutils/man/wkutils-package.Rd0000644000176200001440000000164513774416052016130 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/wkutils-package.R \docType{package} \name{wkutils-package} \alias{wkutils} \alias{wkutils-package} \title{wkutils: Utilities for Well-Known Geometry Vectors} \description{ Provides extra utilities for well-known formats in the 'wk' package that are outside the scope of that package. Utilities to parse coordinates from data frames, plot well-known geometry vectors, extract meta information from well-known geometry vectors, and calculate bounding boxes are provided. } \seealso{ Useful links: \itemize{ \item \url{https://paleolimbot.github.io/wkutils/} \item \url{https://github.com/paleolimbot/wkutils} \item Report bugs at \url{https://github.com/paleolimbot/wkutils/issues} } } \author{ \strong{Maintainer}: Dewey Dunnington \email{dewey@fishandwhistle.net} (\href{https://orcid.org/0000-0002-9415-4582}{ORCID}) } \keyword{internal} wkutils/man/wkt_grob.Rd0000644000176200001440000000351113774377120014647 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/grob.R \name{wkt_grob} \alias{wkt_grob} \alias{wkb_grob} \title{Generate grid geometries from well-known geometries} \usage{ wkt_grob( wkt, ..., rule = "evenodd", default.units = "native", name = NULL, vp = NULL ) wkb_grob( wkt, ..., rule = "evenodd", default.units = "native", name = NULL, vp = NULL ) } \arguments{ \item{wkt}{A character vector containing well-known text.} \item{...}{Graphical parameters passed to \code{\link[grid:gpar]{grid::gpar()}}. These are recycled along the input. Dynamic dots (e.g., \verb{!!!}) are supported.} \item{rule}{Use "winding" if polygon rings are correctly encoded with a winding direction.} \item{default.units}{Coordinate units, which may be defined by the viewport (see \code{\link[grid:unit]{grid::unit()}}). Defaults to native.} \item{name, vp}{Passed to \code{\link[grid:grid.points]{grid::pointsGrob()}}, \code{\link[grid:grid.lines]{grid::polylineGrob()}}, \code{\link[grid:grid.path]{grid::pathGrob()}}, or \code{\link[grid:grid.grob]{grid::gTree()}} depending on the types of geometries in the input.} } \value{ A \link[grid:grid.grob]{graphical object} } \description{ Using \code{\link[=wkt_meta]{wkt_meta()}} and \code{\link[=wkt_coords]{wkt_coords()}}, these functions create graphical objects using the grid package. Vectors that contain geometries of a single dimension are efficiently packed into a \code{\link[grid:grid.points]{grid::pointsGrob()}}, \code{\link[grid:grid.lines]{grid::polylineGrob()}}, or \code{\link[grid:grid.path]{grid::pathGrob()}}. Vectors with mixed types and nested collections are encoded less efficiently using a \code{\link[grid:grid.grob]{grid::gTree()}}. } \examples{ grid::grid.newpage() grid::grid.draw(wkt_grob("POINT (0.5 0.5)", pch = 16, default.units = "npc")) } wkutils/man/wkt_has_missing.Rd0000644000176200001440000000176413774403624016231 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/finite.R \name{wkt_has_missing} \alias{wkt_has_missing} \alias{wkb_has_missing} \alias{wkt_is_finite} \alias{wkb_is_finite} \title{Test well-known geometries for missing and non-finite coordinates} \usage{ wkt_has_missing(wkt) wkb_has_missing(wkb) wkt_is_finite(wkt) wkb_is_finite(wkb) } \arguments{ \item{wkt}{A character vector containing well-known text.} \item{wkb}{A \code{list()} of \code{\link[=raw]{raw()}} vectors, such as that returned by \code{sf::st_as_binary()}.} } \value{ A logical vector with the same length as the input. } \description{ Note that EMTPY geometries are considered finite and non-missing. Use the \code{size} column of \code{\link[=wkt_meta]{wkt_meta()}} to test for empty geometries. } \examples{ wkt_has_missing("POINT (0 1)") wkt_has_missing("POINT (nan nan)") wkt_has_missing("POINT (inf inf)") wkt_is_finite("POINT (0 1)") wkt_is_finite("POINT (nan nan)") wkt_is_finite("POINT (inf inf)") } wkutils/man/wkb_debug.Rd0000644000176200001440000000151713774377120014766 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/debug.R \name{wkb_debug} \alias{wkb_debug} \alias{wkt_debug} \alias{wkt_streamer_debug} \title{Debug well-known geometry} \usage{ wkb_debug(wkb) wkt_debug(wkt) wkt_streamer_debug(wkt) } \arguments{ \item{wkb}{A \code{list()} of \code{\link[=raw]{raw()}} vectors, such as that returned by \code{sf::st_as_binary()}.} \item{wkt}{A character vector containing well-known text.} } \value{ The input, invisibly } \description{ Prints the raw calls to the \code{WKBGeometryHandler()}. Useful for writing custom C++ handlers and debugging read problems. } \examples{ wkt_debug("MULTIPOLYGON (((0 0, 10 0, 0 10, 0 0)))") wkt_streamer_debug("MULTIPOLYGON (((0 0, 10 0, 0 10, 0 0)))") wkb_debug( wk::wkt_translate_wkb( "MULTIPOLYGON (((0 0, 10 0, 0 10, 0 0)))" ) ) } wkutils/man/wkb_ranges.Rd0000644000176200001440000000231013774377120015147 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ranges.R \name{wkb_ranges} \alias{wkb_ranges} \alias{wkt_ranges} \alias{wkb_feature_ranges} \alias{wkt_feature_ranges} \title{Extract ranges information} \usage{ wkb_ranges(wkb, na.rm = FALSE, finite = FALSE) wkt_ranges(wkt, na.rm = FALSE, finite = FALSE) wkb_feature_ranges(wkb, na.rm = FALSE, finite = FALSE) wkt_feature_ranges(wkt, na.rm = FALSE, finite = FALSE) } \arguments{ \item{wkb}{A \code{list()} of \code{\link[=raw]{raw()}} vectors, such as that returned by \code{sf::st_as_binary()}.} \item{na.rm}{Pass \code{TRUE} to not consider missing (nan) values} \item{finite}{Pass \code{TRUE} to only consider finite (non-missing, non-infinite) values.} \item{wkt}{A character vector containing well-known text.} } \value{ A data.frame with columns: \itemize{ \item \code{xmin}, \code{ymin}, \code{zmin}, and \code{mmin}: Minimum coordinate values \item \code{xmax}, \code{ymax}, \code{zmax}, and \code{mmax}: Maximum coordinate values } } \description{ This is intended to behave the same as \code{\link[=range]{range()}}, returning the minimum and maximum x, y, z, and m coordinate values. } \examples{ wkt_ranges("POINT (30 10)") } wkutils/man/wkt_unnest.Rd0000644000176200001440000000226713774402556015243 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/unnest.R \name{wkt_unnest} \alias{wkt_unnest} \alias{wkb_unnest} \title{Flatten nested geometry structures} \usage{ wkt_unnest(wkt, keep_empty = FALSE, keep_multi = TRUE, max_depth = 1) wkb_unnest(wkb, keep_empty = FALSE, keep_multi = TRUE, max_depth = 1) } \arguments{ \item{wkt}{A character vector containing well-known text.} \item{keep_empty}{If \code{TRUE}, a GEOMETRYCOLLECTION EMPTY is left as-is rather than collapsing to length 0.} \item{keep_multi}{If \code{TRUE}, MULTI* geometries are not expanded to sub-features.} \item{max_depth}{The maximum recursive GEOMETRYCOLLECTION depth to unnest.} \item{wkb}{A \code{list()} of \code{\link[=raw]{raw()}} vectors, such as that returned by \code{sf::st_as_binary()}.} } \value{ An unclassed vector with attribute \code{lengths}, which is an integer vector with the same length as the input denoting the length to which each feature was expanded. } \description{ Flatten nested geometry structures } \examples{ wkt_unnest("GEOMETRYCOLLECTION (POINT (1 2), POINT (3 4))") wkt_unnest("GEOMETRYCOLLECTION EMPTY") wkt_unnest("GEOMETRYCOLLECTION EMPTY", keep_empty = TRUE) } wkutils/man/wkb_coords.Rd0000644000176200001440000000353713774377120015175 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/coords.R \name{wkb_coords} \alias{wkb_coords} \alias{wkt_coords} \title{Extract coordinates from well-known geometries} \usage{ wkb_coords(wkb, sep_na = FALSE) wkt_coords(wkt, sep_na = FALSE) } \arguments{ \item{wkb}{A \code{list()} of \code{\link[=raw]{raw()}} vectors, such as that returned by \code{sf::st_as_binary()}.} \item{sep_na}{Use \code{TRUE} to separate geometries and linear rings with a row of \code{NA}s. This is useful for generating output that can be fed directly to \code{\link[graphics:polypath]{graphics::polypath()}} or \code{\link[graphics:lines]{graphics::lines()}} without modification.} \item{wkt}{A character vector containing well-known text.} } \value{ A data.frame with columns: \itemize{ \item \code{feature_id}: The index of the top-level feature \item \code{part_id}: The part identifier, guaranteed to be unique for every simple geometry (including those contained within a multi-geometry or collection) \item \code{ring_id}: The ring identifier, guaranteed to be unique for every ring. \item \code{x}, \code{y}, \code{z}, \code{m}: Coordinaate values (both absence and \code{nan} are recorded as \code{NA}) } } \description{ These functions are optimised for graphics output, which in R require flat coordinate structures. See \code{\link[graphics:points]{graphics::points()}}, \code{\link[graphics:lines]{graphics::lines()}}, and \code{\link[graphics:polypath]{graphics::polypath()}} for how to send these to a graphics device, or \code{\link[grid:grid.points]{grid::pointsGrob()}}, \code{\link[grid:grid.lines]{grid::linesGrob()}}, and \code{\link[grid:grid.path]{grid::pathGrob()}} for how to create graphical objects using this output. } \examples{ text <- c("LINESTRING (0 1, 19 27)", "LINESTRING (-1 -1, 4 10)") wkt_coords(text) wkt_coords(text, sep_na = TRUE) } wkutils/man/figures/0000755000176200001440000000000013774415351014205 5ustar liggesuserswkutils/man/figures/README-wkt-plot-1.png0000644000176200001440000026703013774415351017575 0ustar liggesusersPNG  IHDR4הLiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ @IDATx]hW XQfgaR R/'WFPMM&Z_lz#%ɪ&u d ^y7vBRΪvgEX?=nw;Xzy;߹iy^ @ @ @ @@F/Ϩ @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @  @ @ @ @ 4d @ @ @ @  @ @ @ @Cv-Q @ @ @ p&Ggo~vr6e' @ @ @[lM7_e: ]n '~6H @ @ PN;S/鮽r W"@ @ @R^CJt[.x_% @ @ @D '?|"fSWh+@?pٱ] @ @ @gJ|rͷu @ @ @ @CQ @ @ @(@Co @ @ @ @ W\;. @ @ @ Pb7  @ @ @ @@ vF] @ @ @ @ %n @ @ @ @\r팺 @ @ @ @@J|['@ @ @ @ 4u @ @ @ @ 4N @ @ @rhȵ3"@ @ @ @%h(qm @ @ @* АkgE @ @ @J, P: @ @ @U@!Ψ @ @ @X@ͷu @ @ @ @CQ @ @ @(@Co @ @ @ @ W\;. @ @ @ Pb7  @ @ @ @@7Zx'HE~qm @ @ @@05'x7q̙ógV,,,  @ @ @ @rbX%[gf!@ @ @ @hf ⩧*m @ @ @F% 0*#ěַ=\vn @ @ @ 0*Qɖlݧ~z n-x≒v  @ @ @ @` -z3%}GxG:u*]{ @ @ @ @kh%\"pM7ٳg{^|/>_[o?yބ @ @ @\M@jB~7͗\?1bzz:s5> @ @ @ @r~7FU_F?Oq]w=_lƫ^]3@@a @ @/x'g?Y"k^Ҍ @} 4Wx+_9x\yn/ƩSbuu5>G?x}uw[Ϗ~|g @ @J'F#X:&@ 0L-oyK<ˊox{rK}_׎_~kP @ @,=\|s{70? @ܘoh1?w_Ax|CJsJ|+?oo}8-i=WN?uBw|L @ 0lxҲ @h1?w_{K_Rx/|mzkjGŻ9 y}}A{ @ PN(̙3i ~0  @>ss>nwuW<կ~5Ο?+ ^xq/Ș @ @ ŋϯVthx0 @IW'Rıc'Gy$>uae-'@ @ 0N=PZ{#G @/ pvNe7ONz~+ @ @4zOOO'?)S  @LWNL`SmKz׻?裏?/mI @ @%ݴVo)C @ph! jk(> V|gWU/zj… Cze @ @\@Q h4' @Ch%F'055o}[F+ @ @؟|\xqpSZ-j @*^ @ @HN'z4ڊ#G @hU @ @(@ٌ^7t;v$;M @+ pޞF @ @ nAՊJ @ O-eI8zh|H[|k_ @ @ PE.,,DHs @+ 0\ω]|g|ߝ @ @ ŋUXZZ-~O @ x ๕ @ @rt:x衇fȑ#in@ @ojE @ @&LlFjzz:;6a; @ 4 @ @ zZVT*47 @ @`4 q* @ @ PE,,,DHs @F' 0:[+ @ @ 0ŋV4;R> @h^ @ @t:qܹĭ8rH @ 0ZZ @ @1h6OOODZct'&@ 0 7U @ @ 0BMOhZQT܀ @ 4 @ @#(̙3ⅅh4in@ @4 @ @ 0&CT[VciiiL*W& @h~  @ @7 tܹsi8rH @ pp gI @ @d.l6 cǎe^ @L@ @ @؇z;ZVT*47 @ @` @ @P(8sLlaa!F @ p o @ @d&0tAUj52P9 @' P1 @ @/t:qܹV9r$  @8qT @ @2h6LOODZc2L @- P= @ @R n2hZQT܀ @h8<{O&@ @ @3gΤ h @+ pN @ @! ,,,D#@ @ @`:N;w.qss3jZ @ p  @ @ pf3z1;;{x @Wh @ @ 0Q뱻jR @y4U @ @ pEQę3gғh @4  @ @ 0bvTXZZ-O @ 4\ @ @+NΝK5onnFVKs @hȫ!@ @ @`Df3z`阝ѓ,K @0h  @ @؈TcՊJ @' А_OTD @ @|447 @ @ O<* @ @$DVVciiiH+[ @Q 4R @ @@ӉTfj47 @ @ _|{2 @ @nP ^otn'@ @Js @ @8PMlZQT܀ @ @ @(bmm-9??F#  @_@! @ @} _5vwUXZZ .'@ @O @ @P:N5777V @! 0}R% @ @(^opt^.#@ @ ' @ @nH`cc#vZjERIs @G@a|zR @ @^B(X[[KWGHs @K@aZ @ @ l6~[Vcii W @qh. @ @t:܌Z @@L @ @bz1;;?W @ 0n 1 @ @ "hVJ%  @O웪  @ @(bmm-Y8q"F @ 0 ; @ @(@ٌn;pVqқ @ 0) I @ @ P2N;;;iכQ܀ @h @ @@i ?==q @( 0]' @ @.v;jERIs @_@a{h @ @J%PE=8q"F @ 0 G @ @ PfnwjO.m @@m{%@ @ 0N'vvv.Ξ=Z-  @饝 @ @xz}=  @ 4M @ @`nSw_T*47 @ @`&vC @ @`"մ'NDHs @vM@IDAT&O@azjG @ @&NlFZӧ'n6D @^aF @ @@fN'vvvRUWOj47 @ @`2&vE @ @`b Scnnnbf# @\Y@6~C @ @! n*ᄄT*in@ @ 4Lno @ @X Ei'NF @L@d @ @@UnwPZӧO^N @o @ @F,tb{{;=Z @L@  @ @@zޠzc @ pc 7n @ @,6vVmZ155 @C@}K @ @c!PEZO8333in@ @@yk;%@ @ @UnwPgZӧOg_  @@h\J @ @>:Nloojin@ @@o%@ @ @zޠz֪0 @F/ 0zcO @ @ @*ochVSSSin@ @@s;&@ @ @Qj:~x̤ @h(g @ @@6WMtA=j5M! @@{2 @ @ t:NWOj47 @ @  @ @8t3zAz=fgg& @ @C}P @ @ n}ZJs @- P= @ @C("VWWӳ?333in@ @g @ @j[Vcyyk@ @hȻ?#@ @ 0qN'Ӿ666V @  @ @*v^7xf^} @ 0 'U @ @hi/V+܀ @ 4'@ @ @N<nwNZ^ @C@}K @ @.tb{{;=wcc#jZ @ @^J @ @n_cnnr# @h(_ @ @677nZJs @\M@jB~O @ @tcff&  @ p- ע @ @YɓvWX^^{]H @O @ @nXvZgcc#jZ @ @ZUu @ @\U`qq1=. @ @.3 @ @-v;jbjj*  @ h @ @ E+++wǏ47 @ @~+z @ @.8ydtj5/ @؏@~\K @ @%N'Q܀ @# p=j!@ @ @ ,..`^cnn.΀ @+ pr#@ @ @ 677n'VSSSin@ @h^9 @ @(@Q>OL @ @FnDϽ @ @J,pvjw}w5l @a 4 [z @ @J pN;]__Z @Qt? @ @ 4^Gu~ @ 0LajZ @ @@ 677nZJs @ C@a @ @ P(buu5 333in@ @a 4 K: @ @J pɸp`j5  @8 PL @ @c(pNGVKs @ S@a"@ @ 0f3;݄ @J@aT%@ @ 0A[[[nӎZVLMM @- 0lQ @ @0(bee% 333in@ @Q4B՚ @ @&H; . vTVcyyyvg+ @* АkgE @ @ ǃ>*Y__G @F% 0*Y @ @^Gu~ @ p  @ @P`kk+~TyՊ47 @ @(Fkm @ @c*PE033 @@èO @ @` ㎸p jc % @ 0 = @ @L+ѣG܀ @! pʞA @ @`coooPq^& @ػp/NHBl)J; 3)H2Ё)dHHr d-vւŎqtʴ RZKR^6BX.$U\~%.ϙ{=?: @`44 @ @ԱhLNN lmmm)6 @ @J hhX)i @ @sJ6mJYfOfxߘb @Զ @ @:Z|>qR#@ @444 @ @ru]o1Sl@ @а#@ @ P===177WˬX,F  @VS@Cj[ @ @@dd˖-֖b @P& @ @:T*iӦyo|Sl@ @аZ%@ @ P}}}1;;[$ +) @ @ BC @ @-*P.㮻Jxޞb @Է6 @ @U鉹Zb1wb6&@ @| =D @ @ZB`tt4&''S[l @ @`44X @ @ T*شiSZ΋7)6 @ @@=hh] @ @ڊ|>֯_[ @ а0'W @ @h rwuWn @ @^44Nȃ @ @ \mb j  @,^@CA @ @!JRLNNƢ- @' r!@ @ LJ%FFFw^tvv؀ @&vD> @ @A/fggk3X~2bJ @,4 @ @(q]wnhooO @Q@CC= @ @,@OOOf,q/"@ @hhXW @ @ R)hkkK @U@CC @ @@R4y)6 @ @@= hhݑ @ @#Xn]f~#ͭ @XY +m5 @ @+"P.cin!Sl@ @zP;$? @ @!sss;b1[ @ zV @ @ET*d{ll,Rl@ @F$G @ @ T*122>󢳳3 @h S$@ @ ul|>ׯ_].!@ @@ hh= @ @(˱{t 7)6 @ @@# hhhݒ+ @ @C\b! @[@CC} @ @,HT*dvll,Rl@ @Fh;&_ @ @T*122Ξ{ٙb @4F59 @ @G`ݺu1;;[;cÆ |jH @81Ӗu3'?(q}3( qq5Cj @ @,@ݻwunhooO @U@CC\5$?C|O~'=鐙}ߏ??]o;~_EqgԾ& @ @zzzbnnaX?:K @ʉ۰zIwrrફz}CqM7ŷ63ddY7pG!! @ @JRd{E[[w @4޾O>{µ^Ƽ΋ oxCviq=?}{_5 @ @_ T*I{ntvv؀ @.wp ~pqwQ磻;~ 64Ki @ @@M@C |3m۶wx^{~=Oֳ6m~qF$]]]ݓ"{ã>gN @ @ZI =ݻS_}؀ @ vqj^5q饗[)kde 5"p >زe˼skW^ye!kvXfMsSk8cX/~ݟy @ @VIO,qz  @h -KQſΛ@.Jb @ @brr2mmm)6 @ @@hhh\:/[aڵַu޹YľǛz`1ǯkȞ @ @@RT)6 @ @@3 hhh\Zy ͋-'?ɾG=/൯}mu =O7 @ @)066,nkkK @Q`uk36iM~{U=~ ysbzzvWxGO<쑊Y>|q|[ߊ~9dSz& @ @Js=7:;;Sl@ @fЬ;uկᄏ6?R)rwk!e/{!9؇[n?/#Zɣޟ\"@ @"pl|>6lhA @C ޟrJ6[yem޼9/; {Zǥ^Z{Jþ2g?Gҥٓ^ק؀ @ ЬS+T_)6 @ @@3 hhh]^lj'f~G_җҹ^җ\NOLL 7ܐ o[yo~#-v @ @Z'j5yki$O @hhXK~)e˖x8^شiSd8Бr~({MEݏwܹ3N:餸ӥY#@  @ @*066,nkkK @]@CC׼&.y3G? nƸ{E裏O}SvG8j߳6|;ߩ}͕ݟe/{Ydx\~wSl@ @Vj&@ @+T, .$C @а$@ @ brr2ydq[[[  @ ЪZuM @ J%SsNtvv؀ @,w_ @ @*pl-|>  @ POi7B @ 2r9Tu])6 @ @@ hhh @ @@OOO.vUâ @W 3"@ @hZLeq[[[  @ @ BC @ @+(PTbxx8x9Dggg  @ @$ @ @XA/8fggk+_-E @8{%S @ @(qw*hooO @J@Cï, @ @,@ooo(ve] @hd {r'@ @h-[Dwll,Rl@ @44 @ @XrJCCCis9':;;Sl@ @ hh @ @K*p%lm|>K: @ ЌqWD @ P7r9vڕ뢽= @ p` vq @ @\mbk׮]yMB @f;> @ @UزeKLLLƢ- @ pp   @ @T*144?s3 @ ph ) @ @Kbvvvo>ÚM @hU &@ @X6rvJ_wuޞb @x| o  @ @퍹=b1֮]]L @ @ @XB-[Dqll,Rl@ @ а0'W @ @x\JCCCs9':;;Sl@ @ аp+W @ @8%\k|z @ @44' @ @,P.c׮]뮻.Sl@ @а8/W @ @8@ooo>+v^$ @,L@Cœ\E @ @[lyT @ @44, @ @@R}Օb @8< . @ @5K.$fggk|>d @ @` 44,) @ @ZS\.Ǯ]R]w]ttt؀ @_@C۹ @ @z{{cnnP,cڵ-.| @,4 @ @@ lٲ%&&&RťR)Rl@ @G&M @ ЂJ%Sg}vtuu؀ @\@CÑ @ @.䒘U磿K @аV @ @h"rvJ]{ёb @X Kh @ @퍹Zb1֮]"+ @++aeF @ 7tSLLL JRr @ @ hhX:K3 @ @4@RTg]]])6 @ @аf#@ @hRK.$fffjoJE @P  @ @:(˱k׮^)6 @ @аf$@ @h2ޘUU,cڵMVr @ PoOdD @ PG7tSLLLJRr @ @hhXW @ @4@RTg]]])6 @ @а|f&@ @hpK/4fffjUoO @8{%S @ @(˱sδ^)6 @ @аf'@ @hPޘe_,cڵ Z  @ ИsdM @ 7tSLLLJRr @ @ hhX~c+ @ @4@Rg]]])6 @ @а2V!@ @hK/4fffjo̥I @\ @ @#(˱s4õ^)6 @ @аrV"@ @sޘeY,cڵu @ мwoUF @ n)&&&R)r\  @ @`e44 @ @PRP쬳Ί @ @ hhXys+ @ @ԙ^333| Y!@ @@ hhh=W1 @ @>r9vܙ\{ёb @X nU @ @:퍹Z6b1֮]['I @-_ @ @馛bbb"Jr)6 @ @аzV&@ @XEJCCC):+Rl@ @+auN @ J^ziV100JX @$@* @ @4@\;wH @ @ @@oooV-qp#@ @xB>'@ @h*o9&&&RMR)r\  @ @>44>Ȃ @ @`*J :J @ԏ  @ @,^333U| ,'@ @pr#@ @h(r;wL9_s5ёb @/ !@ @X&ޘ^, /\LK @K!a)A @ P7|sLLLKRr @ @@ hh= @ @ T*L3uYՕb @O /"@ @X".,fffjXMC @)a9uM @ r9vؑrk# @ PwodF @ p177WX,ƅ^x3 @VJ@CJI[ @ @`En昘HkJr)6 @ @P#; @ @T*188<묳+ @ PdH @ H.,fffjwX .'@ @а;`} @ @%(˱s45\)6 @ @$K @ @ FZ]], /\.#@ @zPO! @ @#cbb"Q*"˥؀ @G@CCL  @ @!PTbpp0]qYgEWWW  @ @444~ɖ @ @ ]vY>100p+&@ @F$G @ @C عsgk @ @@ hhh=1 @ @cz{{ZŸ s @M@CC|  @ @ |111ΕJr)6 @ @И&k @ @T*188,7  @4fIu @ @ZL\.Ν;S՛7o @ @@c hhh= @ @eZ/qE  @ ЌqWD @hro9SR)r\  @ @444 @ RJ%Sgyftuu؀ @C@CCs* @ @-#peL|>7nlJ @VJV @ @@ عsgbёb @h ͳ*!@ @4@___TZb1.袦Y @hU &@ @4-)R\. @ \k?UC @hJJ7nLyՕb @h> ͷ*"@ @4_333憦+VA @ P @ @rر#yH @4WU @ @F/jB]tQԦ @8 @ @`nOYJr)6 @ @м{2 @ @@C T*ظqc3ό @ @@s hhhU @ @a.򘙙574lQ'@ @ hhX0  @ @VJ\.ǎ;r7o @ @@ hhh=V! @ @Z. qE5\ &@ @#pd~&@ @Xb[n%ӬR)r\  @ @544> @ J%6nܘr=3; @ :ZgUJ @{/˶  @ @444 @ PSSScǎM# @ @+"&@ @XrިȊ@IDATVy B,&$@ @\ @ @@ z1>>*JRl@ @$@* @ @,@R4g)6 @ @p0  @ @X+<|>xN @ @@khhh}V% @ @`;Hnڴ):::Rl@ @%P:>#@ @8lިV B\n$@ @z{b @ @ z1>>)JRl@ @O@C  @ @`QJ%=gqFtww؀ @,D@CB\C @ `+"fffjظqu! @+a @ @G,055wqGgӦMQ(Rl@ @*aR#@ @x\ިVFǽ @ @@ @ @nOJr)6 @ @а- @ @PR@O @ @ hhX  @ @+bffv>~8A @#a1Z%@ @O`jj*t~ӦMQ(Rl@ @G@Cᨹ @ @ FZY#COOÒ @Õs @ @@z1>>$JRr @ @pr#@ @@RpGwww  @ @hh8= @ @ZX+@>P: @,5 @ @;HDPH @8R G*~ @ @@ FZU52d @,4 @ @nR\. @ @`)44,9 @ @-"PTb`` U{Gwww  @ @R hhX*I @ @Z@+Z|>[j% @ @jhhX uk @ @P`jj*㎔H  @ @а"@ @4@oooTZY#C; @ @r hhX.Y @ @H`֭1>>**JRl@ @Z@CR @ dJ%RU~ztww؀ @,P5' @ @ʘUcppS  @ԫzy @ @@`jj*nH  @ @8j&6/ |ߍ_wdSx _^1s)'@ @VH7jm! @ @`%44r<*9ꨣ~Rƍc177-ҹ'?w+8y @ @`niR\. @ @`9rb9uhO}Sё^W-;#^Ν;*J_>;tc @ @/|`` MpGwww  @ @r hhXna8?5fff .7Mut @ P+k̂ d @ @ hhXQ[l1<<||xGU=qO}sdܶmۼ˲WU<#  @ @#+czz6Q.#  @ @0:Fٓ=7ě}O-xgg}}( c5.7WtzhE׳ @4T~M6E @ ZVK׽U'|rjh]F񶷽m-t> @ @@s EZ526w#@ @ʉߢLK^ybN:i-333z }SZU  @ @anZ{ބKRdp @ @oⵏ?y=yϛ/68p^\oAW,_VIsO'?q0b @ xVF,v @ @zP/;`y<{#Hw}Uqtl|Mbccc/~1ݒ磽= @ @n{I7J^9 @ @"pT$"zDkoOxEtIկ~ud w#>Ok_ڽ>1000ﺞxғ4 @X@RN;->+  @ @ hhXVY;~MG~87O<(C=w}wdOfyeM6lwN@ @,N+MS7  @ @ x 7|3/~q۠s?;={Bִp)̐]=c>' @ @ LMMߞ.Bb @ P/zHu)W*xG_j|_/}Ko٣*zŃ^?|; @ @b d Y @ @(wsqI'վ_"o!{ɼg<͂\sM\q} @ pm۶^^9 @ @(wrzw\o{564|cyw5 @ @/=]?xiŚ5kRl@ @M@CCHg>37Ծ8<Ȟ𖷼%O$N>Zu @XUW]ӵ2 -fW @ @Uа 譼G}<Ⱦ @ @ LMMӄ###|bЀ @WqmK @ @@___TJA @]@CC @ @G m۶سgOatt4WN8 @ @@ hh @ @0*JO;XfM  @ @@= hhݑ @ @ꪘ͐=ahhfs+ @XY +m5 @ @LMMZ###Q(Rl@ @]@CC @ @!jvgȐ @ HiJ @XmbϞ=^9 @ @$vK @ @T*ߟ:b͚5)6 @ @"QvJ @ @\uU1==]2{*r  @? '2"@ @Tl߾=;22B! @ @444nɕ @ pV+F,v @ @FШ;'o @ @>۶m={3rA @U@CC  @ @_RD8Sc͚5)6 @ @(wM @ @}ꪘɞ0<<ϧ @ @1444ɚ @ P۷'( )6 @ @*QwN @ @jZz{{ @ @ۨ @ @m{IF>O @hd {r'@ @ZVRDSO5k֤؀ @4FA @ @-)pUWt\.-h @h^ ͻ*#@ @T`jj*oߞ˚ B  @ @@3hhh]T @ R}}}QVk5g Y @ @&vT= @ @@S vmgϞTh @ @f,; @ @*Jlذ!yꩧƚ5kRl@ @I@CC3Z @ @ꪫbzzVc.᦮Wq @ Z{UO @4Tl߾=e53  @ @fl; @ @)ZjA @Y@CC3 @ @bϞ=)6 @ @(wUM @ @@T*ذaCSO5k֤؀ @4fYu @ @M!pWt\.MQ" @ @ hhxb @ JZiJ @ԭ@R 6N9XfM  @ @@ hhhW/ @ PW_}uLOOrr122RyJ @ @ @ SSSnb1<<Bao; @hI -&@ @I/j-! @ @44O  @ @UȞ̰gϞh @ @VЪ;n @ @`*Jlذ!q)Ě5kRl@ @ZY@CC+  @ @UczzC.U @ @44nȅ @h^7B7 @@ @@___TY#úuV# k @ @P[#1 @ @Yo{I华F>O @ O @ @`*J_>x)Ě5kRl@ @R@C @ @ \}1==][1 n) @ 8gdJ @4Tvm( )6 @ @~%WF @ @ejZ[#kdXnݲgr @ yN @4cϞ=))6 @ @ hh!"@ @,@RקyO9XfM  @ @44o  @ @`Iwtm\.###K: @ @@3 hhh]U @ P7SSSm۶P  @ @p`g  @ @K"j6WȰnݺ%$ @ @444 @X5۷Ǟ={Sl@ @\@Cm|B @8lJׯOr)f͚ @ @ph @ @K]zWLOOr1<<|X @Vyu @ @&055۶mK EXL @  @ @E EZS(bݺu @cރ?r;{ZzH ;NU[@ՎΠ9do! v%!ء:bZiUFR.2Z9Tsz>o,do:3}s>y^Cxs @" 4[@ @E믿>򕯤n---) @ @'`\E @xZGy$u{OO @8| oJ @ @!V^=PvM.O~򓇼އ @ @S hxj @ @[{;w?ODkkk @ @ h82/W @ @*P,c߾}g/jE @s' @ @ c||S###Ғr @ 03 3s7 @ Є>*  @ @007V%@ @@\.PsΉ  @ @00wV&@ @\`155ubÆ uޑ  @ @@hR) @ 0{oر#x%Dkkk @ @ h[_ @ @u*P,c߾}Y/:D @ @> 4繩 @Cn!###Ғr @ 0 @ @@ Js9ёr @ 0?. @ @@^:js\lذN*W& @h, u!@ @f pΝ; \rI\@ @̟ @ Pb1*JVŋ+V @h\ {:#@ @@ntH\@ @̯ @ Pr9Reg}vttt\@ @̿7# @ PcW\.^ziU @ |uL @ P*bΝK.$Z[[S. @ @F@¸ە @e˖ERɪYxqHe @ @-`_ @ @nO###Ғr @ p @ @ J}ёr @  @ @ ^:s\\z Tm  @ @ h8 @ @(Js룵5 @ @` 4, @ge˖ERv]xq,_|+ @ tN @ @@C x1>>z  @ @0P  @ @`r >H @ s*!@ @X`155K/-O @s @ PWR)vܙj^~}\@ @Ԗ: @ @s$lٲT*/˗N%@ @fC@l(Z @io1S###Ғr @ P{jLTD @̢@\g) @ @)`6EU @ @, TZ.K/tV  @ 0R @ @ JرcGaښr @ PjlTF @P`ٲeQTU B,_|+ @/ %m @ @`^nO{nݺ5ZZZR. @ @j[@Cm @ @(188<쳣# @ @ 4 @8Bޘrq饗 .'@ @Z@B  @ @Y(Jcǎ룵5 @ @> 49 @8Le˖ERɮ. |üe @ @@- hP  @ 0#o1[n  @ @0P?gR @ @r9K.  @ @0P_Z @ @)z{{cjj*4ƍJo @ @ `NI @ @!JRر#]~hmmM @? wf*&@ @ lٲT*ٻB!/_+ @ @@ hS/ @ 0Mo֭[% @ @> 4繩 @_rbҥёr @ PTN @^72\.7nlz @ @Q 44I @4@T;v/hmmM @o }~'@ @M+lٲT*YB!;F8 @hD xz"@ @ .pM7xr֭Ғr @ P u@ @J\.@yҥёr @ uA @F7~s\lܸiz( @h& tz%@ @u.P*bǎ/8Z[[S. @ @G@C㜥N @ @@ ,[,*JgP;{  @hV z&@ @u&pM7xz֭Ғr @ X w:&@ @5%P.c`` tYgEggg @ @@s hhs5 @5kTVO.M6Lm Y8}?pؙ @\@ @ @@ JE])4c=wyg{׾6g{lE/w]q~ $@ @L8Z஻{7񖷼%N9唔  @ @qbT*B+Vhfu$nX~A?ٟ%Kd OZ @ X<벛[ouo㌌h˓T4 @LছntS[ZZR.hlqgGuPp_O/|!?| @P@C  @ @@ HmuYٙrAc G?5zq{7 q'޽{'7To&U_#Hs=qW5 @ XOĮ]w?qvݕW^'tR?>o @ @@ S- @'R4/hmmzկ~'3s1qeg>3M~o~37Ho @ @a}{/S~ӭկ~ @4hNlx>/zыy{ޓ?7~_  @ @kM\tEښrA |HMvuux&A{{{կ~2=^WdI @ @@ hèR0o?ؽ{R߁qƣ~L>/ iI,zzz{޼V|o۷o^ @%P,Rd Xbš.Y 7 )iP]k@Á{t] @ @ hX3 m~z6ذ ?OGbxx8gMOsU۟41W{=պ?O# @ @`^nK{DKKK/PGS'|rg/~.~ @!cjԉgOk?i_׾6i7cr),xqp@ @@\dqYg"8cxF{޽)ipZLs? @Ԑ'4aS)/{˲߮ٲeK <կ퍋/8,Yw}DG?QWy{^=R+ @ *vژʺrW6h:@u/xA @ @@ T;Rd XbE7çx;ޑ>?_K_R̖9o}Lt? @Ԑ:z.%Ƕm۲2x_Wq;xE @ @|Wedd$ZZZ~69կ쩎3aD_~z<ޟI @ `Zxw{ZYqꩧ+-*!@ @(ߟj;묳3Xxq,Y$5f͚x衇R~Aon[jU @ kO>9>Ν;|fE|>;~ @ Xk׮\.7nlusտ տ׏"^pzt[uhR. @ @0X]|o}[7yZ}wqG @_T4@IDAT*ŵ^~%@[[[-W_}uBNޡL\qٓ{iu @ @ 4y]c=6_}d)b<} @Է@*JDP+VwCuñrʴnu5˗/?`wި>}TZb0sN: @ 5Hڨa;..l//~v) @ @@} |166 >e:088է.T`mۖy_ox׾g?Of9r)ޗ @ @@hhNĿgqq7| $@ @(ߟn833O}yk_{nLMMFϡ^guV5p(% @ @|Da]ug=+n?&F]X @xJkצ)bӦMOy8+2^W?O8XdIu]qww*y @% uuM N;Ї>_n @ @JR?袋m'C x≱bŊOuF_"?x _yko}k<>Z>$@ @0XYWݼ//}K]=o| @ @bT*P(dcMtx+Nj @T 4{x3kAk9 @7cccihiiI @ p#@ @[\.GB833 @ @L 4DϽ @ @֮]SSS@.M65  @ @00ۢ#@ @M P*kM[.R. @ @T@LO @PX,FR:/ r&T2 @ 0R @ @nKDKKK @ @00 @ @M"P./u{gFggg @ @00[!@ @M vژ:riӦ&Z @ @BhXu{ @ @:(Jqצ׭[mmm) @ @fS@ljZ @4@XJuX(bʕ ܭ @ @0а'` @ PrKJGFF% @ @l hmQ @ @(ח:33 @ @\h Uk @ @3LMMerشiSu @ @V 4ɨ @Ԁ@Tk&UnݺhkkK @ 0WJֺ @ @bT*B+Wl@ @ԃz8%5 @ @[bll,<22---) @ @R@\Z @ԩ@\Tg) @ @Z@\ [ @ԡ@uajj*<ŦM % @ @,`OO @ @`JR\s5iuE[[[ @ @00 @ @u$P,Rd XbEUT @ @Q 44I @̂-ccci) @ @K@|Iۇ @Ը@\T%K3 @ @| hOm{ @ @ɬ\.7ojF @4F?a @ @(Jq5פ+׭[mmm) @ @[@|ۏ @Ԡ@XJUV(bŊ5X @ @f0LW @ p[n%'###S. @ @,P' @r%KDggg @ @0аP%@ @5 Y%\.6o\U) @ a @ ФR)P\@ @XH oo @ b1*JVAP+W.`5&@ @L00CF @B[oH  @ @ -`aO @ @`r],Y) @ @jA@C- @ @< T&''s\l޼yw @ @ 4 @ @@CJkR/CCC֖r @ @V 4I @̃@XJT(bʕ- @ @G.`A @R[oTH  @ @$`NC- @ @`r՗,Y) @ @jM@Cz @ @dr.͛7.$@ @̞ٳ @IRW_}umhh(R. @ @ԢZ<5 @ @Y(QT B\rW @ @`n 4̍U  @ @@Mz166j|>r @ @V 4ɨ @P\.G___Zeɒ%ٙr @ @ 4騍 @@?&''r\l޼y @ 0n @ @`^JR\}ihkkK @ PjG @BX,FR, rʣX- @ @0аpv&@ @s"p뭷XZ{xx8| @ @z0PF @ pr9K,  @ @"`^NJ @ @0crr22͛. @ @jO@C흉 @ @Q JӽCCC֖r @ @ 4i @BX,FRɮ( rC\# @ @@m hQ @8,[o5ҵÑS. @ @ԛz;1 @ @'KqՕr @ @ 4㩩 @ ;\..> @ @S@C}  @ @@&P*ꫯN֖r @ @^ 4ɩ @@OOOT*̢P(υ @ 5A @(p뭷hj}xx8| @ @z0Pϧv @hZr}}}38#R. @ @Իz?A @ @@S d{..)4M @4=[ @ @@ JSw֖r @ @ 44) @J'*JsP?, @ uI @ "k׮M G>O @ ($A @ /P.cڵ38#R. @ @4F:M @ @@C dc.. @ uO @u"P*bhkkK @ hDC @ )J%P(ߐ}j @ _@~ ?  @ @@ ڵ+FGGSuÑS. @ @4Fr @ @ 44  @N\.ڵkSgqFtuu\@ @h pz$@ @ɬ\.]vY]կX @ @lh Ek @ @Y۷- @ @@hh' @ԅ@XJZ(ϯI @m -j= @ pvtp  @ @$`N[ @ Pr9֮]  @ @&`N\ @ P199Ֆb˖-5Y @ @%`aC @B`bb"oߞ>  @ @(`O] @ PSb1*JVSP?S  @ @`! 4,=  @ @صkW&) @ @U@C  @ @`r]6]]]) @ @Y@C3  @ @`Abrr2!Ŗ-[ @ @jI@C-Z @ @i&&&bpC[[[ @ @f0O @ "P,Rd{ XjՂaS @ @@ hՓQ @4m) @ @Dh @̣@\5k֤+ @ @_@  @ @`brr21Ŗ-[qw[ @ @G@CJ  @ @&&&bpC[[[ @ @O@ @ @9(QT= BZjN8 @ @ 4驝 @FnTp  @ @ h!#@ @.P.c͚5iJ @ @l @ 0199b˖- @ @(`OUO @ P3qUWz- @ @ h8w  @ @ŨT*ZB!VZ5+Z @ G @ &pmhxx8| @ @O-`m|B @Z\.ǚ5kՕr @ @ 4ǧ @ @crr27e]vT븉 @ ЬM @s&011W]uUZ`` S. @ @xz Oo  @ pDb1*JvOPUV.&@ @0o @En-FGGӊÑS. @ @8< * @ r9֬Y/ @ @#0pf @ @\.[l9u$@ @xz Oo  @ qUW= @ @#0pd^&@ @(QT-ZV:u$@ @8< * @ v[GFF"ϧ\@ @ p @ @ XfMʻNj @ @`ffn @hrr\lٲEO @ h @hBꪫRޞr @ @ h8z;w @ @@ ŨT*¢E .hr @ @fO@YZ @H`1:::|>r @ @ 4 @ Єr9z{{S]]]QE @ 0{fJ @ $199ub˖-Mҹ6  @ @'`aD @ 011W]uUꤿ?S. @ @ h @hbJ%vѢEq4I$@ @̯ @Աݻctt4u022|> @ @00{V"@ @(ۛ:/ @ @007V%@ @ɬ\.[liC @- u!@ @m۶= @ @00V$@ @(QT-Z\pAu @ @@ h3Q @Ԑݻctt4U422|> @ @007V%@ @(ۛ:/ @ @00v @ @:ɬ\.[lNM @? wf*&@ @ym۶= @ @00V'@ @:(QT-Z\pAvl @ @@} hsS5 @̡ݻctt40<<|> @ @00v @ @:(ۛ*  @ @G@8ۅ @D`hh(&''js\lٲN*W& @ @ 44y @f 011۶mK+G{{{ @ @'`aD @5.P,RdU.Z(.Xy @ @0иg3 @8ݻwhcxx8| @ @+`a~F @5(P.7U) @ @̿7# @ԘPLNNfUrkB @ @O@C󝹎  @ @ضm[z/S. @ @X nW @bJ%fѢEqHe @ @4> @ @v`xx8| @ @ '`aL @ (P.7U) @ @,; @,PLNNfr @ @L@TG @ -011W]uU걯/S. @ @Xx * @ @y鉽{f.Z(.yv @ @O'`|N @ %pǞ={ROÑS. @ @  q @ @y(˱zSgggtww\@ @ P;j,TB @s,nݺvrq'@ @8Z G+> @+ضm[/S. @ @- u!@ @9鉽{f/Z(.9ɲ @ @!`a6A @5-pǞ={RÑS. @ @= w&*"@ @Y(ۛV  @ @jS@Cm @ @`֭[>`Z./|V  @ @\ hK]k @ @ LLLĶmR }}}ޞr @ @@ hݳQ @P'ݛhѢ g  @ @K>&D7C='tR%/mۿ{ @8,o=ٓ|>r @ @@m hi/}Kc188|;z7  @ Tr9z{{ǝݝr @ @@ h3 gC ?#\O9˿8Z˧}.o~_]zW7|s<99إ#@ @֭[>`~./Ix @ @ 4luo;Ak>}X,Ɔ cMTQq۶m)?೟l/~җpnq  @M,PZ/ۛXD @ @8>VB \qw;jZۣ>7o38#'+ _B_Jwg{T  @鉽{fV"w6M%@ @4F:y:̰jժxkۿ+VdRo~_ 9Tp=?KoKo}, @aQ]^U;3 @ DuŃ>9/ @ @0Pg7W򕯤=ǸnذaSOhxӛccc7]WT|C??M*xK^]wݴK7)!@ @&&&>]M4O @wϏ]=aaŊ)7?U?usLlٲ%TtҸ;_W L:}d<m^ @QD+T_- /L @h( us??ūC G>YzV|O~x O{?PvM4{طo8UË @@3~:<<|~' @ @@ ʉ:=.ŋdz!_մO=i&{]ZK/0CG5 @uSz{{ӺQ}ʛ @ @@ xBCtC}{hz~ģ>i @ @ԝ#[_WᄄT*)o|c/.+JOwA??I @@ ޽{O[zuJh @ И\gWUi0õ^ n7oi?qUWM{կ~\B @@s |S={#ϧ\@ @ P 祃WOS{O<Ĩ>Yc]u ⮻JKD[[[ @4@uX1tttDwwws! @ GDC /MozSyaޭ>a}ljw^{ޓ @ <֭Kֹ\.i^ @ @&0D=VOU+-{7&կ _Bި~K_ܟI @@ LLLĶmRk׮  @ @GiE's-𶷽-.]wqǴ>E3>|7>}{_|_Gy䠷Uh?$@ @zzzb޽Y͋-uՈb  @ @V ڵ+>яV/^سgOyxx8| @ @%`sλ9bΝq5?mSO=uZ~4Ikkn>:H}'}  @C\.O{CGGGwѽ.  @ @)`9}]{q=PUā7qwm @Wࢋ.|0kc^ā-5y `/"ȨLfh)8:QF mӴER6FQQgP)ķD( pm$;kue~/466F:: @ @@m ̪d7_tvv|͑Y @ M6=cW- @ @ [ z @C3Έvͭ @ @,w  @ PC7n4˗ǜ9sX @ @4~˖ @+bWOT- @ @`4L  @ @`^xalذ!΋ٳg @ @@ (h=1 @*J`ӦMeOc8c# @ @o '@ @ q100PZGccc]vd @ @/a  @ P7n4e˖Ŝ9sX @ @~4˜ @.b5Y @ @@e(h}  @ԝubÆ iw^̞=;5 @ @[@AC}  @ 0-6mt8cX @ @ @ @`8(S @ @T#@ @@ lܸ1zzzҼ-[sIc  @ @ @ @`JڢX,lnn)d @ @!:*  @ P֭ 6$={vk @ @,a @ 06mt֘;wnk @ @*a6 @L@ggg oll  @ @[Pа% @ ƍ;oٲe1gΜ4 @ @ 0\@Ap1 @d.b4nssstttd>  @ @jK@ACml @ Pq֭ 6J^51{4 @ @ 0T @ @@&6mt֘;wnk @ @ؒ-'@ @쌁85 @ @d)!KMc @ @,Xbasss$  @ @%adK @袋bÆ iFɫ&r\k @ @Z@AC֢#@ @@ ƒ%KҬZ[[c޼yiA @ @`24L1  @ PC100Pʨ138 @ @L6> @XP(DWWWAGGG4 @ @ 0Y &Kָ @(L#)hp @ @  Sl @TE](@IDAT}}}ʓWMr4 @ @ 0 &S @RXdI֘7o^k @ @l -l| @T@ggg V @ @R@ATj @U P(+]iGGG4 @ @ 0 B @"(777GR @ @ 0 Z| @`.(&riA @ @`4Ly @ Pdɒt1o޼4 @ @ 0 R\ @`(138 @ @L7/ @*HP(DWWWiA @ @`4L @ PmmmQ,K+knnA @ @`:4L  @ P]tQ+I^5X @ @t(hus @ @Bcɒ%jZ[[c޼yiA @ @`4Ly  @ P100PZIccc$Ogp @ @ @ @i( ՕμtiA @ @`:4L  @ 0mmmQ,K+hnne˖MjLM @ @\@AC @u!pG___kwwwr4 @ @ 0 {O @)ŋq @ @*A@AC%5 @ @` :;;c``4ccccL"@ @ 06 csr @jBP(DWWWҥK#ϧ @ @JPP);a @(cٲeS0) @ @_@AA @⋣/]{wwwr4 @ @ PI *i7 @$088/NGomm;.5 @ @TJ!@ @$\2J#766FOO$bH @ @ (hH @HBk׮M׶tiA @ @4TX @2hkkbX9-["@ @ 09 &ը @/8ҵtwwG.Kc  @ @*Rwƺ @ xt8X @ @@% (hݱ6 @lʕ+c``4BCCClhn%@ @ 0 l @Bk׮M|> @ @*]@AC @ @`mmmQ,Kw655Ųe&0[ @ @L73 @&E/tU\.5 @ @Tj%k$@ @cխqqǥ @ @jPP-;e @ʕ+c``teCCC$Ogp @ @F ոkL @Q B]6=|>5 @ @Tj-k%@ @VڢX,hjje˖mj @ @T#@ @.KM^5X @ @@ (h^ @ ŋ---qqǥ @ @jPPf @"r(444Doo @ @S@ACuU @ @$P(bڵҥK#ϧ @ @jPP;g @xR-bɢ)/_΅ @ @@M(hm @(~KS\. @ @Y@AC5 @ PhѢ48X @ @@ (h~ @R`ʕ100Pʽ!z{{A @ @+vVf @Ԩ@Pkצ-]4|k @ @ r @ @ڢX,rnjj˗U%@ @ ϲ$@ @F֯_}}}i6ݑX @ @@(h @5/088/Nlii秱 @ @ZPPK) @jZ3όR [J @ @4˞ @*( f͚tK.|> @ @jM@AC| @I(ܚb5 @ @lPаYO @T룯/]]wwwr4 @ @ P jqWD @@ ŋ|ZZZbiA @ @V4ʋ @83KCCCD^ @ @ - r @$P(b͚5K.|> @ @jY@AC- @j(bU @ @h @S$~Kg\. @ @j]@AC @:Xxq?~k @ @ r$@ @ @ @<%) - @L@[[[MMMbŊI @ @Y@AC5 @ P5\rI\. @ @ (h( @ @ sXhQ:nKKKiA @ @H #M @ @ SUVEĭt| @ @E r"@ @b B^:]O{{{4 @ @ @`t %@ @@&mmmQ,Kc555Ŋ+2  @ @j]@AC @6K.$"˥ @ @[Pаeg @ 0aXhQzKKKiA @ @4lY @LH`ժU_!z{{'4 @ @ԫzyy @ 0iB!V^|>5 @ @ضm @hkkbX)VX1]L @ @@  @ %\}}}]]]X @ @ (h @ MXhQz]KKKiA @ @4ʕ @تUtMCCCnz'  @ @ز-8C @1  Xzuz}{{{4 @ @ @`| j @*p(sMMMbŊQI @ @4U @آ%\_~yz+r\k @ @ 0~ 7s @RXhQ @ @LL@AE @Unhh^2 @ @d !DC @ PB!V^&dɒiA @ @4LΝ @Թ… X,Os @ @N`VvCzH뮙R$c,, @ZK//~c=O[{キn?l'x, @J8)[ZZNHc  @ @_@AW]uUo;cD?p\wu?gqF$]bE#A @VZ744Dooo5a @ @*Z`fE*NG˗G=j1?#q9甞hi1 @( ztK,|> @ @d#!Ǻ+:xǕskzիJ׍.&@ PaȊbiUMMMqW - @ @@mxDmdqwFgg爹k8C]?KˮMwt͂  @T^_~yԵkF.Kc  @ @PАe͏tiŃ>9cƌ8Sh466I㡇s=7>شiSٹx'" @ P-Inx'pO @ @2ʉAku'q~6֬Y3!h~0 {e%AO~#u @TÑJ-9Rj] @ @jB@ACMl'qחM6т=3D{{k'կA @B d%KD>I @ @$(hZ?yYZC-;1J0s>V*;cś @*M yXX,-)N?J[ @ @9Y5&E`hAC:8`$_Θ1=s΍k&{J!ɫ3~_L_=i[ @`^zi\~k׮\. @ @LqQ7nܘGԅ+V/֬Y~=Dkkk\{n8JO @G>撼zNHc  @ @&O`b+=y1r ҂| @ZH|wVӓ @ @ʉݚZXR0'>14P{vo|뮻ݿj*- @ @ @ @4ߞO(:쾳:+n喲/x "yMBccczj|/ @ @ @ @@(hޮL_+^tb|?L&xի^bƌOi @ @ @ԇL\fM8v[yq'_v~<'g}[>ě: @ @ @ @4f+_xX6f$>:gGrD8sF~]wA @ @ @-7;H^?cwҩ1/Y$9~bL7 @ @ @jJ@ACMm'G___|Yfp=7ގSN9%.u]{  @ @ @ @F4FNe3gΌ+VĕW^/+<Ȣ!e޼yqM7miS @ @ @ @`j4LwMvǗ{oL k+J:ꨚ  @ @ @l]`;~F̘1#^8Ak_R[[n`TC @ @ @ @@% (hݱ2]v%8ҟ @ @ @9- @ @ @~ տ2 @ @ @ @5'TB @ @ @ @4Tʀ @ @ @ԜR  @ @ @ @PP{( @ @ @ Ps jnK%D @ @ @_@AC  @ @ @ @@ (h- @ @ @~ տ2 @ @ @ @5'TB @ @ @ @4Tʀ @ @ @ԜR  @ @ @ @PP{( @ @ @ Ps jnK%D @ @ @_@AC  @ @ @ @@ (h- @ @ @~ տ2 @ @ @ @5'TB @ @ @ @fU 2 @`4+2N=N}ߣ>_~y  @`wu/p23Ӏ u}k[Y:Wu[f,0gΜ-t @ @ @@ *޼ .&6(p'uW*fMo,'ys܊Y @V~oRz|3c}TEwqGi=\.oY @VGvmWtA P1b1nt= .TC@m $ /2f<䱵 #@@ z]JtuuZ!@@ ^:,YRZ_X~}ŭт Pk֭O]  Pg{ D.eH K[nSN9%vu X% @⊸~w޵  P_MozS/Yd%!+I @ @ @ @ xDf"@ @ @ @PАq @ @ @ @4dFi  @ @ @ @ + YI @ @ @L@ACf"@ @ @ @PАq @ @ @ @4dFi  @ @ @ @ + YI @ @ @L@ACf"@ @ @ @PАq @ @ @ @4dFi  @ @ @ @ + YI @ @ @L@ACf"@ @ @ @PАq @ @ @ @4dFi  @ @ @ @ + YI @ @ @L@ACf"@ @ @ @PАq @ @ @ @4dFi  @ @ @ @ + YI @ @ @L@ACf"@ @ @ @PАq @ @ @ @4dFi  @ @ @ @ + YI @ @ @L@ACf"@ @ @ @PАq @ @ @ @4dFi  @ @ @ @ + YI @ @ @L@ACf"@ @ @ @PАq @ @ @ @4dFi  @ @ @ @ + YI @ @ @L@ACf"@ @ @ @PАq @ @ @ @4dFi  @ @ @ @ + YI @ @ @L@ACf"@ @ @ @PАq @ @ @ @4dFi  @ @ @ @ +YY dTwOv[g֬Y Ͽ䏃&p]w\7nB/b>7|xqGnj36 @`>nR+297ǩ 0qn!.Ҹw]s={};o޼9N\ٝ~O񏏸0y/yKJ;$O~'? Oj.#&@@ xBC Ygɻ }?䮾Rnn7|_6|cj0[kܹQ( >ғpgoRЋ/|կ&@\ 0+&38 @ ;UVŧ?gG?HZv7Ʒ;}'O?QOV=QDd"0:ꨲ.xV?x;M\|xv @#/| Xֿ9H% }Μ9sg?Y̚5ke~ @(>׎ <=5yM\y啣&yT5kF=FE/zQ<#Sv_ZKʰK/7c$;$9 @z>eEJx衇JO +>O; 0~/}Ke7ޑgdz8#.ַU  @4TX 8`3 ݸqc$_\8 P^{mYsLYUzUKNs=qo  @fUZ,*GGGG-ٴiS$188Xvc=?p̞=_@z/ɗC׽uCm7?nz~A>ז{ 0ckweU/n,~l T/%@`;o 6ݏ"x]v) @^?!%/yɸ?chAí:1@z^vZTx;ҥΜ93+g} 01arA4K@@ACl N yu]W6`pԫ~s\e}c .;"yΎ;X/ @l|(뮻RɐGqDk @~ӟ|QGŌ36ww StMhѢkJO9#뮻F( e @4TߞY1$6>ٓ-o) @?|0#]b@  A@ ~qꩧ(;} }7n,`v+DܵkFvoק  09!y¯xK^ԧ4_c9fēw4 @`4LX lٲ׿^}+V( @?!ʹݧa"!@|ݺg]w]zk^󚲧5'4 @`|g͚s΍)9Cw1?8ꨣ|Siꫯ7MiA#zJ &q9͞jb;  Poß0ړba,J!@ \}~&@@"p5D#}s1cƌ]~ @@?p$Oz|iWRp 7D?{^BK/}KC?  @J4TFY&#<2?_: Po=PY eX5<A\Qo79{*TC 1o~R̙3cX|ߍ>8xWwÿo8JE*_+VH)x'bq駏7wAzH8xGcnvN;4]H \;^LDHo}'tRk @@v[% D{{{Y!h3k,\w=/]$ @UQ"<&쮻ֻoa~(gb] .`ٞH>0; @gQ bCɭɣ$[z 0ϵ%@D.8[s'? +)~IDAT6{gs~~C/| e/[  @4TX^xa}+CTcK8⪫zVR \ܽ2X`ƍqa(fH>&a7tT/ Oݘ0I @ Z  @ꞷm>_hiiI 0sQ >qvAݓO@+ 7VF \}1f}k_ZС섀Jɣvocnv'4υH|M)4 @@___Xӟ}oYߖC+bĽo}[#z6<).0xq뭷K_b@ )D $H~G)xΜ9o;  @)e```DL /VEyEuGRsΉH368#.vmh6 ?p}g?{ؕ[W=9xӞ6K"sVp"@JE|']{Cʝv)K{qx12 SFm"&*^{E'sύKo~s8(^w\ۈ暲+^Wزϵ[q @z^X| Ixnm{> P *s_Ihoo1>Xre̘1c9 0Ry{^477wܑq4{q-';, @>׎Y / |կ?~sXC@T#Hۛ72)h5*K`ƓY/zej WҗCK b…g@Ժ@R vc}B;殭x{ߛ^ܗHLyI4 P>&JH^,N5k֤l]CGESn4Kfzio_HOj @@ ̬Y&Q;w1!.6 ohjZo|cY~/ _BYߖG}4:묲LD@>׎4C P{'tRYR7tS|/ZaÆbcn~ @`4LXJ]/`fX)$Ak -J\H hZ&B,D[f-\) ܈TH+ڄ-E FŚ̙ygao/|-߿K39A]`: ͛gꫯ?8xpu>AÌX]t  8wܘgڵcϞ=O> '+W\\wo1mv8/^O=x֭[ozӑ^xq陿ڵkL!@?m @x衇믿>ҥK'W{1>q闣GϜ,n{w, @#cǎGu~20~~sXZ'Oy>'~}e8e׭[7mذa|' @`VY i/nŗ_~y8qi @_x[o5se˖g}v8p`|-kի309}{9 Xw\2֬YSZyFpsXzׯ_<WZ5>cGgX+ ]jϸK. hӟA"0q7|oݥgώGyo]ߕ @ ,}7  |ލ%,Qӛw^?<{=1Â\*uR}=n @X|8u8rXbł0_LGf3,ͅ  h pG'O&@/So3gΌ-[m:rǗ_~9ç!@[ x]{k# @;8vؘ^ٳgLG{;ww}wCW,b_9w p |7ܹs?Ø>ظqشix @ @Aয়~|ꫯ?]66l0$|p$ ePs @ @ @ @@.+'rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @!7@ @ @ @ ePs @ @ @ @@. h - @ @ @ @eAC @ @ @ rC  @ @ @ @@Y@P5G @ @ @ @ @ @ P4A @ @ @ @e :iIENDB`wkutils/man/figures/README-wk-draw-1.png0000644000176200001440000073145713774415351017401 0ustar liggesusersPNG  IHDR4הLiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ @IDATxwU?X{ED AMH,(cbA1D 1&$ػb>bƊĆ}a{Ͻ>yf=Oy}2#8 @ @ @ @ tMh-B @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@{ @ @ @HN@!X @ @ @  @ @ @ @hH$D @ @ @4 @ @ @ @+ @ @ @ @  @ @ @ @ 9JbA @ @ @ @@ @ @r a֬Y5/ k?zʜ桇 mQf @ PrU @ @§~fϞ]S" s 3f1gΜv @ P[N֮ @ @ @tNS* %@ @ @ @h(O]) @ @ @4 TJ @ @ @# PZR @ @ @ i:M, @ @ @G@$?><MzV_}зo-آ裏BuJa|4O[͊+ZjO|=}f{'ǬY»[w.]UW]nF:aܸq_ N*v޽[ozT @ @@'2R  @ @B/;'V>}Tmn\.:]tp3<rhm:JaΜ9 0`@8~qG1cƄ:f C wqZ>cù\7j5??}-ڣٳ[MnOxt믿jo;p1ǴhA^Źoy晰WN?c9bX'֭[}96pì @ @ rR  @ @&M [mU8⸙3g*: }!=g~SOV2>~h!sυ:(+l=urg5e'x{sNPw]i޹}wzqI'5tr) !Zyam q1Dȳ}  @ @c:ߧ @ @o%|O?{|+(Io馰Vʐկ^[oF.z];=niPkRG 3fNwĭ=m馕->͓/g}v!GqD83!n1|}'(AĒB&g;O @i 4U!@ @u_ꫯ!~Q=Keqܮk?ߥK0lذ/C#OVjR)1H!1a„zS 4v=XnCW\qEZ[;~p9{ @t>.Ҡ}  @$%;'6].{7߬|=}s:ᥗ^ q?oqxwk[uUFmM^y0uym^z_lo:ٳr=ׯ_x׫5Uŭ&V\qwD{f)S}l_+:455e}#^6l>SUN@b-Vdd饗n~EYr/m喕{#n7d>a }N @ @o+Z @ @1dȐy7ɓk? }'4iR裏jUo;z:C\b_WfyA y'ß[nJO>xC YG|@29O{УG]x`+Bo?֧yߖm'n"^l|}l h/{^}vy95uYGrce 7xc}>^7 @ @CE$ @ PO`РAu< zSUtWO>$K8S;g5 ^xafWA{GX|k~zb֑'Oܨv|W!k5X#lՆ6|nΜ9?9&nC,q+>vmp'֝6u]3E믿>F @HS@!ͺX @OBh!e]6k|CQoVZ)zYSkO?K7<923&L0!/Su@ @ 4$+"@ @ o}Vymq<̼s_jqz_ K.d)Z/8ğ kv֭[>)Nr-UC iEfy͋za86`o3}Ccb8!.d2eJOp @ @@h\Z @ Kޖs̩9ߛoYO>/=zm];hhO8S|'Ozs?v-W=]vYx7:瞪{P!7 @p// @ @%s,byx_M#_&WYm'j1[oU30hР0p7wou~qk; 4|' @ P@C1f%@ @ {B֭[S hsǭt 6,rJC3 vy;c^}w^[v+ba-7&LPǬjm$T3mڴ@ @+ б> @XtEsiKaƌեKʗƸo^ 4.9vuךs5?O? <@~C MMM5ۋh5jT={vOXi5kV>: @ @@Z ij @ @@]eY&s=Kot椝q5W9q矇s|A=o\@̙3k~[>\z>{w{?Z[{ @t@C` @ vw>neP(g,1c4iRxiB|E>yke;d5W@ @߀$wD @h$0yz,tlAXguj^Wvپ;h7|3wqG+pwW]kע->y  ߼KZ~;1X1nܸ"̛餓N +Ҽ_̚5+}ѭOѭ-$? ~UM h8 @ @s 4tzY- @vό[+[}꫚_O>=<á{?r˰*\_]z6dk;ǭ*YfSN9%ĐDz.N?O-:ns W^yeC?b$j @ @@ Ʋ @ @@*{WRGqD={vf6|50AT=DÇ^R|C#o!k=%?yX3s1a̙}mF @HS@!ͺX @HF nApQG]τ fmV{7L:5L2%#F|:>+BhBϞ=4hPX|ūU;?{՚ 9{ ]q>hϏHm=?ޜq[BF"nuQ/~Qv @HT@!X @HI# lA%'\yZC=B߾}+ǍWwB-NwXdErvq1̰6|D#еk_'M>=7id'5V^yʿ^;jذaW^;G|:ȑ#Ӂ @iת @ @Xr%C %ğEqKn-,EL_yD [W >ws7rH]q駟S!^[cܹ Z9tuzE#C @ߝ@wg @ @@Ohk=tKTXm:5;nnkf{s[oVYeϸRK-U3"lQRm?ZSs1qM6$8  @ @ -a5 @ @ i/?>t޽]ڰ[|1I|jE 5;jKgv_7bM4/}dv/"O?[o q+<ꫯ^ٺdȑyK @ 4$Z"@ @) ᦛn =X%6^xpW74.N{WO: *K4m٧T3<3c~0z>YtҤIOlO8S‹/ci @ @@'2R  @ @f͚~裏>oƌaUW / e@ٳg{'<7 SN z<%bm _ 8 @ @`hXj @ @ @ @B! PE @ @ @ @K@aᪧ!@ @ @ @ @BQFA @ @ @. @ @ @,M U @ @`0aBx;[o0lذ_ @ @2 4ꮙ @$.pm .W9b @ @@Yl9Qʻn @ @ @ @Cű4 @ @ @ PVVu @ @ @ @^ @ @%޽{ׯ__}^:| @ @*e7GY/u @ @ @ @i r"ͺX @ @ @(@C  @ @ @ @@ iŪ @ @ @ @@J]~O @ @ @hH.VE @ @ @J- Px @ @ @ @Cu* @ @ @ PjR @ @ @ @4ҬU @ @ @ @R 4. @ @ @) Аf] @ @ @Z@w @ @ @ @ M4bU @ @ @ @ .'@ @ @ @i 4Y"@ @ @ @h(u]< @ @ @HS@!ͺX @ @ @(@C  @ @ @ @@ iŪ @ @ @ @@J]~O @ @ @hH.VE @ @ @J- Px @ @ @ @Cu* @ @ @ PjR @ @ @ @4ҬU @ @ @ @R 4. @ @ @) Аf] @ @ @Z@w @ @ @ @ M4bU @ @ @ @ .'@ @ @ @i 4Y"@ @ @ @h(u]< @ @ @HS@!ͺX @ @ @(@C  @ @ @ @@ iŪ @ @ @ @@J]~O @ @ @hH.VE @ @ @J- Px @ @ @ @Cu* @ @ @ PjR @ @ @ @4ҬU @ @ @ @R 4. @ @ @) Аf] @ @ @Z@w @ @ @ @ M4bU @ @ @ @ .'@ @ @ @i 4Y"@ @ @ @h(u]< @ @ @HS@!ͺX @ @ @(@C  @ @ @ @@ iŪ @ @ @ @@J]~O @ @ @hH.VE @ @ @J- Px @ @ @ @Cu* @ @ @ PjR @ @ @ @4ҬU @ @ @ @R 4. @ @ @) Аf] @ @ @Z@w @ @ @ @ M4bU @ @ @ @ .'@ @ @ @i 4Y"@ @ @ @h(u]< @ @ @HS@!ͺX @ @ @(@C  @ @ @ @@ iŪ @ @ @ @@J]~O @ @ @hH.VE @ @ @J- Px @ @ @ @Cu* @ @ @ PjR @ @ @ @4ҬU @ @ @ @R 4. @ @ @) Аf] @ @ @Z@w @ @ @ @ M4bU @ @ @ @ .'@ @ @ @i 4Y"@ @ @ @h(u]< @ @ @HS@!ͺX @ @ @(@C  @ @ @ @@ iŪ @ @ @ @@J]~O @ @ @hH.VE @ @ @J- Px @ @ @ @S˲*Y%\^{o3 @ @ @I ZMMN@-J 5-a_W> @ @ @@GqDD:md6 @ @ @ Q߅%Z ⚚@G l&a%l @ @ @m8qbxg4W@ d 0Ø1c2h$@ @ @ QR.PkD'@ @ @ @ 473 @ @ @(X@`` @ @ @ @A @ @ @, P0  @ @ @ @ ͌ @ @ @ @ h( @ @ @ @@~fF @ @ @ @ 4 lz @ @ @ @ @C~3# @ @ @ @ 6= @ @ @ _@! @ @ @ @@  @ @ @/ А @ @ @ @`MO @ @ @hof @ @ @ P@C'@ @ @ @ 473 @ @ @(X@`` @ @ @ @A @ @ @, P0  @ @ @ @ ͌ @ @ @ @ h( @ @ @ @@~fF @ @ @ @ 4 lz @ @ @ @ @C~3# @ @ @ @ 6= @ @ @ _@! @ @ @ @@  @ @ @/ А @ @ @aQ@IDAT @`MO @ @ @hof @ @ @ P@C'@ @ @ @ 473 @ @ @(X@`` @ @ @ @A @ @ @, P0  @ @ @ @ ͌ @ @ @ @ h( @ @ @ @@~fF @ @ @ @ 4 lz @ @ @ @ @C~3# @ @ @ @ 6= @ @ @ _@! @ @ @ @@  @ @ @/ А @ @ @ @`MO @ @ @hof @ @ @ P@C'@ @ @ @ 473 @ @ @(X@`` @ @ @ @A @ @ @, P0  @ @ @ @ ͌ @ @ @ @ h( @ @ @ @@~fF @ @ @ @ 4 lz @ @ @ @ @C~3# @ @ @ @ 6= @ @ @ _@! @ @ @ @@  @ @ @/ А @ @ @ @`MO @ @ @hof @ @ @ P@C'@ @ @ @ 473 @ @ @(X@`` @ @ @ @A @ @ @, P0  @ @ @ @ ͌ @ @ @ @ h( @ @ @ @@~fF @ @ @ @ 4 lz @ @ @ @ @C~3# @ @ @ @ 6= @ @ @ _@! @ @ @ @@  @ @ @/ А @ @ @ @`MO @ @ @hof @ @ @ P@C'@ @ @ @ 473 @ @ @(X@`` @ @ @ @A @ @ @, P0  @ @ @ @ ͌ @ @ @ @ h( @ @ @ @@~fF @ @ @ @ 4 lz @ @ @ @ @C~3# @ @ @ @ 6= @ @ @ _@! @ @ @ @@  @ @ @/ А @ @ @ @`MO @ @ @hof @ @ @ P@C'@ @ @ @ 473 @ @ @(X@`` @ @ @ @A @ @ @, P0  @ @ @ @ ͌ @ @ @ @ h( @ @ @ @@~fF @ @ @ @ 4 lz @ @ @ @ @C~3# @ @ @ @ 6= @ @ @ _@! @ @ @ @@  @ @ @/ А @ @ @ @`MO @ @ @hof @ @ @ P@C'@ @ @ @ 473 @ @ @(X@`` @ @ @ @A @ @ @, P0  @ @ @ @ ͌ @ @ @ @ h( @ @ @ @@~fF @ @ @ @ 4 lz @ @ @ @ @C~3# @ @ @ @ 6= @ @ @ _@! @ @ @ @@  @ @ @/ А @ @ @ @`MO @ @ @h?Ĉ2 L4)\{.}ذaa{A @ @ @S@=5&O9yW8f̘0vpa; @ @ @h/[Nd9sf8ák @ @ @hO,\]vYqû[«w @ @ @ P@CQ% lAKܹsKt. @ @ @h(JdN6s=Ww @ @ @  -Zz:G mY8g}@ @ @ @ @FY@)3&7.,2-g͚=ܰ뇿/a̙-ڽ!@ @ @ @ i~x≰F-oʔ) ]tQ/ @ @ @& PMŹ\묳N[M-(uwy'ya5׬蠃ɓ'_~󀗢v+&@A0*@1W"*E( `@0EAŰ߂|=m0w½3sgͭPOz+t-Zpl/KQ%2V@ @ @ @cJY+ׯ﮾j׫W/w뭷Wy.GVN'o;찃;4iӴiӴ*w @ @ @ @(+r֫Wϝwy{sw3fHۘ~͋LV/^ @ @ @ #@ȉ ܜVXuM6M8ѝ{Bdɒ\7> @ @ @  ev*t򗿸ۻ?ܽ .p͛7@ @ @ @BN"v9}z7w\[oE)Sf`k@ @ @ @(;U 7ić8}CG  ϗ_~Yh @ @ @ 8 | J+Zn?%} @ @ @ ry; @ @ @ @y ! @ @ @ @%!< @ @ @ @y |.b@iӦ㏏ZGy2 @ @ @ |@Аo6mڸ#GVh߬s纣>͞=;;Oڅ Fy2 @ @ @ʍrboY;܄ j\xZ=> @ @ @ PdcRe] +zeJ֭[#q@ @ @ @'3ep;vtsq =QL;ݬY!իWCs,@ @ @ @y%!8Y4ٳg  ƍ:Z+ݕTF9}iJ1DZ @ @ @ eL4=)-rnvr^z}S֡ @ @ @*ʽEi믿E |]ӦM]V '\s͔н{wwM7\g{{:wFׯoI!@ @ @ @ h \ /tSLIyy_֭k\:u:}(f*/Ozo Gv뭷^j!@ @ @ @ ,WmI&0h {W)fw׻:}YwWTN:u[ @ @ @  eujd%f8o<3Gn0n9 ôiO?Jn-?Нq˔S@ @ @ @GAC]ӂhƌw)ߤI'qŠ+n^u]w{ݥ^<@תU+K.Ľ{qz2*s%Kxo?xLz鴏s 5k'T  @ @ @*ʾyk cǎ'!<.\s5 ^䡡]vW^qoT? Qq'+Z.Ӹqc7bĈ*cƌq}B  @ @ @ PY4T,XkFaGnvx+{衇r˹T];wvvX_~qǏ@ @ @ @@@Py״ -zwJзoh̪v횰yn5H(f!~a6Q @ @ @ʔ2p>/":df\ztSO=5a[lV[mPJXf @ @ @*ʺk͂ }oFQ>SiӦN'̲BX}Kd[E @ @ @ @HAC^B4iu׍vzk df?lN9sK@ @ @ @KAC^ۼlM7rL۶m:͜93SMPޢEe @ @ @ @ hYlfѾ%f>|x)sw/}7t{Mu7|sBY˖-Y @ @ @ "gZ['/vK(˴+;yVXnܾvDL0!_WFd @ @ @ @6\yEY](jXdk׮3fL{Ƚ<3\3HvuI(c @ @ @*ʺk* <8a #Ν;;} 뫻O?g}u]xN!.[o=w饗") @ @ @ T(+]4:t;0#$r/qܰ*$vAsj@ @X3i/^V[m5W^=YuU]'][y_e@  @ @ kb}i< @Ok׮n„ \n圉 LTp92gyͩEa @ @(E @ Pn~m7~nݺ^QAD(_qJ @ @ Հ& @;~EڶmwE K,q|wwXAj#hѢVBcLVXɻ+O:C"[US[q}>}T Q; @ @(2 E @ PfΜzꩨ}q_m槟~(|0q !J a -#C!?׿?1)AC*DUET-JüW*G.CGQo ǂ @ @OAC_ @eE?7uԩZj}\sjmnoyCC-Mr45\f 3,*M>:W:zDm!@ @(*q @(_|{ٳgI̚WXV[A~cL8uM6l<(d/6!uJUf˪+Er2m*oWzڏW&4AKzRdH QNݺuS~$ylˇire% @zs~9ɞb+r}6 kyXYSWYrJ]V>flUM?G Tez Y^婶mR k\n˶1oTe=m mǶa>>zϱ|X2;Nymj,ܯGӰ,[,zK:|;vtÇwGu1c2dM6q-[-ZtWu3?~ի]W?}ߕ6op .d:!#)- @@ <M4;X-XO?d*63O&vN]6`um}XǶͶ+^y啈_| ҥ:R7u.*IBj!ԙ0aQG9浬C+*6\|TOUnv5hڞO*(eu6V':aTSZ lm 9YTulK.۶l&o*ze_S둏Y&2[,,uaY|Uez @9:В7n\g^HXf7H`uY'޹LP &w믿~u@ | @ |[owy~P4*̿eK1c P vgDuj;6> 8J( A $66c@ڲ:ںo:6>ϩT^6H?]?ض/A2$ 1DG܄нZMZ:a=+Sj嶍R}g- ZYUۥ\Ay:ҀHhY$).L/cjWU'Uyv~=Z0r6ձo@3o??"/>z m5ֈ :ݮ*{GP h;@ dE`Сu5SNjr E_Fl dkZuU^zȶ%2 |Ui:Z+mouGehP_Xf23]G<`|-Kgpe4l0:fxڮuVWV}e間}MBUBaN%ٶH\ky_[Pu(pL9Z4y[_Uy6նcƌqK,^׺uk_cK}YfvJWO^/7|7n tX];+SyX/6,9+߿ɦu֭?9sx lMrU!ࡁ @ X`Nu G:Gա'ث4KKAU#) $[D}uZz4uឪntm^LxA*: ;SLaguT+B/vz+Kr^~Rg[d[7UuΪ\WŋYqA@gyiG0 뒗ú:WERjy ~i>*=jժ{qXQ$ooĢ/Jl 'po`xCzΐXZwqB6x^8swm5`\N$ E' 5N:$c9ss~{j…!:h?Lqv?CА _r@ dM஻r!ݳ:+m˽⁚SGiRd3 H>jR Z)/qHXr[ײ}e婶 k=mkBG5ZG3u]t\GL_F KGKxw}]^ܵ^A~GEz:w {9ӽ2nִiS%k׮N2 nnРA~V)0ѽ\צM@ zճoF.sMwiggymvGuC q={EO'A{oK8j;{Fȳٛov['Mn4I0w\[{ pٮ}ʓ0 BjIp$Ff ;AH&! @@_=Z>蠃 &sk3b f>n龾x9眬bfAa }Yr⒆f!N߽1̚U[iѠfkvX&lAC"e&4 :n̘1n}`B*P=nƮe˖޽ށY6kL  !@b:D(4PPz(kԨ{לYÇ[QI_}xCzMBDžѣG;y=1Č_~yXm~?AFG}yqylP! @ !A @X@^"ëz3kˤ.!p)KäIP,l^2vanZ:[nn-tjnh?dA@fN/PH޽{Pl$͛:(?meH]vѡD+bCFDdu饗ym9ܸq㜼6q^,_XQQRtA {RD6jw +KNZk(Ӥ𚘠Aݓ&OZhaxiH#A @ $аaè<L-G5Sgf#BѶm[Y C!'#%Dz>^fq!J~涶o?+.x!=< xhH5CCzVXz! RBN7cR_l  | D>R<3ٳd@@ @i ԩk^uZ\3텪c=h^KgTه  xhHCAIkkBK9D衡 /v?|oqGbg<v" h`t[rrO zf@bwj&fO8i_ڇM5)\vo"->8/w8M]y};h + ]QymetnrS ѠM 'B!$ҽ,,(b˖-%\BQfs ֞Tۤ 7a7nvm7[! Q'x"ZG @@ZrCi°㖮~n.T,{WO>ٍ9IL p 9O׆3!tq|ˊ? WXڴM6$:? Ϧs5?)W]uk7x]{n}u~W;}t7|p믿?oݙD.=j(ׯ_?wYg>{|x㍽OtW^y{u@=|Y] d"?i{LFa̙cs=.t_c~.iܢp>ڨșN:ɽn֋묐s΍ iРU(;Bu f|0*OGѽW^N"=30tJﲼ= ;adH!X  @5 T~ ;`m[ԩm375{DNCx~wwӦMugz̆=zhH5C ζSnIuq4իW-'?F@`[86Y[Lqy zmK74$^ I8 -G}R<3g{Գr6#U؂UVYŋ$v[ <.<^Y?Ty},( ŗ3ٳgn}ރ'zh;G_O>^2tP/N®m۶#vO@ ^ q&bw .<B+ʓč7ޘVLzmC!+2Y*A kk)$fƍJ\i,H!BN @ bWE=̖Gy(UgBQ\5bb^P/Qsxh(u  b4ljh wjzd}_zh7g_zh@Аx5+hH-Uȳ.\gE|.]܆n_F̐rQTpխ[tUYG3H̢5/K|衇Ν;[o_Svuw(VkL 4h6ez!רQh'wJ7 E(+CNaybyQ0l\W(<<2 j]Ue aVl O*R@ 9/͇ @@&5,f|m*1լ-yhP\V3 ~(CzUR*w`b +<#B`:s6~!34,iz9rg}a~{<X[_T .T E?COEbgƌ'. #1ZJTI^$$|8p袋iC.>ćjuLe{lT,)a{,ZG7?(@!@ I$f"RrۚB U 7HT6IS'bb!zh@АyA]GZq4,Y$qFeL3KzhЀJἌSmS/-hvf{cyn]u\,3gU"n-,瑀n&5o-UyjazR7uﰾCz`# }u̒ *!CO?= ݣ= cذa#qE|p4@ӧ; 5kVSj޼{'} @t?I/1d) E(i>LHbO;ޮA'BQ& h=Sc:ĕzi7 @ ~eU ~:ΝJawXS+yEd K @ȉЪ:PР@;΂<4,ԭ[7ۯOI )q]FI`9*ıiw=;"鹊YDȿ #욭`hL~ (Ԁf4wqǏw&Lp'hԩNB7nmsYq?|ع'zgSN^>CO4ɵk)ԌԖm6{z'70RO!/>CyAb3^̕˻XziwHL/"6 3zh; R@ 4t@ # W˗^ziTՙ+щ`F rCƺ3g5 Oڧfy b§,x<4Wg)YMu^z!k=4h`,beJ$pfXJBf e++c~:_w9y)P( &oZeyxyOP[eȋ~gN<Ą~]P[x=x㍄~ }0@@ @) խu )bkb \~~Ɨuj֠fk7,õ ŹY8H$ ϵI 4Hgޡ!nÁr4"R4V14 9  n5b1=#ĭ/9eokӣ̔)S"nm'7܋T[aB.6T{׍;F|lCTԆ0]8#jȋAνwyZvEE>$FGR;s=\ð) P4!@ P((+ݟr)n7TM@JA&L35F3i|| uF͑tHgpjjggsA8gêub{{{ K"h7kv  KITA9S#7 {PzVxbbwRR =4(dѽD@!L{\a$bE/ S*̏?6gI 3bNBaWZiH ˑl}ucƌ!;:rA ! sA%!מC @`6lXT. F8rD ^{t;\orj֨Q#w]w9uk„ ~fL8;{lw)Hurh {w@jUPx6,Zinh zhw=^+PQowE}&;09sf&HР6^ C͞{9tӅ.ZȲiSIL@"Qp Y(pQ;ZMΝ]UQc@< hu @H PkDBo)vb%x৞z͝;ן +8Z?KI{?)X۶m]=Aӱ<$Ƀ iҠ0 yavM7-]wun޼yV44V‚b^q$?SBA>#EW!BV CƄ!'1- @@Fr[:43B!8쳽ۋb*fl7ް"!6yd !*,PF1mVsK>5\yкN:aÆE3/^{o7~MY A  dn{v64,v׫W/tS\[֭kٲL{F) !4HW16 F"1ykذa\yɓ< ? n/phԨl|=>)\`Sm(c  ꫂꫯڵ#)zrM6u-"|wG aa}Tx}7:DB'[.mv"g}V%>  8@ :^'1bҌM< MiYkʝx^ܰGeګLŠ{Tq?h駟v>;wfj@O\嗀`i@8Iȉj6X_c5j>4CCrBovQ^R dMӐ-ԏV$=N&/or Ʉw n `3H_Ҿ}{-OnSy8Q:DO>K.%|F6J}]U<͖*J  @9N|W_fUlnݺHt5P\;S|"v 'xO ~Bc2P! Yb]ՙiV 1 {rcKm$l<3Rq4P 4Vs 7jWrЊ1wH]0zgݥ^Z倮Įcƌq\rA)d.V~}.yz'5kop3g]&Uga6sӧOwvg\y7`Mj̮JwE٢y督|QG ?wi1 @! 4;CB=<=C\˖-w~ׄqZJmb1"A@3լڌۿ/U(2lvljѣ)l?޵n)VsV[;=d7͓&dgAC80n0^v Kk!Y87|dK;CtbAFW\q;wg+ɃvVc6r+z~<YYk„ ^̡0Er1߿ `1۷L#YYcIY壏>rj'ċx]oZ @ BA::u;SCS"lᆾ(.MLg?F3F4i]ʥȑ#ɓ]82S^.Srqr5[>cǎu:6]OX%`3S؃: 2BBNdΪkFp뇝q4!'֭[҅"^R* tMSAаE=4K?l裏3%.ҥU46{lm!^^{((p $ ;`@$Ƀ@M $`H-O;[ozd}sΉ~ KR0Pm]vI Qy& ˷i5v" P4Tu @Ȋ@(hʉ'Ah /7o;l㒆dz:hTRǗfnO;c ?Yy6P:\4%ע|}ᇮ_~~Ly^DR0yP5Foi^{gSGUf#8"rU_W);PЀ+ȅ~U&PРYq2,Tsl+EN= 8=4ڥU*9-XuY%6,bA'ZQu]N #H\$Ne">swNbdy3xSU-2]_|Z6lЇ:tBh} gvUWw[.Vk}+yyg>}?ڧ Zh>s{DT+̉{]7Wux]ƍMZ#Y(|N*fTACp@@P&A @ Wj^&Ca'4{䡇O>䄎ޫS /X94lL|3U Q7gsBבpAQ%l0`{׽ -C,ͪ;K,DMeO@aG$2 !<ȞTjŽ<CCCAC῿xhX/`Cmf8 x / N?Ǣ 駟aqe}/'a% iakfDj"z mÇw . }gA{Y}!믿}RճM7TcѷB{/vbavm 묉 {D$Ps5m/o{!q{r9)W%hwlѳ= &g@ ;GyĭJx;>p4y.;)Aqΐ38IظϟLlSS~QѣG{ ǪSٸV5\Er[;Ϸ:‹-ҋ;&MDXRP M=2_C̼[Aߙq4 eBA55c9nIQ7kԨecNfzJ5`m㘆;0W*^q-t;wC L>?[=znX^v@t ˻%`Zk@;yVwzAkS o U;z?"/<@$"W8SO=UQ" yِWć~صlSϭ'tkt KX/MJ0W\z]cM4NS'ґGJ={z5;"p ϡVg!Xvgiv[dzVx]nEvSNt Lu}O̺wnيK5( {Xȏ?W8zi%x*Oՙ&y%Ajx]J!<7H РAzжm[5}Q/ҷb_o)Hd3rțٳ|L fKIrkG{zWrݕW^B.XSTcF#TZ<4皆PVQ,hݔ3~K e6&(h{;L' ŧr=,Ln~64xܮ];[U$PX uAv@CCn܄ \޽{>Ĝ<9HP0gX &πp!N:ErTg}Bf^2 H}WcڨkAa'$0!ECT-$'vA=#sӧ 59@T)DBP골$+aC4$`  @eE@.9#B>L9d3lKhB.2m4{|'|⫪cJ< S.6p&U3K3Սzu黠TrڣGcš5jc(h;Cv(4dǩBACUqkzr>4mp5 C%RU &שe0A܆lM>|?cZ4I@bl0d 0ȃ f~ӦMSڗUǬI^gyGby8C xM%D_{ᆄoVV w^M:U^%h޼+O6^:/6z$˅%-$Da]vq c(A/˺ٚZ("YaIN?< P9QfA T6T&w8Ԥr@yWMIpѣ}'fL,0\j@rACzV64m=i~#:s4ڰL3aȉJ4R4(<4ʄjjL4H/w~ܹ˼k؏<) aÆ~@-c4k{ړoݵn:4?s@vۄ SB$&줚 F_~ӗ}@-}a&b;=}}ܐw6C+ ̙=֪U+MBN!Wߑ&MF5% T2eJB; eLxhJ @*1|pɡI@%8J4K>}jv\`*B((6k'͠Pǃf$رw38"c 5".l-آ>?xߡjqz!?,0lt衡<B2 $S'z􉻠!MzhǠSm{Fx/ > YlGo,Uz^ duL>aҤI3yd]MۚUsd ft>@. '')u5o߾>l뭷J$bGW-TBYf%G]{g|~CrXȖn(Eme !&ɦc=ևTOvyg}1uȨwZ+нv&>KHE$رc瑸?RT2 |ui @@P,PဉxX: 3@@3[3M|AwꩧF3aԱաCӵc]XBYK\UWGf9KgV{5ֱV!k jr/hz{grr"΂J.!n!'p GS4b'.^{{w ~yLTOJsƍ!C89 !h~ɺt= e]QC#Qi[ԵkW~Bf`a"tyT( ԩ&!H6ʇP;fΜ^Yѳ!΄0=3Ny lK @ʜfĨh7v\rX١Y2ꈬA@H*/ c8TGⵆqkM޴M4f0Kn+[  U@J* lj,֐a)J4@p緦0… rѢEߎNqԯ_/joNh`Zn5Z򰠁Dy[Ӏ>ʫL3؎%Fh7Xy)7xctz ѷkGd (B>ڷoXᏥC~5^^PCH{"fJCu47+ABp0Q j@<|vs(f.+$VuוsCLQ;q{SO>%C8s3O-q/Dd!"IĄAOAC_cZ@ P4@pf)T4hpGDuȕfiYA"948vV؅АpV5Uֿh{hKh3<4LCACx/)h`zUVN).^}Y?SY `V[m1[F4X4(-sÆ BitRFJ< y{׽K~# Q;O*1qĨ(UGd!Gug'07Kҡf'{`^l;p'j[ow7)w[;CРHȯK/hJ x+)CvڹPb uO?*$8n_cJ(%A+ r1yzL_arru!#g @ P4E/q6cƌ(Q!ɮJ/p첋wie*HRnUJtt.rZ ٱ gmMl hXJJpfX™6㵜3ZJmAh;R9# Mh5Φ]wh08h^K+A<Ë%F]k6)llW:;00_(cHaM0_{˔)SxN>/K Qhz?~/! NCh L-¬Plw^`aN%>H+vuWS/_& iNp!SG&]_C6#4 W_CrT^%O?ƌ\2 Pa4T9 @K@zlM^Չ0k,Z3/=6PꠑR3glR;r=Pvk{ }ޡBNdG;춤V$ZdIT}5ֈq˄&v<47SԊ^RjtMSA͢6,f̹N8~UVn5׌=nA]vt?M.{֥zƅ!=$8J+4ow#{FDJ * Ơw(Օ!Ww<>事+S(yHMy@5vu+9̕t!S}"PUg:~䚼M@ nH>W{fmLR2=GiljN@Co3krwy'ڼTbv!:&p hY!$,w衇S<h/̝;BBCx\'ɛޟY&[SXT߹P s8S@ $Ν;;y(i@H3Qpbť 6@N &NSuLj0e˖N.NۼΜ9~vС[kا,4,AӧO_-|^pGzw ӻwo'э\쪣_ /PaӠXm144!;t!Ugv{V:!&(=!n lh93&hwՠyUm}FmD8"_p5ZJv7Fgh% vaN=xGmQ&ɓ'{'EEZ:q}9{^xoOiM4abL' <7܋[8J-r(#xww375jI{kYNU Gwd׊b_s`( c˞!@ 9d5y.7ѶRP&ƍRS.d5kCJi0o\5k4Lq;o-rA>,JROACkt?oT'R.ӌ!ylt^)!B:S^iPS3HÁ&ͺ7o^rՌagu$f(A8{( ]l"@IDAT!qUf ^y啄Y;S r ^;F-2)?؅=+TC%ݻwӨc*<_ |嗄4M&Qym` /folh<,]B{AP<<#=uzMhݺ W7/zu;ޛC{J=W^:*7|Ə  PY@  }UW]C-hY3,@2G-3fmLtujmQA;9#=ߝcr2 m0ـHH"$9YD l&H&M4 r0}}ڮw4V7;zkRwշ0֜~>w0k  H R Rcj /@9{a9!E reTq"5ށ!Z1j`0?{7 Iy8al Э }Dt)e,#zsEhfNVBQ[։<82sz]c eG^a]_\9u~y4r4@C chZ' Щ%K|b #I.IpV!c=64m묳No }f@,qOI;ntH 5v{~3nN;5蛷#ws>:3Na=3{nVe 6XǑ~r~sj%*M`Nib0 TOh5LӀi4`0 @8PSGuT}e ( 87dNq J'~ԨQt$9XAQhXZj)ώQ/g-wF`e2e;f2dRc[Ihn]w4C|y"X#Hs5W/L0qw/f)2䠀0"7 *8&}%L.u]'Z2̍dʨ=~5b84 䫧ۨ^{Oj~ř<{.qi:yEV_ց{jWt0 aU/䣏>Qzn&i;nBp K <_E7ә'Yg1}t'00!#`P=n8&M kS{@ܰlX;ّN =xNj@q3 +ӀiZ1$j4п ZY~s=׿ʰLӀi B[)q㠌WErbEi") 8051706k<΋Ú @)L0QM׳D}{slbj{H `M ~:g[z]s C=4aYb%eX"߄vͳz崻T¸$wX| i5 zed'O`7 'b8`H3\li8yoF3K 4<Ih s}4E&L@%4@t*iN[EVb׏stoi>0tb !ZM"kz衰Qd_0VMf*o: ,cto'#O,D&<ņG ~%LZ{_^1/ vzs=,ԏ6щ62s3a$dmqz R]Nehyuj{Z )=/7:c㞺4`FFep\nC !8:&N8bJ{ /W8;FsԩSr \el>i PW А&@4`\i4`0 ~ E0Q`}':ĤVhlxj6QCDz!Pss9gP,Caءj8ڡNX f?9=-FTUp,3I<BĀ> [űe{{ '[8Cu;] (wxY[Gg9 ?Y]yݗX䄃g,8y!nzs9ԪlxH;Lpo+㰖WA;8n/r[+`4]hb} c# [+» ,?hu_"ӇӚ1ae"_e}'=&ec0>t㤓N*1Y;bH; 3(J YQcAA x[noXqzx?}0ضt8(e Iz"0N^rkvv@fEhE]#K'x!NHN8ᄠ "P-a]; ksexI `"$>|x( +m0SQH;(Ei1lX|OL?Jmb@Å^Z9^Qp.ݱ+6b~O'5(( i TѼIרL0 @Vͷ~/lqc쓰7pn)JTM_T-*&>b)'RwͭŦӀi4`0 L=ԋqf@i0|0p 6˶PFzovޠ$2HQF[1ԞuBYgҠ%Xw2O7Maj0wԥ-"3P]k!2;(Ju!r]yiC=CYeБIg4P&zAQ;)q4FD@ODnVT.3fԤP, 80'ݖ[nW|9<{w(&e+mP!;=~!-'B"=ɧ~9νmҼ|~)p>Ȧ`mog 9}I |'KiLi ebV_Ӏi4`0 LRjc9GU^{mOuN\xjfN==P]fQ@ݨ0dQFfS*bڗWr^{E-24| o^;,ddJ ɤꫯe{qGb0NB_xlp<~MF} g4 >4J"- _*@9lL祏J Ӏi:VLӀi4`0 jh(yUqt]<|>pD㠂q '7N2}L+;^X?G{&3)HWҪ.>Z') c^cR@:7 XTߍА ϹJY ԟ;guo1c|DƈVgz3n{rUVY3v躬94lя~V_xaYը<5);u}zNY^`^}4`( P g6 LӀi4`(0Jǃ|5F #;ۂ0QZf0)YAV1dt[ωT1Dؑ]g9/3)ϫ\%jp-+={R0mvvs i8\sy5YEK/yGJV4@f6gmɓ} őGI5} sZVйYɳcb *<1c[6pWfUF>:thHhBQ*HҪgq-\8>J+  =dW>a~bM cdžT'.=%t;c=V4`( P h7 LӀi4`(x}%1NcЈYBR(# 0B-đ;2(; P_wT Р^5@C4k2?ӑy1~/S#{QVWp!]D6 /5 D 7kǏ^i>o 7NñN;5E3.w_ryymֳ-it\Ȭz;td; H "}n+P 7s߶0T9眡24h#F1SZ<[.s؄ ￿Z.%tO<wGʌ-b&wy ϸ(VhaXC ŇI0L׀ Ӏi4`0 LT&L#` -!0΢-Ġ 嬆Qzjp 8*mscp74i^\e;lPe 2mf5gnw8∆q Q0]tE`úKBFeẘ˼*i'T8cO?)20!٪|{ :[nd2w6m~_d!0M 8\<~cy h\ B021 ʯ4Z LӀi4`0   P7j_*^ՈXQNr5렂?eMj5!&A+kw=@l2@C# h23@C}Ei)'leu+55@׋ށv3r _ U>k\o> Gu;C^k|zЉx&J^Cme ;K:rwp.B%饗V54|]@ !u10zny `~@j?=rH{ylzM'{:txt mڴi]<sGC|2fx{,ݖMj %hVeӀi4`0 Lkcq|EPy3LjcqD\`\1c8b]3Wyhc bi 6X5,fmb`-x׿5lA/TРC˹+Ǝ6U![*1[G:rT'.eJ] 3f̘JkqF|7bD#l=NԹg'}^tP1@jz گ Jˋ x$42x}!mW_Hْ ^AVhܟAp/yY{x)xFl T*쳏[mo|pTH ŮVp 5ʰ 2*a5zCwx&&<p"hӻz8 )yb" JQA0^7Ds0͐(/AK. jkd@OW4`m( f'd c7xC9"* 0D\tEa[B y衇E#hMbk ž>V;Ӏi4`0 Li0Ad1b``{ホ*JH _0ب>n,bDY߫znUHB2@Cc]U߷׋cc؉݋uN؜^yP띔*P zOGW_}&N;0C֒K.ĉKj.Gt,A鷉=~oFcn׿OAwy !D[ 8y|:wl; |c@AUvaPuYW_zpe]6,lV;VЀ [Ww]wU~?is8 UqsX b8 ; L:=}Y0ePGR Ų 09~~N=Ԇ̔yT i0@C94`0 LӀi7n7xS=#z+iG4'_tPjj ȕEehwyCCjg*r4cRE@fYYzmyjnrs舼VIz}4QJw馛:QU&L;͋}N!4G-ilRNtza |jl0 LӀi5_s=SТ :ˠ% T@0AHNn w%5O6:"A#Un8Q(q &@mljQV_K-|r: \V@Fu\f /d{.VbW8ϙ҂%8hSN^rnWj+wwb;>&qþx7x뭷g'S^7pC˼_W\ѧ(${ڏi4 +jLӀi4`0 䡁>G `?/(w}w\'܌dKʓou0}4@C=K\sg Qk0 Ar Wh0 LӀi5C9G] /P/BϨiub540p'￯c@7.&@-5毂144vRgY }k$>yr,etD" 3r;cv_|ʪw tʵʊcq2Ǐw"jnt+`-c=Y!G'-:3}t^k+O@J#^& _>`#83˔O‰D;cj1~_`#z?nHrLJt@5`b_J׎gyM4ɝ|# Ԝi4`0 L4C(~!Nf ʞ&Pà`@r-3}sK.ݞǀ,C@H$+"M~P4)ԡAmkވȍ#Ɖ3_sLe3Fb@CcvN8Ā04ve.Z>yuR_#CҢ`@ÇZ2,-xuq8۠;cb/_[|ذa5egpfLDž%8 cǚZ:TbŰ4pwBb@CUꫯ*!Z_ ,2gur{2e>ݍ|KrG?SҠױ'qӀi<TjZD @{4m47}t\ȈL;(GnvyӀi4`0  {*׉]fh))ȷ \j̢$ӟ#ʼnc;Q=D9Վ.O?  ^J 8q=\|61!9*i fhPRsG^hw`Bŧ}ؖ4t1!v0 kr vSE@Ih8*ԯ5@*r5Կӿ S,dqueS>0 {C3BO?tM.N]k\q܉⩯CcQ[Ζ@pXV8Т~AZ̿ /B -4(q7Z}SL_& ;CPoE-Nt;Tdǂc ۸q\SDL5~F<8p쳏/1/&:VX=~,#"[ޱ#o l9s)^@ӞN )x7v9wqG` T6ؙb:th˽PߠFao`0 Wh()dAiLcVǒ8H'Ѫ` ᣄÁR܉m,4`0 LjH+Oq.Vkq\4WmP6#{Ũor,Q0@PGV ڎ Y˺.͎n[~ ^y1̡k\1NNi#vxWz^Z&ས; NjmOi>Ufh>2ؾ_98?ڃ ̤u lx" oG4mљpmGHulVE>` &x;(d>?g^1>󩊇 R ;SxfKBp"K h@_SQDY@I;a41Rt i H'-yg;uɞ@ 6$nGp@2wl < 4j\g 0|C=zA1b61 LӀix 3Hrqu 4 `XI+,P@i.첞b61@`5}n:G]l@ Pڡ, eE1~hFu@]ͥhVl ĎТ;6ISg}]%0 9;6h]lh ft%F) {>-n)˙׭QݭI.;|IOw<Э>M?i׏iyWYeϖ3μ zmy)/.`ҤG[7 h4[9;|9%mv2 *Mkmtv55M h`NdP"?v'4MLbj ż.#< fSC;Pti]fA'@.+ʖ>iӦ$ԩS-¦F34`0 L "(IZ3 xne]&l @AnvXj~i@: f?#?}>L"cF?\y , PgQ1,D4∵f}u|+~=0-ɧvqĐ{ ZR-iuv4cg|Xic-ٲix0@CI!k-m c~V >cciLtVHA1|^z)q{@&Ӏi4`0 ^8nj YYz=av(c&[}ti=}hԀ1*m>jFh9cpB]׮ cP#0CKN5"6`xh &@w@) )5q51m馞JC^(ܻy;ڎjx-^ȡ|!@B 4GsB hz/'N 8{.0u>(!UIc R@a@PJ' (2tPճ`O}X0P.)N*` @.0@C.j~!SLȸt\'bC%wynwH_w~x@ ݕjTeLӀi4 AB:rƀshQo@1qzuňsI'ya}q4vPOv4sDO5[.@1<_Rl/̔bÈ#/89=vɪ3&A 0a,C=;a'xrePO*?;01};h1`Ayvc֣9 %Ӑ!CV4lIGƍ@lDbw D E|- ý>~x0`11 4VJߣ~tc!¨Y0<C^ᰎjӀi4`Kϸ4iҤBd kOET4A8w^D0tʺK.OBD} m#Z.R(Z{H3g~W\/1 o6)ȁ>(I4?w#ժ Ό 9*4|hB;b:BVvJ ?;ͰAhLSNk'4iMI8ʹ7N1@q:8]RK-SPnnFTF6s1SN9ryIE3;0͑#G6s3 %%#i%"a[pzR##q#`BR?us3Z^@’҂::+Rk3n8#>E`  / ~z SLҀ LLj@:Ih#4=a_=N: iQ~jʓMvX61 L@>}z"h0+%3ft/OK&/rB%yFxSA"N&dHHP6+mY"轘5@J"R_*)ъ"hAtgUv@:Hʵj5 A$XlAhD藨3WU-by*pnqvL)Z">CP`3'pn"NGɃ'y'B?/A'OHDv29g/,ƉD(U\`F"FdN$*?&D?r9Ҽ kHX/ ĞZ"D 9wY&.h阸7&KHF"$@({-Cр[azJMX'@SxG2a߾**J#rt2 o+5 (ǁ}Q؟u]>*S9f̘O]o9qK8D7>fg.{蒾0SZTN6~䆇" .BuV^ye @IDAT:62CJ@$;;Ihyw=S @;>#+ҟOS Ӓ8q sN]EgmUڎ_4v#yʦɟx9n{ŻYg5ų{>*lM=!ݏi4P< xפ58TitD#:.&Ӏi4`0 tOZ|'tLTaJB݊FYSNu7|ODYFO J"knWAl|cmx#Lz8BР٦8hw'0@C'uqiK9^z$!-3ݔ=ç©矻M6=c>^=2N>}NQ/R~lh<&7չn)0qtkL(&ay InuuBQ#xk1z`+4>#ewl*;P3N p8CL@(ah WAXgKUgӦ9>߫ꁄ뭷wB>\sKP;I+vi'(7o:N DwBp^dtkYIvn<[CX' D*4r_\/zԅ`QGWs@~L9 4HZL\V_}uꪫt\6> !⋎,c饗 뛔CÄCI5s-qʃ>X]`Z`_f67 4tOץ>SLKq,of(}bǰ ۲i4`0 ʬ8E$ߪ7 Иm&mt_SQن_2(7hH_\?+8T@$ tu)8JN?twp˳6eAcљeoo/zØ_(ڿh&FfU= pEM5uQbU evQ9lRYj$==}HN[qҗ<묳|')-D( &koVp.8qbh6HŔ?cKRtC]vYwq."I% }X%y1ĎaR u;_qډzA4cLjRNT99ɿ@SJFۺs9r-萺۠:6l4`0 ʬP>0Uh$W^`$o~SEn'ǻj4?Рj%W-uƎ`Ƃ j_‰qCkI>v`U#uք1@0 iPo]vu޼>69_jsamx@嫂oNyGWۼ4] @QmnʜrB^FLG+@&@}n A-p1=yC|H6 :]ζ^w@Wv;7|ӯO/_Ʉ BpZb@\z%8aF ԅ^;x'2fbl8m4q+ YG_W;oO~6wM_|qlG_b6FNEеJډ?5* 4<ӾoNغ S%΄1/I&5*ڶL]րgFLC.6>/|& h`'ttZ5`]wu~=اz&n44vUahy, { Iq`/]&lCN%׿8G9>(0-([>8x·I裏U3L1TEYDH>MXم;iAѿKwA]PgONAޫr??7Ȩ@Ϥ j 1<8ḵSvm3Qth/a'p#,a:(w:($k[g0 @201 4y99#dccc? oŨ=5e5`tŲi4`0 KbM9H𾎿,`:sDv1b~/㋲11EZNÁyWG ;E"V=vO{w'B~WEyBz̤tWW9N UhR! Gc3F1^7sHOBx' ;VZtEC]٩Kd"IHiP8,Wc>%D0݉2S_k zpW")L a3I<&]03$/`D:_B'~~%L"]]9 Z #P"`D@j5r-6@?pɕW^ U"i4`0 ʤ^{ͳ1@WD3Ƒ≼H8yhĎN8~qQ`(?: i'h[ل~hy_u &N>daSvfgWdD>bfhXs~]w9"bY D9W>=ލYuom1ux܆,s-%Ӌȶu14t |*W](qI`Hag}; ,fsdgrHFD`fBmgn{%q,Vq;D=F~i*o75h _췤2d#/`#m1,-=B  o{W|Cr)ӻP ~W<,CO<-Uӟ35ptJ89Rߒ$ǖK. 3G1'Q܁0=Nz+7`y01 zjX ʢ(O騤E"M=DrPΘ1Í9ҽKXvanNw H |\Ëi4`0 FtpBo Rj2 )IF2V@(ZT6Oks {7nmQ]yy `CΊrT&4ϵΥ8csOGnzBgt~p=vXΐu fmg8:tM5`lZӀi4M D#$ϏN4g !re;\pQ"gA]jDUF[o1p~E$*37oHOQܛenwVɑɳGv`]%8X !D<}~h?|{p0Xc-h0OJDYb;~qX6.B2􋕡[AI*,E8,-nBtnlOʐ~裏~.`*UQzy }Ɏ;8ǽUO$%n?CƚvŪq%z'NDa+@2ݴSVu]C}І*8=B⼮Bqb$aV^Ѝ^ ys$&LH c9<LNx^.?Rv2Bכ|wےzpFB^X׭.ޕhdwO:Dꫯj+)2k@XŁ~=(AQB/yWQU"Ch zow8/n8aߵzTB]+>o FDk%&Unrö `,Ćr<%Br!&l,8õg =Gp˜N@GV_JBj8ww2lذPF>hHN=D؀lKփpm/ fw@B9 01@_"P7ܿ%D4d)T!ޏ}*27Ru^8&P&Ai_O'@E\m;Sոd^8i4Pj `t讄r  %:ͷA"#lTR-H*sބ/ƀۉ0Ktw_H(Neb&#5)N;6I4R"DGozYXFaxH$B3SW޵3=Y}.C؄:2F~yw6D軓}yc`^o03Լff",uGRQ$^ziLJr5 cz87`!y=@* Ca^</z@aI!X[ica %9יc2 kX ybYyڠ&7,MӀhNOi4`hW2xԈjӜqPkBѹ~Ms=n8'P< XaNz,VO}L>Pڲ xL2$>0_}R{=\)O_(4:g۸/ )gt6[iSBHBqBbMN|w8t!ҵrlO>٧Et&<3L=|>lM鋖\rI_oyR.q#ǂC" +p[YSRPaX,|ꫯ^<V `-! C*Pwо=أr]N@.MuT-qCgf+"`wS̘s2קgp Ig5@>8)@ F[o=7J椴6 %%ÜkɖMMiQ3'LzK9[h K1 CB?Y$: 0p qe>$!5d>o0 I8H$ّ3:+<1nnYgm[5 y_uUmC-oDG=H#OP` 8SYDۺnaP@^x@W9q$xINLBmȑ!9" L5p{#5w>Y9U=ܳ{スvG_5=CtD2Dz}|_kz !GA]+<ȭχ&c3>2ƣ&KE{oN]wݍ7ﴁ~`04x#| '8a#@^I1)-e&0_3aڥ/: V?g\~%lVYT `c믿W:Ə$!]o;xf58gMeh+}MCփ@*# ȰbSkp#Fp oq6[ ;z.YcbV>i=ʨT'&KNʱaYӀi x'~Cw)tm}z", z3EmR6nMր1/N$2//f[cEȕ 9EmRB$lX/\zmYy?g} 2ۥ[?묳nI !i&N=Yt"$8O H|λ{)]>?eM'?]&N]M 8[;ye7O3'O{CzHaO";5:r?5r;A'-NFz &܈fBXo cdtر]9Dn[PC"Wo`lPBʵ# z0o>;蠃*0~b ~x8ɗB} SS;~GG$pfT\+-6|pG4-B^lhX߸K]1!рѦٔAwyLfy?.fλy3~[(t9,ݕDM3Ҽ'L=P_|v[74"Pm Qb2|o`2'D8e U:-x0HpʔF5ӑGe#YS’#΃p +Š>\裏|˱sBH?PW_}1cݴiСC[^iiO`407B3L6}vNg1yLҺ0O/w%{/"hHjқi4  JSL$^SNu]z:wYMic v΂1礓N>@娒6V =3jC ^C2i'H7>O V#@#1ܛ*Pw Kds1NC2.:`& > дR(e:.% knyXh|:UVY- l2  4pѷ+ϜJ'zNZk-:Ff·SF YfҼY SRl!KK*s9.j <.Tz6=B? 7K?iИH7GpiHV%9SԸ6U -{UڋT߭ 8R3g,$τp]pJ1>w?/:}Ș}zz]Zii@X<8Jq Ǎ5e{L\-LףoGҀ9Q9uDD`(Wf"k}"5z٨ng0 ʨpџBk! [;Gyă1BQzrHq}[n956,&!<\[{=DyB.sD?5+r4~w_ryl;Fe4%6@IMo*ay |^U 4oUWu@^￿׋_qw/ Mp:4Utd!4t#ge4p+kM*C@3-Bg+ {cY>Lsprn |W=_7jviKZYQO|%}{Ul_|zê>/YZ?[VA4`$4@ 0Uqغ@1 v$R@9)m*-\0g˴@s0@Cszrv]{%YMe־4`0 L@ 0m̤vN40@#BzF3ZW|m+a1+VLi?ׂH:j !O{QfCr;DF㨤c͒﹩dt __ڼ Ka!Cx1l PVMxpkZ=N9DK yzCy8p,VE:Q߫[aqږgyƑNt0l`;K9y}gvL_DҰYHoR׀sgi,%?FC?`Po  ~*cowG+HzEj$D=о Ӏi4`0 t[W{u+s|NO| quq1Px≅ O\08aAVBTb~y C&NN xA胈kn6oי{xˆ Gs޲nV)St[@|;3mk%co;ޅ<ި2X0s '4o;oFaLoaXe]R@C=dG[N| ᝖7y^& 61 'O3.>sYNT嚊 g}sUW9&Jn '@Ŝ]oaJ^ %tR>>ظQ``9?L@KQO{ן{),L11 4tOו:Z}@ f F}ב;H̐.CӦMHvo0 LNj` Fn#Q@`/bgl㪦a9F" ؑڨq^FFe4 `C v*XgK"rN4ᐈjXpp6 =,\&>Ζ@fwq,cp|0->{}X!NAo:ckqq3gh R}㣩svj) h o0 4/[4@$AI6O?tI @v )105eMӀi O h+e2vbLc;&"H>\3'n#Z 9~ qTuu]aR!r^'#Cc /}ؙ1SV"NL_{pp^,-^"TTExvYMeO_J7zLBXc ?+1Ys:l)ڡ +; cYj_Cqƕ9ؽHsa|t([gӾxW|aF<@.Hs8|pmJkD{>Nh)sO֜p Pe0`NFVi-:֌yW]uU_I`iJ[/'Q[ :ԧ$a{D]9LH7C)p ل &511 p `)4` =W,[T#Z^Y 6l3I@D^x1rqFx-LӀi Q7 S_1jL橌H8pHj1# H?O=Q7*:ub9fh$g ,n) 0PČTʹ'G}4Ny7@$6f*IT#s&RL 4pn1iMoF_ޭ1))87mSNs[n+c*) ݻ߀Clw_ ?\ef}I'y01i)YYa>*2HhX~T`j Y ,fe<!,v띺;$6iO8r*X v]_<nƏA}I#G*Ͳtb9PFbk062K*i8MnM7 n֐=_ \Z.b[)s%&o(gbhJ/8x"7L8L'$biKB)isK)i8F}8eӀi4ojF<;%NDr5'֔;4u\;ItB")HU!FD5uv@4 F*5pmF^X T!qm@j[Sa(T8_ڗ\~?mYw8/EnW&D\uVW[6O'j3$^8?6e4Cnw$O>dr7&qa~b0s”~o%7tSƁ:oO$X!GZ;pߟwy*$j8IARC" /2q$"0GZ8֟~BGe٤4@Ti) HgxY.ɟp'x"ciL\0:4:/548k#kYɫZWoSN M(O<JD 9a&Oʥ׮ Efx#<ҵjIp$qAr8xNpn)=Iֵ6vD`Xݹ$A{7 kj}Mg;u$6|DIچF47!#l }W5@CI7kW_ %'NA_#w n l%J' ŭ*_}>*h ڂi4`0 O(͠A;Fw|QƎs D;s:I$'x_lO/|!61_tZCQW^yʼn֑RN"I ,>xqSLq诈IsfTgSN9OOs1N͔)_~)*_m mհ\ ͒h' ,e_ U*\:IE~[E09I}4:Vc{k'N6k![_:ai}rrD3`dhXhDOrI'5>0:(I縗3q~&]Nm~mإiBq3,m[ 'gu'ItYEQRizIЂr9I9'e1;üoTѕ6KE]w!+2|˵st( 5mM@7vj~"j99pǃ)?b*14T[M!|k |ۦs%D"DWMV]uF"q:黐Ӓyq}kvRch+^'/baG\.{G8F 8f1 LҀ jܗ_~|-4Ť (~.h{VeA ,q>8g##~*`AaѺ:8=B__|yDq?䬳Ϊ=P'!{l!q.$0̬Xh8l˽35\.Sƹ +f*1C|T /YKVuJ%~?꺢G-k?m~Mɜ tD|8!|[;IGz W_氘#ĥm\܋ rRBd=B5iN16SPNDߎ}Y'ix:r?|7qDwAÇ3q;VUYf݀>Lwq?NfBԲ0ۛ`4ozc"y0u`+x;V75ҩ:>ǎkvlc0i}@g!^:^ $(|aE}*kRNTضf ;OHiH@tsF4`0 G l|)c+T1A~':a(24lP: a  Ft 0*HƏ0u]s P C/ Z-}hO'M~zvqtIf;t:! )WW%K 2X5)SUkoO @F$~}WL'4a9)3ǀB3.3g?oheK9!,A&Lp͌6@P>q]%WcR_ʻĹ>;' O5pG{8J;AO!JVlշŻ}k=zU~o)J {W_}pZ g3)qu,#!)xWyC=Ow{K \.]r%ziB+om_`. 3|Y,!M94RL6MǷ ~e #4jwPi62Rf ;_sۈ|Ά)*f!`DahD9Fw'"UI|AGѣ 03 JРYyCmEj C z衡MR9wz"bTnj8 ֠BGuDQ^Dx8>uNRČ}{(BnB DnބSDObj8_TJ {~mTG|ob[R 8ŭD g^+Qgu)`3NYJlA5tiZ18hՖZj)Ǐ["NibDxy agD| p2qΑ#G꿥z{KG;!#TR886|s'*T9v3׮ᨄaQ>όP)w`ZCj\[IQȠ"S.,V2;`R'FN=6m5@&8.v}fvchA"5UXefG`==9Q@IDATǎ#`-w'х 0hǫSBK0 CsJh ]C>2Jn8YߏACQȋU|I [e#h-9Q jEi鸳l8C:A!:᫬Jv8G1-RC\0"3Ju@GǥD{2"Z,BC J_N/A!LtIf~)Yc2 AI)y%Fr.KrvI!oDsi&xH"D{/P *9ݙgّQU)0 qW4Z%l7 2⪦{:eC}v7zm Rp_CpbB^s5[: 6 L;8 ճ:s믿D| 3zs^SjA}OYo>?}j) v7J.oAbi:ܸqAqUՐ|@*iD 3C>Fh>L?&|Wqh+6R0󤈶6:DtujUeH4.OD[9y*+'N A%Mq6Ui=qysi4( 6ÐV#/lQ-%4ABhSkePQ҂[O=PQC\2\"R#H7z]_=ޞAb:׷suP#B~̘1W: 7MvmQH4/~j#w狶!mueԠix/曎^ G"8jK9S8ʘV[מ ߙ" j+ζ<Ɖ̷4Y =ZAq#o@-+2BBҤr4kQ Qm@?,%-@^ 5U"e]BGfJ<-ot,h"@%5Hw;]g!Fh ]VshGYBģ>f0xB1 C4(4A?E#$_*Tuvm`'ʀBAT pM7 Uej5'fqF2CAhwr2XMT eNy9bMe0Bv0s.Uh3iQK/ ԇe](U]JGZyTS"`@?*vjDqN8jpγu_gz*~)ݺ#b|!1A*Y387rV),)48Q #E֯)84QjMH P#rX1%#C`PR*.J(õ0ka%3p=Q'*zj(bHUȏ6;"?H}R,dLzpo8yr?V*!K,ZQH Q:-C)exgfm W"t7`Ub-\JxW\Qk[f ]K`!`/rJ& tR-巪!iPhPkCq:vXb'>Hl/T/!&|rɔ;JhDGw8N;5,%ʠX(Lq)W R-" 62I:\DIp qVSO=5Mey1?~8p= _X=h%94_68WI}_jytT3; /0T`>hϲ}!r_8H5^j&˯Ht6EgmwO>芃Np  &L L)bi ߓxΤiSOqtmW%1^K /UrdV r8ٟ)nh 0!^/Ô`N{?A; j`}7TZV55B%[3I=XL/q5S9蠃LH!%% ~^|WH`~~䇦~!·SN9!`!ShPT;%6.sfO#@i[o5E-hS ([՗ 3/2AF=M34a`/IhY%mQ TTKqR 'i<]Ϧn:Gj6hzzy:R)T uC=g(xdkud7H&N }O?tRuppFm;Ƭ;H9FVÓа[2jR#t7K?ELC8SJN"3dzBԗ]vY l^;b<8[lZ a/UVk¿⋃җר}mʽJ1vgVE1!b:RB7ڱzfeC-@Ȗ|7!Ҧ#H?`pG;aH1q@mf4&l宫<^>MzCy{gy|+P1of@}ǷB"PQ|^XC u@ŽOEWvuW'Zl!`@@i 9ֈCVՑDV"PhB!&M OX(Iq#RAlB"%e6tG~FuȖ"[roHQlww2C%y&MG,_~,›wy+ߊ9Bxns DʢB{bІ\ MDbZg&"]nJ_*Mt0(zՌ)$o5{n'|2\v M")4CڦƺE ޫP9}±-Dãkwq!ųqc</v/^m"ӥݞeo.;EݲȆJZ-u QZ7qYcVU#F2*dvvyEҹs̷9 C1r1> rѐYdEB>g$պёfpD"ma Is[ner0 CR  @h сܺyj]?)\-ˍ|:y0w j0hN $z?@~soݍkj(]}ƳAJ"[rmQAWd!58梨ZWDoD{4\,we-ɻ',cN>j[rT3k7r8m8ONԮB˪Z(*vF)XG T%~x?_#w$*%ð6WW&0)h%[BrN;oD#Dn[i˜|}=^ B"F?Uti&!cFT I! 0А'M4lzCAg[n9N;bU$>f!v"4iy.ko '>`G!qתtnG:E$o()رc)E<$z^ GPhA@;"QFv!|H _~9rd (0t ڙ&LR@LLv[^yFmNQBe6mR%")@Pa1@k.NQl; ?A ZCX lXOplAtH_wu_6l0 3T*8y7rĉ .~RGޕ5o}[&vH7Rok K@HNF@)0BC).so* V"?$y]tEÇsV ~:f!`@-Dx@nլ;nt iig|5ztePYc7NAdLjiAfqApcZkJCfҴ6E 4p/3XFDX-%4! j <F.Xyw>WׯQSs5Bu@m IOr;1Rk4F_o~ذ +Vy;: wTHK;58SIEIy5u+|_ Hh @d?N; A"}s="֝vX+d򫮺*,Z:T%9 G gymf!RzG鋨(ժchWoZ=Nַ[c]w80F)%,MQPCs/I<7zZw1ڙf!Fh ?F  \C0 CvXPm.۴39Dv`DؐWnP/Qr2@# J,C{ 4ȡvM7GQ?GqD5uE28f5<u yp׺n~g/]R2ɨd-Τ}Q2w#`)HQYvBpjwZ2춵n=X 2I/xFy睁=c +2H3HZzS8pW6KmQ 2jQC\s56|_ܰ2˄g޾ܹTay)$Q3 u;bB@z!3ό!i< d7i(0} #(ԲTaPvSOӶB8i[QOҶ(c&)1h/c#4*[ C0 !4T3 TՁW'F ea hZh!/q}g>S/^G2ϭp.8r<epcHDۏ3KtD_ҋxN;ԋS {LqP^zKg/^"=D _@.nRyIa-a)Y^^H}y]a?EacAڮ\[ Cί`7Q^RxUq\y(k崹V#}}\qDHB6,3$",nVl|x GϦ8=]^8sڤM7]GHVD^ȼ^Hq_!z!> Q6/K V[mɽDruBi(֪#ۢ6=/JcD=!?>n/Ou26TxIPZ5* L _s-T~ $D<7ӟ;d>1eެ\X y!`@IF/ƼY Ygy&Ch=P63 sO})~'; [nDҠ@L_D5C^<mHQG4 yYgNt2\7J.uTOG{QV?Ct0S&@[jPwչ<ς 65#}E7dCـp*F)H)Dp~0]n ߨN\fi&GNuN_D]צРwD( ]MXj-ovkv[ݎ>IbPP{Q;Ѭ^_jE,`E1\sMH)AZZJX =lUl"dDPgM{89o4PiǾCJoq :0.vPR?֣pQWG(m'OP3N9唸Zq̈́m;(r4K/պ H70^f[6(`|4%(ZbP z0ZC e[!`Vud0T*ZOˀ!ydRBSF3 +;:#Fșs<)K4m.CNdܻi`\Oi%Ԫ묳;vl׆d7RE'+SYj&Hf=SKeuMոyYqIWc "G3z衐@Tj"NFwsoIuq-џ^RK g 4>+ SW)i'^랃dsꩧ6{5{ Ʀؓ(`'+ MrLMi~AjbʆN;m\ |?fHTܒK.vfv!`]Q!`!P@|O81 ghuM\i3m#Gh#=! j-#j~M6Yp3b]nHTlܸqnDUC)QE؃ owqNV\Ѐr<l%q0Pˀv#cpW8+TuAhu F!EҘM=܊|3QMXLh@0lӮ(} NsO=T1p]w9I!H#b T(i/i,U+mlud)LjY~``]~).7."'* 1?e}^zK*CSLѷ*aַDP]vgzꩧ:(]"B6. Qy+ i;VnjNy?@bVZQѨ^pNRą?@rtZ*4$]e^[4 h3C(҉CC773 C@y|Ԭ3d@ÿ+^DzrmʀFX%L%bVd]/N ܅E&ދxHcw C!J^9w{。h y7Es&ܠ 5% zw} y/7L\ZD]y!vz+,Bb3/d-琁ϊmR[Tjuy%%OhsZ%o;lxsL;lfx36@@~'NHY(SŹ~?t*O]x f~{J=\_˖etU.%5^h )3_BFĺr_š^ԽF̐ F}L!%}唯@p?eYe.ϘB?tKDmOZH*ƞtXoB, QiXQFm[}XnI0 D|駟KA%#fB:3C(Fh(ȅj@D'D*VB@6%]/j ^""ڡj4Q*yeD/؋V d~a;gkVȥ 1'r=+Z:89f_#q-zf<&ˍx ozoAEKMpS)*CvaN26l+KH$[| rIb<' ;VHb{;fЈ޸$XK{BQf@^7?_}U> nL!zMuJ[?u䅸BeJ:1škk6 8Z>Ȭyn-i[+)b ,實˷; mQQNr,=&mjQ O?tS-F~a Ƿ`X3e2BذyD91xD u q"v8V_}YDZ@(M6$Fh3?zQ%{=n乍Ow-~l)KDG94}resxD3B믿B[ + ʔJd"YF9MCRބ FmTL2%nR T9眈1~Hy3֍z-p~]J]vY /M}:mA9 VHH5WwioVxj,%3g1+g!8tvt _ I믿(ؿH{7>B id~PZ-2r^$ .QҲWOQ:_k8qȾC*ԣPL{GrF'NIJ8#zX$s#{뭷*THWgVD*/IU $0a%p&b$2 Jwy-"E EK01+iW!`!P4On[ƙwr!iD}.A c=s0k(l:| tx'WhfrDeJ:U+D dzaw 5F5\㈼U{wi ϩY Q#z9Hdv LUd]"\Ĩ]r%!j}H)ڞ0΃yF?嫉'wq}ﯤiw>}Y7ڌDc :w8N^tg@kdEK37[CAl~' +U,@s8ECG~-y;2v6H@5|Qgf#`)'ȶ0 C0JHҰF]IgШ QA.9Q {/ T1XUPiDꫯ^G"n )N:IO,$g5w^zfqJD5j%ӔAP[b%p뮻fm" uwT,SQ'ǏRect ]ˠ-;lرar-7< (as_Cf=5y晃|WxG0@rzRɂ! k$y  2ǐH7nQ$qEPinzZʉ_mmj(צB>i>`'Q%#qN6V\c5(s2 )yu$H+Q9 )Hwh]1\r%3Y-Em!Tk*8RȼgɸI?Dm{QRQ^Ǯ?v$ ȋ:A⏿=-o=GǹBTR, I,b)%%^CqyE/'_ܧ)⤉[+fRNdJ DD@A0BCA.U0t&luf犰}QK U XpXgN%㬫E 6∻R/2 t鹙'6F'V""N:yqf2‰8w ^{yQ&`p>-}%ҩ\<(3^?eJhx衇TURaz."ޛ Ͳ(kƵ3_vN{w޹㾖rr\g'|x|-;SYqCz(Ѷ90w}Y)fr2dĵ=ztG躅 IsYm" Q[Í1'j.qy3Q;_Tb3#4 Q0BCխtt*lt_R  <̠=CǍv0ܓ46:.r +j'R%EA.}2%@#ov(\ ϪqQ|_|Ŭ;I*whJdyWD~AdsEh S<^~ 2ާL3Uvq*~K׉4/BZ{w";r8c5uYv\;P\9rzUu 1>>^3ҳ O>$_)Bl&F{Gt qɢ^ Ѻ5+4edRi(x'W_XdiIO[ #[.8i_Q^qpbΕk x6hL0Ļ<_|@]HI#ݬY}P21BCձ44*jt<= 60UVY%S{W4>Nl%8d9`Qt;S!Si'XLmGY{{=KȐjjI'闺]>ȧM4@z?2oV.Pm-8Fh(m"/Ls9+kG^{Ig_T$oŎyZngPߑ0]z+a*Z^-tf>\Z]O~j[0 =R።o$qeխUHHnV9IfEGvJڙW^yeSN跡Jgg-ߕz$r6xc?qLa3[2 SGדH.ATMߪFS!6Hөu4\_Y 2)O1_OZN Flȑc[TL }/FhvdC O8蠃SH~ϲ ޠq>?4z՛u?@I*,/rG/ΐw{c Jvz_^ci5F %4v, R{Wns뭷>?1kE a#:w_ŭW%2NTyN(C{ZO<1>8ISt{w*9%"6dà#fyM;#[oۓFsC=l馛AcyVn GnҤI~m϶~7e;qDoȱV[ P@y(vIo:%gWs/@Oy+?q2#qf-A8o3B@䔝D"BmW X^wR_-L৶J+QF9qv.rB>vcǎlRK9!8(y߰YIx'ywǺO?}+vBRO0՞'m(IShCmvxr,0>qE"RO3Bq?q|Y61X?klL]ydPƷg אw*Y>>VM~fC{F D\rI,Nj! 骂SOd@d{<|(L%wX-a2Mw:ω*F ?yQp1_rR-‰FUjb}zK[o5"81Q+pᄏ% ^{9Y!NJz' .Urzy~[dMDlo)5ĉ^$x3͚(܅#Ȅ_?잒ECfr;ԴϨga}#8"y `W،!PRz-)VmC0 C0&[0IX"uȔmݏ1JVtQP'2nGU 2ि?ObJQ$Z ?"!D4Pc &7=`3Cl AN:1@U1bĈ#B 黎AJ #<)YňR5X# 6er^{kT"Nh_RQŬ8* U(aԒ̲UɻvYw .T{%zpxy6h2uw^1aWwPBY$N#Ը&(5hέo敨Kx^! 4k \uU] J7Jr Fou҇杤dVe'1Q%~ՄZD%A0%8Sbj!>aQ $t+ {_)iK"AU4Y17*$n%?2)A  :3a@Hã Y)VX!ҞZ~O}ԑ'Mmr{챇[)7u|3rM7dDUW]Aj7beV+[ w;QU+R;>B9& Sh-=Ug-U\~(mVSOP1TSg )9 DTh C=ԓ8Oƅp0?f̘k=nWG'#1VlYg  j "J#:J[9O+r7\/B]\pPW>msNiqk{ >)iw}:e6rN6|}ؖ:1ƒAe"n)ze=ذdB[1tB֛O?[luy'4L;,*4P8<+xVP4""bR# 33C(pB ? CHGȋ#.>h4A7/) 2D+,Ygtt]ܝO#fܷ/r0DovBfPye0ӟs9x ˋ#'sb9%:ˠsʘq?0jQKbdv;i6-Ԏ5Dދ#+^#Iֵc@8HߗAWHX$DTu@ﹿ$ub\3!{QlwQs}>IIB%駟zQsB(k$P;{Iu9jL[B0ܔAly.YY) 2S BFIjG/*)^o{oxzYf/ LEI5=eK s5SZ)&K&MRYquRM$s6BfbQR&Qlj0oV.LA f!`@@攈ڔYm0¥^A=3"ߑH<\Gˌe]_HA-⎨TrWod[/~QÐ؂^@Q:MH\i3T,P\!- Fډ:**1\su{{)Q;Gv~}{,Ef#+]ߦ ړ#G<ht[K,DonrK f_G%1 wyg<?r֓^dSO=Ti PPɲ&Qi{'+^Yy;T UtO&eLH{IwĐ2Z8f{q5"o ޗ>)2P9ۄ SZW/`\i" 63^ ÁciNA#57[n0f{7hK<ㆴƼ+4~@Vs6͚1γRKg1փrCgYS Ph0 C(wuW蜤!JPAjOFCNCZ9眳b& ݃>ح*իBGDY%\҉CcT: ^|Ŋ>Gύ7n\w{0x;pfE6رcà91>g9߬H&r:k&` zQhbllf ڬ0h%b4Ng ^{}nl}D61cKpLbHSXџ%E\'?q{#5}6joROP'k 44U Nϲ w.Ұ~H>r7ʄ(ն!`d~ 3?HѰ\ =Ѕ^&5#a ұH뮻st}i-RL$H PPZh4X裏v#=M \#0x+!`t K9-$8@ΉwrҸ2hsΎ%b+c-op6$d"iO! 3/uzgW YI`YKߢof Qг@O!|$l=c /O^ @XN349zرccyӕ2񖜾#+D7cuH9׼єR} %Hx,-h%cL*)#GxB,m8%V/JIXBi.n{I78C=T#%^tJ2(x4?y C0 \s${ NSV4HQm{IN_|ECSq(30S)t0N(uS=F|63<J.qCK;5Dm'V1"ZHw*0DJAbxBi T&4H&"ʲ,˚0.sIYAl"3jf# ŽǵZ"R}>[瞱vB<иf"/;qԆ_~9d;R m?vlߦ+BHJ 6` _yGB}٧4%4_)*@A5Xn@ݢն %0l榜rʶ"Z@{M6KQ3釡V߿8Yz RԨE 2 `2\e!`@裏B<쫑s{FC#)?aqEtbiK,2/R*ܓ-l v ۘjȗ20_fꪫ6l٤̐geƧ[u'18 U)~L;7`^ίe3qͤM!.5j̆G2vXl7d+B>%v nA4MA?px` }>q&-ҘloG@z0#Qwq{|M7^z)\sRI7.e4)LQ-M7AzvL? !4f^){uE$5R)J }9U+c; 2"`2^u!`x9縹;ւС#ZaMpEVUdJa"Yh$@m:XX`X3<83kQą,>[PAB">W+d1jzp?AҔAAXv _#<"}G{-0q ؐ,D׽$os\??}kƓlz ֿ=+%\ ѱ(xwމEJu65mQf @o\sMGS/~{ Dx6~x* rv}7>s#FJnq# Ǿos jd_ ÓWJ뭷^gZ+;Wz?|5WCT@YvEEェvZyzuTer 7t?zu^;!UА+c2 C(D!*i#h\p~UA"B1L.-آ[yp; g:32PfG%i.h) *ҦQ֝wy{D e֓enLAH里&mPwDl$nLRYmh<R7qӝD)^_JobRWR#2}„ i ;6滄2QR⯼.i DzJGLPNRC@8tY3O<1n&8HRE0-rȐЖ^:[@xNσ2CgH2 %4І!Hj{RkSC ȋ0 .~̛`/D/NL곩Sq>O>d0LzTdmf%2.֓ sx*ڈ,^!7xu"3텠{_>@; ǺO1^tv;M;2`D2/Pe/-I4E*ًԋkA?0$UW, 34 3D9>2ω(EtʷJH^d;8bRry: qO6d38ikc,7c%E!/-O䪬o Ei*Wu(ba(UqM(џp -WoW QcdqQBZu ~Eu"4-^mUEbQ%I[N|kI j?q? {HÓB C0 n D)IS-uMTS?xRyncGR#j9F`/z$!YC~v=zt jiX\X"_<(?mD$rE2,nyu"W]uՠ#̊\Gu꫻w(r[Hzig?=>ScP Ncv(5\!_PiP]S5jTTe6u!5rO?t{"mW\i3C@% = M=uw{'VQ,r=n;B -s1fG>?gxA(œL@ག>F ku>iQ/ 7Ss()X*ʵ1R~SrmtZo~RC4#OӾBVYeXlROB $ +!`A eBCl!e>묳|IC"em,R(, Fص21'X_}Q/R^5qH{Y]^p8H[W^7]+">`⏿+(OZwO1tm# Qzp]Dʷ'i"}m;!晔Z;a#AwuV2.ZuR!34Sć8+++vU(7)߱w߽n-8+[o* Ud2ۮvg^NrK<*(s˼H巭%i*yI' ~V_Xs/K~UIeiOT?WDӦ6y2TZD &RQIM^HSEIRI#^*Sh'd駟՜O Ss/|wC=TL$Y֫BC!~33 :TPj,t:$jEmP2E;$96)7RE75t0 Q,DLGz=Uf# fSHtOMu@PDx* 2[~=9 g`GVD9@O|T%2o໮fs:iof_#0MF89k Crh͆hQZh ZV`cGKS/O7ԗ>S;C奪uɘZWg^C/￿4=q=-ҧJo IuiqEGe$``ԪSnF)4^d&ThTSM%GFړ>;QLA CQ[{lE=Q?O34R B@K-l딪c!c8ww ;Lq):zJ#Ҩ·Ki)ui駟;i:q\l<8u4/S7!veI&w{.z{2L?}[ins\}Ձ:ɹÃ@ /ju, sN#4dZXI 0BC2QD*즛n 4&zre@=\5zWH"J".2q@u6\ P5. $y霡4.EŴ[o+BrXHbO'+P\(2轁C) FtiiBJS"j{~{<ѷfE`vx ]6ј*!m/iw 3}؉zZSRʡ^:"ʑBZ)[zMR&o{o ?.gqHզ~x)9i2MSO=ukIͲ"k׌)C=EqdQn)ə4Tvzawu_q+ SPHsZF3BC7u0 H9 5rvjjeU(2$I$d*ND~; ?pB|h8_2'q[ω4,3`;C‰rCޫ֕[jDЉoWmDr<_Yfɀ°Nh+? nwjI䊣 O"$DUoZx@A\??Ie 7_8q 99dP5"-Nl}&2{ެ?7q̆?މ#''k(ӄcKІɉqwW]uU?裝($2"a |-K9! :!M: 1qQ1N"q%S78hqF$CFw{ Y*nUW ?oyq=a=P'x_&0sL6>u(o ?&$'j%j춺xjI<Ό qGf8uO%IZ0PKY@Y/vugP3lzt8JЬ6%vyՙ޾lK༅(&y8uj 8Khñ%2:cyL JC\MMr(FyI*믿 qfL™ 3hSt[l˘c+):-I3XM:M,DVhrW-2 *M$;3C}%Z1 Dd HNMۋ1r!׏A/nȑ@XNoSy'$1VBB'H 8\s{,vE#^}ޯjww *9?bűU!@{tYfdGQs 䓪j+)V"m1k* d4)CVLC>-߽:+KRμHهHQ'i^–Xc:B>uXznk+? u%= 딀 ٔq2xտ #`_T@RN8y 2H Afq!z"(=HZ y@Q~[L&c @F $09 & "'K$ @F,L sկ3w ]|̽wg_"Ï,$swZD!Γ|1#-N`uD;~`1, ѧE$,``?&``$ֆuYgUf w"FaBN>Hr6,ZrVF*jlcE vYwn NE%zaY#Z-ZI`A3aU rëЬh(PE۞tIv)R+1:֖X'm4z}Qgˍ7hс - mݬqiG( @PcF`_T=>tDi'q$*0ܐ,/p%aY]/Y.z♥ $(BOcG90(dtA hw[R2Zm3ؐ>4e&}i^'5S-/l, LPcsէ'&({FSQgyX&|f0?7mvq 0[ DB# f!8;N鸿`m~g|P{;nǹDz :݇mHykr<`ƽ)opg` QФZS4>s CkQ֊i8 CAX~4 ~6mZ5V2oQ0s N4-|(̽444C qw"``,g*NS<¹ֻ.\@qS暫>nYGnbX>Me9ïo@6 A'/-"l0aeͦ2MJxB`ɋyĉQ/3XeM7Lp0ZP$8>(sV4FYC8ykx!МZke#0Bro]ŵ)~NZ~wO9I֭_[;ב6'BD/M.N4GqĶRS@C+Njȳeb~>G̘1)l 8DG ,~0@ |pD^j>8OϘ (s%Z)OCzUpq_c}xnoر{1ЖtqQG2% ,yB'ERW@yx^r饗*2o *Aku wj9kCAWfm iP;~Dop#iYx.']m\E 9X*(` ҝ^y4PE @C{=9h h h E `#GhW hNa/Hm diB53ezP]ۜ."*CN /F jd>~h#JE.e-8.SO=s~~58:`9PdMt7hhH;8alY?p_3!" h)(ÿOplQ[M1[{3Ɩ3ejYz 5̥٦Nʚo:9-sYf˘9ujAz"8\@(t@IDAT yaI}y+H?eXR<`d`˼V5x1dY|Z3`}Rø}@`倥M#GsnXX)`q)]wމHMXt(&DJ;3 9NB= 礚5J% Z7@H9 X.C܏8[*my>Flf@w00OuѠw-H kO?^uKöET5\$E]=5]{ʰa,s~5P:g8b_}@@@4㍠>oΥ)!G.`u% *L hߨqQ3Əo#/Ө Dapg! CBZN.|P"C|a-N;3ꪫs?>XruNy#0$A,lq6d)_N,wr [`gT8cR>@ =(Gkm9Np.g?w"yʔ);mӓ6m@C`hIW~7;zXE[TQHt9k!Z H?{dcc v#8{|G,snUn"W(RxJ{ߋ/:?6q4 <%ZگGe=I%|nKEӨ~^{fzڀb}ZfbOveY,`SI X(@R==-\aCh,PktټGԊ^'J+@z=6lkv&9 jԹΥh$C/u TRb 44P G?2  Jb4+o:$jB9ˆr3ԀB]ʢb/ëh#k@k,s#F"]3IimrوU#bV#QF FFFu#,##/#T#c%Ј>RZ@u,4E"Ks[nTP9;?1ZRPQ&qVwBY^}֩;6WaB1'g$4.&Pt-W{aD'|rj9ŘVz!W` w4 V9XVQMRp߯]Vʦs;Pc)5 bSAZߊymSN9%*.K)HOaDZ,lJ>zMO[~]I]@ aI9koՈ-ŋ$R)B +['M;A 0]wvXdEl:b=怬HъM#@H!/M[{8#a)>̿/%\bo>KOU"a_l&{[lH:3`K(I랷0]w֋4- ΥxRmЀh*xen qɗ(c2ˮ!DsJ鏕hFIs`&1P}6l8{E?rrjd+0 Bry>Bt VЭ[O@戄V c$sU]4㏻+X&:Ja>CS}=6y~;C,#q-R6~Ѳ.kOw9ӟd^<%j>yV_f)O{~ZNVVu\:#{t#Z޻*8*ygO`!>A 2Ia ;-S˖)}a< ]xp@CL-; m湪_+)2A'iA/8& r07HݢKO-%%}& f&L tދ@}o1p 2< NtgۿE]4 ̧QU Ux2.g!>ADd`<(ծA D5&blWo˳`d/ *ءM[9_c`O?xVwxp/g!vXņ2 s1WEpTa>?iҤ8$u?/&\O8Hd[EFBɈa /HQ9rm –lF_袙CYnZDV V56~24`,Q j khJäyo3E#@zP6 @ ~^5\#} @|1o3~xÀ_뻬~ܤJ&#A#3M'Uϰxbr7;g O &!']{pر2q)4<,|wтi(Gu/[{=>[vQ~> j3POm qϨ({ XP)vCfi#]v a΂3<֙VU-&n5裏.5 ;IC =444 `q&X +S JUaܸqjRƸI6"D|GPИa䠌@#'c 6HAc_y2۶j8"?/Gp @sQe%i(HEa̘1?lȁ+4"EmoJQ?|@Ae<3X`Ђ=f~]v5 `wu ]p3<f2` (enjH"vp>ʗk}0ê45|gٳrQV_HRw)!̥{,8'OMeiowbA; hox'k:UOiZ; sM/B>#uKC aMd>cK7 > ^ةaƌ}W R k{ %K{:mt&`zq̋ TYPm@܉$ sϵ`]HPk"ЉJ . gmuIE<QAkދƏo !<C;O5Y=zNj5 /+RV~ _ёܓ0LgyD5.?m=o߉YTHvv2ik;=y߈4BD#\ cfv@'xMD[0 :Q78oJ Ə3Svy,3ޫqmfk:s>vygFȻ{*S|8xYx4Z1EN]eev}ݶ5(l)RPg6e_jHk#WR44P  )Aji@&DFR ˜PCw9ԀDY>kSD(0v$\w *5~F1N_.bؑ(:#+D3`x6x12:X/#htwAzqt>'f+ucG'tg8{D~N6mpө/bp6+]CiFRTnDMg8=IVN1+tBҦ^ə3|Jnyl)hX筁 2 -2w_ϛSs*[A[lkgSN9]璀=Heo?#XsO r:>ifsyꩧR<Iꮁ|o߼;t+2_AՀLq}g{_ @H"O AAAUPԧ%K. Ɖ'Fq^bTiFM.["WW &"?/OU= ?3QZDA6s01YRKg[,h(8Ð-B!:Hwö\_&Bu̘B6ca?; c^?p4D2$.Ћ:bLy#x(D^ o7.2XSDA Y` 2KMa#s UvqDOܧm,t2'k!T̤>)ݏa'3 p);2Ms=0K,KXM'|Kꖍ>vIv&c̣6`ql5qi}^4JIM=`>HMɚ4;tޱ؁T`jmCC:@o [iiЋjrDMt#5O 票YYɡl`MX/+J/JGB߬PҦhPu1tc1H8裏 uӪ1Ԍ3;_8'gz衭KYb0r!R.}QILJPvVP8c Mjp#DI5O=V\qECh4@#T@B 쮧MnaykLI:k#uY`"3)齌"w,ThOwz`H~tEoTrSaM0A|; MIUc$CsNcY)̛g!Ď (]_W-5:5ϵKۧ[%k] ]o<-H:ꫯ< k{^5[ع= ȍ$h h$td ̀F[o5M~t"$, F*3,qD28R`A0a" | O7X!E MEr6KWւ\CFWǗrMnh[n?`cT"yY^ЋN>=/UD=0J4~8xf`+S}Z_A7p-2߇>Vs S)Tk{)rp)9&lb>쳢4zVF7_.(^zi +[3s}s`sDE +Q|'|x:V #i]rcita!, LMZ*_#:8O܃ +nao.@C;(@C  RKmZؤG58Y[t30/5"̯UW_}5!a¢Я ̱k+#k9(7|ӂ0.OBgY8'᪫2Bc\ש\~fl>FN+ 4-G8qL=#^plM}/*qcgV lC=?omZW6=5 [cVhg=\ƱN-i!G^?:MH>[^[Q^zi믷WPΏFR{vWy{Sn)c?H6gmcn^a~*HJ2ϸAB/E-;6Hԫ/{G:+l`gT/KWn֐01u;3^`.v!T]%=k?c=b?Sгa @C.%T*h3 @Cgz+Y%]$>Ɖ?4saXb ÂE+7.pq'0ϴRi}PP-KK.\vez[`) jL;IB4)zl)0rdEIpO@Hb Hѻ΁~''&kt"3<6"Dvlyccw"J$*DuLNrZfrfu`k`w҃*No>`)qj=X4{Z\?M)S_w8_@W}|PI_8>\A^xaYհ{Ow^?:c5 0AVƖu`M%;ϬuZ'4kB06ҩLq1ir6[ezFݩu $HH9Q1 U@4;n]w[0鄧G!C'l|IMx ڨF_:qXz41vѩ:$@F=/5#8`CYcѯk9ӟF1?l]:whs(3f0DՋXTͮzV"9#ty~L3e͍BE|曻>x pJ0R43AjyiRyNGydIN;@-]Uq{98 iuq]ۈz0ZP)0Vume=E{u)!k_)%}^A"U9v*6j9lqI_bbU]` 9DXT i5glb?H4 ڒk J GO11J7 _} P` Gm8%WkZEcƌ1&L0ovV{mxmbu`Zw>lk'(Ό+8kE6 n8~4u=IN+2ǵ//BBD?E oS~ʣg{,G \n\%O'{e)3j =R9{LQtω E5Fn sLQO?:ڜ矷^:O $= ?wz6W'XtU]vŵPh?! 7D?XՇ16j(CZ Y )1br- ,kl?\ l~~,?xj\~R9~J{-ό޷+@C:+P mzCɌ$#ޤI(c=O;HlC bر-=s)}(1>5bq`Czט{Ͱal-ܒ(o"!U7Իh7~󝜴4w 0&u%1yNXpm: =}뵺K䓞6ms_X[#l (olrU4iŻLN bp: ycoo;P0;h,=(,ԩѱ5|v7]'17dn㚈 5p;]*ZC-Ak~Iሦuش! <5zW? as`v{-袮NZ70&Md3Ϙ:hB;hC;(Ǐ,vݤc"Z})g?&ʴ=O ycZ-L @CGB4TCKh(Y6i  /l9M [N`0F4K]p8ŝl[o 3ԩSSoc.#GLȾ}G"<6S`[gubmckfpvRROu]i{vޥ^t#G*] 4S?Ѷrd h>E,?Ӂ?,KoD˻>uf*CgDĤb 9V[͵~9i~QA׀D#o/[gwr-a}Op~F}6%8Yg1ɚVy v=3L։trD?-1wE>*YnWNG в 5HwXig sAfj =Z_2 @C:AsXԻLn. O׺(ieKT: t;'?(W_}u^/O\=lD}]XȁoN wD_;pB @LC_XI_[l1"a)qs+?aɫ> Zl41TG\-v=k-J-(VN."1;rDkq"J{9?ؕjTհ:'Ov8%Hw`=e?潲N^<يx)L/O;}FX 0ȲY^vef6G{H*H[06kLN;5 : $ XmQ5o 97_I iTݴ]9Ϭ 35  P/dZ9ЫaY=YwqM @ 1eCn!C8 y &8N2u?󩧩S>|g`XՀ@:2 MLQHd@A'ywؿ?at9c"E9cq'-^|Eeƌq/ Cs^ -wuKdV +ֵHV$?YfýYva}BXk]r4~}ݷ~#/ 53 <7^z'WpF3U-,}RP(c ʎ3 x嗣^zqPFORbԏ$(Cbp|WXK<j[(LlQv}4 b b䌘;7|YyƲFh+$-+]$j4l07`o$EjBue/@H\Z6d˩ jH~{%]$QYg5\O}'RGD]tv%O*[o=mhw3H״QD!H#JHzќs+f[DcG^$#i|/Mf ؑH1Q~}]~VX80Ev[$+{'ǖT}/L$"IIݒ뮻[[SnF[Ė:ZiУG*Q[9'\p׺k4Aߒo5h[[ AofiL"}AsR$_nҙ1wq9ي L <1]E"^ri(-9#e( *\o_׾VW}<0""I4tcA T7dkE(g?Y4qD[UnE{~k m\n4IC0a_6w&8.z&džDFyqhs$au#=q5˸ ЎY̼M^ :^GX?__ )E=NfEa*) \DzjߏU5 ;vl$,X )@.8 ZZmL   2G1bDHXm)|@RcbD1VM| I0B?}mA?]u@CuG@4TCKh(azMZa"v -dm+l%j^MyWψ.!6vQ^{m/[8Oq\֡,[ Dqӏaۢ` Z|{p O/aiWa]:H g}f}Z%}qcH0BQl<7 PQVڊK;@lj]myOT&zP Nџi .[_i1^--`|G,- $̈́@{`u*,Ɋy/>HR4fkwVFhHjh}4 %Ds^yHoY,HRR=&GSN(9ջ.3 #UrXbYD`-ᩧjǢH㧟~j K 3w,N;4W$N[nwau $IB 5࿇H(FqBʳbn=(@_gmZ&{2`?*CШh)7>/np(YfUVe][w_,IدDr1'*XePܒU6*eZi4#=f/P B,0YT1Һ/<#x!Pu5{*T&(:Hۓ-qHw9/U}=6|svBEx\ۦr_rAXꫯhEp3J:)FfmVN1`o| ZYh&8щ'(|ԴPgvctd ޣқ~ pK*_-.ziT A~5{oC@AJAy?O`p},i[$/1\zʼnU"?,ҽ@K3>S7\rt|kQA/Q 5O;V{f5 _ր D8{ :8,PaÆI5;찃>#FF WFCލᗩT]ӀPb;݉}_a?#Hm 6 #F@iFIK/dbh$'K1]X@nfkI.n|T,Zϵg|߻B*)j:E#ːӣzx9358zZ*]LRfIt\]ґTI]U@Nw7tSWedvJ\W]Fv#)\+HҶ.lNvkO?{q8\; -aL^}UntBF͊C$ǮyY#kjmy HP_ ۮmQHJцS}2$e@].fe&'RZ-j࣏>_o/~ #TKD ($٠B^ w\ ըsMoK,a0&E?a*pӅPMu3%`Bڰ8$۝!kmxNqN8; F8t8WHX#FhDfka{gU$ FwQ$z۵wD3}P(cYD9a.sudyT3v}I)ѕc`0(c{ҦvQ".{rM."QF"ܵK58Tdyt\%(7`b}O ZZMڍ3O"檫2*`$-i}SpKz oF N=`mZnZj)oE@ iA#m8%%i{3Oұ._Kg=zFHDFFaVZpc?{|*6@,]k  ߅M _Ćh 53#塇231eh tmdcm \xᅱ "7Hc w!l !#:d628.~\wuAߌp?Xcfs/s^@N%nj~f.Wt:m* ;.b[atpj }Pz. 9Pn5 j0tAnbJ+}!8>? 䵌t,N&JtF8ێw,m<ꨣҼOi cI;AoN Պ An4%AZ@;xIn^3cƌ (}#s9'ëh~U&wz舔ko˜^#e (nVsz=z~K>?_}HjI>UX]UI׶`g S6VN3kқ$Z[!E[ۦϯoF+7a\z5h;cy3 Afj/R[+kQ[l .,u8nx&S۵^8QOËQ2z^*r)JAj :\1#:dĢ!xV~!B3tePXj[tPBx~^v",k{Yy*ZzS{0`1!L.,@IDAT"Aj# ~EޡVW4|'P^޿CYiq1FWA_џQz\ҙHzMzd̘1Z\su)5cJVzL;#}zY0& ֖9Ϧh{ \se׈eKPznA9N#0)bH5cбH9R:]Nnꖵk Kن$R- @C;rw0Tz:̴$?7S4[H2 &#!گ1NN?.tF+ >e;bĈ:jw?pl zQ`r}DO?ݬڕ;'ZÝ-ϝ^i@9QIotz%b1/|2.Rqǻ t e믿޵GdmYǃcjYy4LP]~\^[^έIC V(,A-SG;/amW_}uvYо_N-$ƍ7 s" Xʋ/e`S!C-W\1=# +J`3WXaҮH1q7ڔm?0rHʢ_vrYg t(|3=)Xl0_vi!U٧}[$nSM{hof -k H#E2,,~~k+@F% ],E~G0?h~QYݜ}OHѭ`!I-Q?_|EE|tG]W_]B蕱Æ scSOFJ${st^{-ƒ3ƛ{(IJ<iu#f= ?=mՋLe[6@WqοO| +s9gu O@#reNmF $=$Nl&͸"q`yW^h>yop[[xChf C‡~v՘/.a^вX RZR?7uogydpF/gBJ{ &%㭼fL O>Ėz,[>PVFvcW ~$H\G>@Cz<)XDff+M4z$+_Wiߗ2&M{Kq$$<"{%D <{LZo 7aۧLZE*E>߸w|ɾU"P FGu3eʔ,.20,10qS!} c+Qtg'QrKq]ȟ(_ҵk_Z&y!%?G2ythwNʴ}$N`L[]`"1添>e܆YLt v=3 AE>oPa4,sdmdzK8x#nq_}}4{ڿy`Hmuy9S,gM73L'o{]p4p饗ƞ/ @4 I *vhk5 b?O.ĬiE OWYe 8~x.TMz꩘YK2yV30*B^W_}5K\ ?JKD(g {7̺RY~N})v^r%?+OEGrIBTH4W`76vtcH2j(fUt"}Z}p*1GZ[ř4e>#5:}激 +wO?̚ƞ*AflR0Oa&h0XH012v׿^HVcXm3,mXA*c={ ƅ .,yAE#@7?ӝ{1qڴiMK$Uއl^z˺qN%\yenu2.Yƻpz:*X|'k{f545 6y+:[D[gubcj噚utS>ERNS;CK&Nc`> Ft5{ &X Ӏsp:7Pm-|] M.pU5:7t>[r^|}y뭷,Q.'[킄`8qJm* +UH=ʧβѝ~o} n&׷1JD?/>UԩVS(y>Zz_|EH U?oO06GD2yeorO1?SxO fg6lSz#ϪE{P]H {ث?}РAlj㔔)Uں]i{ ~>CMm<,)cKJ8I^xE]Rѹe3MdM\-wt+d|XXfick-֬0]&MlJ:RFY0WBo/ /aRa3V`kup&iP¸mlMض}!l1Aj J@Cz;u1 "wU$+ڮ:`+IJvMu]fO*!t#mt%%I}]w챱3,l喱19yʓ 7lg?DaUI0h\[ϗ|駗N8{Bî"Wu@G'|+d0rWQp蘅S4O 8 ?͝ߟcƌ)DCx5hXS'hW/+ɜWu63O0wnHWf0w>3'YWx@*`Bc( v0݆o m}ChzʷP|݌A]'i]KPi8|rUm ,CNgYDvS!C8=T%vN&JǨcwaxNz03b5'ދ/hoX1 i>`Jܢ {Fl#"l(juToʴD ԯ\N?N_~k㷿ms+r:Wvc*3^8܃dލDAߊ:}r{Ѧ}6 ;c$?m64e .D/G)qPvs+eVC|+ڛy `#X>38k'|2a-6)S >, )8cB82iܿ@C7bu;&4U}뭷\YKp L^k ďW h_VCˮ#1n5t:Q0Fw[/Jc #"lں{V_D4fhuE2(SNEa+ST@?zir MvکS<6kgޝX%}g;kU]wN<1Uzo7`}CEu-𫯾ڛt@DNTWꭷjQuѸqO zdK.˴iӜN[7tSUq-2N:Xy}Ap8⋝Lx2'ۄ رc Lg0E I1~Wy%RUg uYp@} @C}~\4<&]aI[X 0u7:(KÎE ,0PTkF Map }HcH 4Ǩ3o Zqݽ@ۊK;>׀vu]gCMa.iRal6oUw:>U>ʻ&G幺ߏU]:,7f TuuD/BNﰂ5%ߓJ55JxV!2c?o,Uj͝ku{ᄆvJϝTW^y~bOr}O?0I<5/)\%_Ek6hHl83ѣ[ݽ k*a WiC+ x P4 ]/W'3]fvZʰx&9cӅVyС6{y}]O",bV_}u `!_Ҽ i7}@y8 U@d~9;&T e1p@ě91?poq!,0sLn0 Gc";$8y,1_bi4fjtFzv=V6}>կ~Cɩj7ߌ9X;L<5H=;,~D`(kR>/6Eb׮R>`gjmoA5)i!C I7 A@ovg19[G>CipL@n4ߖ裏6 u}/䒹o+ y)zp5/6CC,Z@f}o~Nrtbö카|:_3a$-#H8-U'.8`gG}_}ՙ곘Q6y" z\v;i;SIi񼄆ʲn9}5XþfhǏwmml^ZǕ+ҵE"w^z*B0m;LYAfj`-pz,Dte328c{fsPj03k{7ZΘ1cbދb̻."C:D@K6tϖ:&y/ҋ[c=ft܍1i bYlS]/fԩ9ug"umny䑮 ?~wVpV@4믛? >%`z@4M~ *rhce4;n-K2 ѽLǍg@'L㳉>\q]{Ͷ8*^k @8I=hyq, {8=?qjBvw}2ĉ]Cs[4 ߳ELщy'Sm@{(v۹#O8}c63<|gU + n{؏x? <@K:X\ASK5xOPznVdΪj?Zޯ|hVOo8֦?9r-Ysl|_-)|E]w*:V׽|tس|]ff"/9dѮ}o;O~zY); |M7sc~{ߋ?O8*Pܤy6An AA%Ѐ8ӧۖ!%hUo g?Y$FH"#1Db1 R3b?)b,ߢw}7H0anE i,H :B j)Dsʲ#ƭHlsĀ =AHh_ &XU][$R׿u$@ &β8 F$W#aUq~F|p$/Snhsqw H iyjOt=DbЍzw4iҤHr_Hh5tMHswifF:Hϳ~8s=^9jc2O*fw"v#Lc Q ˓?VY/iqSt.Jo=3D !T(ߚ[anپsx޶%maۻq!h`F]s<Gs][M码i 04tYDoQð!SOuwl(sɃӱ9r@w]H =[eq"_䠗`ٚr{h腢'67Nq[6z/*q՝*yUUqg~r 4@e>RMn鬃JG;)IZkkfݵ_[ڎ$kzb'tRJ_~듏?IP/2N?D.mZ$ZM[P6)҈w$i~󟛳:2]@5+γ܏xSfo|a[:i HU~ߚ^zɦa}Oȟ}Xy&!*?/O> "q$yǚOj@oO7E)ҕ`eH?Ah9RZM#Acb4}33R_nKH9Q^m&_ $dX'- $ į?ܐ'q{4z $/f>TtzD̨!SOuwַęAH;i&r/b#fEqm|1L-ĘXl%yE9@*EMנϣ|'frFZ 50c 3j(+ށe}@Y5a&1V{ ZƁ]5`Yxchʤ,w<`(;g L~=:[X i۸ Ѝ7ciDjai^VZJ,i_?I1d9d@*=n,T 76uz ,]jX5aNjp\@K*~Йޗ-$R^s5?lx{1԰) )*E 4P $?ޝ %:PA뫔OفRJBAUF8Bw2 O?`t!D^ Y#ʙK9(Z<_>aǧ('CXh%I@ }tYħq%TXU^F†p W4vhwIt(ʡ0TkYIǼ(L u \t9wy'"eɵTʏ.ܧeAasF3޾I4s%;mZ)uXn$-fR1cQgt֎V&s(XR C$2H9#lmUHCBQ>jk+m~衇r]mYK$FaOI6{-24 LΠ/MriCj6Fo1ݠZ\xᅙDi6g$hm(ÉD])N24+6$ +806ПZ<eCDs䠃>m'A5m:Lt 8СCm<%x`ճ:yFFa^r 740h̆^JRLjJAZ׀ςL 3[aӫ5# W{4;/{G`g zd #}/̄ ̙gi$2JR0v#w~D F~ lJ-v(H0&;k]35HCCcאr=W) @Cݍ1NJyB$nZ8q@ nՠ`PHʺnTVI0-yG1 I4I*K..XXP/!ϓŕn}cg:q*5MzWҝabѬL6BYNJ *'rj{%!-Uʖ{ު \_/`@Y꧚»!Hc @;R-Nt'Afj]w9'`n ZI=2k0Uap:%liUWIӧOѣG~sm {{uV*41}<VAÚ/O 88f?cm3[})e7) )B>{:nviO,жbwὊ]GmJQ8 xڠwM?$Hqt9ش4MV,um' ;`-iHi[Xp 6D揙Fݤz׭9Y>ghӱuүMF99ϚFBjRxZs׮`i ** j Z38c d_ ,xɛ\jk,!Tj6*B21c7abH':XhbQ:-S.nG0m|vu!,EHkc4 2P8UGlA!4^}C7hq~E삑I#usyj]rˮ纱mTG=0REv(i64;}6Jqы*NŘ9GILLs/( 2T_VQDVR$ <(|XV'zQ1`94@;tIki.dӾ`Y6a~ OX1hРCW=P7nLMA;zOYs=Ho4@Y- 0*;NAAav  V<%ANYWڌV Ҳ*Áu4 [ vf!#C-nqGiY{n)PqwC;m$_%wFPm@XHM#-D0QӉ{Ec| eL`h!}Z 5@2n,,N8Gec99<˸q\]NԩS^\pA]'!D{᧮W&|n R[{~ sNdذaxnt y=)ad:*YW{p7z{?+-̿I'dn;2 1vE-_*i:@"Rʅ-Rƽ\6gy\Hhj-_|lm{^yL̀0k-))FU@^z { A$(~ceʺa sSXޭLZglӦMmC[M]i$`7MAU@:a|@Csh(sUNPqc' /ygT_zvF ~}JD+h^UT,]՛UF C }?E;9M6SOnYWyeҤID+%O}GTVLBԱ>wWk,.Zi "+ wmv"Q|dH\^u馛1Y UFqXk1Oz[F(cu>um3aׯ,E>dLcUgedCc eĉy=1=E d{l@7"I^ O7 |6Mn.XCn4/ʪX]wXJ!}')qQVJ|{6L)Ak G@C{7r]O0@{-4µ:Q8r!"6[`p`Ѧm@He U=ꨣ,5$v>VSD;%7, U?h<+g}!74XeυJxFWXt?"]7Gs￿7.U%%7 ,{gςf7M 2PbT׀ z§T5Oyq0bޅCdoYhbۇ *+lᆮ8H[j+ZhIDMXz*@PGC=ymA-/of]h 5TlyѪ7>+_V}x+^hP >m͎-~ ?.عh\8ǘ'yk_w}-{z[춤dرv7}t}-HkT֣=UI @CnA &{[b~KNRP`ѣq~i.J~K!@1 Һp<%rVXaZ;h >fѲC(׍jrok?3>͢R94Onr10$uaB%v gh@*qg:1 G#~x v|oc±@&^]RK-eYHgꪨ,i2sSN9Ů`Gi5Y-pe֥t"3f0@m[[q^ֺ%Eo?k "18܇ dkg~ wڇHT- hXNYcbc~6x`5 RhOSX7x|Fyc\2D~isW: :Wc|ʡҜ[d*D: qBTrI跑R>BVp<'D. +Q)+mJ-gYerDZg:}Wmry@bh%!;C'K 'tsq-D:>l+'3.Itfɪ~<'Q%ײPT8Or }Zˉɠ簓o'x_feH;Xˉ4hPc J >xґ7DɠAq'D/')ATNR9u$ߺZv#*Wgs=D?ku۞C$IA' ~*DŞvzK|PGQџ6VXa;jܔ)S wB D?wYnϳ׏(V䮩BcBmZKGdz۰t{% Rܰa|xתC9 yDa`0*E/o im^RQUbB}VZ)LBC%6!CH/Rt:k QA'|;uM@Lh9&2nmu8$I.ǎ&,ŦS&x0q|N?wC q&M d[D8[/BU r g:VJM%/l'yK?.<^lp0O+q:٩n&5\3Weulgf! `N"~ 8!x{@"M Y#{`$pz`,Jԙ(P:Qua%&rSo!BXPCm\n_[nMF@ C 'Xʉ'R"_ҡfB<2 󉥫 rtS(ri}"5HN7ҲH /q$21k1DsjkT %bGG E:ܑ$:\0`@N;%p ѣ|5\s";Ƣ> BӂrO!_3`'C^]'N<5m/4  up\ˀmA*ZA5r8g$4!}QO/hxN8Z'Lv^V"T\-brxG+VN4!U&r&FT<,BTKnDѺ]C$)[RH_\8{ 8{lB GpXT QUM' \B~HFI<}nB>;}SR%?jLs,=6`h6riMM - Rf]`3?|)~N9؂JH֥3w{wVZZ)I@j>!6nJ|o!>{w-cT n?4Lnf3C%Bn"ە&VXorUb;4 a*3[Q//."_j>6|pwwx4EHH"#{wqyPrDcDNq_ $F}42jDwb GdlȔ#⋇M\?5m?ǿ/J+/:Huɟ8T狗/#:BR )jDcȣq$o;Dʣc=`*B K"k1p@kDAo ?dDAb BB G/y1`mRy3H EBvBgxAƻR|M y|B'%,Rzr<)J#. D 2 B<[}ɢ`<:F_RH@b@J"5*iwNiA˶5R D`tf`sͪ#hoF5k,|I> pIDf2$mlk}pvi8iqTz#:JI TIdNrF8p'H/Ԗׁ H2s)| sSSBEySghVKwdrӘ;x+)E8g'R+)+Fnv<""|Yi_ɀQǏE,tsj !sB@7|l\p]-=`ذaީCR ]f8_#G'\9YlO#4q9:pQ՜(H++ܓ4T!.(ACcAQr:xp*`FjyVzA넾fl<QS$@Ń:]pTcDJ!C71Iw_~ٽ[)^Qx/ffM6q<jGDyĆ Ym1(lf$A7rƷ1dMx1_{<rHA5A};br a b1tO~|_ 8ո*HiyRSo%i-zUАC@Fhzx>Z3k? >0p$ *RD!6c@BJYrO%: 3rp~K<~8dd}U5}~ƶHU3⡘Gvo#4t`>!`ʇz*[^a L 55o/G NGG,,y?f13g.0yT˱!A"s}JQ~Crm[;P ";(YBlöIWWnHxJwHMq3H.Lb=NXf#ӌH`Ԉ 馛 @n"JD^pFe޿} =\4 X❅Dn#W  e ;mg_HDʿ(}b~ZciUd(ߤ^Gqrq??Jg:uOIO1R;{/o4dxCrs8MOeZ cƌ $ 7RFBHټH}m!.-b / loE(m7!O aq]@lI)p%GC>%Vx<hs"e * ϙuFh\Fh(-72 OZqT= `EAG}#HA#̚@|( 9ITic"yqVkX6xcOb@%f@' 6%BO7S=;(N>Yz|t>jn!#C\f!o3 Ҫƀu38 R#^q 4뒁F9x_Ө;+:}ZG.DxzbP&7nlgyfHe//7 ۶%00EyPrDjѻm' qO܁c3 pqoSGѨ~w%U "Do6d{neVp/bX׮yB4;L8F#S13aqo޽{ޝ'x}7{NeEY2W]uWCJ*}-S .Fby "]b-V o7 u+5RE˝s5T*% r(m%3eu][#44Q+h#?yI6V准L]͚ ͡w|^ژm<GvW"q~ă H}U %gw3x'pSA;w63 "\ Hx^iءVtHԢw$z] ŋ{u]֬)kA8)bglq] {a:6+8(=۷:ޯx~Сk#}] NvJ8UVYœP7PkTu-YS)-+=h \juŁC AĬvQ1|4i|kc`j/{BHBAb@u:RtgD 08I͔'ĉiTa#k NpUCqPGov6 k|&l8Yp8@b@MCJaBTQ\S{U*-3 l"s"V(EzeSWdUU= 4~v'm+ )f6sDHǀ#k^GQY5(A~Wu*,WpWZw n0S<F?OZeZ/^a0*j䯆t>x'|8<'MîcOvoB9+&>Y?&mrcܗ7QFy%@ k/ {H{EIघ!J~_K:ri zSըk1^F_206;!6@/6ۨ_A-nxfO>ᚤ1sd)uח2,!H!*i+H \+f:A03CTv"ND>.AM$Z"Q h%rKd0Ж)/)4onp@t8n&OK>2zݕJC"LY]Ѿ+^&u O8׆8^vT@,J(š\f{"}0r  ,&BrH$eW"28s5Aqx..Ew$Ėe]a% Duw燺++-D"O>zigQrHD9J$W9dʔ)>%B0bI뚅I쀧BS_C=4`M.($BXKDq&)" Lx0 \vv۞=8dȐ14F&B,#圉:P"ijCXx|ND*0 mdtIXH: Ͳ($) *喤SrUO!f03zDf b`v'36fՆ+]a #Wɹ 0i*S Ht qȜ> j /BIQ e*:d0:Ր'K.l*|n6@_`qi4ι]_WAM*xnrDٚ"@3DA ":i1>U[>iEUBC@=G y(dy YY}ս*3Ʌ,UV> ʠ$WmHCpU nƦPH w]~xl|%1=[j"BEԪk:nV={GGkD/{fB=@k^OUN$=P"o`M"%Sh`1((༜ok!Xg.N8!+UoI=_)cDor:(`F3 _B6 HƎ\z>:+HL|Wi6r@{@]SSߧzHBSS*7>WP4X+tFi_9*A jEz3SBrqx/}L_NPYםy%MOnT `A;t %`3,{'B 5KKIm-EZ wFd!#$7VɗYbi~-Hy3|'8qΛU;3;˽ˇ0=HضU*?z[?74KX;FeG@ƓH\Ӗk6~Kͯk!`Uk$NoQ؀vq)?@ڪ>'Q ('%gܧ/[d`?ɜsnh{*|i-iW_ x01<sV `/-)4G}?\sTNTy Q=>|OןN_yHEʭZ++NkUV[uX;N 5 R ,ӧIs̑ >!R:Di!bf4 /ˇuwGnn'^f[H ng+ E:y!]eV~dM u2x\uDqK"ʺvDzDEZUW]Վd2($#_ۂ!iH .z"u̲<)dЫǦE_dAQz60 Cq45D6ܬ4ǤÐ,;7sgi5כ`jL9e;GR(BaR,!}L_|ѿI ;!O PKۇa&NЎ_|O!3sҎrqZ}t| ٥!iHr!@)4]j{W}5%DBؔ)S\#;5=F{0.&D7rHbO?ݧuYrNn6"^ (Ud)5חTwjYf 0T_ NTr%lWnZO7!` `OjвmB3;IԼ#TMԊ\'xbbmD^ (RwXh3% H\i'$:*q})hmZ85_!,0a_ H5Il|AI&&bm I; yaE"KKt4hPi[kO>۲[ozZys=."֥S(Dh 7DjpJT;#7jF}+?MqBER; $5۷S2 uT2ꗅO[KϬvz衰q 6SKcJ+PA]qvrJ9jV >$Չ_ctYf ЊR&h % 22C`$6`ô&/F$4CHo&HYbL$*&)3R!` 2 (@>Of%5oͳ@Nu]óg 428 Mxd)~ !yPQH)ׅЛvZ WTL0!A濔/y{eе\.c&K!`>K)ȿs9&M_&6[D&wqGӏ۬T֬\ > Ɯrq{ lEm1簔/8`;T6QIkP2y7% zK@DrGf:%&)ߴ=Bl[jV].­:ro8[/!$nEf8Ee}HpjŃ2CtP/RvmWpV^yԟ'H? PI?p /;{GJK8cf! yq>kVjaI7J;v*"Cْ x4b;IȢ{,kԩ(q,&2Sɛ洼k[n!s^RP浩 iV[m:SRf%}w'x]3 mY e36BZXzK*B(;o[!Ub(|hB]2 'V"Ͳdbʮ3%M8[I HB!hhDUuVj Y~{qMelw6B9~Κ#ڢO>,;\fPP?Plvg] ߷Dd?ߠ9$GHْ6 jWr&30Cu_c#gi! - ~hqd>IaU=_b[J:(iJ_nr%w}7A6T\`ꪫI-mCL?w"]{ޕP_mg]~a܃^#d(9Q7oFKkN!Z>xB1Z>ijũ~65w\A`iF`j!,q: acf4*(S$ ~Wc6s7tS7 6c# NS'aü|(;w;k32 Ĺ +W_tD8qgIm +.'N"3k-=38QqmkaڴiNDg:b\"~'RNҠRc@SNBNy| -TǴ'{' ?\ (;s%($I߆r{>!wQG9q^K.q:kXf3I K,>C_w/;{~iǵ* k;qW$\7~H5WoV7_&N4m;tt#рe㶪pI%)4rLytQ68_X`3 A\/r'W'<_DV!eIV!xnNRKa ;ew휐f}nz{/WmENqv1 Q 믿e?0͟N5 c,ID{طUp0ޢ&$袋OQYnWPK?v 4 M CZ GOlt1?c(Bj|HDKyA"&85Ǝ~gu@焩qR+0ڴ՛c5u?J.I'yc r?I۰3;4 yDu[t{vJdz~13 C `',qyBN_w  U"=QH=\'*:ȦY%4DM :H;IK G E=b2mLIXn9QjJ;$ŗŵ@,0'݁h۔P|@d`9u*; "$eߘqmlG۪*C9BDw}tQG4 ʆCujkN;4ّSm%Ճ'~׎>:QDp11 $ZYW<"C%A _lX+\lc;x㍳ܔ;޵J6oNTb*"Ɨ-V!P"TP1$GċV] e953!ꫯUbXѡ3 Z2>ǩAF"D&-n]vK"<*kG(暀 @w>sL3Gሞhƀ1*J` Al9|hJ+!P+ Ph~e{#f`#nHDc "a>PCfg@L3X+gu;C"*pZUԱBhh$It_$} 0D㤥,j|gqs@jASb"+q` <NOp c8 P R:{+I睭yx;ά_,B8Ygկw^z)cǐ a 0R B aOwx??5}jiSc)&8.vBm)E@{"}C3C0ZZr^ʩV2c۾C Vh0BwټQFy;"cq6-*>Vil?34tYv6xȇRCMI3 29Row\<@A*RfP)i%0 !mH)l!`d@M+VnrDFizb2P@9 4BrFb#x?A6ج4;pҗaa{A{G}44id*5/n !|`p + Jqⱦ'x!hYQ߆>JL]N=Ԃ1 /v)"Pe  vi.VJ!A7]W@%80IRu#݆zaǽ$ȑ8]OʑZ,MS2oj: `'e|!`B BÎll|of +~t$q޺buNF:r#P..γӖ}>Tq\(9VX @"p '| b[Q׿5C3 H+iܗ228J`ZsWڼ!`yAjytInM6.GQkHFzSN9^%muK;0!C &T\U͔7QR#c=Tw2SRFiQlq_O6Om' wu~?};TTAҶ=_F'Dl< v}Ёh4uT׫Wx\3As&4fvs|Sl7"?o /u̦ ھQ)9\Z]9GqWPyWOz8p2&:(4@y)>7=^S21 7?T t@Pϴ On'>}% 23 CՈw03#Z ymc#!PShp^rnʔ)]`c)VEFvD,RԀGc%TCG]S ǒMNDy`1pbnh<缮W0?8`gy2g r}H:v dq~*Co 0T'j)H@ ڧQnl {"l Prĉ}?TސkZ޽<#:?:@:ed%8Pu[E]SV.T dE:*ǔ<)[ˇԇ ڌ[l|50ҽys 7BC`&oD cb/仕wRP1+}VRj>E*.gCAK#F] Px7FK8kJeuʸJ/1I@GVۚz{'DA$BPeu^<\r뭷&Bж!`C/x 2D \N(`Ս897DCpm%Xq&uW^7[v*!TGDҺs(rɻHp-?ps)O"Z!@))_ހB -55ovn1kQsR!$d2%%p"d Y N( a{ u1_~ُK\r%OQI_Dȟ?ZN~{-T~ucg= mY CW : Sh7Y?IJO&|k28&90t;%B9JdpciA1"6#oa2,;i&5XHn6Mda xĈ>?/%6rf!@wժvk\@$_툌@Js@"rrF"ٝ-^}dv3 NFଳg!eP\Ei#9)>C 0K@LU-vGBm%YFpoZ/#D#`DB3Ruހ,Om}>!?\O48On\}ơ Q̟`'¼7-#Y2N)ϳ8|- <Qd<6Q 8ݒK. @Qt|{~(uwφnJ0_ P .0tUt`,+eJ)݊*5mY6!|x_|14g : l0 CoXkkEXA.n>f*8A1).DBYiL!I`5҉=E´a(fDAuB?.}@yʼn9СCC9Z z E Ϳ#l%u4c"=eٌ!`@,&Le{.-+rg}vU% %}-.q0WUm=D&*gy+l1cP"0+qJޫ|HZ;p ^qkGq䰕kvBoށ:dI3p}`wD1>ՌW _%<쳅_-A7 NRT^X[ő.9ONyH;"'p;.iBCer-a.w۸o.*[qr ɸc`#=5nCڴv}]wUQ^TsYB$@Jw}}UJ"cezP|DܼKuUg=MTA2׎y=K@an{ˤ V?C0 М 4ܪXkFʟA8'ݪEN#JRl!DDivP!l^mٳK/w8Irz2?^0.u7u.D#/"7iҤ7tS/QL 8>`̪"!`@hlFjͶۿbe_}Cg~?%9_UF, S E(l7\بg>c#}§ 6l[p6ģp:a{N8ᄲcaB(umbawGsk^oAZksfinp`]jܥ^ZbUWuwywǬ}pDŽRi'< h HY1%N9D$X4MLC 1+"T~)S|WmwXi3!`@F:u7Xc  ):W8uQNdOӲ)g #2լ(x6m:G2a5ͺ"`_8%ldȐ!NRe>> h}ya$= ?9 hx$;cGV_ 0 ve!`u @w:zWZ;,eT^Ԑ(_q@P꫽[oՉ exoi96O>$DرJɒc0N68PQ@A}ۯ_?!=37O>s.?WOu)DQF2cDx 5C,bNr %J(.x2.*~킪5-S  Q nסaf!1d@h "s=8|^8 !!!m9NZ"PDH6E1`|'9~GA@>j!D0v4VR)$sNBmvcrH'"E0ZB~d&Tr'mQ":a{Ŷx{畨f$J$i!` &&+3Dw}$ {CT%:5|o!")?8NrHkۼ!䢂^?L_w;jD2H}$X"AIrBu{8Ɩ묻Fˉâf؉m3Ͼö~mr'B\*؆Й;6jf҃V[mΙlXńeK0G"BB&M<ȒRމ{l"D}f\ix)ZR%.RoYZ!D$x!̛uD-C@"6L&Ho2N`+$J-<;%{.3Jő,%B b;jW,B I4TIwn)9#élàHnD" b C0:JD:c !QD{ ^}uׅs!M8B}D+HT|"ZZ)B"{=LDKY;a!&fꫯ.￟&7m1 # Qls5mO*'yoO$e"a>!y7|ӞQ+B`6 K.hJ7kCR$by^;: XOk$U["pSQJ$5'3=lӷ7GC6vCh<Fhh?k(DSqRBq^xWrM?UUq!QFV%ǧ*9)tl'Nݾ^'Dwi9 Vpx!8Q.6C0RR}zrYEvN3QM^xᅝ5<˚4|||0Oi5~=M٧Kԡs^B>Ps+t%jI,Th!fȹ+RnJȍʬugvXdoYfwp-Zk$޾;ɰ6mߌGq!`@:qJgV@[C馛:l[=mH  s{w?ʬe?݇G- |ŃݵB@r"I}" ZU;!`@[X>DȔjh[Fo8n8m궭j}[q8 Zt)mS p_~y8[( j単p'{}OgHeo_7JکkZ*Z>*7-uC=P~TG+ &Y mc8g}:uCŐ$mvVIO0AJ".[+^xnF#)oE-55|p#< BH('e^yO*8qb" Uxb&Ɠgۂ!9')|bc9sε-%jK/C +yԕMʨQRW/!P |\!7[LJeدI絬xigWmc!>=CEY@}"rPI7="m]=#8dD80\hwSLq+RS}ODF[a6oǕRU2͋/{ؚj;v'3hXM-AzSCn.2eQo SNХ2_#,(Z* zR %\U>Â3Ÿ $@}g~ S 5EgRs@T6 c=g(&tF@@v0BCvU3jjfjeV^}Uo:[h|_ *F;bHhxꩧ2Ɨ_~YpuG#@J 0:IWbA˔y!`uQ^r] AO>\{g*"͙@3ЎYycb y|4_6] iԹCHODn7I'N+ :TnJd-gهYixf?uaEuHH7f#p7T2ij'(?wygAk #KUi4Y >h~uГ3\{Ydh f j,R;K}nF[j;qT `|* )0hſن4.7tSj; 2&SCԌN V=~xOC0oK7BCPNy瞒-s vn0 N'4|H!?|z\3-7g=Xە++K+Fb C0 C}oQ|5ׄJ9܆6pp\d 9- ol PD:@.{r6 qO^z-UK&ɐFb//X6]uUnwKގ+(VKxf!p}q_ܽ[a{IO48Ow8!+}׺)JtPS"QX4zAJa4R7Uou8 ;bց9r~=nS =) iO0*/ WbTv)5\MJ` #`!e'$k!-vHQ9S+e| J* 96>Mb$< P0 C0 C8Uմ)/?m`W&D8ܬgHѯ_!*TFn6[Ҥӧ{ih_`(N6-:H]O;J#pE:(R$5AޫW//rUD!Cx[O{t P}W-S_kqPS0bYy/|H=Qu7Zonf CfD#4dl_׿ԥEB>$ĉ'p;K2:bt^xnFh+o!`@@3MƠ<_cSТ8_z>}o *7n8_WEwκڎU ж&M2mlhŏUVY}UD ?|_x7#5tVcI!8Mgq r)P֓2쳏'k> Bt(&;VZƱ LSJem{&=6/ptDΪH8j&"&BߜX1z 6۴JM=ɓ [1Z8Mh GeP5Qj~lZJm}oRBGc?PJ+ [`kXN0v ,"-i / ~7x뮻viIEj< ZAt1uV(ЯABgn}cƌq#F(7|_|/#Շ+l0e& 9P&en|8#D# V*ꫯF2@ņW9˲߆!`!`!~ӟTws54VyOY/i^C:F#t dYg;ݞѣG*sOA^ 6(48EJ#PA4;4f)矇y4ތu>cTb'¨Q(8I{-kNWDZ1. U-ҫa}&NVPR*OmV߫\x4* b-T'Zve  3PA}W>$ HԐ3J/xd {0 CEZyEॗ^rG}tt.yRCxgNq#*V\qEφ/I't\rIyRStM C0G c1%A3seWOo k5{EVt7  ?`iƆ!`!`!`t^wuAnwܱhbqB"Qt g@B -m.2Q8 ȓ4۷C%#dHҰcΐvs ֫W/ T43syDc1y%\^;E,i)8[tE #Ÿq<g/yVi7GYr>㜤6l_WHk]!Ew9OSp Yl"ov+f!`G 4%2PxAD@qO/PQ@?l3a/nANwgf!`!`ΫuJԠSOzDh@\ u$b8xC~Tz uu[\g}|865rJ{LjYy衇M7Խ{|;o[wzv\#i5kEV[m51ߥBGG:<sǏAFS 1 CYRw)V@8 ?o<2A* :^j?ܧ~D]tMa3X1a":a= tryGĚo!`!GldM|Ӑ5Tc2QMn iYJOBt"G%5M c7={w5E4u[ #F:kE8vuWCMC* ;oxr:y|>N?$P :Hu6-D`n~!Y|}#ovW^y'Sr!W4h'@@SՉ (Px'?w.8/^ISC(SvzGzZ ,=Δ2EY|gA0q=\Xr@w+ܛ< RUp-3ChrHH+VL\m4!` i:)K,G2Ϟ &P>|X`!`!`@g"5k oV(U͐21쎿*( Zz.owgqvmI3<ӓ6yBfqFJt" )ѢYĥufL^QZj4\8c-Rzj qwZرcu=šq ) ^j e 7Яù~mB+WDf`)}K/],?Gwԍ6xc_Nw,x@⡇WZ(d8w˒4Lny$UW]AR =;D1cL#3dl[] C k!kgM[GoЉ G0 C0 C0:w}74 gbBCnx S =SJdЀ U:AJmO#8B2EG)P0:8ΙwGUԐv'"āIF(QK>`\f!Qń_;yuA:+P{ZveUW]kl:J2_HvPG PBn)'q݊;i֮ O*y|>̿Q!e‘G!(dw$munPD9" ,>iBHs9g))ߦO[-O*)%&*V-^}lK THusȝ}y6_5?2K(!) gLy@ }\ Hʢ_w4i_?ajΞ:u?'a!`4Shh +tSaH"bthch 7 C0 C0: ` ;Fhh BNoL/e e _6ࠏ'YSi9'&3l&啒zJ8E_yL޸q|4f!u7Mȅ:Ef=Ƅ?ϊN;{;IWP"  8,6c_|mv ZPtӎ 4BCOM08>}$@Ժ#<շ~qĉ=Y؞#?/#euY/nԨQcfP m^xa.A10 C㎎RZ\e C0 C0 C~l#4ԏyuM+C૯ ~~?, Ǐw$o%Bõ^Ub5LGI(YH'(ĎE"N;C:2j>wok2M^ ~5ҟdx""c9]ve1dPfa5|ɓ':3{)bE98{ q|]x; R)@j+BRLt阷rOTkcOb=$8qf!`ARNe meX݌v2@ ~P9 /y a!`!`G Vh#s&6W#468B=h0`@H7Aȟ{w}gS3!Gu=ztC?AjFY>} P@DN:$cS `Gu{wڱ1/yNwLbPg^ۓA\VȺ_#l]vqoWg Q֤I69A@RW!`yFrrQ@q^.qTT2C2B|FҌTf!`!`!y|Gh)4(aYUD.[Ypy[sfs-5éPu9; 3ҮЀn뭷. 33<>³s#FJqP{s+n6uP"A^ x,Jw┨m5fC_=UЀ&̐wW_p$}^᪫EuOcB3\wyy/YfGqqǹK/qn |>@ 5dŞ~i߷t[.+De-VOC0~[TbRJrqAi@_p_WUK`? C0 C0 C *8l[PqdՈviM+@w}uHcD6"ܨ( аM\SN e6̍;6NLLhx7*~Z7|K{y睺ȭ*'plAX֌g/81T7e4C^s}YuAM/PH¸^z" վK 9r.k3  nj_}\-.+^ܟsJkuY'J!wА3ܠ>m/wȣd$_c[L~/؞f!`!`!ЙĄ4IglĄK7Q^|?_s5nM7lJǎ;Z]wGܑ6Z}}xVE@@K/8 RBYtEݔ)SZ꠪,b> z$?vm%ߩza\R J!χPao(cW\qc9*aa 3PP3B"Q>p[wu k<ũM~UQ! )*?Ч!l\Ϯt0 C#4aA` 7t~^XJbanyu(B]CrYg!`!`@g t;@kww|1Ѣ .𤀬(a |1w#ufO!YIJiK;o {ilu+ '_%qJV%"6V#y']3Rn7tSۇ',@_mWYi NU#r^3$ˍ6A2FUGqF*SN9ŽkAK=FkJ눪5'zO?]m;C0 2 04!/2!0?DPPQ.0 C0 C0F:Shh9 PHnڴiaN85?/}7o6K}pLhxgC9õ:( knNv]lNv=ӟ;+t!o&{cBN_@z =#AfTHCrؖ]vYLz#H e! $ *&?#zꥳ65 C#4\/qؗH-&q3H)l03 C0 C0 FsuK}5-aÆ9"w'Li{[lPݯ4q\z饡^8z衊"a&@TQkDD)iW:VA;uyqmynn[hĸj[ƃN{S4z)꫽3;dv5\?u UboOsYgTr!$Vf0 V"`Vc~^w-o*Rw ^{m/E쥙!`!`!`Bh` ay衇zkwt΢]6Tgɓ YЀs6p5\=᰽{v-HKtBڀwyǥE"gёn\iRLM 80\7f'qL4'=2d_[/$ ߃M0A=u]PK;?|M7j(m'jy&4I>dCwj)#H^<#ەFTjYzƣ>vG4= $׸/v*/r!`Ԇj*BQh C0 C0 C(|AXe fbux G)a5HD6ej_1cƄpwqȒA WK/MډV;O=T%# 'ѣaӦM"up-QO}x^ťnW(+M2%ԍJ K\qo}٧2h C0E c+ C0 C0 C0҂@n4EϥZAc5K7Hƃ Z tj[nƏ 0.gPP2`vCE #3#c Ch Fhh V!`!ٻxo322Eɜy)CDI*Rf"SBfJdR$!C2e܁pZ:{}νF@"Y x Cã9uߙ֚_~wtFv]>S8qb4n_j4i_.ˎ}} W^G&8MSFW4t@k>|5t]]A@:Z'5e͚5|D/ZC?nH'L\|پ "\5h Tv`f40'4MK,DVӬ!<*!}10<#r )Sh*ͼ6n8{`Zl);VF 7   >8u=˖-[LrgDסcǎm24y>z{sw^s\?wIG'umMޟwޣY,<3Ӟ+W4A :L|8κ۝;,/v/gJм79/駟cgDhvsN9t̙ԇץfl:!8~]fM3 ZD':kժ%K.5.!hrʹt=,ϟdg߁ڶm+'4MT͝;7ЮG1!3f-1PP@;Lb,8ӬCZnKOBjǏ V,t?-w2{l"C"  x_@('i[@3 8OʻJ;u9!-="t2… Ƨj[pko{Wg N@S(Q;Hҹsgɛ7N'Чk׮mRk`SMF GK = * 3e^up]Qe4 >s;9q9L6G|wk!}9/,s13gK@ !l92   N5hI:s}X~n]ս{G.:&e/Ox|b5QƳ5kL)bhXlnZWȜ9lذAҧOkSRƍ!nו/h@|#@@o9    +慣pЉG;xNfC~! ,\?{i͘1Ô5k$IWy4;Eeȑ|cǎ]2zt^'vVŜ)SF֭[gRkOjƍ g4i&"-c4248YfȐh޽&'8MO:%Z(3g8Z+^zp7|#ICާMK_^f͛g6-+k;rXa% @)@@@%Mx^C x vM~ٴilݺU^j8,Yb&4wܹf@8yIOn:qF3_]<ܤ%K'~ ˗y3+ǻݱyѢEv ^h-OMy#&P㏲{nàn&@Gi'9dk&Ç@/۷Nsw)L\rx!cƌL0$LPfq iqD扲gn)޽k_ NM<^ w&A'H֣GSyer/[-Aˆ L6̠Oz hEÃg-[V.\hW*WB5POsYnhfu^ fH ]G@ jhwΊ   T@:ܽ{xNXӍ/̚5˧cF%SNԹKz)^ ,ư7ؖ-[^o!Cub}>NȻ=DȳvAE~hקGikW_}U:w,w8y3gb:qBY2lD#t򈧚-G:A 4|ce/=+:GȻ%G+h9;s>>ů `)ɓ'x>yZEO|f9~xh̘1r{OB;f׾k"E 7o]%*w^D:: Q+@@Csv@@@@lN&='|b?:wiaȑC+I<]G'52O:Gx턬 ͛7ΞSLqQ'k;ߴЉY͛K3p@kϦY4[>OO߻wO/^lNA'|ru;رcKڵ~Iz)ɒ%ͽ{ӧuʕ+WJ@@]G@ h{@@@@ 3ĝܹS{9TέKM#޴iS;5H#]tn_kر+V,3vM9ΐ! <؞Y'4 N9&4|Q=h}Ç˟?>ZHE>0z4J<[T7ߔ'N UV< ?,X`7uU/ 0+]^Z4 @]4~0@@@@g2e2 YtBAkGD[>aY^=;׭['ٲesv\E-[򓎦98m7o4_zk׮Cr(P@Fe&:^РO|/Pl@]T":tg⣥i֬dɒE{=S>{hƌMk6'J*`I&9TR? f$t@W `@@@@ h-w}:uڴi}mW^fA'_Դumzp|XfyMNc2dpo@IDAT'Zu‰6Ktr.[\ ѣo:կ__VZe3ы/4SxD QoRN-<,4hi~}Y{Y^x?ܹsǞ@+"9J\D„ v<(-Z0%=9s攌3rZɒ%M$I8X"L   D@۶me֭9sf{z`nh;xNx|fn_tL۷?X/_n_ @6m쎻v ʦO,wbŊZ{,[Ԩϑ#XCӴ˗Eko۶Mh TZ^:[pa3TZ^]tI<3|?#OC&Cy\r@:aN{UZ5i׮/-Wӧtd;{0gΜ~<͎s sy;wn={=gEWx  b/7,F!l@ {Km΅@$ @@G1tӴ̀::+VpN-=ھ{^zJ @ \  4nlZ^zرGoҤIR`AމzV _|EId=qDD?úpEt.OĉSjBKcС)#׮OkItZnm5<곮<<t}m`jԤ }եw#sҼys*4@VZk* fH*UMF #!9< ڜ @@9ħ>)蝦ZWYf*.5ݼN$͞=W'tIӢN@S/_ަ'>J nѧ5wtR'7n,֭3ڵk'F}]ѣG%O<^N={/h0@رҭ[7tRm 4Ѐ'Y]y}kϾM'piɎ?!C9y}u\]`޼yfb]ߙ={v9q#u#G Ѳ  Zy`lߧr2NK]s Lp R\#>dɒFHߚc!mg[wߟ - >T   @ CN9O+A=fܸq*4 @zDK`%-Μ9#.\0Ѭ}/Z_ޜJ')W\d:\N=֟wfoQ9xď?Ġ DŰB<%k֬vR\4>Ӓ)S&eKVAv{ qV 'ɂ4t 8K VAZDMFO6nh2^q ow"&@@@SM6˗/-[֤O6]wޱPhi7MNR p[n,1&T o94}X'M5#>햶|ryСC:uj9u &! o^Mf(Pc#+#]駟Νk36<ĚAKwA'9< @,=C .>kkwOJt"' շ!6   T 4h u͠u|'ҹsg"EȡO hɄ K.KGc) ShШjHYY43gZnFfd˖shf }R\3^hMPc¦HFNI# 4:uj/W_}eB*c~GRi&I.]N ^{o|1|qV΁    O=DlV5R|yр J׮]c&f$ۢA'NsJ(8Y>^TR_8=_1c|ᇞ}?qjԨ(A8~9s;OFtYP@I,YbϨ44I&RV-? s%৿fj=zB f.C0Cly &t7     ' &YfĉEkzksɮ)oݺ+ѧ][hadΜYWƍrq;@أMvڲo>9pӇ)SvKժUeΝT^=3F <҉yZc7+a7҉ʠ?ѣGFQYu̘1h /@@C@@@2-yfD3 txԩSΪ.u2aÆ KՉ> j[@ҿvd)Lwؽ+X>-,Y23+WL qf 9W.{KJ,)l<=:Gma:th ċfQXzԩS'b9sF4KPHnݺҡC6@hÛƐ@@@@7 <&-}2es, k5k͛7n:xqj6i$;(L(}M'|I&5)ԝw6s.o &rk֬ 4lc~, EKm۶& U\9N̑#UK.r`H>L6-zV  {9    oI$}['E>|lIm)%HԻ|z9؛X-[?`+V,ԩk޽č\~O-[4w\裏y4S[oe_K/$Yf5{7{HV@K 2Dr(I\dǎRpa/XdBQ"Y'>F?1b@@@@:;vX% X-)$sJ*rY_8qdRBW^ .0qDRrΙ3}M'bZnE'hRKJoPB&:^П={ǚ:u\~ݾ1 1пK,)۷olٲutK@gnB~4@%@@C\     ͚5;w$g0K.ŋѣGʕ+&3É'f}RC׫Wٝ4 E47ͻ=Nzz ^?|nݺe&M J)8DZ!YdfLOC؋UaL@͓r    tbAQO?dʕ+'G%[_@(קeɒEj֬A+&eʔ֌  zviР9sR3,ZȖCy8Np'xB:vh7|r=N֮]+=4o\L40_~to)mlc[n 1'a„&EKW@ rE    +'O.V2AU fxItW A!@bҤIԋ~;wv^@ƌiӦL:#GR)J-[7&MF;;fz 4k׮AW@  n&   UVZwSO=e>IBi'|y/^4fʔ+A@7o={:8q}Mw{'`M6t W_}U}Y*VjUQO? 2|`WfΜl=+@ ~r5    ktstƍ)i#p1o퀵d-2d :I봀)P2\K-mШQ#{yf Xdh ~V\ٞ, "PG{ɑ#3Fn߾mEcqv%˗o& 64%CΝ;])h _B@@@@U'O9s1}g/>KsN,Ξ= "R;3O';'Ѭ&gϞu^i٦Mٿ}ԩSXb5RͼC裏f .:f0adϞ]{=z]̙e?H z:Gwߕ/RΝ;E=3B6iXDKm@@@@ dʔI>Qm6)Y$O&ܹsbdɤYf.m1˗/K"Ed֭aaƅ {4}-k:Q+лwo;9s戦ُM:>s ݺu2JJF)Ds%v:F@ A7oh @ !fg@@@p@ʔ)eݺuҶm[;'N>R[ĉotDiҤ1i +V-Ge ow\1¾M63hYNӚ~N *$WGhy&-MtUǏ :T @ s5W   J ^x2m4ɉر\"5k-KAsСCf@bŒN:gp1d$8|3Zg3P}]iDn޼i_GΝ;\rgsFWMg2|6KItO@34AFz  @  !p.@@@p[oeje;ODNbC߿L8^fȝ;}Mw,Yf':EÇuNG֭+Y$IYlh:t z]tIfΜAzqD?ԫWdٲe=MiƊG tmtb@߾}m^={烆 hYE@@@\):QY7{ܸqRvmv+SuyYd.]> +VL'իW'知B (7o.ǎ3t>;t@ɥ]vvTcƌ5h9uhٚ ]Qj{޼yDh1W gΜ4L>]ҧOsAr@  o>   I@kٳGtik׮5O-j,ȝ;w5N:Q3j4իeРA f}_;wߕUV9/ޓt)ĉc4Fti/^^z /SEDi&џ hS7|c͠ 3hF@@@\)O_n޼Y^z%;~A/.vF@K~L2Şcǎvծ%qAtiZ~Bi,ZH 6i `_qiԨQl_;ׯ_77ٳgc۷͛W.]j~+Wή HRJ `b@@@@7 $JH y/)_hrv)O6'/^tgz@L gΝ;t|ɜ9s;wvܱc}O2~xS:Bj<eΜYf̘!67t]@|+@@o9    @(%?y>ۼys8p`(. %IDҥKd|駢@4͛"E Y|轣@ѢE3[eiRs5%wn>~TdrqyWD@G H6    D@˖-eÆ :uj;_4i"nݲD@,Yo4 ȑäY8qd…xCO>v/n^Z *$-Z'Oڡ&NXy__ mt@@ 8!   D@ҥeϞ=֝Z*  z=!!ЫW/So9֐!CrK~&PfMɓ'f<3f`RLU)# VtEN8!|$M@ bb'@@@@Ȗ-h-*Ua޽[/.xW@dʔKӧm \v\7Fz۾a֬Yr%-~Aԩ#xm6;,fرc2aI6F@ ab_@@@@(H,h:N:1NzZx !rq]v̙SRLi_O-ܼyS&M 9uꔴnZ ,(+W 4ի?ٳ @@ 4U@@@@L nܸfROӯljnjڵk qEٸ hKVdIҏ$H ]vWn߾m_GE… ҳgOɕ+̞=[ӞyٴiY:8Y"  !"z@@@@ JtBmժUNC:v(݋1EדwVwڳ>tYf 0W_ɜ9s䊮_.ȑC>cs3<#˖-;vHrz:  7h"@@@@@jd5kV{S;r]G'b4DW~lbt[ UTsG:/#} FKG 8P4#g̙3Rn]g5K@@4x!   R gTN[~y} g<Yfl_\xѾzر;&W Ҭ7 "w&pZԩE+?n-9Y"   @@@@O>lܸQ7onϭ~%JT$x44 /_^2fhv]޽;w}eDaճ5jGFgʕR`Aiٲ%ߴiS;K9_~tSwv7oζmۤtRNŋ']v5 36iҤv@@ hla    3}zX'r&LhΩ۴i#oO#D/_ωԺu>Ms@Ϟ=%gΜvp|2l0ɞ= 2Dnܸa/RJ*, ڵkK2edF4O?$Ǐ͆CC@|-@@9    @ 4nX6m$iӦ>|4lؐV$t}ʅ Ή'qƅ%ZrBg+W&cÄ D}h'ЧO;ŋ˩St(TZ*!jԨ!0oeh/@@_ Km΅    %JȞ={@|K.5O vG hӧ}ɒ%}MǝǷ,ɓ'=tMr-gϖmt/P^=y@߿/cǎ נ5HGs0gΜ@eYzu:oB@ @@9    t]'kժeo>)V|vwǎm {ƭQߖ_Ք\ C'[n->h?bǎ-z6mhжk׮M Ͷ♩#_||rSrBKO@@;8@@@@.OI:I@PlY/~>?ƍ~fȑ#rJ.-bŲ@)dСr ҥċ^q x~z{4%UTfׯ_)S`5p?6%G4ӊiYfYfɡCN:j  khpͭ`     !O5Gf/nܸ7oޔ^zI cԩS+Ve˖JA3qDyͤgd^ݻw寿~Iv)k֬se?GӥK'&L0-Z^8モʕ+ˋ/(wvVtfԩ{ghPmkGKhi\rIϞ=EKM8-u2fyhժUσK@@ a ".Ppa9p9PBd?(G@@@@  lذ2xi<Џ?~4-;0i$ѴA'B9s4='A5 _ڵkK{$Ip>}D3@ lCz!cǎa3F/ %Hhp]`    nЧkժ%֌_tMn7D-&… eŊ21hYUJݥZj&(A')4ݳ ,rv:}:]1hЌ ۷ÇƉGnݺ%NFk;oʺiVǎM˓O>]ن hp-_^1!    5s]vIrn*%Jcǎuٻw+RX1>]hQiڴivn]VW.ܐ*U*T֭ٳ#xرCcD.]`|M6QT))^=ɓ%iҤO'JH~~}^@K{hgr,3xeΞ=+~td/ iZZD=7n@@W4#dl    xY@'u^3g8qByYhTTg]f4qMJh C֭~r ~-CnZAKI/^<>} 4qF2ZFCdʔIڴi#ڵ̙3L^ei֬9s2d̘Q͛g&J: ifͺiDmY@[1p@@@@o曒+W.i޼ܼySݻ':u2)GIyo54kq;W_ۛ@oO&}:dɒrI3 GV\)ӦM3ۜq2h Sjժ&kCZb|Q;%4w tU4@_ &,g-EIhp#_|Y   {.@@@@ & ԫWOm&Ǝ+u T'|b3h醑#GR fO:,XL˗O ( _K D98M'׮]+ח,Y}7gsZ={d0` f,%} !Smذ|y~) RZ@ ܰw^y+ Sp6@@@@%Ppaٳg)R^ի^SNunhjQF!v9F}v50۷)O7iD$H`O|˒)S&?lGlRf@Oɾ}hѢrx,r.ubm֮ D'Z@@@@", /~c?^ʗ// ,ֹ}1cǎIn"u4kCŊerSZ!o޼/c+W.PWCK6;'OIҤIeFkr8jN?j# ~/@@B.@@@@: f͚%7rM6ۧf̘a&`7qARJeJ+9rDn*-Z`6m$͚5ҡet_mZN)\Nzw<ҥKһw@#߿|.\dx Uzg.@@@@ jJ֯_/:!o ppKx 6]v>}zЬ}2~x)P˗eر/_>)S̞=[>@@ ]l讋9~!@@_&   4oP'|uUVv]X;:Ow'i% '!k]^*>)-?]ĉm=f)Y]V~GC4@Rիkזĉ#رCXt8_uEK迉9~2 piѱt믿r7n0dɒ%RZ{D6hqZ5d֬Y&MgK@APb*bR s   X`I)Y֯_?E@Xmf&uZrLipN5NkhfnI{_M3$d˖fX7n |\+V̔hР)ٴTLFjY͠YT5k&4>|#?cD@ & vk|k@@@@@ M47Jڴi!^zI4H fҥy`(@ҥҷo_Ѳj)Ss犖D xmZlٲYΜ9#6l0,RN09נ?fBe94#C})CeZh!I& ֫W A3 h-9wPTPpH"F̙/}-RhQрüyd̙8qbg5K@@P $vA@@@@ <:i=4U2edٲe=g{}>w܏ݟGŋ&k3I7o^3fLxe/^<g_e>M6$I:s>ϕ9r-!~4(7zhi۶ܿ?4,=zn+Q `R  @h@@@@@ ر#Ivmn_1"q~wy7e…v>AOC 2 Ж AY`2#֭khpŋQFR4_~1eUj֬i+va֭s\n@IDATٳk۷ou.]2٭[7.VXƶm${t@@&@@Cؼ@@@@p hPڵk%y<}J6mݻsNiܸS#G;wҥK' 9y7n^ $J|rɘ1=~/\b_&Mٸq+Wmҥ&,XPVXaO^֭['CuM`@@hp@@@@WRJ&pAO{nRD'{ݻlIĉEM&瘵j05kVꫯlpϭ[D+c] DݴjԨ!ju  @h!G@@@@@ yݻwK2e{.\`р-SH miӦ G >}|+&|ˤIpZ˖-M8\`W^yE͛gTbEYz$IĮ  ]@@@@@ d˖-.]:#FK/$7o޴ ^  B˙̟?_ŋCz}yٸqh\v=iڴ,Xrʲj*   x_rD@@@@,PhQٳg,XоW+WNΞ=kA <6A3{'N(9rp^FW_ TrE 1qƲh"kTZ5Ybͪb7A@ ^'    O s̲m6Y=޽{DrAaرc-͛7-ZQqY&uT`F9Fl2I0%  @$ @@@@ $ID/_.=zo=}.]ڤ+  G4fٳˤIBNr@'z _~ ޗ/ܹ#Z FN],]T$Hb  4D20G@@@@ qđcǚgk~ԫWϬ? tQN3!A@L(    ] VXʬY$~)10lذwDKZj%>4ה?~=z_^_"EO?cu\ržFڵkRZ5ٺu=ܫ*3gvt@@h*@@C4\    @ЉKT̅$Чܹ/wޕ'Oʖ-[W^ءMy,X,~I2 ѡ{3KիWJ*}vҮ];>}: V  q~@@@@#PLٵkԬYS?n1g3l2 a h(>}Z~w ?w&o< A?#\6֭+;wEDY<6 {#W &`E   =     .İn:ԩI_dɒxbXb˛"O`ҤIҭ[+U mڴ%Kyda=kO>[D._,*Uc=7n}M@@]4~0@@@@%/^<6m̙S'Z@FVI߶mp7E)SB̐.]d8`W^Gt@@'@@ #B@@@@ }5e&^yyܽ{Wڵk'?yr_Eޟ7|$YdR~}Y$Ibiπs΅_z% fӧ92   7Μ@@@@ ͛N:[-C1w\ X8Q:sNYtիҺuk)W\okӥKgtΟ?/6moѠaÆt@@+۽Ccd     ^Eݻ`:y^lYȓ`t"$Z"ヒ15s֭[P/lbՌ3X:  hp-b    O@Kl۶Mj֬iKbv ]V .l248gVZ9/Yqı̠6π !  s) {ACFJ4F ;!L#32a4f;3vl42L9$SrLcdcBCbTT֪:\We @ZUVq~4:@޽sJ ,[,;B䣏>ӟnh׮]hH{&M4 kM @@nr !@ @ P7\sM_ .;,ꪺyhu{O=<կ~izh"nb6[W쵍~U[?9sfv2 + @hZU* @ @H4|_ǧ~iĀN;-^{ꫣvX Rp! ^zKA/Т]n~/WGy$9Sҽ}ݳ}VVXLFhӦͪ'W'MQ6-۷]wݵ"@ȫ@i5U @ @ "pǓO>;vwuAH! 6,~F뮻gw}7 3$1rtlM?)h-]tQ$aG1}taVڷr!N`˿Kپ2f̘oV͝7o^aDѶm)2gΜ}R͛7cƭ-[\5ԓW4$vbʔ)&2 + @h(R( @ @ 'Fx?Avә3gFϞ= d;+|%˞{ 4Y #0̞=0-G~Yf _|E<1dȐW7"gҤIyi4É'R@uzTu]/bv@CFa P6M˦RV@0 W\ݺu+n$@ @#4bҥK,<%,зoCQoB GqD6Db„ vۭRWQaСij`?~|痜_G7pCnݺ<5 T7Bx뭷skSO=[nݻw_ @O WQb邏N=# @  @ @KQF_"nlŋG6VmuK.$>c6l{ 3\o^)R$pgFFrkof ϞtDu=d'X!@ȥ@C.EQ @ @Wc-M6X".H,YRzIW\qE#ۮJ{>}/_0ȑ# OL6-~VΫF`u~KwU 4n @\L9Q.=N @ @u,gC=qow}wu\F7ވ9sFHSOlevϲaVh}ʱ 檁e˖ ņ?䓱xf_O?m 4dV @e' Pv]` @ @+}/_ovك_G}Y\VN7=zr)չrW^ѺuC 3L:u>-ZT؟HX @So^_{l;<; [;{Oӷf?DfV @ @ѣGL6-/r?OメC>*^}U XShhڴi|ߌKNׯ*B7E( PY7G]! Vu )'|n @ @&W]uU\{Q .^\vY}7"%+UX 4t5~Bič;~CɦMSm @jh y䑸ˢYf)oVs6bҥ~+ @ @''MSOlƥ_8?/L[_>hV&2ܮT 4"iINN:)> Xiٲeq' @@ 4a4gӦMw=++_*z_V @ @*OSON;5뮋C=4>l_V,XSLJh(rRuʉTdutM㬳Ϊ} @e$ PFRsxbС%%KѣG=zt, @ @)Э[Yzpgm̕t޽{ޘ%yv-V7BC lڴi K.0JÇ~Ύ[!@(OUfW_'Nm6oqg{wV @ @*K}sHFիW<3]sذaﮊG[jUS itشl/ǝwf͊y? En:-R @4sk8CW^A;y޽{7d  @ @h޼y??k|ijo=W+F4 Fq9#⢋.*ṉʁw1.( @`}Gϵ m6;vll2;g{qGV @ @*GQF_"nh֬Yaiϣ>[z=ĿۿeMbz뭑_`MWB @hX_AׯVO^z0`Փh >`  @ @*H aˤIM6VX"^%KyK?1bDs1QSNqFIR O$@ԕ@C]ɺoAK.O~xܹs#MO1th @ @TӦM]w5k]8ދ:+:v\rI|l?9ڷo_u:bzD)'nK #uFҴiœSNΝ;4k- W @ @@OǷM`zZo}WfϞC 4 W\-n[Gzk׮>+!иqW o$@l(Pwu~/ 'PQ @ @*U`x ~ӟfM|7#}_4ylߺ _W뮋/"Mv◿e[ѧOlXy! @@vZj7tSu]k} @ @&l7pC\veѨQB|IaZҴ]4iϞ=o/2Ebёw^l1+%r %@@ w} 5O^+)0lذZy6= @ :?<8p`{~8dܸqѢE]Z?M[Q\k>}z>W @C  @# а>z]o4aq @ @{g|;/`ԴTswf /^j#4p @T@Cwn O>ت?TG82C۶m㑞A @Xgv!x8/矏^zc=\㽫а;\O`ɒ%MӒڎQ<' @@y 4w}N̚5+s΍6mDO>Ѯ]m_ӦMcС^)S@CB @Ȼ@V{3<3Bs̉8 n´kC@C.]Vwe(B GydL81㏏w1۶B P ǹlapĈT[_ƍw1|8蠃=N @ @H=:ve8S/ ƠA+O?}~ꫯfАQJVc)]In @44fN:JHS+:vݺuDZ)W_}KZ|y<ѯ_7|slkA @ @8S"~i~FL'Q1 'P=4{Q<䳌RwqqwfH4j&M}V @0ګH`ҤIq9 /P iʅK/ /07{ 5L0!Ҽ @ @8㩧|;1{BCnjoV-"H.j(n,O+VO~T#zqY| @T@onhQF!0Czg}#G?<>B \|T+釗t_  @ @@e @MoЇz(?~|mC )n,SfH#n뮻Yf]>  @@Cmn 3y晑汫͒~,qX4{w!Fa9sfw}q%D߾}W3" ;h!@ @|ǣ>GuTW_}5ŋ n馛VW`ذa1vجᦛnB ^sw^㎑ ե"v[<ٵ͛74`J><;H bq-V[m]VҾd  @ @H!G+/5*5۶mW>d8㌸k{]c6Y!@h ש)%_d6i$=ܘ?~sł V0 wqE,.)]}gGc=6T)_uI#8X @ @@ .iLoU&}wd)oѣFiF&L-[Y!@h ת)+.)F\KKFQH#43y0`@)*N8߿vlM+:t믿䔉'ƢEJ @ @lG1iҤz MzՀ4꾩˗/ ?U}'پ?8wwU+OK MM<9f6 @>(_8h ki&fΜYؚ5kVm.Yٳg:Ob @ @ FI&6՜{bŊH#{7n4hPXSC)xP T !T]OS!gC-;S!̰o[ @@ 4T`Eo/R֯z,]46dZ=*g~?ZYb k׮U @ @ \sΉw1?XdI|?̓B-*Rj _HؐaLw}|e}oz @ hPmݲ[0Ø1cjM7T6M;oGqjZI?l]s5%%6 @ @GӨ ;SO=}o~hԨFJ߉fŶlWЖ-[[lQ-ܲzn @% %6V'^{: ?M:k.#+@ēO>=y;gV @ @$>}G0`@!Ȑ]q;ĭniU%HH-[ϫwtpAu5jchg @T@Cm#^|},X={6AUY!/ii~D  @ @ȞO?tzwYwqG{W:Aq}u4Ri>U)\кu뒀B+WS @&/)"F73?Rx߿u]YxqL4)F>hm^ @ @m]4 7xH˽_0ܐ[%pQGń b…"N @ @hժUw}q) 7ܰ^mLa*.p(Ҿf͚W .&@ bGǍW;u^a:uj C )*֣| @ @4 Mرck׮.$B]] !M`!@ @߼;N=Ԩ:`׻m;w.gXFiD믿>~Vm @ @@8H, @@*Wy8c̙1bĈm e]^ 4T]zӧOfb @ @ @ @ 몉K\tEG|8_~vUK @ @ @9hqSib4 @ @ @r;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @v@IDAT @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @@;@ @ @ @N@!w]  @ @ @ @)SwމYfśos΍6mDO>Ѯ]Yg @ @ @ @Fh؈ ӧO#F#Gy?.uW^C=pu @ @ @ @ʪ6~)pgƲejUO/[4{w!Fa9sfw}q%D߾}W3SNYe @ @ @ Py קu֢W_}5;j;F '4klcǎn-~X.iӦnݺ .ɓ'-[mUvMZI}6 @ @ @ @*OEÆ /"&Msύo=\,XRw}VXw\Fd8#cu˱iۗFp @ @ @ @@e 4Tvn֥£>/҈ ^zi( i={#< ί:E 'ώiCqח2qXhQ> @ @ @ PY ՟u֚qƕpG߾}W-Z^vH'7n8.^W݁ACK,)SdV @ @ @ @*OE>lvJ խj* Rrsα[F3f̨e!@ @ @ @2h(ӎ̙=SNѺul{M+'tRݻlvc=,9?,ٶA @ @ @% PYYg;wnv.]d5t1ťAϕ`! @ @ @ P ةuѤm6mkXILYfWs%Q", @ @ @ P ۷ekv_=.]m״>6lS8^jϜ9d׮]Km @ @ @ @@e 4TVYkvm)0f̘ln)XhQ<ӱ|.)9bŊkJ%6 @ @ @ @*?5{Wɽ?xwKմѢEH#+4nv] D<7o;sm @ @ @*O`~\yעZ 80,X={'kZaȑq)\|iE&MJ @ @ @ @h֤QF]r4ĀbРAq7Ɯ9sJŋ<09HS\v!^I @ @ @*дBۥYu ЧO9sf1"vmc~ʁ^z?z  @ @ @ @|O*͛.]tQ+i]z˗/>8mr]xK,y @ @ @J@d}7tSOg}6:X`FkϢE6ڳ= @ @ @+`ʉt=jƏQ VS] @ @ @('U1;F:Ma!@ @ @ @@ 4kϩ;]volٲzWuʎΝ;Hq @ @ @X@5t@] ;1k֬x7cܹѦMСC'ڵkW׏7n\Fy< @ @ @! PʞcĈr,HA޽{㠃;  @ @ @ @r*oeSN-x㍘7o^t1u?m۶֐Eꫫ=Vܹ|xǣ_~1hРc7/I @ @ @. P\W͛4iRs9 /T4СCK/&Md\x5g{)0a„aV>l @ @ @*PqIX`ԨQq!6̐gȑ#?P_|:U+ġZ:E @ @ @ PV e]f83cٲe*fqέn޻rH0̜93ᄌKo߾ƌq) @ @ @<:kѫw^q#5kcm?pvyqeŴibqaEnbqɓ[n*&}?|> @ @ @ Py קu֢aÆ_|ݿI&qߎ{.,XP)y+V;.gqI#2}ّc4DKNI#8X @ @ @ @*7XR`GiąK/d4BCϞ=GdWNgִҡCKN8qb,Zd  @ @ @,:k͸qJFX8ӣo߾}^-o/ ;7n_~jAb١%KĔ)Sm+ @ @ @ Py קuҢg}6o %\xVZjC )9ܹszKfh3f2 @ @ @ @@ 4iws٩ShݺuN:pKk{l @ @ @ @h̝;7w.]V:viR D\`AO @ @ @@ ԺhҶnݶh 5i&ˬYk9{( @ @ @\ ڲ]w5믿K.ͶkZg}bm)ktzgΜYk׮%6 @ @ @ @*?5[vf3fL]M7~,Z(~X|yM_bE\s5%v}m @ @ @ PY ՟u֚ګ~%jhѢE7^."|͛7w9۶B @ @ @'vYkQ-UC ,={ĉky?-0r8SJ.>ӢI&%l @ @ @ @@e 4TVYkҨ G.Fb1hРcΜ9%ucqǁsN).;Ç/n$@ @ @ @ hZҬ:ӧO <8㎒{q5j( -[,9^ۍ4"QG&L V{٨QN @ @ @ȥr--jܸqq'V[`N+lSN]maȐ!@E @ @ @*J@ӬY;vl\wu&<{%ѹsU.K#> ŵ^1; @ @ @ @2*_U'|r̜93F[y{z?w@C^bp @ @ @ P>M˧TM`]v.W^4z.=z˗n}oz @ @ @(C2sb-SN O'@L{|ᇅݻǷ- ߅=o 4s߬xdX[%N;]?lt'|2z]cC!?1~ٳgL6-bqg$?ӟDr"pYgW\QfСqW2e PL9PzZ;  @ @ @ @@ 4Qg) @ @ @4I @ @ @H@:K @ @ @ @44N @ @ @ PF eYJ%@ @ @ @ E@v @ @ @ @2h(R* @ @ @h(  @ @ @@CuR  @ @ @ @@Chh(= @ @ @ @ʨJ @ @ @@CCi$@ @ @ @e$ PFT;\ I@ H kHX 0"82/3( hP#A@ `"k 6%lj:'UU׽]+Nusw @ @ @ @]4HN @ @ @ Dht @ @ @viI @ @ @H@@C  @ @ @ @v.#:  @ @ @ @@ hhU @ @ @ .e]' @ @ @h" M4XJ @ @ @E@@C$@ @ @ @M$ KW  @ @ @ @@hhv @ @ @ @44`* @ @ @h 2Ү @ @ @4&,]%@@>^Xc5 @@FGC hʨgBkf!W+e @`y9X1Ty9W @HNO},0mڴp 7+7t (rK2eJ8èQT%@>4iR1cF8#ȑ#NG"0q0gΜpGZjQNXCwy'|n8СCNEiA @ @ @,`ˉ @ @ @ P_@@C}#- @ @ @ @4  @ @ @ @iA @ @ @, dpoG @ @ @PH  @ @ @ @d %{; @ @ @ @FZ @ @ @ @% h( @ @ @ @47҂ @ @ @(Y@@Cގ @ @ @/  @ @ @ @@Jv @ @ @ @@} @ @ @ @JP2#@ @ @ @ ho @ @ @ P @ @ @ P_@@C}#- @ @ @ @4  @ @ @ @iA @ @ @, dpoG @ @ @PH  @ @ @ @d %{; @ @ @ @FZ @ @ @ @% h( @ @ @ @47҂ @ @ @(Y@@Cގ @ @ @/  @ @ @ @@Jv @ @ @ @@} @ @ @ @JP2#@ @ @ @ ho @ @ @ P @ @ @ P_@@C}#- @ @ @ @4  @ @ @ @iA @ @ @, dpoG @ @ @PH  @ @ @ @d %{; @ @ @ @M @0ua̙a֬YaȑaԧK/]‰'X}+s1ղ M9z?pߐ!C:ƍW&O"@@ =G?s/=P;>UW]5;6am  jqwx~wLu4$@ 4GG/L4)L6-< :vi0xg?oK ;A;Rv!p ''u|ԨQkݶ W^ lAx'8cù[- @]ʞc`q^9& @ʞ_}pgs9'k=r3&L0!l="ZA` ]vY\I'<̺.3n4 @@&9ё"޺2ni[lQcWH@\rI)3Kyꩧnvq0{~#8/oh2D>:!we;H(s=ӟToO? ?vapϒD'PgB]3 @w\ NM0Cl _ҭ+"а@馛!^~.']i¶n[YJ|%~W?OC' @ʜ{>?}喫|^".i^׿V WR2ZR9: y.K.d+x6r $?*)Ǡ;K`BW nj-_:n_SI@hhvd&0wܰw"{nJ4j*.JS\FZHD\A"@@ =GqaaÆ~$iSL~&L>?: _nje@st\&6k֬6lSYQ''3f_ A mO;pu J#F+"צxwL H`H?aAַJO<A16}_vE@ tDGI 0gw|u'>x ,b;޼z Nױ,XoN ZB9;?dȐ;v<@]ˉ'ѬpѣwVX  Ьe(εX)mo@/ܾZkx G}t.ꑥτ;E_|m'zk{w]Z"@}1#J([ >uv<[)el;nDW^yeMƋqnA({K'L8ׯzU ~c9z|K/-) @Uʞ;n3<\"l>-᪫J#<~ @oW_}u8 )C=PLH[$0st+ϛ7J5|ʊmQng]) CxA"@@ 9GG;S@O~PWG?XbB#DO 4qZ5τhj 1{q= &)ST]?ᦛnw hQ -:.F]`\]!.:4 nƐ.{k;7jC(s7n\8þ[N#H4^!nx7 u h2{,i'>[E;{hjMzO"^fmlIe~&? @eM<FGǃǏ_Y!;+6nAQxZZ@@CK#@ W%6z뭵Uݖckkf_Ν8y*]vYXz饫u2hG2o|-οqoɩS.=S8.>0bĈBZA9vuF5̸ N.@68#C LC ]tQ4hPgUL#^$@@ ,X*y4$ !.  7Ї =ӺDvnq!C9$-*IOo:V#@st#qkiӦX9*H-a/P]O<qY/,#s1a 6Hz̗cGHX9(l VߋcoK/S @@N   P׿;av q' /J++? ^{mY{=TH 7>;⋅veBY$P=gΜۘ1c FUhW\{ u h'/O,\r P={+ j4@_ӧO/r|X Je[/-\߹>0k֬1 |WOy÷pV; OuQ}#]wglכor|04! оh߱wd"ޫ <8-#&OP0C<7>1("D 9Gw߃`_Wqڭ  B=G׮W6[qF1~PCI' Hߟ 9 @Ij_Z!CwܱK0C\g7[oux_80eʔx `C|2a7\sMz=^bSN Y}%qĉaРA:@sߵw8uYq ƫ:,첅z@st ݭ[ Q҆vOƭ7W<Ӫe|&4) @j~7C\%8M_W*[*w/;#zᥗ^i:U|+eh?[Nߘb2KxŽu+6`V̙3Cӟ4\uUa]vr"Fw߭V_xᅖ$j @(P]|UЩڥa ?إ^ZM97(-C-' c&pWgyp'pBX؀x> V @@ OWgqF8Ç)>t7v_2L0!}х{l~È# h m2.b??ᄏбT%\>Oc!%|ɕ/tϯ[o=#/gY>裝1O,C({;s{vi|'x]U @ʜi .NzÇPm 2l c#G ~B_c I @ r)p# 'xb]es9նs̩<~Z'C@ ꘨X\+%@B Yw呇.)IDAT~>~-X;2kܼ++;{NƧf͚ƌS}̤IY qr-W.VV|-Fv#Z @`qY `;蠃_ . uQ]U @ 'fi{sgquFӌ3_8n;CN!Wsm0>i_wyiUC241  G8Gm$VǵiԨQ K/tKݖyYg½W_=} _rٳw{ SM֛CmS潕n;%4ݱq>~bַ ؖbky@@ 7U$_.(d} 7T /O8 /Tqae @(P]|z8yҴKaV @ʞk[-LnZ[s;"p5k}CF e&47m  l}9G<8{i 7[],9sf4 @%"-.[{:bĈZn]w]brsO?]7\}=fR]zhnA /r-]װ[) @ʚ{cne]‹/Xhˇ8@$PjKO?{eYkHfO.c*-h'@@wq)n\nim2-.  >Z??ʽ-=}kSzW^yn^hfA 4&@)y4^@p~UVٙ7o^Zk: 6&Pzk+C%X"Kp W_}ukXԀ?\ @ƍ sk휝)JO:^#@`uL<Gm؆^MҬ]NДæ *EIK-THWOnOޜ?n1o1ZP @Za>I'el^ziX|Ż Ќst ; ;sCSN-G>R(+ @` b~qڇ/G;{+ݩ#@une*?p!5jT:cWH@f1t^͚5o$3soYq~ϯ|߬뮻v+݌-p( eQ} 'xbN=p駇AuyMI9z̘1Uўx*~Νf̘Q=>f> heVbʲ?jA _stw 7' mC cY@@C>^%@@ {ow}wi5XZכL<6?S*.߸(K8^tE$䗾e Њeѵv/QGU w@@; {zNg9[lΪN4P<.n!$ @]j,`_<1 2f9zayWSN9ZMEY^hر:C`p{\$@@>/RL#=m$-+1bD.Hz9g x`ɸb@ˋ@џg q+P;8˟gy  @eq^z{= i' @@f5Gg} W?1?.To~_Ԟ--  vmYgB&L~z*{駟.49#!)( @Ao/zzA?P@v9:>YW*K 'K vXӟTxѧ + @z?7߼P^@|&,l_Gs׻_p|Džo;ҰaúI( Zzx]9 Ġ3<еJî6=>G?QY;O.) @@eѓ'O_V\qŰ{S.ҿx@"@@+ =Gw]x!nԙwm&L67K o}h u he3gy.q3aa8&Пstָ\P^x!lf ?#6<@د}kaԨQ:G`PǏhr])QthM6 rHG?V[m/ӧ{キܹs ,[nxdmgB{E  em/[o~9 @` ʚk<ĉӪʒ1pam [oux'+Aj&MrvWE D;. ;cnQ (u,r(c}.?/\+{ŒK.x/K}\5->bh 3֮2q]MmWck|+I@C_:$PK/[X4 0eѵ믇O[o}nyo:C]) h5K/4ĭt} 70Z@|&,RLLʘ?=n!3fw!`ˉGWA@ HԸD):nܸ` wh123f!@@9eѵW7Rwmڗz,=:ħm5# hQg}˕y/@|&e%P-ntW~!4Hqe iK54渺*H` 8J+cx3o|\azlEX44,89GwpׇM7ݴ&պgz Ў?k]v~(3_.I  P@st >};σ?_2k-'d]&# 9sfx+㗶k <h1st !@ʞ0y0{0gΜˇcVK-TK4@ٟ dhy f 1^ Ze%-Q. @ Аj @ @ @ @Yr"a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@ @ @ @ @R < @ @ @ ,A' @ @ @ @T@@C!O @ @ @d! !a  @ @ @ @ Аj @ @ @ @Yhbt @ @ @H4 @ @ @ @@KIENDB`wkutils/man/wkb_meta.Rd0000644000176200001440000000335713774377120014632 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/meta.R \name{wkb_meta} \alias{wkb_meta} \alias{wkt_meta} \alias{wkt_streamer_meta} \alias{wk_geometry_type} \alias{wk_geometry_type_id} \title{Extract meta information} \usage{ wkb_meta(wkb, recursive = FALSE) wkt_meta(wkt, recursive = FALSE) wkt_streamer_meta(wkt, recursive = FALSE) wk_geometry_type(type_id) wk_geometry_type_id(type) } \arguments{ \item{wkb}{A \code{list()} of \code{\link[=raw]{raw()}} vectors, such as that returned by \code{sf::st_as_binary()}.} \item{recursive}{Pass \code{TRUE} to recurse into multi-geometries and collections to extract meta of sub-geometries} \item{wkt}{A character vector containing well-known text.} \item{type_id}{An integer version of the geometry type} \item{type}{A string version of the geometry type (e.g., point, linestring, polygon, multipoint, multilinestring, multipolygon, geometrycollection)} } \value{ A data.frame with columns: \itemize{ \item \code{feature_id}: The index of the top-level feature \item \code{nest_id}: The recursion level (if feature is a geometry collection) \item \code{part_id}: The part index (if nested within a multi-geometry or collection) \item \code{type_id}: The type identifier (see \code{\link[=wk_geometry_type]{wk_geometry_type()}}) \item \code{size}: For points and linestrings the number of points, for polygons the number of rings, and for mutlti-geometries and collection types, the number of child geometries. \item \code{srid}: The spatial reference identifier as an integer } } \description{ Extract meta information } \examples{ wkt_meta("POINT (30 10)") wkt_meta("GEOMETRYCOLLECTION (POINT (30 10))", recursive = FALSE) wkt_meta("GEOMETRYCOLLECTION (POINT (30 10))", recursive = TRUE) } wkutils/man/coords_point_translate_wkt.Rd0000644000176200001440000000500013774377120020470 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/coords-translate.R \name{coords_point_translate_wkt} \alias{coords_point_translate_wkt} \alias{coords_point_translate_wkb} \alias{coords_linestring_translate_wkt} \alias{coords_linestring_translate_wkb} \alias{coords_polygon_translate_wkt} \alias{coords_polygon_translate_wkb} \title{Parse coordinates into well-known formats} \usage{ coords_point_translate_wkt(x, y, z = NA, m = NA, precision = 16, trim = TRUE) coords_point_translate_wkb( x, y, z = NA, m = NA, endian = wk::wk_platform_endian(), buffer_size = 2048 ) coords_linestring_translate_wkt( x, y, z = NA, m = NA, feature_id = 1L, precision = 16, trim = TRUE ) coords_linestring_translate_wkb( x, y, z = NA, m = NA, feature_id = 1L, endian = wk::wk_platform_endian(), buffer_size = 2048 ) coords_polygon_translate_wkt( x, y, z = NA, m = NA, feature_id = 1L, ring_id = 1L, precision = 16, trim = TRUE ) coords_polygon_translate_wkb( x, y, z = NA, m = NA, feature_id = 1L, ring_id = 1L, endian = wk::wk_platform_endian(), buffer_size = 2048 ) } \arguments{ \item{x, y, z, m}{Vectors of coordinate values} \item{precision}{The rounding precision to use when writing (number of decimal places).} \item{trim}{Trim unnecessary zeroes in the output?} \item{endian}{For WKB writing, 0 for big endian, 1 for little endian. Defaults to \code{\link[wk:wkb_translate_wkt]{wk_platform_endian()}} (slightly faster).} \item{buffer_size}{For WKB writing, the initial buffer size to use for each feature, in bytes. This will be extended when needed, but if you are calling this repeatedly with huge geometries, setting this value to a larger number may result in less copying.} \item{feature_id, ring_id}{Vectors for which a change in sequential values indicates a new feature or ring. Use \code{\link[=factor]{factor()}} to convert from a character vector.} } \value{ \verb{*_translate_wkt()} returns a character vector of well-known text; \verb{*_translate_wkb()} returns a list of raw vectors. } \description{ These functions provide the reverse function of \code{\link[=wkt_coords]{wkt_coords()}} and company: they parse vectors of coordinate values into well-known formats. Polygon rings are automatically closed, as closed rings are assumed or required by many parsers. } \examples{ coords_point_translate_wkt(1:3, 2:4) coords_linestring_translate_wkt(1:5, 2:6, feature_id = c(1, 1, 1, 2, 2)) coords_polygon_translate_wkt(c(0, 10, 0), c(0, 0, 10)) } wkutils/man/wkt_plot.Rd0000644000176200001440000000262113774407312014672 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/plot.R \name{wkt_plot} \alias{wkt_plot} \alias{wkb_plot} \title{Plot well-known geometry vectors} \usage{ wkt_plot( x, ..., asp = 1, bbox = NULL, xlab = "", ylab = "", rule = "evenodd", add = FALSE ) wkb_plot( x, ..., asp = 1, bbox = NULL, xlab = "", ylab = "", rule = "evenodd", add = FALSE ) } \arguments{ \item{x}{A \code{\link[=wkt]{wkt()}} or \code{\link[=wkb]{wkb()}} vector.} \item{...}{Passed to plotting functions for features: \code{\link[graphics:points]{graphics::points()}} for point and multipoint geometries, \code{\link[graphics:lines]{graphics::lines()}} for linestring and multilinestring geometries, and \code{\link[graphics:polypath]{graphics::polypath()}} for polygon and multipolygon geometries.} \item{asp, xlab, ylab}{Passed to \code{\link[graphics:plot.default]{graphics::plot()}}} \item{bbox}{The limits of the plot in the form returned by \code{\link[=wkt_ranges]{wkt_ranges()}}.} \item{rule}{The rule to use for filling polygons (see \code{\link[graphics:polypath]{graphics::polypath()}})} \item{add}{Should a new plot be created, or should \code{x} be added to the existing plot?} } \value{ \code{x}, invisibly } \description{ These plot functions are intended to help debug geometry vectors, and are not intended to be high-performance. } \examples{ wkt_plot("POINT (30 10)") } wkutils/DESCRIPTION0000644000176200001440000000223113777065112013471 0ustar liggesusersPackage: wkutils Title: Utilities for Well-Known Geometry Vectors Version: 0.1.1 Authors@R: person(given = "Dewey", family = "Dunnington", role = c("aut", "cre"), email = "dewey@fishandwhistle.net", comment = c(ORCID = "0000-0002-9415-4582")) Description: Provides extra utilities for well-known formats in the 'wk' package that are outside the scope of that package. Utilities to parse coordinates from data frames, plot well-known geometry vectors, extract meta information from well-known geometry vectors, and calculate bounding boxes are provided. License: MIT + file LICENSE Encoding: UTF-8 LazyData: true RoxygenNote: 7.1.1 Imports: wk (>= 0.3.1), Rcpp, tibble, vctrs LinkingTo: wk, Rcpp Suggests: testthat URL: https://paleolimbot.github.io/wkutils/, https://github.com/paleolimbot/wkutils BugReports: https://github.com/paleolimbot/wkutils/issues NeedsCompilation: yes Packaged: 2021-01-04 12:34:45 UTC; dewey Author: Dewey Dunnington [aut, cre] () Maintainer: Dewey Dunnington Repository: CRAN Date/Publication: 2021-01-11 15:10:02 UTC wkutils/tests/0000755000176200001440000000000013677637517013144 5ustar liggesuserswkutils/tests/testthat/0000755000176200001440000000000013777065112014767 5ustar liggesuserswkutils/tests/testthat/test-grob.R0000644000176200001440000000705213774376746017043 0ustar liggesusers test_that("wkt_grob() works", { expect_is(wkt_grob(character(0)), "gTree") expect_is(wkt_grob("POINT EMPTY"), "gTree") grob_points <- wkt_grob( c("POINT (0.1 0.1)", "POINT (0.9 0.9)"), pch = c(1, 16), col = c("black", "red"), default.units = "npc" ) expect_is(grob_points, "points") expect_equal(grob_points$pch, c(1, 16)) expect_equal(grob_points$gp$col, c("black", "red")) # EMPTY items should be recycled along but not included in grob grob_points_with_empty <- wkt_grob( c("GEOMETRYCOLLECTION EMPTY", "POINT (0.1 0.1)", "POINT (0.9 0.9)"), pch = c(3, 1, 16), col = c("magenta", "black", "red"), default.units = "npc" ) expect_is(grob_points_with_empty, "points") expect_equal(grob_points_with_empty$pch, c(1, 16)) expect_equal(grob_points_with_empty$gp$col, c("black", "red")) # MULTIPOINT has to be handled slightly differently grob_multipoint <- wkt_grob( c("MULTIPOINT EMPTY", "GEOMETRYCOLLECTION EMPTY", "MULTIPOINT ((0.1 0.1), (0.2 0.1))", "POINT (0.5 0.6)"), col = c("magenta", "magenta", "black", "green"), default.units = "npc" ) expect_is(grob_multipoint, "points") expect_identical(grob_multipoint$gp$col, c("black", "black", "green")) grob_lines <- wkt_grob( c("LINESTRING (0.1 0.1, 0.9 0.9)", "LINESTRING (0.1 0.9, 0.9 0.1)"), col = c("black", "red"), default.units = "npc" ) expect_is(grob_lines, "polyline") expect_equal(grob_lines$gp$col, c("black", "red")) # multilines are handled slightly differently because polylineGrob has no # pathId argument grob_multiline <- wkt_grob( c( "MULTILINESTRING ((0.1 0.1, 0.9 0.9), (0.9 0.1, 0.1 0.9))", "MULTILINESTRING ((0.5 0.5, 0.5 1))" ), col = c("green", "blue"), default.units = "npc" ) expect_is(grob_multiline, "polyline") expect_equal(grob_multiline$gp$col, c("green", "green", "blue")) grob_poly <- wkt_grob( c("POLYGON ((0.1 0.1, 0.9 0.1, 0.9 0.9, 0.1 0.9, 0.1 0.1))"), fill = "grey90", default.units = "npc" ) expect_is(grob_poly, "pathgrob") expect_equal(grob_poly$gp$fill, "grey90") grob_mixed <- wkt_grob( c("POLYGON ((0.1 0.1, 0.9 0.1, 0.9 0.9, 0.1 0.9, 0.1 0.1))", "POINT (0.5 0.5)"), col = c("blue", "green"), default.units = "npc" ) expect_is(grob_mixed, "gTree") expect_length(grob_mixed$children, 2) expect_is(grob_mixed$children[[1]], "pathgrob") expect_identical(grob_mixed$children[[1]]$gp$col, "blue") expect_is(grob_mixed$children[[2]], "points") expect_identical(grob_mixed$children[[2]]$gp$col, "green") grob_nested_point <- wkt_grob( c( "GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0.2 0.2))))", "LINESTRING EMPTY", "POINT (0.5 0.5)", "GEOMETRYCOLLECTION (POINT (0.7 0.7))" ), col = c("magenta", "black", "cyan", "red"), default.units = "npc" ) expect_is(grob_nested_point, "points") expect_identical(grob_nested_point$gp$col, c("magenta", "cyan", "red")) grid::grid.newpage() grid::grid.draw(grob_points) grid::grid.draw(grob_points_with_empty) grid::grid.draw(grob_multipoint) grid::grid.draw(grob_lines) grid::grid.draw(grob_multiline) grid::grid.draw(grob_poly) grid::grid.draw(grob_mixed) grid::grid.draw(grob_nested_point) }) test_that("wkb_grob() works", { grob_points <- wkb_grob( as_wkb(c("POINT (0.1 0.1)", "POINT (0.9 0.9)")), pch = c(1, 16), col = c("black", "red"), default.units = "npc" ) expect_is(grob_points, "points") expect_equal(grob_points$pch, c(1, 16)) expect_equal(grob_points$gp$col, c("black", "red")) }) wkutils/tests/testthat/test-coords-translate.R0000644000176200001440000000735313774376417021375 0ustar liggesusers test_that("coords_*_translate_wkt() works", { # point expect_identical(coords_point_translate_wkt(double(), double()), character(0)) expect_identical(coords_point_translate_wkt(NA, NA), "POINT EMPTY") expect_identical( coords_point_translate_wkt(1:3, 2:4), c("POINT (1 2)", "POINT (2 3)", "POINT (3 4)") ) expect_identical( coords_point_translate_wkt(1:3, 2:4, 3:5), c("POINT Z (1 2 3)", "POINT Z (2 3 4)", "POINT Z (3 4 5)") ) expect_identical( coords_point_translate_wkt(1:3, 2:4, NA, 3:5), c("POINT M (1 2 3)", "POINT M (2 3 4)", "POINT M (3 4 5)") ) expect_identical( coords_point_translate_wkt(1:3, 2:4, 3:5, 4:6), c("POINT ZM (1 2 3 4)", "POINT ZM (2 3 4 5)", "POINT ZM (3 4 5 6)") ) # linestring expect_identical(coords_linestring_translate_wkt(double(), double()), character(0)) expect_identical( coords_linestring_translate_wkt(1:3, 2:4), "LINESTRING (1 2, 2 3, 3 4)" ) expect_identical( coords_linestring_translate_wkt(1:3, 2:4, 3:5), "LINESTRING Z (1 2 3, 2 3 4, 3 4 5)" ) expect_identical( coords_linestring_translate_wkt(1:3, 2:4, NA, 3:5), "LINESTRING M (1 2 3, 2 3 4, 3 4 5)" ) expect_identical( coords_linestring_translate_wkt(1:3, 2:4, 3:5, 4:6), "LINESTRING ZM (1 2 3 4, 2 3 4 5, 3 4 5 6)" ) expect_identical( coords_linestring_translate_wkt(1:5, 2:6, feature_id = c(1, 1, 1, 2, 2)), c("LINESTRING (1 2, 2 3, 3 4)", "LINESTRING (4 5, 5 6)") ) # polygon expect_identical(coords_polygon_translate_wkt(double(), double()), character(0)) expect_identical( coords_polygon_translate_wkt(c(0, 10, 0), c(0, 0, 10)), "POLYGON ((0 0, 10 0, 0 10, 0 0))" ) expect_identical( coords_polygon_translate_wkt(c(0, 10, 0, 0), c(0, 0, 10, 0)), "POLYGON ((0 0, 10 0, 0 10, 0 0))" ) expect_identical( coords_polygon_translate_wkt( c(20, 10, 10, 30, 45, 30, 20, 20), c(35, 30, 10, 5, 20, 20, 15, 25), ring_id = c(1, 1, 1, 1, 1, 2, 2, 2) ), "POLYGON ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))" ) expect_identical( coords_polygon_translate_wkt( c(20, 10, 10, 30, 45, 30, 20, 20, 40, 20, 45), c(35, 30, 10, 5, 20, 20, 15, 25, 40, 45, 30), feature_id = c(rep(1, 8), rep(2, 3)), ring_id = c(1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1) ), c( "POLYGON ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))", "POLYGON ((40 40, 20 45, 45 30, 40 40))" ) ) expect_identical( coords_polygon_translate_wkt( c(20, 10, 10, 30, 45, 30, 20, 20, 40, 20, 45), c(35, 30, 10, 5, 20, 20, 15, 25, 40, 45, 30), feature_id = c(rep(1, 8), rep(2, 3)), # new ring should be detected on new feature_id ring_id = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2) ), c( "POLYGON ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))", "POLYGON ((40 40, 20 45, 45 30, 40 40))" ) ) }) test_that("coords_*_translate_wkb() works", { expect_identical( coords_point_translate_wkb(1:3, 2:4), wkt_translate_wkb(c("POINT (1 2)", "POINT (2 3)", "POINT (3 4)")) ) expect_identical( coords_linestring_translate_wkb(1:5, 2:6, feature_id = c(1, 1, 1, 2, 2)), wkt_translate_wkb(c("LINESTRING (1 2, 2 3, 3 4)", "LINESTRING (4 5, 5 6)")) ) expect_identical( coords_polygon_translate_wkb( c(20, 10, 10, 30, 45, 30, 20, 20, 40, 20, 45), c(35, 30, 10, 5, 20, 20, 15, 25, 40, 45, 30), feature_id = c(rep(1, 8), rep(2, 3)), ring_id = c(1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1) ), wkt_translate_wkb( c( "POLYGON ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))", "POLYGON ((40 40, 20 45, 45 30, 40 40))" ) ) ) }) wkutils/tests/testthat/test-finite.R0000644000176200001440000000224013774376712017353 0ustar liggesusers test_that("wkt_has_missing() / wkt_is_finite() works", { expect_identical(wkt_has_missing(character(0)), logical(0)) expect_false(wkt_has_missing("POINT EMPTY")) expect_false(wkt_has_missing("POINT (0 1)")) expect_true(wkt_has_missing("POINT (nan nan)")) expect_false(wkt_has_missing("POINT (inf inf)")) expect_true(wkt_is_finite("POINT EMPTY")) expect_true(wkt_is_finite("POINT (0 1)")) expect_false(wkt_is_finite("POINT (nan nan)")) expect_false(wkt_is_finite("POINT (inf inf)")) }) test_that("wkb_has_missing() / wkb_is_finite() works", { expect_identical(wkb_has_missing(list()), logical(0)) # WKB can't do empty point without missing coords expect_false(wkb_has_missing(as_wkb("LINESTRING EMPTY"))) expect_false(wkb_has_missing(as_wkb("POINT (0 1)"))) expect_true(wkb_has_missing(as_wkb("POINT (nan nan)"))) expect_false(wkb_has_missing(as_wkb("POINT (inf inf)"))) expect_identical(wkb_is_finite(list()), logical(0)) expect_true(wkb_is_finite(as_wkb("LINESTRING EMPTY"))) expect_true(wkb_is_finite(as_wkb("POINT (0 1)"))) expect_false(wkb_is_finite(as_wkb("POINT (nan nan)"))) expect_false(wkb_is_finite(as_wkb("POINT (inf inf)"))) }) wkutils/tests/testthat/test-meta.R0000644000176200001440000000717313774376776017047 0ustar liggesusers test_that("wkb_meta() works", { expect_identical( wkb_meta(wkt_translate_wkb("POINT (30 10)")), tibble::tibble( feature_id = 1L, part_id = 1L, type_id = 1L, size = 1L, srid = NA_integer_, has_z = FALSE, has_m = FALSE ) ) }) test_that("wkt_meta() works", { expect_identical( wkt_meta("POINT (30 10)"), tibble::tibble( feature_id = 1L, part_id = 1L, type_id = 1L, size = 1L, srid = NA_integer_, has_z = FALSE, has_m = FALSE ) ) }) test_that("wkt_streamer_meta() works", { # point expect_identical( wkt_streamer_meta("POINT (30 10)"), tibble::tibble( feature_id = 1L, part_id = 1L, type_id = 1L, size = NA_integer_, srid = NA_integer_, has_z = FALSE, has_m = FALSE ) ) # multipoint expect_identical( wkt_streamer_meta("MULTIPOINT ((30 10))", recursive = FALSE), tibble::tibble( feature_id = 1L, part_id = 1L, type_id = 4L, size = NA_integer_, srid = NA_integer_, has_z = FALSE, has_m = FALSE ) ) # multipoint recursive expect_identical( wkt_streamer_meta("MULTIPOINT ((30 10))", recursive = TRUE), tibble::tibble( feature_id = c(1L, 1L), part_id = c(1L, 2L), type_id = c(4L, 1L), size = c(NA_integer_, NA_integer_), srid = c(NA_integer_, NA_integer_), has_z = c(FALSE, FALSE), has_m = c(FALSE, FALSE) ) ) # collection expect_identical( wkt_streamer_meta("GEOMETRYCOLLECTION (POINT (30 10))", recursive = FALSE), tibble::tibble( feature_id = 1L, part_id = 1L, type_id = 7L, size = NA_integer_, srid = NA_integer_, has_z = FALSE, has_m = FALSE ) ) # collection recursive expect_identical( wkt_streamer_meta(c("GEOMETRYCOLLECTION (POINT (30 10))", NA), recursive = TRUE), tibble::tibble( feature_id = c(1L, 1L, 2L), part_id = c(1L, 2L, NA_integer_), type_id = c(7L, 1L, NA_integer_), size = c(NA_integer_, NA_integer_, NA_integer_), srid = c(NA_integer_, NA_integer_, NA_integer_), has_z = c(FALSE, FALSE, NA), has_m = c(FALSE, FALSE, NA) ) ) }) test_that("wkt_streamer_meta() works with NULLs", { expect_identical( wkt_streamer_meta(NA), tibble::tibble( feature_id = 1L, part_id = NA_integer_, type_id = NA_integer_, size = NA_integer_, srid = NA_integer_, has_z = NA, has_m = NA ) ) }) test_that("wkt_meta() counts coordinates when NULLs are present", { expect_identical( wkt_meta(c("LINESTRING (20 20, 0 0)", NA)), tibble::tibble( feature_id = c(1L, 2L), part_id = c(1L, NA_integer_), type_id = c(2L, NA_integer_), size = c(2L, NA_integer_), srid = c(NA_integer_, NA_integer_), has_z = c(FALSE, NA), has_m = c(FALSE, NA) ) ) }) test_that("wkt_streamer_meta() returns SRIDs if present", { expect_identical( wkt_streamer_meta("SRID=33;POINT (30 10)"), tibble::tibble( feature_id = 1L, part_id = 1L, type_id = 1L, size = NA_integer_, srid = 33L, has_z = FALSE, has_m = FALSE ) ) }) test_that("wkt_streamer_meta() fails on parse error", { expect_error(wkt_streamer_meta("NOPE"), class = "WKParseException") }) test_that("geometry type converters work", { types_str <- c( "point", "linestring", "polygon", "multipoint", "multilinestring", "multipolygon", "geometrycollection" ) expect_identical(wk_geometry_type_id(types_str), 1:7) expect_identical(wk_geometry_type(7:1), rev(types_str)) }) wkutils/tests/testthat/test-debug.R0000644000176200001440000000215613774376626017175 0ustar liggesusers test_that("debugger works on wkb", { point <- as.raw(c(0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40)) expect_output(wkb_debug(list(point)), "POINT \\[1\\]") point_bad_type <- point point_bad_type[2] <- as.raw(0xff) expect_output(wkb_debug(list(point_bad_type)), "Invalid integer geometry type") }) test_that("debugger works on wkt stream", { expect_output(wkt_streamer_debug("LINESTRING (30 10, 0 0, 0 1)"), "LINESTRING") expect_output(wkt_streamer_debug("POLYGON ((30 10, 0 0, 0 1, 30 10))"), "POLYGON") expect_output(wkt_streamer_debug("MULTIPOINT (30 10, 0 0)"), "MULTIPOINT") expect_output(wkt_streamer_debug("MULTIPOINT ((30 10), (0 0))"), "MULTIPOINT") }) test_that("debugger works on wkt", { expect_output(wkt_debug("LINESTRING (30 10, 0 0, 0 1)"), "LINESTRING") expect_output(wkt_debug("POLYGON ((30 10, 0 0, 0 1, 30 10))"), "POLYGON") expect_output(wkt_debug("MULTIPOINT (30 10, 0 0)"), "MULTIPOINT") expect_output(wkt_debug("MULTIPOINT ((30 10), (0 0))"), "MULTIPOINT") }) wkutils/tests/testthat/test-draw.R0000644000176200001440000000121113774376644017033 0ustar liggesusers test_that("wkt_draw_* works", { x <- "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))" expect_identical(wkt_plot_new(x, main = "wkt_draw_*()"), x) expect_identical(wkt_draw_polypath(x, col = "grey90"), x) expect_identical(wkt_draw_lines(x, col = "red"), x) expect_identical(wkt_draw_points(x, pch = 16), x) }) test_that("wkb_draw_* works", { x <- wkt_translate_wkb("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))") expect_identical(wkb_plot_new(x, main = "wkb_draw_*()"), x) expect_identical(wkb_draw_polypath(x, col = "grey90"), x) expect_identical(wkb_draw_lines(x, col = "red"), x) expect_identical(wkb_draw_points(x, pch = 16), x) }) wkutils/tests/testthat/test-unnest.R0000644000176200001440000000643513774377107017422 0ustar liggesusers test_that("wk*_unnest() works", { expect_identical(wkt_unnest(NA_character_), structure(NA_character_, lengths = 1L)) expect_identical( wkt_unnest( "GEOMETRYCOLLECTION(MULTIPOINT (30 10, 10 10), LINESTRING (0 0, 1 1), GEOMETRYCOLLECTION EMPTY)", keep_multi = FALSE, keep_empty = FALSE, max_depth = 2 ), structure(c("POINT (30 10)", "POINT (10 10)", "LINESTRING (0 0, 1 1)"), lengths = 3L) ) expect_identical( wkt_unnest( "GEOMETRYCOLLECTION(MULTIPOINT (30 10, 10 10), LINESTRING (0 0, 1 1), GEOMETRYCOLLECTION EMPTY)", keep_multi = FALSE, keep_empty = TRUE, max_depth = 2 ), structure( c("POINT (30 10)", "POINT (10 10)", "LINESTRING (0 0, 1 1)", "GEOMETRYCOLLECTION EMPTY"), lengths = 4L ) ) expect_identical( wkt_unnest( "SRID=12;GEOMETRYCOLLECTION(MULTIPOINT (30 10, 10 10), LINESTRING (0 0, 1 1), GEOMETRYCOLLECTION EMPTY)", keep_multi = FALSE, max_depth = 2 ), structure( c("SRID=12;POINT (30 10)", "SRID=12;POINT (10 10)", "SRID=12;LINESTRING (0 0, 1 1)"), lengths = 3L ) ) expect_identical( wkb_unnest( as_wkb("GEOMETRYCOLLECTION(MULTIPOINT (30 10, 10 10), LINESTRING (0 0, 1 1), GEOMETRYCOLLECTION EMPTY)"), keep_multi = TRUE, max_depth = 2, keep_empty = FALSE ), structure( wkt_translate_wkb(c("MULTIPOINT ((30 10), (10 10))", "LINESTRING (0 0, 1 1)")), lengths = 2L ) ) expect_identical( wkb_unnest( as_wkb("GEOMETRYCOLLECTION(MULTIPOINT (30 10, 10 10), LINESTRING (0 0, 1 1), GEOMETRYCOLLECTION EMPTY)"), keep_multi = TRUE, max_depth = 2, keep_empty = TRUE ), structure( wkt_translate_wkb(c("MULTIPOINT ((30 10), (10 10))", "LINESTRING (0 0, 1 1)", "GEOMETRYCOLLECTION EMPTY")), lengths = 3L ) ) expect_identical( wkb_unnest( as_wkb("GEOMETRYCOLLECTION(MULTIPOINT (30 10, 10 10), LINESTRING (0 0, 1 1), GEOMETRYCOLLECTION EMPTY)"), keep_multi = FALSE, max_depth = 2, keep_empty = FALSE ), structure( wkt_translate_wkb(c("POINT (30 10)", "POINT (10 10)", "LINESTRING (0 0, 1 1)")), lengths = 3L ) ) }) test_that("wk*_unnest(max_depth) is respected", { expect_identical( wkt_unnest( "GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 1))))", max_depth = 0 ), structure( "GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 1))))", lengths = 1L ) ) expect_identical( wkt_unnest( "GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 1))))", max_depth = 1 ), structure("GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 1)))", lengths = 1L) ) expect_identical( wkt_unnest( "GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 1))))", max_depth = 2 ), structure("GEOMETRYCOLLECTION (POINT (0 1))", lengths = 1L) ) expect_identical( wkt_unnest( "GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 1))))", max_depth = 3 ), structure("POINT (0 1)", lengths = 1L) ) expect_identical( wkt_unnest( "SRID=21;GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 1))))", max_depth = 3 ), structure("SRID=21;POINT (0 1)", lengths = 1L) ) }) wkutils/tests/testthat/test-filters.R0000644000176200001440000000551313774377161017552 0ustar liggesusers test_that("wkt_set_srid works", { expect_identical(wkt_set_srid(character(0), 1234), character(0)) expect_identical(wkt_set_srid(NA_character_, 1234), NA_character_) expect_identical( wkt_set_srid("POINT (30 10)", 1234), "SRID=1234;POINT (30 10)" ) expect_identical( wkt_set_srid("POINT (30 10)", c(1234, 5678)), c("SRID=1234;POINT (30 10)", "SRID=5678;POINT (30 10)") ) expect_identical( wkt_set_srid(c("POINT (30 10)", "POINT (10 10)"), c(1234, 5678)), c("SRID=1234;POINT (30 10)", "SRID=5678;POINT (10 10)") ) expect_identical( wkt_set_srid(c("POINT (30 10)", "POINT (10 10)"), c(1234)), c("SRID=1234;POINT (30 10)", "SRID=1234;POINT (10 10)") ) }) test_that("wkb_set_srid works", { expect_identical(wkb_set_srid(list(), 1234), list()) expect_identical(wkb_set_srid(list(NULL), 1234), list(NULL)) expect_identical( wkb_set_srid(as_wkb("POINT (30 10)"), 1234), unclass(as_wkb("SRID=1234;POINT (30 10)")) ) }) test_that("wkt_set_z works", { expect_identical(wkt_set_z(character(0), 1234), character(0)) expect_identical(wkt_set_z(NA_character_, 1234), NA_character_) expect_identical( wkt_set_z("POINT (30 10)", 1234), "POINT Z (30 10 1234)" ) expect_identical( wkt_set_z("POINT (30 10)", c(1234, 5678)), c("POINT Z (30 10 1234)", "POINT Z (30 10 5678)") ) expect_identical( wkt_set_z(c("POINT (30 10)", "POINT (10 10)"), c(1234, 5678)), c("POINT Z (30 10 1234)", "POINT Z (10 10 5678)") ) expect_identical( wkt_set_z(c("POINT (30 10)", "POINT (10 10)"), c(1234)), c("POINT Z (30 10 1234)", "POINT Z (10 10 1234)") ) }) test_that("wkb_set_z works", { expect_identical(wkb_set_z(list(), 1234), list()) expect_identical(wkb_set_z(list(NULL), 1234), list(NULL)) expect_identical( wkb_set_z(as_wkb("POINT (30 10)"), 1234), unclass(as_wkb("POINT Z (30 10 1234)")) ) }) test_that("wkt_transform works", { tx <- 3 ty <- 7 t_test_trans <- matrix(c(1, 0, 0, 0, 1, 0, tx, ty, 1), ncol = 3) t_test_rotate45 <- matrix( c(0.707106781186548, -0.707106781186547, 0, 0.707106781186547, 0.707106781186548, 0, 0, 0, 1), ncol = 3 ) expect_identical(wkt_transform("POINT (0 0)", t_test_trans), "POINT (3 7)") expect_identical(wkt_transform("POINT (0 0)", t_test_rotate45), "POINT (0 0)") expect_identical( wkt_transform(sprintf("POINT (%s 0)", sqrt(2)), t_test_rotate45, precision = 10), "POINT (1 -1)" ) expect_identical( wkt_transform( sprintf("POINT (%s 0)", sqrt(2)), t_test_trans %*% t_test_rotate45, precision = 10 ), "POINT (4 6)" ) }) test_that("wkb_transform works", { tx <- 3 ty <- 7 t_test_trans <- matrix(c(1, 0, 0, 0, 1, 0, tx, ty, 1), ncol = 3) expect_identical( wkb_transform(as_wkb("POINT (0 0)"), t_test_trans), wkt_translate_wkb("POINT (3 7)") ) }) wkutils/tests/testthat/test-coords.R0000644000176200001440000000571013774376502017370 0ustar liggesusers test_that("wkb_coords() works", { # point wkb <- wkt_translate_wkb("POINT (30 10)") expect_identical( wkb_coords(wkb), tibble::tibble( feature_id = 1L, part_id = 1L, ring_id = 0L, x = 30, y = 10, z = NA_real_, m = NA_real_ ) ) }) test_that("wkt_coords() works", { # point expect_identical( wkt_coords("POINT (30 10)"), tibble::tibble( feature_id = 1L, part_id = 1L, ring_id = 0L, x = 30, y = 10, z = NA_real_, m = NA_real_ ) ) # point zm expect_identical( wkt_coords("POINT ZM (30 10 1 2)"), tibble::tibble( feature_id = 1L, part_id = 1L, ring_id = 0L, x = 30, y = 10, z = 1, m = 2 ) ) # linestring expect_identical( wkt_coords("LINESTRING (30 10, 20 11)"), tibble::tibble( feature_id = c(1L, 1L), part_id = c(1L, 1L), ring_id = c(0L, 0L), x = c(30, 20), y = c(10, 11), z = c(NA_real_, NA_real_), m = c(NA_real_, NA_real_) ) ) # polygon expect_identical( wkt_coords("POLYGON ((30 10, 20 11, 0 0, 30 10))"), tibble::tibble( feature_id = c(1L, 1L, 1L, 1L), part_id = c(1L, 1L, 1L, 1L), ring_id = c(1L, 1L, 1L, 1L), x = c(30, 20, 0, 30), y = c(10, 11, 0, 10), z = c(NA_real_, NA_real_, NA_real_, NA_real_), m = c(NA_real_, NA_real_, NA_real_, NA_real_) ) ) # multipoint expect_identical( wkt_coords("MULTIPOINT ((30 10), (20 11))"), tibble::tibble( feature_id = c(1L, 1L), part_id = c(2L, 3L), ring_id = c(0L, 0L), x = c(30, 20), y = c(10, 11), z = c(NA_real_, NA_real_), m = c(NA_real_, NA_real_) ) ) # collection # point expect_identical( wkt_coords("GEOMETRYCOLLECTION (POINT (30 10))"), tibble::tibble( feature_id = 1L, part_id = 2L, ring_id = 0L, x = 30, y = 10, z = NA_real_, m = NA_real_ ) ) }) test_that("sep_na works as intended", { holes <- c( "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 4 2, 2 2))", "POLYGON ((11 11, 20 11, 20 20, 11 20, 11 11), (12 12, 12 14, 14 14, 14 12, 12 12))" ) expect_identical( wkt_coords(holes, sep_na = FALSE)$ring_id, c(rep(1L, 5), rep(2L, 5), rep(3L, 5), rep(4L, 5)) ) expect_identical( wkt_coords(holes, sep_na = TRUE)$ring_id, c(rep(1L, 5), NA, rep(2L, 5), NA, rep(3L, 5), NA, rep(4L, 5)) ) # multi-geometries should only separate between simple geoms expect_identical( wkt_coords("MULTIPOINT ((30 10), (0 0))", sep_na = TRUE)$part_id, c(2L, NA, 3L) ) # null geoms at the start shouldn't insert a separator expect_identical( wkt_coords(c(NA, "POINT (30 10)"), sep_na = TRUE)$feature_id, 2L ) # empty geoms at the start shouldn't insert a separator expect_identical( wkt_coords(c("POINT EMPTY", "POINT (30 10)"), sep_na = TRUE)$feature_id, 2L ) }) wkutils/tests/testthat/Rplots.pdf0000644000176200001440000002526713774412136016760 0ustar liggesusers%PDF-1.4 %ρ\r 1 0 obj << /CreationDate (D:20210103150045) /ModDate (D:20210103150045) /Title (R Graphics Output) /Producer (R 4.0.3) /Creator (R) >> endobj 2 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 7 0 obj << /Type /Page /Parent 3 0 R /Contents 8 0 R /Resources 4 0 R >> endobj 8 0 obj << /Length 688 /Filter /FlateDecode >> stream xUMk1ﯘYtMh R/: V3Yc/.}7'&._Jk }1ZxmnAcc`~𡉨PC"]肼W;e+Mټ +V/_ԜHsM Wp4J{N,mf6 |Ay?N.NjZtFuNhج 'w6*0i}^ist'(rtF;ost'Xy˼p/;#Ft Sg<p2EZ1[kr"Nh^u ͊]n?Y1=l(сo0=t]1DD}´uSȃy (x{,G)b&l_/_i`pq[._Ң `:7 R`/|:m|qchQnc%@ƈӽ Z OVyq NQSq3IqqeE#m4];/y-㖍ѥId678\ndzyMb~ub/B&M'CDD ed@E>B/X+}ZRl)xiD 4Ct"Z+55īd Uendstream endobj 9 0 obj << /Type /Page /Parent 3 0 R /Contents 10 0 R /Resources 4 0 R >> endobj 10 0 obj << /Length 694 /Filter /FlateDecode >> stream xUMk1WTǬV&C =$!4Nsp@C~jơ`oߌf4ka6 B5"E;՝J:.hc M]߂eaeK|Q 5a caCWvkhwޕ]'xo'(t|7bEYiIrݫG43U6/_mafڨa6]\2ߑz27Kdn<=սvlVuq9a9Ȩ e 69,a/ +a`I.Bh%̝ }A͵+8h∃>:LA#Myᰓ&c>]x!GҸb:覐Yy]:#scN}*to9'q\ox^jзV9}7/ 㖍Ib6ߏQ7Q8Tp WvMDD>B&ϦċBJedw@D?B8WꮵAM=RS1ۋ*ةHUj$ R2h|endstream endobj 11 0 obj << /Type /Page /Parent 3 0 R /Contents 12 0 R /Resources 4 0 R >> endobj 12 0 obj << /Length 554 /Filter /FlateDecode >> stream xT=1 +\S|dZ@: cKD".ڂO2~N9NHHD3g9=yz^>}Cw'stZL?Ot_73D)Qv69l)VEi0_1vLUU x*;'ZYrD%,ֵ(.Dh)V1$e$L_hQr ?-6j{(shEJ&% %2pBgGi[RG˱UUsZPI/:VP` 4"6l YNG݌a]j7 ^=͗jMisˡ߳ʹ*83vWB/4v|Pc/gƶLat0or;RcJR/(CWeط_{ ԮB n$'uOe9G3"vK:1תh@MEN:ٰ )& @fBdOendstream endobj 13 0 obj << /Type /Page /Parent 3 0 R /Contents 14 0 R /Resources 4 0 R >> endobj 14 0 obj << /Length 930 /Filter /FlateDecode >> stream xWMo1 ϯq&J ]ⴀjR'վϱm ZSӍzP!kʃ׳Un]}Vi8~z65\}9_ӗʨok8S:$\, ŨmBĔ vV v,hpd[*~w|~xg &CprA2nzש6yd밆y 3ǁ!g^4lnf/̠nq vuL# v;{n|(uX6^B0:^e[5+Ͻvf6:;CO>xۮY=C伀켩BGWjp$Nm jN:&AQrO:%>xկa1`Aկl-kC!#BAb}@hWc\EȄKntbtź}Pnw"wX^%g< %%^C=}f>oyӉ\v]Q$Wjޔް's`Q&޾L؃Pݼė+;$+jt7)/yӻ7.|ߙ#4JQGPňYxOoye{Կ /  4R6LvxЍ ٟՍbE7:!x,PʙK0w)j٢*h縨Rrմ U0ӽ/HXn<,/<۱8|Ҧm5O&O.bWLc.M&Y\Wܓf Fendstream endobj 15 0 obj << /Type /Page /Parent 3 0 R /Contents 16 0 R /Resources 4 0 R >> endobj 16 0 obj << /Length 930 /Filter /FlateDecode >> stream xWMo1 ϯq&J ]ⴀjR'վϱm ZSӍzP!kʃ׳Un]}Vi8~z65\}9_ӗʨok8S:$\, ŨmBĔ vV v,hpd[*~w|~xg &CprA2nzש6yd밆y 3ǁ!g^4lnf/̠nq vuL# v;{n|(uX6^B0:^e[5+Ͻvf6:;CO>xۮY=C伀켩BGWjp$Nm jN:&AQrO:%>xկa1`Aկl-kC!#BAb}@hWc\EȄKntbtź}Pnw"wX^%g< %%^C=}f>oyӉ\v]Q$Wjޔް's`Q&޾L؃Pݼė+;$+jt7)/yӻ7.|ߙ#4JQGPňYxOoye{Կ /  4R6LvxЍ ٟՍbE7:!x,PʙK0w)j٢*h縨Rrմ U0ӽ/HXn<,/<۱8|Ҧm5O&O.bWLc.M&Y\Wܓf Fendstream endobj 17 0 obj << /Type /Page /Parent 3 0 R /Contents 18 0 R /Resources 4 0 R >> endobj 18 0 obj << /Length 930 /Filter /FlateDecode >> stream xWMo1 ϯq&J ]ⴀjR'վϱm ZSӍzP!kʃ׳Un]}Vi8~z65\}9_ӗʨok8S:$\, ŨmBĔ vV v,hpd[*~w|~xg &CprA2nzש6yd밆y 3ǁ!g^4lnf/̠nq vuL# v;{n|(uX6^B0:^e[5+Ͻvf6:;CO>xۮY=C伀켩BGWjp$Nm jN:&AQrO:%>xկa1`Aկl-kC!#BAb}@hWc\EȄKntbtź}Pnw"wX^%g< %%^C=}f>oyӉ\v]Q$Wjޔް's`Q&޾L؃Pݼė+;$+jt7)/yӻ7.|ߙ#4JQGPňYxOoye{Կ /  4R6LvxЍ ٟՍbE7:!x,PʙK0w)j٢*h縨Rrմ U0ӽ/HXn<,/<۱8|Ҧm5O&O.bWLc.M&Y\Wܓf Fendstream endobj 19 0 obj << /Type /Page /Parent 3 0 R /Contents 20 0 R /Resources 4 0 R >> endobj 20 0 obj << /Length 930 /Filter /FlateDecode >> stream xWMo1 ϯq&J ]ⴀjR'վϱm ZSӍzP!kʃ׳Un]}Vi8~z65\}9_ӗʨok8S:$\, ŨmBĔ vV v,hpd[*~w|~xg &CprA2nzש6yd밆y 3ǁ!g^4lnf/̠nq vuL# v;{n|(uX6^B0:^e[5+Ͻvf6:;CO>xۮY=C伀켩BGWjp$Nm jN:&AQrO:%>xկa1`Aկl-kC!#BAb}@hWc\EȄKntbtź}Pnw"wX^%g< %%^C=}f>oyӉ\v]Q$Wjޔް's`Q&޾L؃Pݼė+;$+jt7)/yӻ7.|ߙ#4JQGPňYxOoye{Կ /  4R6LvxЍ ٟՍbE7:!x,PʙK0w)j٢*h縨Rrմ U0ӽ/HXn<,/<۱8|Ҧm5O&O.bWLc.M&Y\Wܓf Fendstream endobj 3 0 obj << /Type /Pages /Kids [ 7 0 R 9 0 R 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R ] /Count 7 /MediaBox [0 0 504 504] >> endobj 4 0 obj << /ProcSet [/PDF /Text] /Font <> /ExtGState << >> /ColorSpace << /sRGB 5 0 R >> >> endobj 5 0 obj [/ICCBased 6 0 R] endobj 6 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~endstream endobj 21 0 obj << /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [ 45/minus 96/quoteleft 144/dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron /space] >> endobj 22 0 obj << /Type /Font /Subtype /Type1 /Name /F2 /BaseFont /Helvetica /Encoding 21 0 R >> endobj 23 0 obj << /Type /Font /Subtype /Type1 /Name /F3 /BaseFont /Helvetica-Bold /Encoding 21 0 R >> endobj xref 0 24 0000000000 65535 f 0000000021 00000 n 0000000163 00000 n 0000006942 00000 n 0000007066 00000 n 0000007189 00000 n 0000007222 00000 n 0000000212 00000 n 0000000292 00000 n 0000001051 00000 n 0000001132 00000 n 0000001898 00000 n 0000001980 00000 n 0000002606 00000 n 0000002688 00000 n 0000003690 00000 n 0000003772 00000 n 0000004774 00000 n 0000004856 00000 n 0000005858 00000 n 0000005940 00000 n 0000009917 00000 n 0000010175 00000 n 0000010273 00000 n trailer << /Size 24 /Info 1 0 R /Root 2 0 R >> startxref 10376 %%EOF wkutils/tests/testthat/test-plot.R0000644000176200001440000000213713774402775017057 0ustar liggesusers test_that("wk*_plot works", { example_wkt <- c( NA, "POINT (30 10)", "POINT EMPTY", "POINT Z (1 1 5)", "MULTIPOINT (10 40, 40 30, 20 20, 30 10)", "MULTIPOINT EMPTY", "POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))", "POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10), (20 30, 35 35, 30 20, 20 30))", "POLYGON EMPTY", "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))", "MULTILINESTRING ((10 10, 20 20, 10 40), (40 40, 30 30, 40 20, 30 10))", "MULTILINESTRING EMPTY", "MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))", "MULTIPOLYGON ( ((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20)) )", "MULTIPOLYGON EMPTY", "GEOMETRYCOLLECTION ( POINT (40 10), LINESTRING (10 10, 20 20, 10 40), POLYGON ((40 40, 20 45, 45 30, 40 40)) )", "GEOMETRYCOLLECTION EMPTY" ) wkt_plot(as_wkt(example_wkt)) wkb_plot(as_wkb(example_wkt)) wkt_plot(unclass(as_wkt(example_wkt))) wkb_plot(unclass(as_wkb(example_wkt))) expect_true(TRUE) }) wkutils/tests/testthat/test-ranges.R0000644000176200001440000000520713774377042017357 0ustar liggesusers test_that("wkt_ranges() works", { expect_identical( wkt_ranges(c("POINT (1 2)", "POINT (5 6)")), tibble::tibble( xmin = 1, ymin = 2, zmin = Inf, mmin = Inf, xmax = 5, ymax = 6, zmax = -Inf, mmax = -Inf ) ) expect_identical( wkt_ranges(c("POINT Z (1 2 3)", "POINT (5 6)")), tibble::tibble( xmin = 1, ymin = 2, zmin = 3, mmin = Inf, xmax = 5, ymax = 6, zmax = 3, mmax = -Inf ) ) expect_identical( wkt_ranges(c("POINT ZM (1 2 3 4)", "POINT (5 6)")), tibble::tibble( xmin = 1, ymin = 2, zmin = 3, mmin = 4, xmax = 5, ymax = 6, zmax = 3, mmax = 4 ) ) expect_identical( wkt_ranges(c("POINT (1 nan)", "POINT (5 6)")), tibble::tibble( xmin = 1, ymin = NA_real_, zmin = Inf, mmin = Inf, xmax = 5, ymax = NA_real_, zmax = -Inf, mmax = -Inf ) ) expect_identical( wkt_ranges(c("POINT (1 nan)", "POINT (5 6)"), na.rm = TRUE), tibble::tibble( xmin = 1, ymin = 6, zmin = Inf, mmin = Inf, xmax = 5, ymax = 6, zmax = -Inf, mmax = -Inf ) ) expect_identical( wkt_ranges(c("POINT (1 inf)", "POINT (5 6)")), tibble::tibble( xmin = 1, ymin = 6, zmin = Inf, mmin = Inf, xmax = 5, ymax = Inf, zmax = -Inf, mmax = -Inf ) ) expect_identical( wkt_ranges(c("POINT (1 inf)", "POINT (5 6)"), finite = TRUE), tibble::tibble( xmin = 1, ymin = 6, zmin = Inf, mmin = Inf, xmax = 5, ymax = 6, zmax = -Inf, mmax = -Inf ) ) expect_identical( wkt_ranges(c("POINT (nan nan)", "POINT (nan nan)"), finite = TRUE), wkt_ranges(character(0)) ) expect_identical( wkt_ranges(c("POINT (1 2)", "POINT (nan nan)"), finite = TRUE), wkt_ranges("POINT (1 2)") ) }) test_that("wkb_ranges() works", { expect_identical( wkb_ranges(wkt_translate_wkb(c("POINT (1 2)", "POINT (5 6)"))), tibble::tibble( xmin = 1, ymin = 2, zmin = Inf, mmin = Inf, xmax = 5, ymax = 6, zmax = -Inf, mmax = -Inf ) ) }) test_that("wkt_feature_ranges() works", { expect_identical( wkt_feature_ranges(c("POINT ZM (1 2 3 4)", "POINT ZM (5 6 7 8)")), tibble::tibble( xmin = c(1, 5), ymin = c(2, 6), zmin = c(3, 7), mmin = c(4, 8), xmax = c(1, 5), ymax = c(2, 6), zmax = c(3, 7), mmax = c(4, 8) ) ) }) test_that("wkb_feature_ranges() works", { expect_identical( wkb_feature_ranges(wkt_translate_wkb(c("POINT ZM (1 2 3 4)", "POINT ZM (5 6 7 8)"))), tibble::tibble( xmin = c(1, 5), ymin = c(2, 6), zmin = c(3, 7), mmin = c(4, 8), xmax = c(1, 5), ymax = c(2, 6), zmax = c(3, 7), mmax = c(4, 8) ) ) }) wkutils/tests/testthat.R0000644000176200001440000000007213677637517015126 0ustar liggesuserslibrary(testthat) library(wkutils) test_check("wkutils") wkutils/src/0000755000176200001440000000000013774605545012563 5ustar liggesuserswkutils/src/coords.cpp0000644000176200001440000001044513774401503014550 0ustar liggesusers #include "wk/geometry-handler.hpp" #include "wk/wkb-reader.hpp" #include "wk/wkt-streamer.hpp" #include #include "wk/rcpp-io.hpp" using namespace Rcpp; class WKCoordinateCounter: public WKGeometryHandler { public: size_t nCoordinates; bool sepNA; bool firstGeom; WKCoordinateCounter(bool sepNA): nCoordinates(0), sepNA(sepNA), firstGeom(true) {} void nextGeometryStart(const WKGeometryMeta& meta, uint32_t partId) { bool isSimple = meta.geometryType == WKGeometryType::Point || meta.geometryType == WKGeometryType::LineString || meta.geometryType == WKGeometryType::Polygon; this->nCoordinates += this->sepNA && !this->firstGeom && (meta.size > 0) && isSimple; if ((meta.size > 0) && isSimple) { this->firstGeom = false; } } void nextLinearRingStart(const WKGeometryMeta& meta, uint32_t size, uint32_t ringId) { this->nCoordinates += this->sepNA && ringId > 0; } void nextCoordinate(const WKGeometryMeta& meta, const WKCoord& coord, uint32_t coordId) { this->nCoordinates++; } }; class WKCoordinateAssembler: public WKGeometryHandler { public: IntegerVector featureId; IntegerVector partId; IntegerVector ringId; NumericVector x; NumericVector y; NumericVector z; NumericVector m; WKCoordinateAssembler(size_t nCoordinates, bool sepNA): featureId(nCoordinates), partId(nCoordinates), ringId(nCoordinates), x(nCoordinates), y(nCoordinates), z(nCoordinates), m(nCoordinates), i(0), lastFeatureId(0), lastPartId(0), lastRingId(0), sepNA(sepNA), firstGeom(true) {} List assembleCoordinates() { return List::create( _["feature_id"] = this->featureId, _["part_id"] = this->partId, _["ring_id"] = this->ringId, _["x"] = this->x, _["y"] = this->y, _["z"] = this->z, _["m"] = this->m ); } protected: R_xlen_t i; int lastFeatureId; int lastPartId; int lastRingId; bool sepNA; bool firstGeom; void nextFeatureStart(size_t featureId) { this->lastFeatureId = featureId + 1; } void nextGeometryStart(const WKGeometryMeta& meta, uint32_t partId) { this->lastPartId = this->lastPartId + 1; bool isSimple = meta.geometryType == WKGeometryType::Point || meta.geometryType == WKGeometryType::LineString || meta.geometryType == WKGeometryType::Polygon; if (this->sepNA && !this->firstGeom && (meta.size > 0) && isSimple) { this->writeNASep(); } if ((meta.size > 0) && isSimple) { this->firstGeom = false; } } void nextLinearRingStart(const WKGeometryMeta& meta, uint32_t size, uint32_t ringId) { this->lastRingId = this->lastRingId + 1; if (this->sepNA && ringId > 0) { this->writeNASep(); } } void nextCoordinate(const WKGeometryMeta& meta, const WKCoord& coord, uint32_t coordId) { this->featureId[i] = this->lastFeatureId; this->partId[i] = this->lastPartId; this->ringId[i] = this->lastRingId; this->x[i] = coord.x; this->y[i] = coord.y; if (coord.hasZ) { this->z[i] = coord.z; } else { this->z[i] = NA_REAL; } if (coord.hasM) { this->m[i] = coord.m; } else { this->m[i] = NA_REAL; } this->i++; } void writeNASep() { this->featureId[i] = NA_INTEGER; this->partId[i] = NA_INTEGER; this->ringId[i] = NA_INTEGER; this->x[i] = NA_REAL; this->y[i] = NA_REAL; this->z[i] = NA_REAL; this->m[i] = NA_REAL; this->i++; } }; List cpp_coords_base(WKReader& reader, bool sepNA) { WKCoordinateCounter counter(sepNA); reader.setHandler(&counter); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } reader.reset(); WKCoordinateAssembler assembler(counter.nCoordinates, sepNA); reader.setHandler(&assembler); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } return assembler.assembleCoordinates(); } // [[Rcpp::export]] List cpp_coords_wkb(List wkb, bool sepNA) { WKRawVectorListProvider provider(wkb); WKBReader reader(provider); return cpp_coords_base(reader, sepNA); } // [[Rcpp::export]] List cpp_coords_wkt(CharacterVector wkt, bool sepNA) { WKCharacterVectorProvider provider(wkt); WKTStreamer reader(provider); return cpp_coords_base(reader, sepNA); } wkutils/src/ranges.cpp0000644000176200001440000001553413774401440014542 0ustar liggesusers #include "wk/geometry-handler.hpp" #include "wk/wkb-reader.hpp" #include "wk/wkt-streamer.hpp" #include #include "wk/rcpp-io.hpp" using namespace Rcpp; // I'm sure there's a more compact way to do this double min_reg(double x1i, double x2i) { bool x1NA = NumericVector::is_na(x1i); bool x2NA = NumericVector::is_na(x2i); if (x1NA || x2NA) { return NA_REAL; } else { return std::min(x1i, x2i); } } double max_reg(double x1i, double x2i) { bool x1NA = NumericVector::is_na(x1i); bool x2NA = NumericVector::is_na(x2i); if (x1NA || x2NA) { return NA_REAL; } else { return std::max(x1i, x2i); } } double min_na_rm(double x1i, double x2i) { bool x1NA = NumericVector::is_na(x1i); bool x2NA = NumericVector::is_na(x2i); if (x1NA && x2NA) { return R_PosInf; } else if (x1NA) { return x2i; } else if (x2NA) { return x1i; } else { return std::min(x1i, x2i); } } double max_na_rm(double x1i, double x2i) { bool x1NA = NumericVector::is_na(x1i); bool x2NA = NumericVector::is_na(x2i); if (x1NA && x2NA) { return R_NegInf; } else if (x1NA) { return x2i; } else if (x2NA) { return x1i; } else { return std::max(x1i, x2i); } } double min_finite(double x1i, double x2i) { bool x1NA = NumericVector::is_na(x1i) || x1i == R_NegInf || x1i == R_PosInf; bool x2NA = NumericVector::is_na(x2i) || x2i == R_NegInf || x2i == R_PosInf; if (x1NA && x2NA) { return R_PosInf; } else if (x1NA) { return x2i; } else if (x2NA) { return x1i; } else { return std::min(x1i, x2i); } } double max_finite(double x1i, double x2i) { bool x1NA = NumericVector::is_na(x1i) || x1i == R_NegInf || x1i == R_PosInf; bool x2NA = NumericVector::is_na(x2i) || x2i == R_NegInf || x2i == R_PosInf; if (x1NA && x2NA) { return R_NegInf; } else if (x1NA) { return x2i; } else if (x2NA) { return x1i; } else { return std::max(x1i, x2i); } } class WKRangeCalculator: public WKGeometryHandler { public: double xmin; double ymin; double zmin; double mmin; double xmax; double ymax; double zmax; double mmax; WKRangeCalculator(bool naRm, bool onlyFinite): naRm(naRm), onlyFinite(onlyFinite) { this->reset(); } void reset() { this->xmin = R_PosInf; this->ymin = R_PosInf; this->zmin = R_PosInf; this->mmin = R_PosInf; this->xmax = R_NegInf; this->ymax = R_NegInf; this->zmax = R_NegInf; this->mmax = R_NegInf; } void nextCoordinate(const WKGeometryMeta& meta, const WKCoord& coord, uint32_t coordId) { if (this->onlyFinite) { this->xmin = min_finite(this->xmin, coord.x); this->ymin = min_finite(this->ymin, coord.y); if (coord.hasZ) this->zmin = min_finite(this->zmin, coord.z); if (coord.hasM) this->mmin = min_finite(this->mmin, coord.m); this->xmax = max_finite(this->xmax, coord.x); this->ymax = max_finite(this->ymax, coord.y); if (coord.hasZ) this->zmax = max_finite(this->zmax, coord.z); if (coord.hasM) this->mmax = max_finite(this->zmin, coord.m); } else if (this->naRm) { this->xmin = min_na_rm(this->xmin, coord.x); this->ymin = min_na_rm(this->ymin, coord.y); if (coord.hasZ) this->zmin = min_na_rm(this->zmin, coord.z); if (coord.hasM) this->mmin = min_na_rm(this->mmin, coord.m); this->xmax = max_na_rm(this->xmax, coord.x); this->ymax = max_na_rm(this->ymax, coord.y); if (coord.hasZ) this->zmax = max_na_rm(this->zmax, coord.z); if (coord.hasM) this->mmax = max_na_rm(this->zmin, coord.m); } else { this->xmin = min_reg(this->xmin, coord.x); this->ymin = min_reg(this->ymin, coord.y); if (coord.hasZ) this->zmin = min_reg(this->zmin, coord.z); if (coord.hasM) this->mmin = min_reg(this->mmin, coord.m); this->xmax = max_reg(this->xmax, coord.x); this->ymax = max_reg(this->ymax, coord.y); if (coord.hasZ) this->zmax = max_reg(this->zmax, coord.z); if (coord.hasM) this->mmax = max_reg(this->zmin, coord.m); } } private: bool naRm; bool onlyFinite; }; class WKFeatureRangeCalculator: public WKRangeCalculator { public: NumericVector vxmin; NumericVector vymin; NumericVector vzmin; NumericVector vmmin; NumericVector vxmax; NumericVector vymax; NumericVector vzmax; NumericVector vmmax; WKFeatureRangeCalculator(size_t size, bool naRm, bool onlyFinite): WKRangeCalculator(naRm, onlyFinite), vxmin(size), vymin(size), vzmin(size), vmmin(size), vxmax(size), vymax(size), vzmax(size), vmmax(size) {} void nextFeatureStart(size_t featureId) { this->reset(); } void nextFeatureEnd(size_t featureId) { this->vxmin[featureId] = this->xmin; this->vymin[featureId] = this->ymin; this->vzmin[featureId] = this->zmin; this->vmmin[featureId] = this->mmin; this->vxmax[featureId] = this->xmax; this->vymax[featureId] = this->ymax; this->vzmax[featureId] = this->zmax; this->vmmax[featureId] = this->mmin; } }; List cpp_ranges_base(WKReader& reader, bool naRm, bool onlyFinite) { WKRangeCalculator ranges(naRm, onlyFinite); reader.setHandler(&ranges); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } return List::create( _["xmin"] = ranges.xmin, _["ymin"] = ranges.ymin, _["zmin"] = ranges.zmin, _["mmin"] = ranges.mmin, _["xmax"] = ranges.xmax, _["ymax"] = ranges.ymax, _["zmax"] = ranges.zmax, _["mmax"] = ranges.mmax ); } // [[Rcpp::export]] List cpp_ranges_wkb(List wkb, bool naRm, bool onlyFinite) { WKRawVectorListProvider provider(wkb); WKBReader reader(provider); return cpp_ranges_base(reader, naRm, onlyFinite); } // [[Rcpp::export]] List cpp_ranges_wkt(CharacterVector wkt, bool naRm, bool onlyFinite) { WKCharacterVectorProvider provider(wkt); WKTStreamer reader(provider); return cpp_ranges_base(reader, naRm, onlyFinite); } List cpp_feature_ranges_base(WKReader& reader, bool naRm, bool onlyFinite) { WKFeatureRangeCalculator ranges(reader.nFeatures(), naRm, onlyFinite); reader.setHandler(&ranges); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } return List::create( _["xmin"] = ranges.vxmin, _["ymin"] = ranges.vymin, _["zmin"] = ranges.vzmin, _["mmin"] = ranges.vmmin, _["xmax"] = ranges.vxmax, _["ymax"] = ranges.vymax, _["zmax"] = ranges.vzmax, _["mmax"] = ranges.vmmax ); } // [[Rcpp::export]] List cpp_feature_ranges_wkb(List wkb, bool naRm, bool onlyFinite) { WKRawVectorListProvider provider(wkb); WKBReader reader(provider); return cpp_feature_ranges_base(reader, naRm, onlyFinite); } // [[Rcpp::export]] List cpp_feature_ranges_wkt(CharacterVector wkt, bool naRm, bool onlyFinite) { WKCharacterVectorProvider provider(wkt); WKTStreamer reader(provider); return cpp_feature_ranges_base(reader, naRm, onlyFinite); } wkutils/src/finite.cpp0000644000176200001440000000606113774401745014544 0ustar liggesusers #include "wk/wkt-reader.hpp" #include "wk/wkb-reader.hpp" #include #include "wk/rcpp-io.hpp" using namespace Rcpp; class WKHasSomethingException: public WKParseException { public: const static int CODE_HAS_SOMETHING = 2948379; WKHasSomethingException(): WKParseException(CODE_HAS_SOMETHING) {} }; class WKHasSomethingHandler: public WKGeometryHandler { public: LogicalVector output; WKHasSomethingHandler(size_t size): output(size) {} void nextFeatureStart(size_t featureId) { this->featureIsNull = false; } void nextNull(size_t featureId) { this->featureIsNull = true; } void nextFeatureEnd(size_t featureId) { if (this->featureIsNull) { this->output[featureId] = NA_LOGICAL; } else { this->output[featureId] = false; } } bool nextError(WKParseException& error, size_t featureId) { if (error.code() == WKHasSomethingException::CODE_HAS_SOMETHING) { this->output[featureId] = true; return true; } else { return false; } } private: bool featureIsNull; }; class WKHasNonFiniteHandler: public WKHasSomethingHandler { public: WKHasNonFiniteHandler(size_t size): WKHasSomethingHandler(size) {} void nextCoordinate(const WKGeometryMeta& meta, const WKCoord& coord, uint32_t coordId) { for (size_t i = 0; i < coord.size(); i++) { double value = coord[i]; if (!std::isfinite(value)) { throw WKHasSomethingException(); } } } }; class WKHasMissingHandler: public WKHasSomethingHandler { public: WKHasMissingHandler(size_t size): WKHasSomethingHandler(size) {} void nextCoordinate(const WKGeometryMeta& meta, const WKCoord& coord, uint32_t coordId) { for (size_t i = 0; i < coord.size(); i++) { double value = coord[i]; if (std::isnan(value)) { throw WKHasSomethingException(); } } } }; LogicalVector has_non_finite_base(WKReader& reader) { WKHasNonFiniteHandler handler(reader.nFeatures()); reader.setHandler(&handler); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } return handler.output; } // [[Rcpp::export]] LogicalVector cpp_wkt_has_non_finite(CharacterVector wkt) { WKCharacterVectorProvider provider(wkt); WKTReader reader(provider); return has_non_finite_base(reader); } // [[Rcpp::export]] LogicalVector cpp_wkb_has_non_finite(List wkb) { WKRawVectorListProvider provider(wkb); WKBReader reader(provider); return has_non_finite_base(reader); } LogicalVector has_missing_base(WKReader& reader) { WKHasMissingHandler handler(reader.nFeatures()); reader.setHandler(&handler); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } return handler.output; } // [[Rcpp::export]] LogicalVector cpp_wkt_has_missing(CharacterVector wkt) { WKCharacterVectorProvider provider(wkt); WKTReader reader(provider); return has_missing_base(reader); } // [[Rcpp::export]] LogicalVector cpp_wkb_has_missing(List wkb) { WKRawVectorListProvider provider(wkb); WKBReader reader(provider); return has_missing_base(reader); } wkutils/src/meta.cpp0000644000176200001440000000722113774401445014210 0ustar liggesusers #include #include "wk/geometry-handler.hpp" #include "wk/wkb-reader.hpp" #include "wk/wkt-reader.hpp" #include "wk/wkt-streamer.hpp" #include #include "wk/rcpp-io.hpp" using namespace Rcpp; class WKMetaCounter: public WKGeometryHandler { public: size_t nMeta; WKMetaCounter(): nMeta(0) {} void nextGeometryStart(const WKGeometryMeta& meta, uint32_t partId) { this->nMeta++; } void nextNull(size_t featureId) { this->nMeta++; } }; class WKMetaAssembler: public WKGeometryHandler { public: IntegerVector featureId; IntegerVector partId; IntegerVector typeId; IntegerVector size; IntegerVector srid; LogicalVector hasZ; LogicalVector hasM; WKMetaAssembler(bool recursive, size_t nMeta): featureId(nMeta), partId(nMeta), typeId(nMeta), size(nMeta), srid(nMeta), hasZ(nMeta), hasM(nMeta), i(0), lastPartId(0), recursive(recursive) {} List assembleMeta() { return List::create( _["feature_id"] = this->featureId, _["part_id"] = this->partId, _["type_id"] = this->typeId, _["size"] = this->size, _["srid"] = this->srid, _["has_z"] = this->hasZ, _["has_m"] = this->hasM ); } void nextFeatureStart(size_t featureId) { this->lastFeatureId = featureId + 1; this->featureHasMeta = false; } void nextNull(size_t featureId) { this->featureId[i] = this->lastFeatureId; this->partId[i] = NA_INTEGER; this->typeId[i] = NA_INTEGER; this->size[i] = NA_INTEGER; this->srid[i] = NA_INTEGER; this->hasZ[i] = NA_LOGICAL; this->hasM[i] = NA_LOGICAL; this->i++; } void nextGeometryStart(const WKGeometryMeta& meta, uint32_t partId) { if (!this->recursive && this->featureHasMeta) { return; } this->lastPartId = this->lastPartId + 1; this->featureId[i] = this->lastFeatureId; this->partId[i] = this->lastPartId; this->typeId[i] = meta.geometryType; if (meta.hasSize) { this->size[i] = meta.size; } else { this->size[i] = NA_INTEGER; } if (meta.hasSRID) { this->srid[i] = meta.srid; } else { this->srid[i] = NA_INTEGER; } this->hasZ[i] = meta.hasZ; this->hasM[i] = meta.hasM; this->i++; if (!this->recursive) { // much faster than using exceptions, with the added bonus that // we get the number of coordinates as well! this->featureHasMeta = true; } } protected: R_xlen_t i; int lastFeatureId; int lastPartId; bool recursive; bool featureHasMeta; }; List cpp_meta_base(WKReader& reader, bool recursive) { size_t nMeta; if (recursive) { WKMetaCounter counter; reader.setHandler(&counter); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } nMeta = counter.nMeta; reader.reset(); } else { nMeta = reader.nFeatures(); } WKMetaAssembler assembler(recursive, nMeta); reader.setHandler(&assembler); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } return assembler.assembleMeta(); } // [[Rcpp::export]] List cpp_meta_wkb(List wkb, bool recursive) { WKRawVectorListProvider provider(wkb); WKBReader reader(provider); return cpp_meta_base(reader, recursive); } // [[Rcpp::export]] List cpp_meta_wkt(CharacterVector wkt, bool recursive) { WKCharacterVectorProvider provider(wkt); WKTReader reader(provider); return cpp_meta_base(reader, recursive); } // [[Rcpp::export]] List cpp_meta_wkt_streamer(CharacterVector wkt, bool recursive) { WKCharacterVectorProvider provider(wkt); WKTStreamer reader(provider); return cpp_meta_base(reader, recursive); } wkutils/src/coords-translate.cpp0000644000176200001440000000557513774401204016551 0ustar liggesusers #include #include "wk/rcpp-translate.hpp" #include "wk/rcpp-coord-reader.hpp" using namespace Rcpp; // [[Rcpp::export]] CharacterVector cpp_coords_point_translate_wkt(NumericVector x, NumericVector y, NumericVector z, NumericVector m, int precision, bool trim) { WKRcppPointCoordProvider provider(x, y, z, m); WKRcppPointCoordReader reader(provider); return wk::rcpp_translate_wkt(reader, precision, trim); } // [[Rcpp::export]] List cpp_coords_point_translate_wkb(NumericVector x, NumericVector y, NumericVector z, NumericVector m, int endian, int bufferSize) { WKRcppPointCoordProvider provider(x, y, z, m); WKRcppPointCoordReader reader(provider); return wk::rcpp_translate_wkb(reader, endian, bufferSize); } // [[Rcpp::export]] CharacterVector cpp_coords_linestring_translate_wkt(NumericVector x, NumericVector y, NumericVector z, NumericVector m, IntegerVector featureId, int precision, bool trim) { WKRcppLinestringCoordProvider provider(x, y, z, m, featureId); WKRcppLinestringCoordReader reader(provider); return wk::rcpp_translate_wkt(reader, precision, trim); } // [[Rcpp::export]] List cpp_coords_linestring_translate_wkb(NumericVector x, NumericVector y, NumericVector z, NumericVector m, IntegerVector featureId, int endian, int bufferSize) { WKRcppLinestringCoordProvider provider(x, y, z, m, featureId); WKRcppLinestringCoordReader reader(provider); return wk::rcpp_translate_wkb(reader, endian, bufferSize); } // [[Rcpp::export]] CharacterVector cpp_coords_polygon_translate_wkt(NumericVector x, NumericVector y, NumericVector z, NumericVector m, IntegerVector featureId, IntegerVector ringId, int precision, bool trim) { WKRcppPolygonCoordProvider provider(x, y, z, m, featureId, ringId); WKRcppPolygonCoordReader reader(provider); return wk::rcpp_translate_wkt(reader, precision, trim); } // [[Rcpp::export]] List cpp_coords_polygon_translate_wkb(NumericVector x, NumericVector y, NumericVector z, NumericVector m, IntegerVector featureId, IntegerVector ringId, int endian, int bufferSize) { WKRcppPolygonCoordProvider provider(x, y, z, m, featureId, ringId); WKRcppPolygonCoordReader reader(provider); return wk::rcpp_translate_wkb(reader, endian, bufferSize); } wkutils/src/Makevars0000644000176200001440000000001613706311733014240 0ustar liggesusersCXX_STD=CXX11 wkutils/src/debug.cpp0000644000176200001440000000154613774401515014352 0ustar liggesusers #include "wk/geometry-debug-handler.hpp" #include "wk/wkb-reader.hpp" #include "wk/wkt-reader.hpp" #include #include "wk/rcpp-io.hpp" using namespace Rcpp; void cpp_debug_base(WKReader& reader) { WKGeometryDebugHandler handler(Rcout); reader.setHandler(&handler); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } } // [[Rcpp::export]] void cpp_debug_wkb(List wkb) { WKRawVectorListProvider input(wkb); WKBReader reader(input); cpp_debug_base(reader); } // [[Rcpp::export]] void cpp_debug_wkt(CharacterVector input) { WKCharacterVectorProvider provider(input); WKTReader reader(provider); cpp_debug_base(reader); } // [[Rcpp::export]] void cpp_debug_wkt_streamer(CharacterVector input) { WKCharacterVectorProvider provider(input); WKTStreamer reader(provider); cpp_debug_base(reader); } wkutils/src/unnest.cpp0000644000176200001440000001364513774401426014604 0ustar liggesusers #include #include "wk/wkt-writer.hpp" #include "wk/wkt-reader.hpp" #include "wk/wkb-writer.hpp" #include "wk/wkb-reader.hpp" #include "wk/filter.hpp" #include #include "wk/rcpp-io.hpp" using namespace Rcpp; class WKUnnester: public WKMetaFilter { public: WKUnnester(WKGeometryHandler& handler, bool keepEmpty, bool keepMulti, int maxUnnestDepth = INT_MAX): WKMetaFilter(handler), newFeatureId(0), topLevelMetaId(0), keepEmpty(keepEmpty), maxUnnestDepth(maxUnnestDepth), unnestDepth(0) { if (keepMulti) { this->minUnnestType = WKGeometryType::GeometryCollection; } else { this->minUnnestType = WKGeometryType::MultiPoint; } } bool shouldUnnest(const WKGeometryMeta& meta, int unnestDepth) { if (unnestDepth >= this->maxUnnestDepth) { return false; } else if (this->keepEmpty && (meta.size == 0)) { return false; } else if (meta.geometryType >= this->minUnnestType) { return true; } else { return false; } } // at the start, the unnestDepth is correct bool shouldUnnestStart(const WKGeometryMeta& meta) { if (this->shouldUnnest(meta, this->unnestDepth)) { this->isUnnested.insert(meta.id()); return true; } else { return false; } } // at the end, just check if this meta was unnested bool shouldUnnestEnd(const WKGeometryMeta& meta) { return this->isUnnested.count(meta.id()) == 1; } WKGeometryMeta newGeometryMeta(const WKGeometryMeta& meta, uint32_t partId) { if (this->unnestDepth > 0) { WKGeometryMeta newMeta(meta); newMeta.hasSRID = this->newHasSrid; newMeta.srid = this->newSrid; return newMeta; } else { return meta; } } void nextFeatureStart(size_t featureId) { this->isUnnested.clear(); this->topLevelMetaId = 0; this->unnestDepth = 0; } void nextFeatureEnd(size_t featureId) { } void nextNull(size_t featureId) { this->handler.nextFeatureStart(this->newFeatureId); this->handler.nextNull(this->newFeatureId); this->handler.nextFeatureEnd(this->newFeatureId); this->newFeatureId++; } void nextGeometryStart(const WKGeometryMeta& meta, uint32_t partId) { if (this->shouldUnnestStart(meta)) { if (this->unnestDepth == 0) { this->newHasSrid = meta.hasSRID; this->newSrid = meta.srid; } this->unnestDepth++; return; } if (this->topLevelMetaId == 0) { this->topLevelMetaId = meta.id(); partId = WKReader::PART_ID_NONE; this->handler.nextFeatureStart(this->newFeatureId); } // takes care of meta updating WKMetaFilter::nextGeometryStart(meta, partId); } void nextCoordinate(const WKGeometryMeta& meta, const WKCoord& coord, uint32_t coordId) { this->handler.nextCoordinate(this->metaReplacement[meta.id()], coord, coordId); } void nextGeometryEnd(const WKGeometryMeta& meta, uint32_t partId) { if (this->shouldUnnestEnd(meta)) { this->isUnnested.erase(meta.id()); this->unnestDepth--; return; } if (meta.id() == this->topLevelMetaId) { this->handler.nextGeometryEnd(this->metaReplacement[meta.id()], WKReader::PART_ID_NONE); this->handler.nextFeatureEnd(this->newFeatureId); this->newFeatureId++; this->topLevelMetaId = 0; } else { this->handler.nextGeometryEnd(this->metaReplacement[meta.id()], partId); } // manually handled metaReplacement (no need for WKMetaFilter::nextGeometryEnd()) } private: size_t newFeatureId; uintptr_t topLevelMetaId; bool keepEmpty; int minUnnestType; int maxUnnestDepth; std::unordered_set isUnnested; int unnestDepth; bool newHasSrid; uint32_t newSrid; }; class WKUnnestedFeatureCounter: public WKGeometryHandler { public: size_t nNewFeatures; WKUnnestedFeatureCounter(): nNewFeatures(0) {} size_t reset() { size_t out = this->nNewFeatures; this->nNewFeatures = 0; return out; } void nextFeatureStart(size_t featureId) { this->nNewFeatures++; } }; IntegerVector unnest_count(WKReader& reader, bool keepEmpty, bool keepMulti, int maxUnnestDepth) { WKUnnestedFeatureCounter counter; WKUnnester unnester(counter, keepEmpty, keepMulti, maxUnnestDepth); reader.setHandler(&unnester); R_xlen_t featureId = 0; IntegerVector lengths(reader.nFeatures()); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); lengths[featureId] = counter.reset(); featureId++; } return lengths; } void unnest_do(WKReader& reader, WKWriter& writer, bool keepEmpty, bool keepMulti, int maxUnnestDepth) { WKUnnester unnester(writer, keepEmpty, keepMulti, maxUnnestDepth); reader.setHandler(&unnester); reader.reset(); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } } // [[Rcpp::export]] CharacterVector cpp_wkt_unnest(CharacterVector wkt, bool keepEmpty, bool keepMulti, int maxUnnestDepth) { WKCharacterVectorProvider provider(wkt); WKTReader reader(provider); IntegerVector lengths = unnest_count(reader, keepEmpty, keepMulti, maxUnnestDepth); size_t nGeometries = sum(lengths); WKCharacterVectorExporter exporter(nGeometries); exporter.setRoundingPrecision(16); exporter.setTrim(true); WKTWriter writer(exporter); unnest_do(reader, writer, keepEmpty, keepMulti, maxUnnestDepth); exporter.output.attr("lengths") = lengths; return exporter.output; } // [[Rcpp::export]] List cpp_wkb_unnest(List wkb, bool keepEmpty, bool keepMulti, int maxUnnestDepth, int endian) { WKRawVectorListProvider provider(wkb); WKBReader reader(provider); IntegerVector lengths = unnest_count(reader, keepEmpty, keepMulti, maxUnnestDepth); size_t nGeometries = sum(lengths); WKRawVectorListExporter exporter(nGeometries); WKBWriter writer(exporter); writer.setEndian(endian); unnest_do(reader, writer, keepEmpty, keepMulti, maxUnnestDepth); exporter.output.attr("lengths") = lengths; return exporter.output; } wkutils/src/RcppExports.cpp0000644000176200001440000005307313774401535015561 0ustar liggesusers// Generated by using Rcpp::compileAttributes() -> do not edit by hand // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 #include using namespace Rcpp; // cpp_coords_point_translate_wkt CharacterVector cpp_coords_point_translate_wkt(NumericVector x, NumericVector y, NumericVector z, NumericVector m, int precision, bool trim); RcppExport SEXP _wkutils_cpp_coords_point_translate_wkt(SEXP xSEXP, SEXP ySEXP, SEXP zSEXP, SEXP mSEXP, SEXP precisionSEXP, SEXP trimSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP); Rcpp::traits::input_parameter< NumericVector >::type y(ySEXP); Rcpp::traits::input_parameter< NumericVector >::type z(zSEXP); Rcpp::traits::input_parameter< NumericVector >::type m(mSEXP); Rcpp::traits::input_parameter< int >::type precision(precisionSEXP); Rcpp::traits::input_parameter< bool >::type trim(trimSEXP); rcpp_result_gen = Rcpp::wrap(cpp_coords_point_translate_wkt(x, y, z, m, precision, trim)); return rcpp_result_gen; END_RCPP } // cpp_coords_point_translate_wkb List cpp_coords_point_translate_wkb(NumericVector x, NumericVector y, NumericVector z, NumericVector m, int endian, int bufferSize); RcppExport SEXP _wkutils_cpp_coords_point_translate_wkb(SEXP xSEXP, SEXP ySEXP, SEXP zSEXP, SEXP mSEXP, SEXP endianSEXP, SEXP bufferSizeSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP); Rcpp::traits::input_parameter< NumericVector >::type y(ySEXP); Rcpp::traits::input_parameter< NumericVector >::type z(zSEXP); Rcpp::traits::input_parameter< NumericVector >::type m(mSEXP); Rcpp::traits::input_parameter< int >::type endian(endianSEXP); Rcpp::traits::input_parameter< int >::type bufferSize(bufferSizeSEXP); rcpp_result_gen = Rcpp::wrap(cpp_coords_point_translate_wkb(x, y, z, m, endian, bufferSize)); return rcpp_result_gen; END_RCPP } // cpp_coords_linestring_translate_wkt CharacterVector cpp_coords_linestring_translate_wkt(NumericVector x, NumericVector y, NumericVector z, NumericVector m, IntegerVector featureId, int precision, bool trim); RcppExport SEXP _wkutils_cpp_coords_linestring_translate_wkt(SEXP xSEXP, SEXP ySEXP, SEXP zSEXP, SEXP mSEXP, SEXP featureIdSEXP, SEXP precisionSEXP, SEXP trimSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP); Rcpp::traits::input_parameter< NumericVector >::type y(ySEXP); Rcpp::traits::input_parameter< NumericVector >::type z(zSEXP); Rcpp::traits::input_parameter< NumericVector >::type m(mSEXP); Rcpp::traits::input_parameter< IntegerVector >::type featureId(featureIdSEXP); Rcpp::traits::input_parameter< int >::type precision(precisionSEXP); Rcpp::traits::input_parameter< bool >::type trim(trimSEXP); rcpp_result_gen = Rcpp::wrap(cpp_coords_linestring_translate_wkt(x, y, z, m, featureId, precision, trim)); return rcpp_result_gen; END_RCPP } // cpp_coords_linestring_translate_wkb List cpp_coords_linestring_translate_wkb(NumericVector x, NumericVector y, NumericVector z, NumericVector m, IntegerVector featureId, int endian, int bufferSize); RcppExport SEXP _wkutils_cpp_coords_linestring_translate_wkb(SEXP xSEXP, SEXP ySEXP, SEXP zSEXP, SEXP mSEXP, SEXP featureIdSEXP, SEXP endianSEXP, SEXP bufferSizeSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP); Rcpp::traits::input_parameter< NumericVector >::type y(ySEXP); Rcpp::traits::input_parameter< NumericVector >::type z(zSEXP); Rcpp::traits::input_parameter< NumericVector >::type m(mSEXP); Rcpp::traits::input_parameter< IntegerVector >::type featureId(featureIdSEXP); Rcpp::traits::input_parameter< int >::type endian(endianSEXP); Rcpp::traits::input_parameter< int >::type bufferSize(bufferSizeSEXP); rcpp_result_gen = Rcpp::wrap(cpp_coords_linestring_translate_wkb(x, y, z, m, featureId, endian, bufferSize)); return rcpp_result_gen; END_RCPP } // cpp_coords_polygon_translate_wkt CharacterVector cpp_coords_polygon_translate_wkt(NumericVector x, NumericVector y, NumericVector z, NumericVector m, IntegerVector featureId, IntegerVector ringId, int precision, bool trim); RcppExport SEXP _wkutils_cpp_coords_polygon_translate_wkt(SEXP xSEXP, SEXP ySEXP, SEXP zSEXP, SEXP mSEXP, SEXP featureIdSEXP, SEXP ringIdSEXP, SEXP precisionSEXP, SEXP trimSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP); Rcpp::traits::input_parameter< NumericVector >::type y(ySEXP); Rcpp::traits::input_parameter< NumericVector >::type z(zSEXP); Rcpp::traits::input_parameter< NumericVector >::type m(mSEXP); Rcpp::traits::input_parameter< IntegerVector >::type featureId(featureIdSEXP); Rcpp::traits::input_parameter< IntegerVector >::type ringId(ringIdSEXP); Rcpp::traits::input_parameter< int >::type precision(precisionSEXP); Rcpp::traits::input_parameter< bool >::type trim(trimSEXP); rcpp_result_gen = Rcpp::wrap(cpp_coords_polygon_translate_wkt(x, y, z, m, featureId, ringId, precision, trim)); return rcpp_result_gen; END_RCPP } // cpp_coords_polygon_translate_wkb List cpp_coords_polygon_translate_wkb(NumericVector x, NumericVector y, NumericVector z, NumericVector m, IntegerVector featureId, IntegerVector ringId, int endian, int bufferSize); RcppExport SEXP _wkutils_cpp_coords_polygon_translate_wkb(SEXP xSEXP, SEXP ySEXP, SEXP zSEXP, SEXP mSEXP, SEXP featureIdSEXP, SEXP ringIdSEXP, SEXP endianSEXP, SEXP bufferSizeSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP); Rcpp::traits::input_parameter< NumericVector >::type y(ySEXP); Rcpp::traits::input_parameter< NumericVector >::type z(zSEXP); Rcpp::traits::input_parameter< NumericVector >::type m(mSEXP); Rcpp::traits::input_parameter< IntegerVector >::type featureId(featureIdSEXP); Rcpp::traits::input_parameter< IntegerVector >::type ringId(ringIdSEXP); Rcpp::traits::input_parameter< int >::type endian(endianSEXP); Rcpp::traits::input_parameter< int >::type bufferSize(bufferSizeSEXP); rcpp_result_gen = Rcpp::wrap(cpp_coords_polygon_translate_wkb(x, y, z, m, featureId, ringId, endian, bufferSize)); return rcpp_result_gen; END_RCPP } // cpp_coords_wkb List cpp_coords_wkb(List wkb, bool sepNA); RcppExport SEXP _wkutils_cpp_coords_wkb(SEXP wkbSEXP, SEXP sepNASEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< List >::type wkb(wkbSEXP); Rcpp::traits::input_parameter< bool >::type sepNA(sepNASEXP); rcpp_result_gen = Rcpp::wrap(cpp_coords_wkb(wkb, sepNA)); return rcpp_result_gen; END_RCPP } // cpp_coords_wkt List cpp_coords_wkt(CharacterVector wkt, bool sepNA); RcppExport SEXP _wkutils_cpp_coords_wkt(SEXP wktSEXP, SEXP sepNASEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP); Rcpp::traits::input_parameter< bool >::type sepNA(sepNASEXP); rcpp_result_gen = Rcpp::wrap(cpp_coords_wkt(wkt, sepNA)); return rcpp_result_gen; END_RCPP } // cpp_debug_wkb void cpp_debug_wkb(List wkb); RcppExport SEXP _wkutils_cpp_debug_wkb(SEXP wkbSEXP) { BEGIN_RCPP Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< List >::type wkb(wkbSEXP); cpp_debug_wkb(wkb); return R_NilValue; END_RCPP } // cpp_debug_wkt void cpp_debug_wkt(CharacterVector input); RcppExport SEXP _wkutils_cpp_debug_wkt(SEXP inputSEXP) { BEGIN_RCPP Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type input(inputSEXP); cpp_debug_wkt(input); return R_NilValue; END_RCPP } // cpp_debug_wkt_streamer void cpp_debug_wkt_streamer(CharacterVector input); RcppExport SEXP _wkutils_cpp_debug_wkt_streamer(SEXP inputSEXP) { BEGIN_RCPP Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type input(inputSEXP); cpp_debug_wkt_streamer(input); return R_NilValue; END_RCPP } // cpp_wkt_set_srid CharacterVector cpp_wkt_set_srid(CharacterVector wkt, IntegerVector srid, int precision, bool trim); RcppExport SEXP _wkutils_cpp_wkt_set_srid(SEXP wktSEXP, SEXP sridSEXP, SEXP precisionSEXP, SEXP trimSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP); Rcpp::traits::input_parameter< IntegerVector >::type srid(sridSEXP); Rcpp::traits::input_parameter< int >::type precision(precisionSEXP); Rcpp::traits::input_parameter< bool >::type trim(trimSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkt_set_srid(wkt, srid, precision, trim)); return rcpp_result_gen; END_RCPP } // cpp_wkb_set_srid List cpp_wkb_set_srid(List wkb, IntegerVector srid, int endian); RcppExport SEXP _wkutils_cpp_wkb_set_srid(SEXP wkbSEXP, SEXP sridSEXP, SEXP endianSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< List >::type wkb(wkbSEXP); Rcpp::traits::input_parameter< IntegerVector >::type srid(sridSEXP); Rcpp::traits::input_parameter< int >::type endian(endianSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkb_set_srid(wkb, srid, endian)); return rcpp_result_gen; END_RCPP } // cpp_wkt_set_z CharacterVector cpp_wkt_set_z(CharacterVector wkt, NumericVector z, int precision, bool trim); RcppExport SEXP _wkutils_cpp_wkt_set_z(SEXP wktSEXP, SEXP zSEXP, SEXP precisionSEXP, SEXP trimSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP); Rcpp::traits::input_parameter< NumericVector >::type z(zSEXP); Rcpp::traits::input_parameter< int >::type precision(precisionSEXP); Rcpp::traits::input_parameter< bool >::type trim(trimSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkt_set_z(wkt, z, precision, trim)); return rcpp_result_gen; END_RCPP } // cpp_wkb_set_z List cpp_wkb_set_z(List wkb, NumericVector z, int endian); RcppExport SEXP _wkutils_cpp_wkb_set_z(SEXP wkbSEXP, SEXP zSEXP, SEXP endianSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< List >::type wkb(wkbSEXP); Rcpp::traits::input_parameter< NumericVector >::type z(zSEXP); Rcpp::traits::input_parameter< int >::type endian(endianSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkb_set_z(wkb, z, endian)); return rcpp_result_gen; END_RCPP } // cpp_wkt_transform CharacterVector cpp_wkt_transform(CharacterVector wkt, NumericVector transform, int precision, bool trim); RcppExport SEXP _wkutils_cpp_wkt_transform(SEXP wktSEXP, SEXP transformSEXP, SEXP precisionSEXP, SEXP trimSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP); Rcpp::traits::input_parameter< NumericVector >::type transform(transformSEXP); Rcpp::traits::input_parameter< int >::type precision(precisionSEXP); Rcpp::traits::input_parameter< bool >::type trim(trimSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkt_transform(wkt, transform, precision, trim)); return rcpp_result_gen; END_RCPP } // cpp_wkb_transform List cpp_wkb_transform(List wkb, NumericVector transform, int endian); RcppExport SEXP _wkutils_cpp_wkb_transform(SEXP wkbSEXP, SEXP transformSEXP, SEXP endianSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< List >::type wkb(wkbSEXP); Rcpp::traits::input_parameter< NumericVector >::type transform(transformSEXP); Rcpp::traits::input_parameter< int >::type endian(endianSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkb_transform(wkb, transform, endian)); return rcpp_result_gen; END_RCPP } // cpp_wkt_has_non_finite LogicalVector cpp_wkt_has_non_finite(CharacterVector wkt); RcppExport SEXP _wkutils_cpp_wkt_has_non_finite(SEXP wktSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkt_has_non_finite(wkt)); return rcpp_result_gen; END_RCPP } // cpp_wkb_has_non_finite LogicalVector cpp_wkb_has_non_finite(List wkb); RcppExport SEXP _wkutils_cpp_wkb_has_non_finite(SEXP wkbSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< List >::type wkb(wkbSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkb_has_non_finite(wkb)); return rcpp_result_gen; END_RCPP } // cpp_wkt_has_missing LogicalVector cpp_wkt_has_missing(CharacterVector wkt); RcppExport SEXP _wkutils_cpp_wkt_has_missing(SEXP wktSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkt_has_missing(wkt)); return rcpp_result_gen; END_RCPP } // cpp_wkb_has_missing LogicalVector cpp_wkb_has_missing(List wkb); RcppExport SEXP _wkutils_cpp_wkb_has_missing(SEXP wkbSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< List >::type wkb(wkbSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkb_has_missing(wkb)); return rcpp_result_gen; END_RCPP } // cpp_meta_wkb List cpp_meta_wkb(List wkb, bool recursive); RcppExport SEXP _wkutils_cpp_meta_wkb(SEXP wkbSEXP, SEXP recursiveSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< List >::type wkb(wkbSEXP); Rcpp::traits::input_parameter< bool >::type recursive(recursiveSEXP); rcpp_result_gen = Rcpp::wrap(cpp_meta_wkb(wkb, recursive)); return rcpp_result_gen; END_RCPP } // cpp_meta_wkt List cpp_meta_wkt(CharacterVector wkt, bool recursive); RcppExport SEXP _wkutils_cpp_meta_wkt(SEXP wktSEXP, SEXP recursiveSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP); Rcpp::traits::input_parameter< bool >::type recursive(recursiveSEXP); rcpp_result_gen = Rcpp::wrap(cpp_meta_wkt(wkt, recursive)); return rcpp_result_gen; END_RCPP } // cpp_meta_wkt_streamer List cpp_meta_wkt_streamer(CharacterVector wkt, bool recursive); RcppExport SEXP _wkutils_cpp_meta_wkt_streamer(SEXP wktSEXP, SEXP recursiveSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP); Rcpp::traits::input_parameter< bool >::type recursive(recursiveSEXP); rcpp_result_gen = Rcpp::wrap(cpp_meta_wkt_streamer(wkt, recursive)); return rcpp_result_gen; END_RCPP } // cpp_ranges_wkb List cpp_ranges_wkb(List wkb, bool naRm, bool onlyFinite); RcppExport SEXP _wkutils_cpp_ranges_wkb(SEXP wkbSEXP, SEXP naRmSEXP, SEXP onlyFiniteSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< List >::type wkb(wkbSEXP); Rcpp::traits::input_parameter< bool >::type naRm(naRmSEXP); Rcpp::traits::input_parameter< bool >::type onlyFinite(onlyFiniteSEXP); rcpp_result_gen = Rcpp::wrap(cpp_ranges_wkb(wkb, naRm, onlyFinite)); return rcpp_result_gen; END_RCPP } // cpp_ranges_wkt List cpp_ranges_wkt(CharacterVector wkt, bool naRm, bool onlyFinite); RcppExport SEXP _wkutils_cpp_ranges_wkt(SEXP wktSEXP, SEXP naRmSEXP, SEXP onlyFiniteSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP); Rcpp::traits::input_parameter< bool >::type naRm(naRmSEXP); Rcpp::traits::input_parameter< bool >::type onlyFinite(onlyFiniteSEXP); rcpp_result_gen = Rcpp::wrap(cpp_ranges_wkt(wkt, naRm, onlyFinite)); return rcpp_result_gen; END_RCPP } // cpp_feature_ranges_wkb List cpp_feature_ranges_wkb(List wkb, bool naRm, bool onlyFinite); RcppExport SEXP _wkutils_cpp_feature_ranges_wkb(SEXP wkbSEXP, SEXP naRmSEXP, SEXP onlyFiniteSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< List >::type wkb(wkbSEXP); Rcpp::traits::input_parameter< bool >::type naRm(naRmSEXP); Rcpp::traits::input_parameter< bool >::type onlyFinite(onlyFiniteSEXP); rcpp_result_gen = Rcpp::wrap(cpp_feature_ranges_wkb(wkb, naRm, onlyFinite)); return rcpp_result_gen; END_RCPP } // cpp_feature_ranges_wkt List cpp_feature_ranges_wkt(CharacterVector wkt, bool naRm, bool onlyFinite); RcppExport SEXP _wkutils_cpp_feature_ranges_wkt(SEXP wktSEXP, SEXP naRmSEXP, SEXP onlyFiniteSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP); Rcpp::traits::input_parameter< bool >::type naRm(naRmSEXP); Rcpp::traits::input_parameter< bool >::type onlyFinite(onlyFiniteSEXP); rcpp_result_gen = Rcpp::wrap(cpp_feature_ranges_wkt(wkt, naRm, onlyFinite)); return rcpp_result_gen; END_RCPP } // cpp_wkt_unnest CharacterVector cpp_wkt_unnest(CharacterVector wkt, bool keepEmpty, bool keepMulti, int maxUnnestDepth); RcppExport SEXP _wkutils_cpp_wkt_unnest(SEXP wktSEXP, SEXP keepEmptySEXP, SEXP keepMultiSEXP, SEXP maxUnnestDepthSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP); Rcpp::traits::input_parameter< bool >::type keepEmpty(keepEmptySEXP); Rcpp::traits::input_parameter< bool >::type keepMulti(keepMultiSEXP); Rcpp::traits::input_parameter< int >::type maxUnnestDepth(maxUnnestDepthSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkt_unnest(wkt, keepEmpty, keepMulti, maxUnnestDepth)); return rcpp_result_gen; END_RCPP } // cpp_wkb_unnest List cpp_wkb_unnest(List wkb, bool keepEmpty, bool keepMulti, int maxUnnestDepth, int endian); RcppExport SEXP _wkutils_cpp_wkb_unnest(SEXP wkbSEXP, SEXP keepEmptySEXP, SEXP keepMultiSEXP, SEXP maxUnnestDepthSEXP, SEXP endianSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< List >::type wkb(wkbSEXP); Rcpp::traits::input_parameter< bool >::type keepEmpty(keepEmptySEXP); Rcpp::traits::input_parameter< bool >::type keepMulti(keepMultiSEXP); Rcpp::traits::input_parameter< int >::type maxUnnestDepth(maxUnnestDepthSEXP); Rcpp::traits::input_parameter< int >::type endian(endianSEXP); rcpp_result_gen = Rcpp::wrap(cpp_wkb_unnest(wkb, keepEmpty, keepMulti, maxUnnestDepth, endian)); return rcpp_result_gen; END_RCPP } static const R_CallMethodDef CallEntries[] = { {"_wkutils_cpp_coords_point_translate_wkt", (DL_FUNC) &_wkutils_cpp_coords_point_translate_wkt, 6}, {"_wkutils_cpp_coords_point_translate_wkb", (DL_FUNC) &_wkutils_cpp_coords_point_translate_wkb, 6}, {"_wkutils_cpp_coords_linestring_translate_wkt", (DL_FUNC) &_wkutils_cpp_coords_linestring_translate_wkt, 7}, {"_wkutils_cpp_coords_linestring_translate_wkb", (DL_FUNC) &_wkutils_cpp_coords_linestring_translate_wkb, 7}, {"_wkutils_cpp_coords_polygon_translate_wkt", (DL_FUNC) &_wkutils_cpp_coords_polygon_translate_wkt, 8}, {"_wkutils_cpp_coords_polygon_translate_wkb", (DL_FUNC) &_wkutils_cpp_coords_polygon_translate_wkb, 8}, {"_wkutils_cpp_coords_wkb", (DL_FUNC) &_wkutils_cpp_coords_wkb, 2}, {"_wkutils_cpp_coords_wkt", (DL_FUNC) &_wkutils_cpp_coords_wkt, 2}, {"_wkutils_cpp_debug_wkb", (DL_FUNC) &_wkutils_cpp_debug_wkb, 1}, {"_wkutils_cpp_debug_wkt", (DL_FUNC) &_wkutils_cpp_debug_wkt, 1}, {"_wkutils_cpp_debug_wkt_streamer", (DL_FUNC) &_wkutils_cpp_debug_wkt_streamer, 1}, {"_wkutils_cpp_wkt_set_srid", (DL_FUNC) &_wkutils_cpp_wkt_set_srid, 4}, {"_wkutils_cpp_wkb_set_srid", (DL_FUNC) &_wkutils_cpp_wkb_set_srid, 3}, {"_wkutils_cpp_wkt_set_z", (DL_FUNC) &_wkutils_cpp_wkt_set_z, 4}, {"_wkutils_cpp_wkb_set_z", (DL_FUNC) &_wkutils_cpp_wkb_set_z, 3}, {"_wkutils_cpp_wkt_transform", (DL_FUNC) &_wkutils_cpp_wkt_transform, 4}, {"_wkutils_cpp_wkb_transform", (DL_FUNC) &_wkutils_cpp_wkb_transform, 3}, {"_wkutils_cpp_wkt_has_non_finite", (DL_FUNC) &_wkutils_cpp_wkt_has_non_finite, 1}, {"_wkutils_cpp_wkb_has_non_finite", (DL_FUNC) &_wkutils_cpp_wkb_has_non_finite, 1}, {"_wkutils_cpp_wkt_has_missing", (DL_FUNC) &_wkutils_cpp_wkt_has_missing, 1}, {"_wkutils_cpp_wkb_has_missing", (DL_FUNC) &_wkutils_cpp_wkb_has_missing, 1}, {"_wkutils_cpp_meta_wkb", (DL_FUNC) &_wkutils_cpp_meta_wkb, 2}, {"_wkutils_cpp_meta_wkt", (DL_FUNC) &_wkutils_cpp_meta_wkt, 2}, {"_wkutils_cpp_meta_wkt_streamer", (DL_FUNC) &_wkutils_cpp_meta_wkt_streamer, 2}, {"_wkutils_cpp_ranges_wkb", (DL_FUNC) &_wkutils_cpp_ranges_wkb, 3}, {"_wkutils_cpp_ranges_wkt", (DL_FUNC) &_wkutils_cpp_ranges_wkt, 3}, {"_wkutils_cpp_feature_ranges_wkb", (DL_FUNC) &_wkutils_cpp_feature_ranges_wkb, 3}, {"_wkutils_cpp_feature_ranges_wkt", (DL_FUNC) &_wkutils_cpp_feature_ranges_wkt, 3}, {"_wkutils_cpp_wkt_unnest", (DL_FUNC) &_wkutils_cpp_wkt_unnest, 4}, {"_wkutils_cpp_wkb_unnest", (DL_FUNC) &_wkutils_cpp_wkb_unnest, 5}, {NULL, NULL, 0} }; RcppExport void R_init_wkutils(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } wkutils/src/filters.cpp0000644000176200001440000001271413774411735014740 0ustar liggesusers #include "wk/wkt-writer.hpp" #include "wk/wkt-reader.hpp" #include "wk/wkb-writer.hpp" #include "wk/wkb-reader.hpp" #include "wk/filter.hpp" #include #include "wk/rcpp-io.hpp" using namespace Rcpp; // --------- srid ------------- class WKSetSridFilter: public WKMetaFilter { public: WKSetSridFilter(WKGeometryHandler& handler, IntegerVector srid): WKMetaFilter(handler), srid(srid), featureSrid(NA_INTEGER) {} void nextFeatureStart(size_t featureId) { this->featureSrid = this->srid[featureId]; WKMetaFilter::nextFeatureStart(featureId); } WKGeometryMeta newGeometryMeta(const WKGeometryMeta& meta, uint32_t partId) { WKGeometryMeta newMeta(meta); if (IntegerVector::is_na(this->featureSrid)) { newMeta.hasSRID = false; } else { newMeta.hasSRID = true; newMeta.srid = this->featureSrid; } return newMeta; } private: IntegerVector srid; int featureSrid; }; void set_srid_base(WKReader& reader, WKWriter& writer, IntegerVector srid) { WKSetSridFilter filter(writer, srid); reader.setHandler(&filter); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } } // [[Rcpp::export]] CharacterVector cpp_wkt_set_srid(CharacterVector wkt, IntegerVector srid, int precision = 16, bool trim = true) { WKCharacterVectorProvider provider(wkt); WKTReader reader(provider); WKCharacterVectorExporter exporter(wkt.size()); WKTWriter writer(exporter); exporter.setRoundingPrecision(precision); exporter.setTrim(trim); set_srid_base(reader, writer, srid); return exporter.output; } // [[Rcpp::export]] List cpp_wkb_set_srid(List wkb, IntegerVector srid, int endian) { WKRawVectorListProvider provider(wkb); WKBReader reader(provider); WKRawVectorListExporter exporter(wkb.size()); WKBWriter writer(exporter); writer.setEndian(endian); set_srid_base(reader, writer, srid); return exporter.output; } // ----------- set z ------------- class WKSetZFilter: public WKMetaFilter { public: WKSetZFilter(WKGeometryHandler& handler, NumericVector z): WKMetaFilter(handler), z(z), featureZ(NA_REAL) {} void nextFeatureStart(size_t featureId) { this->featureZ = this->z[featureId]; WKMetaFilter::nextFeatureStart(featureId); } WKGeometryMeta newGeometryMeta(const WKGeometryMeta& meta, uint32_t partId) { WKGeometryMeta newMeta(meta); newMeta.hasZ = !NumericVector::is_na(this->featureZ); return newMeta; } void nextCoordinate(const WKGeometryMeta& meta, const WKCoord& coord, uint32_t coordId) { WKCoord newCoord(coord); newCoord.z = this->featureZ; newCoord.hasZ = !NumericVector::is_na(this->featureZ); WKMetaFilter::nextCoordinate(meta, newCoord, coordId); } private: NumericVector z; double featureZ; }; void set_z_base(WKReader& reader, WKWriter& writer, NumericVector z) { WKSetZFilter filter(writer, z); reader.setHandler(&filter); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } } // [[Rcpp::export]] CharacterVector cpp_wkt_set_z(CharacterVector wkt, NumericVector z, int precision = 16, bool trim = true) { WKCharacterVectorProvider provider(wkt); WKTReader reader(provider); WKCharacterVectorExporter exporter(wkt.size()); WKTWriter writer(exporter); exporter.setRoundingPrecision(precision); exporter.setTrim(trim); set_z_base(reader, writer, z); return exporter.output; } // [[Rcpp::export]] List cpp_wkb_set_z(List wkb, NumericVector z, int endian) { WKRawVectorListProvider provider(wkb); WKBReader reader(provider); WKRawVectorListExporter exporter(wkb.size()); WKBWriter writer(exporter); writer.setEndian(endian); set_z_base(reader, writer, z); return exporter.output; } // ---------- transform ----------- class WKTransformFilter: public WKFilter { public: // here, t is the 6-member affine transform in column-major format // (e.g., [1 0 0 1 tx ty]) WKTransformFilter(WKGeometryHandler& handler, NumericVector t): WKFilter(handler), t1(t[0]), t2(t[1]), t3(t[2]), t4(t[3]), t5(t[4]), t6(t[5]) {} void nextCoordinate(const WKGeometryMeta& meta, const WKCoord& coord, uint32_t coordId) { WKCoord newCoord(coord); newCoord.x = t1 * coord.x + t3 * coord.y + t5; newCoord.y = t2 * coord.x + t4 * coord.y + t6; WKFilter::nextCoordinate(meta, newCoord, coordId); } private: double t1, t2, t3, t4, t5, t6; }; void transform_base(WKReader& reader, WKWriter& writer, NumericVector transform) { WKTransformFilter filter(writer, transform); reader.setHandler(&filter); while (reader.hasNextFeature()) { checkUserInterrupt(); reader.iterateFeature(); } } // [[Rcpp::export]] CharacterVector cpp_wkt_transform(CharacterVector wkt, NumericVector transform, int precision = 16, bool trim = true) { WKCharacterVectorProvider provider(wkt); WKTReader reader(provider); WKCharacterVectorExporter exporter(wkt.size()); WKTWriter writer(exporter); exporter.setRoundingPrecision(precision); exporter.setTrim(trim); transform_base(reader, writer, transform); return exporter.output; } // [[Rcpp::export]] List cpp_wkb_transform(List wkb, NumericVector transform, int endian) { WKRawVectorListProvider provider(wkb); WKBReader reader(provider); WKRawVectorListExporter exporter(wkb.size()); WKBWriter writer(exporter); writer.setEndian(endian); transform_base(reader, writer, transform); return exporter.output; } wkutils/R/0000755000176200001440000000000013774605365012175 5ustar liggesuserswkutils/R/unnest.R0000644000176200001440000000210413774346624013631 0ustar liggesusers #' Flatten nested geometry structures #' #' @inheritParams wk::wkb_translate_wkt #' @param keep_empty If `TRUE`, a GEOMETRYCOLLECTION EMPTY is left as-is #' rather than collapsing to length 0. #' @param keep_multi If `TRUE`, MULTI* geometries are not expanded to sub-features. #' @param max_depth The maximum recursive GEOMETRYCOLLECTION depth to unnest. #' #' @return An unclassed vector with attribute `lengths`, which is an integer vector #' with the same length as the input denoting the length to which each #' feature was expanded. #' @export #' #' @examples #' wkt_unnest("GEOMETRYCOLLECTION (POINT (1 2), POINT (3 4))") #' wkt_unnest("GEOMETRYCOLLECTION EMPTY") #' wkt_unnest("GEOMETRYCOLLECTION EMPTY", keep_empty = TRUE) #' wkt_unnest <- function(wkt, keep_empty = FALSE, keep_multi = TRUE, max_depth = 1) { cpp_wkt_unnest(wkt, keep_empty, keep_multi, max_depth) } #' @rdname wkt_unnest #' @export wkb_unnest <- function(wkb, keep_empty = FALSE, keep_multi = TRUE, max_depth = 1) { cpp_wkb_unnest(wkb, keep_empty, keep_multi, max_depth, endian = wk_platform_endian()) } wkutils/R/utils.R0000644000176200001440000000023113706040737013443 0ustar liggesusers new_data_frame <- function(x, nrow = length(x[[1]])) { tibble::new_tibble(x, nrow = nrow) } `%||%` <- function (x, y) { if (is.null(x)) y else x } wkutils/R/coords.R0000644000176200001440000000273313774346226013614 0ustar liggesusers #' Extract coordinates from well-known geometries #' #' These functions are optimised for graphics output, #' which in R require flat coordinate structures. See #' [graphics::points()], [graphics::lines()], #' and [graphics::polypath()] for how to send these #' to a graphics device, or [grid::pointsGrob()], #' [grid::linesGrob()], and [grid::pathGrob()] for how #' to create graphical objects using this output. #' #' @inheritParams wk::wkb_translate_wkt #' @param sep_na Use `TRUE` to separate geometries and linear #' rings with a row of `NA`s. This is useful for generating #' output that can be fed directly to [graphics::polypath()] #' or [graphics::lines()] without modification. #' #' @return A data.frame with columns: #' - `feature_id`: The index of the top-level feature #' - `part_id`: The part identifier, guaranteed to be unique for every simple geometry #' (including those contained within a multi-geometry or collection) #' - `ring_id`: The ring identifier, guaranteed to be unique for every ring. #' - `x`, `y`, `z`, `m`: Coordinaate values (both absence and `nan` are recorded #' as `NA`) #' #' @export #' #' @examples #' text <- c("LINESTRING (0 1, 19 27)", "LINESTRING (-1 -1, 4 10)") #' wkt_coords(text) #' wkt_coords(text, sep_na = TRUE) #' wkb_coords <- function(wkb, sep_na = FALSE) { new_data_frame(cpp_coords_wkb(wkb, sep_na)) } #' @rdname wkb_coords #' @export wkt_coords <- function(wkt, sep_na = FALSE) { new_data_frame(cpp_coords_wkt(wkt, sep_na)) } wkutils/R/grob.R0000644000176200001440000001403713774346437013260 0ustar liggesusers #' Generate grid geometries from well-known geometries #' #' Using [wkt_meta()] and [wkt_coords()], these functions create graphical objects #' using the grid package. Vectors that contain geometries of a single dimension #' are efficiently packed into a [grid::pointsGrob()], [grid::polylineGrob()], #' or [grid::pathGrob()]. Vectors with mixed types and nested collections are encoded #' less efficiently using a [grid::gTree()]. #' #' @inheritParams wk::wkb_translate_wkt #' @param ... Graphical parameters passed to [grid::gpar()]. These are recycled along #' the input. Dynamic dots (e.g., `!!!`) are supported. #' @param rule Use "winding" if polygon rings are correctly encoded with a winding #' direction. #' @param default.units Coordinate units, which may be defined by the viewport (see #' [grid::unit()]). Defaults to native. #' @param name,vp Passed to [grid::pointsGrob()], [grid::polylineGrob()], #' [grid::pathGrob()], or [grid::gTree()] depending on the types of geometries #' in the input. #' #' @return A [graphical object][grid::grob] #' @export #' #' @examples #' grid::grid.newpage() #' grid::grid.draw(wkt_grob("POINT (0.5 0.5)", pch = 16, default.units = "npc")) #' wkt_grob <- function(wkt, ..., rule = "evenodd", default.units = "native", name = NULL, vp = NULL) { grob_wk_possibly_nested( wkt, ..., unnest_fun = wkt_unnest, meta_fun = wkt_meta, coords_fun = wkt_coords, rule = rule, default.units = default.units, name = name, vp = vp ) } #' @rdname wkt_grob #' @export wkb_grob <- function(wkt, ..., rule = "evenodd", default.units = "native", name = NULL, vp = NULL) { grob_wk_possibly_nested( wkt, ..., unnest_fun = wkb_unnest, meta_fun = wkb_meta, coords_fun = wkb_coords, rule = rule, default.units = default.units, name = name, vp = vp ) } grob_wk_possibly_nested <- function(x, ..., unnest_fun, meta_fun, coords_fun, rule, default.units, name, vp) { meta <- meta_fun(x) gpar_values_all <- vctrs::vec_recycle_common(..., .size = length(x)) # if there are any collections, unnest everything if (any((meta$size > 0) & (meta$type_id == 7))) { unnested <- unnest_fun(x, keep_empty = FALSE, keep_multi = TRUE, max_depth = 10) lengths <- attr(unnested, "lengths") run_length_enc <- structure( list(lengths = lengths, values = seq_along(lengths)), class = "rle" ) unnested_gpar <- lapply(gpar_values_all, "[", inverse.rle(run_length_enc)) return( wkt_grob( unnested, !!!unnested_gpar, rule = rule, default.units = default.units, name = name, vp = vp ) ) } coords <- coords_fun(x) # grid doesn't do zero-length input, so if there are no coordinates, return # an empty grob if (nrow(coords) == 0) { return(grid::gTree(name = name, vp = vp, children = grid::gList())) } grob_wk_base( meta, coords, gpar_values_all, rule = rule, default.units = default.units, name = name, vp = vp ) } grob_wk_base <- function(meta, coords, gpar_values_all, rule, default.units, name = NULL, vp = NULL) { # use meta to try to create the most efficient grob possible non_empty_types <- meta$type_id[meta$size > 0] # non-empty IDs are used by mixed types and polygons non_empty_features <- unique(meta$feature_id[meta$size > 0]) if (all(non_empty_types %in% c(1, 4))) { # Need to get a tiny bit creative here, because pointsGrob # doesn't have a pathId argument like pathGrob. The key here is # to select gpar_values_all so that its rows match the # number of actual part_id values for each feature part_lengths <- rle(coords$part_id) part_row_start <- c(0, cumsum(part_lengths$lengths)) + 1 part_feature_ids <- coords$feature_id[part_row_start[-length(part_row_start)]] gpar_values_all <- lapply(gpar_values_all, "[", part_feature_ids) pch <- gpar_values_all$pch %||% 1 size <- gpar_values_all$size %||% grid::unit(1, "char") gpar_values_all$pch <- NULL gpar_values_all$size <- NULL grid::pointsGrob( x = coords$x, y = coords$y, pch = pch, size = size, gp = do.call(grid::gpar, gpar_values_all), default.units = default.units, name = name, vp = vp ) } else if (all(non_empty_types %in% c(2, 5))) { # Need to get a tiny bit creative here, because polylineGrob # doesn't have a pathId argument like pathGrob. The key here is # to select gpar_values_all so that its rows match the # number of actual part_id values for each feature part_lengths <- rle(coords$part_id) part_row_start <- c(0, cumsum(part_lengths$lengths)) + 1 part_feature_ids <- coords$feature_id[part_row_start[-length(part_row_start)]] gpar_values_all <- lapply(gpar_values_all, "[", part_feature_ids) grid::polylineGrob( x = coords$x, y = coords$y, id.lengths = part_lengths$lengths, gp = do.call(grid::gpar, gpar_values_all), default.units = default.units, name = name, vp = vp ) } else if (all(non_empty_types %in% c(3, 6))) { non_empty_gpar_values <- lapply(gpar_values_all, "[", non_empty_features) grid::pathGrob( x = coords$x, y = coords$y, id = coords$ring_id, pathId = coords$feature_id, gp = do.call(grid::gpar, non_empty_gpar_values), default.units = default.units, name = name, vp = vp, rule = rule ) } else if (all(non_empty_types != 7)) { # Mixed input, but no collections (collections should be handled by unnest()) # not very efficient, but better than failing grobs <- lapply(non_empty_features, function(feature_id) { grob_wk_base( meta[feature_id, ], coords[coords$feature_id == feature_id, ], gpar_values_all, rule = rule, default.units = default.units # name and vp are passed to the gTree ) }) grid::gTree(children = do.call(grid::gList, grobs), name = name, vp = vp) } else { stop("Can't use grob_wk_base() on a GEOMETRYCOLLECTION") # nocov } } wkutils/R/filters.R0000644000176200001440000000370313774346423013770 0ustar liggesusers #' Modify well-known geometries #' #' @inheritParams wk::wkb_translate_wkt #' @param srid An integer spatial reference identifier with a user-defined meaning. #' Use `NA` to unset this value. #' @param z A Z value that will be assigned to every coordinate in each feature. #' Use `NA` to unset this value. #' @param trans A 3x3 transformation matrix that will be applied to all coordinates #' in the input. #' #' @return An unclassed well-known vector with the same type #' as the input. #' @export #' #' @examples #' wkt_set_srid("POINT (30 10)", 1234) #' wkt_set_z("POINT (30 10)", 1234) #' wkt_transform( #' "POINT (0 0)", #' # translation +12 +13 #' matrix(c(1, 0, 0, 0, 1, 0, 12, 13, 1), ncol = 3) #' ) #' wkt_set_srid <- function(wkt, srid, precision = 16, trim = TRUE) { recycled <- vctrs::vec_recycle_common(wkt, srid) cpp_wkt_set_srid(recycled[[1]], recycled[[2]], precision, trim) } #' @rdname wkt_set_srid #' @export wkb_set_srid <- function(wkb, srid) { recycled <- vctrs::vec_recycle_common(wkb, srid) cpp_wkb_set_srid(recycled[[1]], recycled[[2]], wk_platform_endian()) } #' @rdname wkt_set_srid #' @export wkt_set_z <- function(wkt, z, precision = 16, trim = TRUE) { recycled <- vctrs::vec_recycle_common(wkt, z) cpp_wkt_set_z(recycled[[1]], recycled[[2]], precision, trim) } #' @rdname wkt_set_srid #' @export wkb_set_z <- function(wkb, z) { recycled <- vctrs::vec_recycle_common(wkb, z) cpp_wkb_set_z(recycled[[1]], recycled[[2]], wk_platform_endian()) } #' @rdname wkt_set_srid #' @export wkt_transform <- function(wkt, trans, precision = 16, trim = TRUE) { cpp_wkt_transform(wkt, as_trans_matrix(trans)[c(1, 2), ], precision, trim) } #' @rdname wkt_set_srid #' @export wkb_transform <- function(wkb, trans) { cpp_wkb_transform(wkb, as_trans_matrix(trans)[c(1, 2), ], endian = wk_platform_endian()) } as_trans_matrix <- function(trans) { trans <- as.matrix(trans) stopifnot(ncol(trans) == 3, nrow(trans) == 3) trans } wkutils/R/draw.R0000644000176200001440000000577413774346367013276 0ustar liggesusers #' Draw well-known geometries #' #' These functions send well-known geometry vectors to a #' graphics device using [graphics::points()], #' [graphics::lines()], and [graphics::polypath()]. These are #' minimal wrappers aimed at developers who need to visualize #' test data: they do not check geometry type and are unlikely #' to work with vectorized graphical parameters in `...`. Use #' the `wk*_plot_new()` functions to initialize a plot using the #' extent of all coordinates in the vector. #' #' @inheritParams wk::wkb_translate_wkt #' @param ... Passed to [graphics::points()], #' [graphics::lines()], or [graphics::polypath()] #' @param rule Passed to [graphics::polypath()] #' @param asp,xlab,ylab,main Passed to [graphics::plot()] to #' initialize a new plot. #' #' @return The input, invisibly #' @export #' #' @examples #' x <- "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))" #' #' wkt_plot_new(x) #' wkt_draw_polypath(x, col = "grey90") #' wkt_draw_lines(x, col = "red") #' wkt_draw_points(x) #' wkb_draw_points <- function(wkb, ...) { wkcoords_draw_points(wkb_coords(wkb), ...) invisible(wkb) } #' @rdname wkb_draw_points #' @export wkt_draw_points <- function(wkt, ...) { wkcoords_draw_points(wkt_coords(wkt), ...) invisible(wkt) } #' @rdname wkb_draw_points #' @export wkb_draw_lines <- function(wkb, ...) { wkcoords_draw_lines(wkb_coords(wkb, sep_na = TRUE), ...) invisible(wkb) } #' @rdname wkb_draw_points #' @export wkt_draw_lines <- function(wkt, ...) { wkcoords_draw_lines(wkt_coords(wkt, sep_na = TRUE), ...) invisible(wkt) } #' @rdname wkb_draw_points #' @export wkb_draw_polypath <- function(wkb, ..., rule = "evenodd") { wkcoords_draw_polypath(wkb_coords(wkb, sep_na = TRUE), ..., rule = rule) invisible(wkb) } #' @rdname wkb_draw_points #' @export wkt_draw_polypath <- function(wkt, ..., rule = "evenodd") { wkcoords_draw_polypath(wkt_coords(wkt, sep_na = TRUE), ..., rule = rule) invisible(wkt) } #' @rdname wkb_draw_points #' @export wkb_plot_new <- function(wkb, ..., asp = 1, xlab = "", ylab = "", main = deparse(substitute(wkb))) { wkranges_plot_new(wkb_ranges(wkb, finite = TRUE), ..., asp = asp, xlab = xlab, ylab = ylab, main = main) invisible(wkb) } #' @rdname wkb_draw_points #' @export wkt_plot_new <- function(wkt, ..., asp = 1, xlab = "", ylab = "", main = deparse(substitute(wkt))) { wkranges_plot_new(wkt_ranges(wkt, finite = TRUE), ..., asp = asp, xlab = xlab, ylab = ylab, main = main) invisible(wkt) } wkcoords_draw_points <- function(coords, ...) { graphics::points(coords$x, coords$y, ...) } wkcoords_draw_lines <- function(coords, ...) { graphics::lines(coords$x, coords$y, ...) } wkcoords_draw_polypath <- function(coords, ..., rule = "evenodd") { graphics::polypath(coords$x, coords$y, ..., rule = rule) } wkranges_plot_new <- function(ranges, ..., xlab = "", ylab = "", main = "") { graphics::plot( double(), double(), ..., xlim = c(ranges$xmin, ranges$xmax), ylim = c(ranges$ymin, ranges$ymax), xlab = xlab, ylab = ylab, main = main ) } wkutils/R/RcppExports.R0000644000176200001440000000761113774605365014616 0ustar liggesusers# Generated by using Rcpp::compileAttributes() -> do not edit by hand # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 cpp_coords_point_translate_wkt <- function(x, y, z, m, precision, trim) { .Call(`_wkutils_cpp_coords_point_translate_wkt`, x, y, z, m, precision, trim) } cpp_coords_point_translate_wkb <- function(x, y, z, m, endian, bufferSize) { .Call(`_wkutils_cpp_coords_point_translate_wkb`, x, y, z, m, endian, bufferSize) } cpp_coords_linestring_translate_wkt <- function(x, y, z, m, featureId, precision, trim) { .Call(`_wkutils_cpp_coords_linestring_translate_wkt`, x, y, z, m, featureId, precision, trim) } cpp_coords_linestring_translate_wkb <- function(x, y, z, m, featureId, endian, bufferSize) { .Call(`_wkutils_cpp_coords_linestring_translate_wkb`, x, y, z, m, featureId, endian, bufferSize) } cpp_coords_polygon_translate_wkt <- function(x, y, z, m, featureId, ringId, precision, trim) { .Call(`_wkutils_cpp_coords_polygon_translate_wkt`, x, y, z, m, featureId, ringId, precision, trim) } cpp_coords_polygon_translate_wkb <- function(x, y, z, m, featureId, ringId, endian, bufferSize) { .Call(`_wkutils_cpp_coords_polygon_translate_wkb`, x, y, z, m, featureId, ringId, endian, bufferSize) } cpp_coords_wkb <- function(wkb, sepNA) { .Call(`_wkutils_cpp_coords_wkb`, wkb, sepNA) } cpp_coords_wkt <- function(wkt, sepNA) { .Call(`_wkutils_cpp_coords_wkt`, wkt, sepNA) } cpp_debug_wkb <- function(wkb) { invisible(.Call(`_wkutils_cpp_debug_wkb`, wkb)) } cpp_debug_wkt <- function(input) { invisible(.Call(`_wkutils_cpp_debug_wkt`, input)) } cpp_debug_wkt_streamer <- function(input) { invisible(.Call(`_wkutils_cpp_debug_wkt_streamer`, input)) } cpp_wkt_set_srid <- function(wkt, srid, precision = 16L, trim = TRUE) { .Call(`_wkutils_cpp_wkt_set_srid`, wkt, srid, precision, trim) } cpp_wkb_set_srid <- function(wkb, srid, endian) { .Call(`_wkutils_cpp_wkb_set_srid`, wkb, srid, endian) } cpp_wkt_set_z <- function(wkt, z, precision = 16L, trim = TRUE) { .Call(`_wkutils_cpp_wkt_set_z`, wkt, z, precision, trim) } cpp_wkb_set_z <- function(wkb, z, endian) { .Call(`_wkutils_cpp_wkb_set_z`, wkb, z, endian) } cpp_wkt_transform <- function(wkt, transform, precision = 16L, trim = TRUE) { .Call(`_wkutils_cpp_wkt_transform`, wkt, transform, precision, trim) } cpp_wkb_transform <- function(wkb, transform, endian) { .Call(`_wkutils_cpp_wkb_transform`, wkb, transform, endian) } cpp_wkt_has_non_finite <- function(wkt) { .Call(`_wkutils_cpp_wkt_has_non_finite`, wkt) } cpp_wkb_has_non_finite <- function(wkb) { .Call(`_wkutils_cpp_wkb_has_non_finite`, wkb) } cpp_wkt_has_missing <- function(wkt) { .Call(`_wkutils_cpp_wkt_has_missing`, wkt) } cpp_wkb_has_missing <- function(wkb) { .Call(`_wkutils_cpp_wkb_has_missing`, wkb) } cpp_meta_wkb <- function(wkb, recursive) { .Call(`_wkutils_cpp_meta_wkb`, wkb, recursive) } cpp_meta_wkt <- function(wkt, recursive) { .Call(`_wkutils_cpp_meta_wkt`, wkt, recursive) } cpp_meta_wkt_streamer <- function(wkt, recursive) { .Call(`_wkutils_cpp_meta_wkt_streamer`, wkt, recursive) } cpp_ranges_wkb <- function(wkb, naRm, onlyFinite) { .Call(`_wkutils_cpp_ranges_wkb`, wkb, naRm, onlyFinite) } cpp_ranges_wkt <- function(wkt, naRm, onlyFinite) { .Call(`_wkutils_cpp_ranges_wkt`, wkt, naRm, onlyFinite) } cpp_feature_ranges_wkb <- function(wkb, naRm, onlyFinite) { .Call(`_wkutils_cpp_feature_ranges_wkb`, wkb, naRm, onlyFinite) } cpp_feature_ranges_wkt <- function(wkt, naRm, onlyFinite) { .Call(`_wkutils_cpp_feature_ranges_wkt`, wkt, naRm, onlyFinite) } cpp_wkt_unnest <- function(wkt, keepEmpty, keepMulti, maxUnnestDepth) { .Call(`_wkutils_cpp_wkt_unnest`, wkt, keepEmpty, keepMulti, maxUnnestDepth) } cpp_wkb_unnest <- function(wkb, keepEmpty, keepMulti, maxUnnestDepth, endian) { .Call(`_wkutils_cpp_wkb_unnest`, wkb, keepEmpty, keepMulti, maxUnnestDepth, endian) } wkutils/R/ranges.R0000644000176200001440000000237213774346561013603 0ustar liggesusers #' Extract ranges information #' #' This is intended to behave the same as [range()], returning the #' minimum and maximum x, y, z, and m coordinate values. #' #' @inheritParams wk::wkb_translate_wkt #' @param na.rm Pass `TRUE` to not consider missing (nan) values #' @param finite Pass `TRUE` to only consider finite #' (non-missing, non-infinite) values. #' @export #' #' @return A data.frame with columns: #' - `xmin`, `ymin`, `zmin`, and `mmin`: Minimum coordinate values #' - `xmax`, `ymax`, `zmax`, and `mmax`: Maximum coordinate values #' #' @examples #' wkt_ranges("POINT (30 10)") #' wkb_ranges <- function(wkb, na.rm = FALSE, finite = FALSE) { new_data_frame(cpp_ranges_wkb(wkb, naRm = na.rm, onlyFinite = finite)) } #' @rdname wkb_ranges #' @export wkt_ranges <- function(wkt, na.rm = FALSE, finite = FALSE) { new_data_frame(cpp_ranges_wkt(wkt, naRm = na.rm, onlyFinite = finite)) } #' @rdname wkb_ranges #' @export wkb_feature_ranges <- function(wkb, na.rm = FALSE, finite = FALSE) { new_data_frame(cpp_feature_ranges_wkb(wkb, naRm = na.rm, onlyFinite = finite)) } #' @rdname wkb_ranges #' @export wkt_feature_ranges <- function(wkt, na.rm = FALSE, finite = FALSE) { new_data_frame(cpp_feature_ranges_wkt(wkt, naRm = na.rm, onlyFinite = finite)) } wkutils/R/plot.R0000644000176200001440000000656713774407150013304 0ustar liggesusers #' Plot well-known geometry vectors #' #' These plot functions are intended to help debug geometry vectors, #' and are not intended to be high-performance. #' #' @param x A [wkt()] or [wkb()] vector. #' @param add Should a new plot be created, or should `x` be added to the #' existing plot? #' @param ... Passed to plotting functions for features: [graphics::points()] #' for point and multipoint geometries, [graphics::lines()] for linestring #' and multilinestring geometries, and [graphics::polypath()] for polygon #' and multipolygon geometries. #' @param bbox The limits of the plot in the form returned by [wkt_ranges()]. #' @param asp,xlab,ylab Passed to [graphics::plot()] #' @param rule The rule to use for filling polygons (see [graphics::polypath()]) #' #' @return `x`, invisibly #' @export #' #' @examples #' wkt_plot("POINT (30 10)") #' wkt_plot <- function(x, ..., asp = 1, bbox = NULL, xlab = "", ylab = "", rule = "evenodd", add = FALSE) { plot_wk( x, wkt_ranges, wkt_meta, wkt_coords, wkt_unnest, ..., asp = asp, bbox = bbox, xlab = xlab, rule = rule, add = add ) } #' @rdname wkt_plot #' @export wkb_plot <- function(x, ..., asp = 1, bbox = NULL, xlab = "", ylab = "", rule = "evenodd", add = FALSE) { plot_wk( x, wkb_ranges, wkb_meta, wkb_coords, wkb_unnest, ..., asp = asp, bbox = bbox, xlab = xlab, rule = rule, add = add ) } plot_wk <- function(x, ranges_fun, meta_fun, coords_fun, unnest_fun, ..., asp = 1, bbox = NULL, xlab = "", ylab = "", rule = "evenodd", add = FALSE) { if (!add) { bbox <- unclass(bbox) bbox <- bbox %||% ranges_fun(x, finite = TRUE) xlim <- c(bbox$xmin, bbox$xmax) ylim <- c(bbox$ymin, bbox$ymax) graphics::plot( numeric(0), numeric(0), xlim = xlim, ylim = ylim, xlab = xlab, ylab = ylab, asp = asp ) } plot_add_wk(x, meta_fun, coords_fun, unnest_fun, ..., rule = rule) } plot_add_wk <- function(x, meta_fun, coords_fun, unnest_fun, ..., rule = "evenodd") { # evaluate dots, wrap scalar types in a list(), and vectorize x <- unclass(x) dots <- list(..., rule = rule) is_scalar <- !vapply(dots, vctrs::vec_is, logical(1)) dots[is_scalar] <- lapply(dots[is_scalar], list) dots_tbl <- vctrs::vec_recycle_common(!!!dots, .size = length(x)) meta <- unclass(meta_fun(x, recursive = FALSE)) # using for() because the user interrupt is respected in RStudio for (i in seq_along(x)) { coords <- coords_fun(x[i], sep_na = TRUE)[c("x", "y")] if (nrow(coords) == 0) { next } dots_item <- lapply(dots_tbl, "[[", i) type_id <- meta$type[i] args <- c(coords, dots_item) if (type_id == 1 || type_id == 4) { args$rule <- NULL do.call(graphics::points, args) } else if (type_id == 2 || type_id == 5) { args$rule <- NULL do.call(graphics::lines, args) } else if (type_id == 3 || type_id == 6) { do.call(graphics::polypath, args) } else if (type_id == 7) { unnested <- unnest_fun(x[i]) do.call( plot_add_wk, c( list(unnested, meta_fun = meta_fun, coords_fun = coords_fun, unnest_fun = unnest_fun), dots_item ) ) } else { stop("Unknown geometry type", call. = FALSE) # nocov } } invisible(x) } wkutils/R/debug.R0000644000176200001440000000141613774346311013401 0ustar liggesusers #' Debug well-known geometry #' #' Prints the raw calls to the `WKBGeometryHandler()`. Useful for writing #' custom C++ handlers and debugging read problems. #' #' @inheritParams wk::wkb_translate_wkt #' #' @return The input, invisibly #' @export #' #' @examples #' wkt_debug("MULTIPOLYGON (((0 0, 10 0, 0 10, 0 0)))") #' wkt_streamer_debug("MULTIPOLYGON (((0 0, 10 0, 0 10, 0 0)))") #' wkb_debug( #' wk::wkt_translate_wkb( #' "MULTIPOLYGON (((0 0, 10 0, 0 10, 0 0)))" #' ) #' ) #' wkb_debug <- function(wkb) { cpp_debug_wkb(wkb) invisible(wkb) } #' @rdname wkb_debug #' @export wkt_debug <- function(wkt) { cpp_debug_wkt(wkt) invisible(wkt) } #' @rdname wkb_debug #' @export wkt_streamer_debug <- function(wkt) { cpp_debug_wkt_streamer(wkt) invisible(wkt) } wkutils/R/wkutils-package.R0000644000176200001440000000044213706037451015401 0ustar liggesusers#' @keywords internal "_PACKAGE" # The following block is used by usethis to automatically manage # roxygen namespace tags. Modify with care! ## usethis namespace: start #' @useDynLib wkutils, .registration = TRUE #' @importFrom Rcpp sourceCpp #' @import wk ## usethis namespace: end NULL wkutils/R/coords-translate.R0000644000176200001440000000672713774346201015607 0ustar liggesusers #' Parse coordinates into well-known formats #' #' These functions provide the reverse function of [wkt_coords()] #' and company: they parse vectors of coordinate values into well-known #' formats. Polygon rings are automatically closed, as #' closed rings are assumed or required by many parsers. #' #' @param x,y,z,m Vectors of coordinate values #' @param feature_id,ring_id Vectors for which a change in #' sequential values indicates a new feature or ring. Use [factor()] #' to convert from a character vector. #' @inheritParams wk::wkb_translate_wkt #' #' @return `*_translate_wkt()` returns a character vector of #' well-known text; `*_translate_wkb()` returns a list #' of raw vectors. #' #' @export #' #' @examples #' coords_point_translate_wkt(1:3, 2:4) #' coords_linestring_translate_wkt(1:5, 2:6, feature_id = c(1, 1, 1, 2, 2)) #' coords_polygon_translate_wkt(c(0, 10, 0), c(0, 0, 10)) #' coords_point_translate_wkt <- function(x, y, z = NA, m = NA, precision = 16, trim = TRUE) { recycled <- vctrs::vec_recycle_common(x, y, z, m) cpp_coords_point_translate_wkt( recycled[[1]], recycled[[2]], recycled[[3]], recycled[[4]], precision = precision, trim = trim ) } #' @rdname coords_point_translate_wkt #' @export coords_point_translate_wkb <- function(x, y, z = NA, m = NA, endian = wk::wk_platform_endian(), buffer_size = 2048) { recycled <- vctrs::vec_recycle_common(x, y, z, m) cpp_coords_point_translate_wkb( recycled[[1]], recycled[[2]], recycled[[3]], recycled[[4]], endian = endian, bufferSize = buffer_size ) } #' @rdname coords_point_translate_wkt #' @export coords_linestring_translate_wkt <- function(x, y, z = NA, m = NA, feature_id = 1L, precision = 16, trim = TRUE) { recycled <- vctrs::vec_recycle_common(x, y, z, m, feature_id) cpp_coords_linestring_translate_wkt( recycled[[1]], recycled[[2]], recycled[[3]], recycled[[4]], recycled[[5]], precision = precision, trim = trim ) } #' @rdname coords_point_translate_wkt #' @export coords_linestring_translate_wkb <- function(x, y, z = NA, m = NA, feature_id = 1L, endian = wk::wk_platform_endian(), buffer_size = 2048) { recycled <- vctrs::vec_recycle_common(x, y, z, m, feature_id) cpp_coords_linestring_translate_wkb( recycled[[1]], recycled[[2]], recycled[[3]], recycled[[4]], recycled[[5]], endian = endian, bufferSize = buffer_size ) } #' @rdname coords_point_translate_wkt #' @export coords_polygon_translate_wkt <- function(x, y, z = NA, m = NA, feature_id = 1L, ring_id = 1L, precision = 16, trim = TRUE) { recycled <- vctrs::vec_recycle_common(x, y, z, m, feature_id, ring_id) cpp_coords_polygon_translate_wkt( recycled[[1]], recycled[[2]], recycled[[3]], recycled[[4]], recycled[[5]], recycled[[6]], precision = precision, trim = trim ) } #' @rdname coords_point_translate_wkt #' @export coords_polygon_translate_wkb <- function(x, y, z = NA, m = NA, feature_id = 1L, ring_id = 1L, endian = wk::wk_platform_endian(), buffer_size = 2048) { recycled <- vctrs::vec_recycle_common(x, y, z, m, feature_id, ring_id) cpp_coords_polygon_translate_wkb( recycled[[1]], recycled[[2]], recycled[[3]], recycled[[4]], recycled[[5]], recycled[[6]], endian = endian, bufferSize = buffer_size ) } wkutils/R/meta.R0000644000176200001440000000375313774346507013256 0ustar liggesusers #' Extract meta information #' #' @inheritParams wk::wkb_translate_wkt #' @param recursive Pass `TRUE` to recurse into multi-geometries #' and collections to extract meta of sub-geometries #' @param type A string version of the geometry type (e.g., #' point, linestring, polygon, multipoint, multilinestring, #' multipolygon, geometrycollection) #' @param type_id An integer version of the geometry type #' #' @return A data.frame with columns: #' - `feature_id`: The index of the top-level feature #' - `nest_id`: The recursion level (if feature is a geometry collection) #' - `part_id`: The part index (if nested within a multi-geometry or collection) #' - `type_id`: The type identifier (see [wk_geometry_type()]) #' - `size`: For points and linestrings the number of points, for polygons #' the number of rings, and for mutlti-geometries and collection types, #' the number of child geometries. #' - `srid`: The spatial reference identifier as an integer #' #' @export #' #' @examples #' wkt_meta("POINT (30 10)") #' wkt_meta("GEOMETRYCOLLECTION (POINT (30 10))", recursive = FALSE) #' wkt_meta("GEOMETRYCOLLECTION (POINT (30 10))", recursive = TRUE) #' wkb_meta <- function(wkb, recursive = FALSE) { new_data_frame(cpp_meta_wkb(wkb, recursive = recursive)) } #' @rdname wkb_meta #' @export wkt_meta <- function(wkt, recursive = FALSE) { new_data_frame(cpp_meta_wkt(wkt, recursive = recursive)) } #' @rdname wkb_meta #' @export wkt_streamer_meta <- function(wkt, recursive = FALSE) { new_data_frame(cpp_meta_wkt_streamer(wkt, recursive = recursive)) } #' @rdname wkb_meta #' @export wk_geometry_type <- function(type_id) { c( "point", "linestring", "polygon", "multipoint", "multilinestring", "multipolygon", "geometrycollection" )[as.integer(type_id)] } #' @rdname wkb_meta #' @export wk_geometry_type_id <- function(type) { match( type, c( "point", "linestring", "polygon", "multipoint", "multilinestring", "multipolygon", "geometrycollection" ) ) } wkutils/R/finite.R0000644000176200001440000000166213774403354013575 0ustar liggesusers #' Test well-known geometries for missing and non-finite coordinates #' #' Note that EMTPY geometries are considered finite and non-missing. #' Use the `size` column of [wkt_meta()] to test for empty geometries. #' #' @inheritParams wk::wkb_translate_wkt #' #' @return A logical vector with the same length as the input. #' @export #' #' @examples #' wkt_has_missing("POINT (0 1)") #' wkt_has_missing("POINT (nan nan)") #' wkt_has_missing("POINT (inf inf)") #' #' wkt_is_finite("POINT (0 1)") #' wkt_is_finite("POINT (nan nan)") #' wkt_is_finite("POINT (inf inf)") #' wkt_has_missing <- function(wkt) { cpp_wkt_has_missing(wkt) } #' @rdname wkt_has_missing #' @export wkb_has_missing <- function(wkb) { cpp_wkb_has_missing(wkb) } #' @rdname wkt_has_missing #' @export wkt_is_finite <- function(wkt) { !cpp_wkt_has_non_finite(wkt) } #' @rdname wkt_has_missing #' @export wkb_is_finite <- function(wkb) { !cpp_wkb_has_non_finite(wkb) } wkutils/NEWS.md0000644000176200001440000000047413774420573013073 0ustar liggesusers# wkutils 0.1.1 * Removed support for `wk::wksxp()` for future compatibility with wk. * Fixed error caught by CRAN ASAN/UBSAN checks. * `wkb_plot()` and `wkt_plot()` can now accept unclassed input for improved consistency. # wkutils 0.1.0 * Moved utility functions from the 'wk' package to create this package. wkutils/MD50000644000176200001440000000561313777065112012302 0ustar liggesusers5d942e1cf430e91472895df804b5d60f *DESCRIPTION 3af0d5f6726a14ed40722905f3202a79 *LICENSE 77b12c0e6a726839ea3be98774feeb0e *NAMESPACE d2238abd449c4713e2167d92e688184f *NEWS.md 9e6b26eae75568a77a214674fb173ea7 *R/RcppExports.R 1b42cf5f0160823b65cd8ee30a8a0424 *R/coords-translate.R 4e3ddc2b5b4a93f1c64dc1af6c1c4e25 *R/coords.R e9ccaf1ce2b1766a32797d1c4f5fc8af *R/debug.R 7955e5795b14ba12bccb45da95f22edb *R/draw.R 84eeb955013fc4c1476cb91f6d0a7389 *R/filters.R a2d343dacc83eda7eac0580e7d9fb303 *R/finite.R a03a8d203015983c2fe93b86603a1c73 *R/grob.R ac9857c4955589fbc8634bda894b11e6 *R/meta.R 4520275e628e5ce20c19e9e2be471db0 *R/plot.R 768005c337aaa29ce1d1a8b749579b30 *R/ranges.R 4163cef7f22f8806ad2526b17e1ae9e7 *R/unnest.R 75f89fdecf90e0412e14ad8a597f95a7 *R/utils.R a6f04b54508534a3b3b40530f9d63fce *R/wkutils-package.R bfd13c2cebb9aaec30f0221d20d2443a *README.md e63bd6aef0d5300f8f2638e8350c005b *man/coords_point_translate_wkt.Rd 6cabce1abbf872b291a98dd352a3a225 *man/figures/README-wk-draw-1.png 598f1d370684ba19e3f9619c0dade6f6 *man/figures/README-wkt-plot-1.png 247ae286d11f103709609471c001f4ba *man/wkb_coords.Rd e262140c0c93e424008aba6b8d4edd5a *man/wkb_debug.Rd c4623233285a8fb6308da4052b77da75 *man/wkb_draw_points.Rd da271793492c94adb9f18635852148ca *man/wkb_meta.Rd 5b2f881d3236970b2de51373ee62d706 *man/wkb_ranges.Rd 121b4a91dccd4f5261dc1f97eae13445 *man/wkt_grob.Rd 7dfdbd10c0aa4cb37f89367e4f0f7d2c *man/wkt_has_missing.Rd f7adf1cb34b83bea1b3944b7b43e0041 *man/wkt_plot.Rd 73c9f7ac057480f200a99cdef46de585 *man/wkt_set_srid.Rd bb69417ba7e9b59a97c6afd1eaccb527 *man/wkt_unnest.Rd 9154e2c8650d695da4e1766ceb4212f3 *man/wkutils-package.Rd 130494f73109e14b1f1d1c73c0530d9d *src/Makevars 3ba88e1510dc18cd78fdfbe732d63733 *src/RcppExports.cpp b0b9afa93564fa41e369f188099a698b *src/coords-translate.cpp adf36642401522d0b6052cd0ced98836 *src/coords.cpp 0e4b6fa3cdb3a28aef7f706228bc4205 *src/debug.cpp 4da420b79d77659a86f1565c1e60fdb8 *src/filters.cpp a584f9f8866f801bc5fc05dee29bf386 *src/finite.cpp ff98d69a92eae95fd5e7826434affa37 *src/meta.cpp a9dba5b383e216ccfa29f9b15915b6ca *src/ranges.cpp e9e1d5ba448e88b03a700c0951c94050 *src/unnest.cpp 141df2b846189579dace1feeebbfe7f4 *tests/testthat.R 23c4d0a2472ac4dc74b45b9a8b4bc964 *tests/testthat/Rplots.pdf 8f42976e3a7aad667303b67fc124d14c *tests/testthat/test-coords-translate.R f84d25ac73818ae0a26906bae946c10b *tests/testthat/test-coords.R bd7837250996fca1b1ae37908a3547ab *tests/testthat/test-debug.R ebc3f77b161f31f52e05a16ff8de7caf *tests/testthat/test-draw.R cd3eb94b12563aad400342e2c4e6d719 *tests/testthat/test-filters.R 3bdcc7047a3b0ddde358b69c5bc9a8b3 *tests/testthat/test-finite.R 76a275bd8e46090808d051e962ca9a20 *tests/testthat/test-grob.R d99a345473580019c5f8012d506e8dcf *tests/testthat/test-meta.R a47b578d83b447654b16cd103ddef9ce *tests/testthat/test-plot.R 38e9776dab091e512de0d4d7077e3d66 *tests/testthat/test-ranges.R 99fb351530970bdd5d853c1071d15eb8 *tests/testthat/test-unnest.R