--- title: "Reports, the 3D views and the interactive model" output: rmarkdown::html_vignette: toc: true vignette: > %\VignetteIndexEntry{Reports, the 3D views and the interactive model} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5, dpi = 96, out.width = "100%") # on Linux the default X11 png device cannot draw semi-transparent fills; use cairo there if (Sys.info()[["sysname"]] == "Linux" && isTRUE(capabilities("cairo"))) knitr::opts_chunk$set(dev.args = list(png = list(type = "cairo"))) library(forensicR) ``` ## The report in one call `render_scene_report()` renders one R Markdown template to Word, PDF and HTML. You pass the objects you built as `params`; any section whose object is missing prints a placeholder line instead of failing. ```{r report, eval = FALSE} out <- render_scene_report( output_dir = "report", formats = c("docx", "pdf", "html"), # any subset params = list( case_id = "2026-004417", agency = "Douglas County Sheriff's Office", investigator = "K. Quadros", scene_date = as.Date("2026-09-06"), units = "m", narrative = "Single-family residence, living room. ...", # markdown text points = scene, # coords_*() tibble walls = walls, # room_rect() + opening() furniture = furn, # furniture() tibble wall_height = 2.5, shooting = list( impact = impact_angle(c(9.1, 6.0), c(9.3, 12.5), se = 0.5), trajectories = list(t_rod, t_2pt, shot4), # trajectories and/or paths heights = c(standing = 1.5, kneeling = 1.0, prone = 0.3), max_distance = 12 ), evidence = log, # evidence_log() death_scene = ds, # death_scene_record() scene3d = TRUE # 3D figure (PDF/Word) or widget (HTML) ) ) out # named paths of the files produced ``` ### What the report contains 1. Case header and narrative. 2. Scene sketch, table of points with heights, table of objects, and an elevation of each wall. 3. Shooting reconstruction: impact angles, trajectory table with uncertainties, plan view with convergence, elevation view, origin at assumed heights per trajectory, objects on the paths, segmented paths and their deflections, convergence table. 4. Evidence log with photo hashes. 5. Chain of custody. 6. Death scene observations (observations only; no estimate of time since death, which is the coroner's determination). Every output ends with one line stating the forensicR version, the R version and the time of rendering. ### Word first The intended workflow is: render, open the `.docx`, paste in the agency header and photographs, edit the wording, print to PDF for approval. If a measurement is corrected later, re-render and the figures and tables update together. The template is deliberately plain so that it takes your agency's styles when pasted. To make Word output match a house style automatically, copy the template, add a `reference_docx` to its `word_document` output options and pass the copy as `input`: ```{r template, eval = FALSE} scene_report_skeleton("my-agency-report.Rmd") # editable copy of the template render_scene_report(input = "my-agency-report.Rmd", output_dir = "report", params = list(...)) ``` ## The 3D views Both 3D back ends draw the *same* objects as the 2D plots: walls with door and window panels, a floor grid with numbered x and y axes and height numbers up the walls, numbered evidence markers, bullet defects at their measured height, schematic bloodstain discs, furniture as semi-transparent boxes, trajectories as rods with arrowheads, and uncertainty cones as wireframes. They are schematic on purpose: a courtroom demonstrative must be to scale and must not add detail that was not measured. ### Still image (rayrender) ```{r still, eval = FALSE} render_scene_3d(walls, scene, trajs, furniture = furn, file = "scene3d.png", view = "dollhouse", # or "door", "corner", "overhead" grid_on = c("floor", "walls"), grid_strength = 0.6, grid_labels = TRUE, furniture_alpha = NULL, # per-object opacity unless overridden samples = 128) # more samples = less grain, more time ``` ```{r fig-doll, echo = FALSE, fig.cap = "view = \"dollhouse\": from outside, south wall removed."} knitr::include_graphics("figures/getting-started-dollhouse.png") ``` ```{r fig-door, echo = FALSE, fig.cap = "view = \"door\": standing in the doorway at eye level, looking at the defects. The rings are the bases of the uncertainty cones, i.e. roughly where the shooter stood."} knitr::include_graphics("figures/getting-started-door.png") ``` Camera presets can be replaced by explicit `lookfrom` and `lookat` positions in scene coordinates, and any wall can be removed with `omit_wall` so an outside camera can see in. Rendering a 1000 by 750 image at 128 samples takes roughly 20 to 40 seconds on a laptop. ### Interactive model (rgl) ```{r widget, eval = FALSE} w <- scene_3d_widget(walls, scene, trajs, furniture = furn) w # in RStudio's viewer htmlwidgets::saveWidget(w, "scene3d.html", selfcontained = TRUE) # to share ``` The HTML report embeds this widget when `scene3d = TRUE`. It needs WebGL in the reader's browser. If WebGL is unavailable the report hides the empty widget and shows the still image with a note, so the reader never sees a blank space. To enable WebGL in Chrome: turn on hardware acceleration in *Settings, System*; if that is not enough, enable "Override software rendering list" in `chrome://flags`; on machines without a usable GPU start Chrome with `--use-angle=swiftshader --enable-unsafe-swiftshader`. Firefox usually has WebGL on by default. ## Installing the optional pieces ```{r install, eval = FALSE} install.packages(c("rayrender", "rgl")) # 3D still image and interactive model tinytex::install_tinytex() # if you have no LaTeX and want PDF output ``` Without them everything else works: plots, tables, Word and HTML reports.