[R] Add transitivity to a matrix?

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Tue Jun 18 15:44:02 CEST 2019


On 18/06/2019 9:01 a.m., Eric Berger wrote:
> Very nice, Peter.
> Here is one version of Peter's suggestion expressed in R code
> 
> M <- M | t(M)  # first step as symmetric matrix as stated by OP
> Q <- M
> for ( i in 2:(ncol(Q)-1) )
>     Q <- Q + Q %*% M
> 
> R <- (Q > 0)
> R
> 

That's not quite the same calculation as Peter suggested, but I think 
it's also going to work.  Of course, I might use seq_len(ncol(Q) - 2) 
instead of 2:(ncol(Q)-1), but that also won't make a difference in the 
final result.

Thanks to everyone who has suggested calculations here.  I'm glad we saw 
such good suggestions, because (I'm embarrassed to say) it turns out 
that I don't actually want transitivity after all.

In case anyone is interested, here's the application:

I was asked whether rgl could render a surface made up of triangles or 
quadrilaterals to look smooth.  It can do that, but needs normals at 
each vertex; they should be the average of the normals for each polygon 
sharing that vertex.  Then OpenGL will interpolate the normals across 
the polygons and give the illusion of smoothness.

To do this, it needs to know which polygons share each vertex.  If the 
surface is described as a list of triangles or quadrilaterals, that 
means identifying vertices that are in multiple polygons, and converting 
the representation to a "mesh3d" object (which is a matrix of vertices 
and a matrix of vertex numbers making up triangles or quads).  Then the 
addNormals() function will add the normals.

But sometimes two polygons will share vertices (within numerical 
tolerance) without the user wanting them to be considered internal to 
the surface, or you might want one sharp edge in an otherwise smooth 
surface.  This means I needed a way to declare that two vertices from 
the original list of vertices in the triangles or quads are "not equal", 
even when they test numerically equal.

That's what was going to be the matrix R in Eric's notation.  If vertex 
i and vertex j test equal, but R[i,j] is TRUE, they should not be merged 
into a single vertex.  Clearly symmetry is a requirement.

The transitivity came in when I thought about how the user would specify 
the matrix.  It's really tedious to enter a full matrix, so I wanted to 
allow the user to give less information and have the function fill out 
the rest.  For example, if I compute

cube <- cube3d()
x <- cube$vb[1, c(cube$ib)]
y <- cube$vb[2, c(cube$ib)]
z <- cube$vb[3, c(cube$ib)]

then quads3d(x,y,z, col = "red") will plot a red cube, but without 
information about which faces are joined.  It works with this matrix of 
vertices:

 > cbind(x,y,z)
        x  y  z
  [1,] -1 -1 -1
  [2,] -1  1 -1
  [3,]  1  1 -1
  [4,]  1 -1 -1
  [5,] -1  1 -1
  [6,] -1  1  1
  [7,]  1  1  1
  [8,]  1  1 -1
  [9,]  1 -1 -1
[10,]  1  1 -1
[11,]  1  1  1
[12,]  1 -1  1
[13,] -1 -1 -1
[14,] -1 -1  1
[15,] -1  1  1
[16,] -1  1 -1
[17,] -1 -1 -1
[18,]  1 -1 -1
[19,]  1 -1  1
[20,] -1 -1  1
[21,] -1 -1  1
[22,]  1 -1  1
[23,]  1  1  1
[24,] -1  1  1

and plots a quadrilateral for each successive group of 4 vertices.

Now I can see that vertices 1, 13 and 17 are the same, and my algorithm 
would merge them into one unless told not to.  So I thought a user 
should be able to say they are not equal by saying 1 != 13, 1 != 17 and 
transitivity would yield 13 != 17.  But in fact, a user might want to 
merge 13 and 17, but keep 1 separate:  so I don't want transitivity, I 
only want symmetry.  After setting

M <- matrix(FALSE, 24,24)
M[1, 13] <- TRUE
M[1, 17] <- TRUE

I should get different results if I set

M[13, 17] <- TRUE

or leave it FALSE.

Hopefully people found the transitivity discussion interesting, even if 
I won't use it for this problem.

Duncan Murdoch



More information about the R-help mailing list