A surface traced a second time counted twice, so a buffer that should read near 100% classified could report 191%. Polygons with identical geometry are now collapsed to one on read. Genuine overlap -- a tree crown over a roof -- is different geometry and is untouched.
Which copy survives depends on what it carries: if only one has a class code that one is kept; if the codes conflict the first is kept and the conflicting pair is named, because silently choosing between two interpretations would hide a decision the interpreter should make.
A new coverage_flag column marks any site still above 120% after that, so
duplication the geometric test cannot see is reported rather than passed on
quietly. Coverage above 100% remains legitimate and is not flagged.
Several classes were too close to tell apart, most visibly main thoroughfare against formal parking. Every pair is now either at least 14 CIELAB units apart or separated by a texture; measured across all 378 pairs, none is ambiguous.
Where two classes genuinely look alike from above, the texture carries meaning: a grid for parking bays, vertical strokes for the deep shadow of an alley, horizontal strokes for the linear flow of a channel, a fine diagonal for a finished slab. Eight of the 28 classes now carry a texture, up from four.
Class labels were cut at 32 characters, losing the end of names such as "Fibre-cement or asbestos sheeting". The column is wider and labels now run to 40 characters, which covers the longest name in the schema.
"unsealed tank (oviposition risk)" is now "apparently unsealed tank", and "sealed tank" is "apparently sealed tank". What aerial imagery supports is an appearance, not a determination: a lid is not always visible from above, and the figures should not claim more than the method can deliver.
Four failures reported from a 44-file field run, all fixed. Two of them could end a long run with nothing usable on disk.
TopologyException and the whole
file was abandoned. Geometry is now repaired on read and again after
reprojection, and an overlay that still fails is retried on repaired inputs,
then at reduced precision, then polygon by polygon. Only genuinely
irreparable polygons are skipped, and they are reported.pivot_wider() returned list-columns, and
writexl refused the lot -- discarding every table at the end of the run.
Such sites are now kept separately as ID__file, matching how their maps are
already named. As a backstop the writer flattens anything non-atomic, and if
the workbook still cannot be written the tables are saved as CSV.mare_categories previously held 29 classes in 12 groups. The article and
protocol define 28 classes in nine thematic groups, with class 29 (PVC
roofing) removed once the nomenclature stabilised and class 24 revised. The
dataset is now identical to Table 1: same identifiers, same English labels, same
grouping. Identifiers stayed contiguous, so no surviving class was renumbered.
This changes output column names. Columns are built as
id_category_description, and category now carries the nine thematic groups
(roofing, vegetation, circulation_parking, ...) rather than the earlier
twelve Portuguese labels. Analyses that referred to the old column names must be
updated. Areas, weights and counts are unchanged.
Any data still coded with class 29 will be reported as an unrecognised code rather than silently dropped, which is the intended behaviour.
buffer_composition() and batch_composition() now read GeoPackage as
well as KML. The format is detected from the file's contents rather than its
extension, and a folder may mix the two. A file may contain one site or
several in either format; nothing needs to be configured.focal_points and landcover layers, and
optionally buffers, water_containers, poi_lines and class_dictionary.
Anything else falls back to the flat reader used for KML.NH_6 rather than
NH_6_Buffer) was treated as an unclassified land-cover polygon and dropped
with a warning. It is now recognised as reference geometry, so the buffer
cross-check works on these files.bufferscape::class_dictionary() failed with "object 'mare_categories' not
found" unless the package had been attached with library(). Lazy-loaded data
is not on the namespace search path; the lookup is now explicit.batch_composition() were missing the
_d_nearest_m proximity columns.buffer_composition(kml = ) is now path = , and
batch_composition(kml_dir = ) is now dir = , because neither is
KML-specific any more. The old names still work and warn.batch_composition(): requesting a basemap with
make_maps = TRUE failed with "could not find function basemap_ready". The
helper that checks whether the imagery packages are installed had been lost in
a refactor while its call site remained.R CMD check no longer reports undefined globals.batch_composition() now goes through message() rather
than cat(), so a run can be silenced with suppressMessages(). CRAN policy
asks that packages not write to the console in a way the user cannot suppress.README.md, CITATION.cff and
inst/CITATION, so citation("bufferscape") returns it.DESCRIPTION, CITATION.cff and inst/CITATION now match
the release tag; 1.0.0 was tagged while the package still declared 0.1.0.CITATION.cff, so the repository exposes citation metadata to GitHub
and to archives such as Zenodo.First release.
buffer_composition() computes per-class surface area within buffers around
point locations, directly from vector polygons. It returns the exact area, a
distance-decay weighted area in which the kernel is integrated over polygon
geometry (area_w), the centroid-weighted equivalent for comparison
(area_w_centroid), and the distance to the nearest patch of each class
(d_nearest_m).decay_kernel() provides bounded exponential and Gaussian kernels.batch_composition() processes a folder, writing a workbook and figures. A
malformed file is logged and skipped rather than stopping the run.class_dictionary() accepts a data.frame
or an .xlsx/.csv path; validate_dictionary() checks one before a long
run. The 29-class Maré schema ships as mare_categories.parse_class_codes() keeps hyphenated codes such as "8-6", which naive
coercion would silently drop.centroid_bias() and summarise_centroid_bias() quantify, polygon by
polygon, how far centroid weighting departs from the exact integral, with
shape descriptors and a centroid_inside flag for concave features whose
centroid falls outside the polygon.map_composition() draws the land-cover map; map_basemap() and
map_combined() add satellite imagery.plot_site_composition() and plot_group_points() give per-site composition
bars and per-group point-feature bars.class_palette() provides four schemes: "aerial" (appearance-matched),
"colorblind" (one colour-vision-safe hue per group, members separated by
lightness and texture), "viridis" and "greyscale". resolve_palette()
also accepts a palette table or a named colour vector.write_composition_report() writes the workbook, with control over radii,
which surface metrics to include, which sheets, label style and rounding.