stla / cgalMeshes

R6 based utilities for 3D meshes.
15 stars 2 forks source link

Memory corruption issue #2

Closed dwoll closed 1 year ago

dwoll commented 2 years ago

Adapting my Shiny app to cgalMeshes, I think I've encountered a memory corruption issue. Given the three attached meshes (renamed to *.PLY, the following code reliably crashes R for me (R 4.2.0 on Linux via Windows WSL2, 4.2.1 on Windows 10, error "memory not mapped"). While the crash occurs when calling Rvcg::vcgMetro(), I think the issue is caused earlier on. Depending on previous operations on the cgalMesh objects, the crash occurs in earlier or later calls to vcgMetro(). For example, omitting the calls mesh$volume() and mesh$centroid() makes the code run through without errors. Adding more calls makes R crash earlier.

library(cgalMeshes)
library(SurfaceReconstruction)
library(Rvcg)

read_mesh <- function(x) {
    mesh <- cgalMesh$new(x)
    if(!mesh$isClosed() || !mesh$boundsVolume()) {
        mesh_r <- AFSreconstruction(mesh$vertices())
        mesh   <- cgalMesh$new(mesh_r)
        mesh$orientToBoundVolume()
    }

    if(mesh$selfIntersects()) {
        mesh$removeSelfIntersections()
    }

    list(mesh=mesh,
         volume=mesh$volume(),
         centroid=mesh$centroid())
}

get_mesh_metro_pair <- function(x, ...) {
    mesh1_rgl <- x$mesh1$mesh$getMesh(normals=FALSE)
    mesh2_rgl <- x$mesh2$mesh$getMesh(normals=FALSE)
    vcgMetro(mesh1_rgl, mesh2_rgl, ...)
}

## all pairs from list of meshes
get_mesh_pairs <- function(x) {
    pairs_idx <- t(combn(seq_along(x), 2))
    lapply(seq_len(nrow(pairs_idx)), function(i) {
        idx1  <- pairs_idx[i, 1]
        idx2  <- pairs_idx[i, 2]
        mesh1 <- x[[idx1]]
        mesh2 <- x[[idx2]]
        list(mesh1=mesh1, mesh2=mesh2)
    })
}

ff <- list.files("data/", pattern="HEART", full.names=TRUE)

meshL <- Map(read_mesh, ff)

pairL  <- get_mesh_pairs(meshL)
metro1 <- get_mesh_metro_pair(pairL[[1]])
metro2 <- get_mesh_metro_pair(pairL[[2]])
metro3 <- get_mesh_metro_pair(pairL[[3]])

HEART_OBS1.txt HEART_OBS2.txt HEART_OBS3.txt

stla commented 2 years ago

Hi,

I reported a bug today to the CGAL team, maybe it's the same issue.

stla commented 1 year ago

The problem regarding the centroid is solved.

dwoll commented 1 year ago

Thanks for looking into this! Further testing showed that in the (simplified) script I use, R does not crash when commenting out the call to removeSelfIntersections(). Otherwise, R crashes for with get_mesh_metro_pair(pairL[[4]]) when vcgMetro() is called. Simply printing the exported mesh3d objects in get_mesh_metro_pair() does not trigger the crash.

library(cgalMeshes)
library(Rvcg)

ff <- list.files("data/", pattern="HEART.+\\.ply", full.names=TRUE)

read_mesh <- function(x) {
    mesh <- cgalMesh$new(x)
    if(!mesh$isClosed() || !mesh$boundsVolume()) {
        mesh_r <- AFSreconstruction(mesh$vertices())
        mesh   <- mesh_r
        mesh$orientToBoundVolume()
    }

    # if commenting out the following line, R does not crash
    mesh$removeSelfIntersections()
    mesh
}

get_mesh_metro_pair <- function(x, ...) {
    mesh1_rgl <- x$mesh1$getMesh(normals=FALSE)
    mesh2_rgl <- x$mesh2$getMesh(normals=FALSE)
    vcgMetro(mesh1_rgl, mesh2_rgl, ...)
}

## all pairs from list of meshes
get_mesh_pairs <- function(x) {
    pairs_idx <- t(combn(seq_along(x), 2))
    lapply(seq_len(nrow(pairs_idx)), function(i) {
        idx1  <- pairs_idx[i, 1]
        idx2  <- pairs_idx[i, 2]
        mesh1 <- x[[idx1]]
        mesh2 <- x[[idx2]]
        list(mesh1=mesh1, mesh2=mesh2)
    })
}

meshL  <- lapply(ff, read_mesh)
pairL  <- get_mesh_pairs(meshL)
metro1 <- get_mesh_metro_pair(pairL[[1]])
metro2 <- get_mesh_metro_pair(pairL[[2]])
metro3 <- get_mesh_metro_pair(pairL[[3]])
metro4 <- get_mesh_metro_pair(pairL[[4]])
metro5 <- get_mesh_metro_pair(pairL[[5]])
metro6 <- get_mesh_metro_pair(pairL[[6]])
metro7 <- get_mesh_metro_pair(pairL[[7]])

HEART_OBS1.txt HEART_OBS2.txt HEART_OBS3.txt HEART_OBS4.txt HEART_OBS5.txt HEART_OBS6.txt HEART_OBS7.txt

stla commented 1 year ago

Hi,

removeSelfIntersections calls an experimental CGAL function. Do you know which mesh triggers the crash? I can report this issue to the CGAL team.

stla commented 1 year ago

PS: you don't need the SurfaceReconstruction package anymore: the AFS reconstruction is now implemented in cgalMeshes.

dwoll commented 1 year ago

Good thinking. Perhaps the attached mesh is somewhat responsible. With pairL as defined above, these comparisons all crash:

metro4 <- get_mesh_metro_pair(pairL[[4]])  # mesh 1 vs. 5
metro7 <- get_mesh_metro_pair(pairL[[9]])  # mesh 2 vs. 5
metro16 <- get_mesh_metro_pair(pairL[[16]]) # mesh 4 vs. 5
metro19 <- get_mesh_metro_pair(pairL[[19]]) # mesh 5 vs. 6
metro20 <- get_mesh_metro_pair(pairL[[20]]) # mesh 5 vs. 7

Oddly, this comparison involving mesh 5 does not crash

metro13 <- get_mesh_metro_pair(pairL[[13]]) # mesh 3 vs. 5

HEART_OBS5.txt

stla commented 1 year ago

Thanks. Issue reported: https://github.com/CGAL/cgal/issues/7019

stla commented 1 year ago

Fixed now!

dwoll commented 1 year ago

Great, many thanks! I confirm that R does not crash anymore with the calculations I'm doing.