edge_angles_yw: Compute edge angles using Yezzi-Woodley et al.'s method

View source: R/edgeAngles_yw.R

edge_angles_ywR Documentation

Compute edge angles using Yezzi-Woodley et al.'s method

Description

[Experimental]

This is a partial implementation of the Virtual Goniometer algorithm proposed by Yezzi-Woodley et al. (2021) for measuring edge angles. It works by selecting a patch of mesh vertices (i.e., surface points) around a user-specified point of interest (POI) and approximating two intersecting planes within the patch.

Usage

edge_angles_yw(mesh, poi, radius = 3, lambda = 2)

Arguments

mesh

A triangular mesh (mesh3d) object on which edge angles will be measured.

poi

A point of interest (i.e., POI) where the edge angle will be measured; represented as a 1X3 matrix-like object containing x, y, and z coordinates. Please ensure it is on the mesh surface (see Details).

radius

A positive numeric value indicating the search radius from the poi for including mesh vertices in the angle measurements (see details)

lambda

A positive numeric value used as a tuning parameter for the underlying clustering algorithm (see details)

Details

This function and its helpers are a modified partial translation of the C++ code developed by the AMAAZE consortium as a Meshlab plugin (Meshlab extra plugins). The full details of how the algorithm works can be found in Yezzi-Woodley et al. (2021). The main differences between this implementation and the original are:

  • This implementation only provides one way of specifying the measurement point: the "xyz method" described in Yezzi-Woodley et al. (2021).

  • This implementation selects mesh surface points for the angle computations using Euclidean rather than geodesic distances. The results are very similar whether geodesic or Euclidean distances are used (see Yezzi-Woodley et al., 2021), although there may be rare instances where substantial differences may be observed (see Issue #20).

  • Unlike the Meshlab plugin, this implementation uses the input POI as-is; in other words, no attempt is made to project it onto the mesh surface. If such projection is needed, process the POI with mapOnMesh() or a similar function first. To guarantee that the POI is on the mesh surface, it is recommended that the POI be selected with the mesh_mark_pois() function. Note that a warning will be generated if the POI is at a distance greater than 1/10th of the requested radius from the nearest mesh vertex.

Value

A list containing:

  1. angle: a numeric value corresponding to the measured angle, in degrees.

  2. seg_1: a 2x3 data.frame object with the x, y, and z coordinates (one per row) of the end points of the first intersecting line segment (perpendicular to the edge, and along the first intersecting surface). The length of the segment corresponds to the input radius value.

  3. seg_2: a 2x3 data.frame object with the x, y, and z coordinates (one per row) of the end points of the second intersecting line segment (perpendicular to the edge, and along the second intersecting surface). The length of the segment corresponds to the input radius value.

  4. ip: a 1x3 data.frame object with the x, y, and z coordinates of the seg_1 and seg_2 intersection point. Corresponds to the input POI (see Notes).

  5. diag: a list with other diagnostic data including: a. method: a string with the name of the method used to measure the angle (i.e., YW2021). b. timestamp: a string with the time when the angle was measured.

Note

  1. Some of the information in the return value is redundant because it is in a standardized format to be used with multiple edge angle measurement functions.

  2. The intersecting planes, and therefore seg_1 and seg_2, are shifted so that their intersection point corresponds to the input POI.

Author(s)

Cornel M. Pop, and AMAAZE (original Meshlab implementation)

See Also

mesh_mark_pois(), drop_poi()

Examples

# Load demo data
library(rgl)
mesh <- demoFlake2$mesh
mesh <- Rvcg::vcgUpdateNormals(mesh) # ensure normals are up to date

# Set a point where the angles will be measured. You can use the
# interactive mesh_mark_pois() to select this point, you can import
# its coordinates from another program (e.g., Meshlab), or you can specify
# its coordinates manually as done here:
poi <- data.frame(x = c(-20.1301), y = c(39.29581), z = c(413.7))

# Compute the edge angle at the set point using default options
res <- edge_angles_yw(mesh, poi)

# Visualize the angle measurement:
## Not run: 
shade3d(mesh, col = "green", alpha = 0.5) # Show the mesh
points3d(poi, col = "yellow", size = 10) # show the POI

# Determine which mesh vertices where included in the patch
patch_coords <- t(mesh$vb)[res$diag$patch_vertex_ids, ]

# Show the mesh vertices color-coded by the surface to which they were
# assigned by the clustering algorithm
points3d(patch_coords[which(res$diag$C == 1), 1:3], col = "red") # Surface 1
points3d(patch_coords[which(res$diag$C == 2), 1:3], col = "blue") # Surface 2

# Show the measurement plane for the angle:
res_planes <- planeCoefs(rbind(poi, poi + res$diag$m1, poi + res$diag$m2))
planes3d(res_planes[1], res_planes[2], res_planes[3], res_planes[4],
         col="cyan")

# Show the line segments where the angle was measured, and their endpoints:
lines3d(res$seg_1, col = "black", lwd = 10)
lines3d(res$seg_2, col = "black", lwd = 10)
points3d(rbind(res$seg_1[2, ], res$seg_2[2, ]), col = "black", size = 10)

## End(Not run)

cornelmpop/Lithics3D documentation built on Feb. 10, 2024, 11:54 p.m.