View source: R/edgeAngles_yw.R
edge_angles_yw | R Documentation |
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.
edge_angles_yw(mesh, poi, radius = 3, lambda = 2)
mesh |
A triangular mesh ( |
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
|
lambda |
A positive numeric value used as a tuning parameter for the underlying clustering algorithm (see 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.
A list containing:
angle
: a numeric value corresponding to the measured angle, in degrees.
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.
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.
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).
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.
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.
The intersecting planes, and therefore seg_1
and seg_2
, are shifted so
that their intersection point corresponds to the input POI.
Cornel M. Pop, and AMAAZE (original Meshlab implementation)
mesh_mark_pois()
, drop_poi()
# 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)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.