Jim Lemon's thigmophobe function in the plotrix package computes good directions for labels in a 2D plot. This function does the same for a particular projection in a 3D plot by projecting down to 2D and calling his function.

thigmophobe3d(x, y = NULL, z = NULL,
P = par3d("projMatrix"),
M = par3d("modelMatrix"),
windowRect = par3d("windowRect"))

## Arguments

x, y, z point coordinates. Any reasonable way of defining the coordinates is acceptable. See the function xyz.coords for details. The projection and modelview matrices, and the size and position of the display in pixels.

## Details

Since thigmophobe3d projects using fixed P and M, it will not necessarily choose good directions if the user rotates the display or makes any other change to the projection.

## Note

The example below shows how to update the directions during an animation; I find that the moving labels are distracting, and prefer to live with fixed ones.

## Value

A vector of values from 1 to 4 to be used as the pos argument in text3d.

plotrix

## Author

Duncan Murdoch

text3d

## Examples

if (requireNamespace("plotrix", quietly = TRUE)) {
# Simulate some data
xyz <- matrix(rnorm(30), ncol = 3)

# Plot the data first, to establish the projection
plot3d(xyz)

# Now thigmophobe3d can choose directions
textid <- text3d(xyz, texts = 1:10, pos = thigmophobe3d(xyz))

# Update the label positions during an animation
if (interactive() && !rgl.useNULL()) {
spin <- spin3d(rpm = 5)
f <- function(time) {
par3d(skipRedraw = TRUE)
on.exit(par3d(skipRedraw = FALSE))
pop3d(id = textid)
# Need to rotate before thigmophobe3d is called
result <- spin(time)
par3d(userMatrix = result\$userMatrix)
textid <<- text3d(xyz, texts = 1:10, pos = thigmophobe3d(xyz))
result
}
play3d(f, duration = 5)
} else
textid   # just print the static display
}

{"x":{"material":{"color":"#000000","alpha":1,"lit":true,"ambient":"#000000","specular":"#FFFFFF","emission":"#000000","shininess":50,"smooth":true,"front":"filled","back":"filled","size":3,"lwd":1,"fog":true,"point_antialias":false,"line_antialias":false,"texture":null,"textype":"rgb","texmipmap":false,"texminfilter":"linear","texmagfilter":"linear","texenvmap":false,"depth_mask":true,"depth_test":"less","isTransparent":false,"polygon_offset":[0,0],"margin":"","floating":false},"rootSubscene":1686,"objects":{"1693":{"id":1693,"type":"points","material":{"lit":false},"vertices":[[-0.0165022350847721,0.325173050165176,0.399703741073608],[1.741544008255,0.0694453716278076,-0.221697375178337],[0.543411493301392,1.49068033695221,-0.784249722957611],[1.24753499031067,-0.140793651342392,-1.70900797843933],[0.899816393852234,-0.641633331775665,0.507175028324127],[0.116094887256622,0.262625485658646,-2.12193417549133],[1.09585046768188,1.01582396030426,0.116599455475807],[-0.949470102787018,-0.422809720039368,1.83467650413513],[1.73623871803284,-0.38835084438324,0.576871693134308],[-0.746923089027405,1.27877962589264,0.450023144483566]],"colors":[[0,0,0,1]],"centers":[[-0.0165022350847721,0.325173050165176,0.399703741073608],[1.741544008255,0.0694453716278076,-0.221697375178337],[0.543411493301392,1.49068033695221,-0.784249722957611],[1.24753499031067,-0.140793651342392,-1.70900797843933],[0.899816393852234,-0.641633331775665,0.507175028324127],[0.116094887256622,0.262625485658646,-2.12193417549133],[1.09585046768188,1.01582396030426,0.116599455475807],[-0.949470102787018,-0.422809720039368,1.83467650413513],[1.73623871803284,-0.38835084438324,0.576871693134308],[-0.746923089027405,1.27877962589264,0.450023144483566]],"ignoreExtent":false,"flags":34816},"1695":{"id":1695,"type":"text","material":{"lit":false,"margin":0,"floating":true,"edge":[0,1,1]},"vertices":[["NaN",4,1]],"colors":[[0,0,0,1]],"texts":[["xyz[,1]"]],"cex":[[1]],"adj":[[0.5,0.5,0.5]],"centers":[["NaN",4,1]],"family":[["sans"]],"font":[[1]],"ignoreExtent":true,"flags":33808},"1696":{"id":1696,"type":"text","material":{"lit":false,"margin":1,"floating":true,"edge":[1,1,1]},"vertices":[["NaN",4,1]],"colors":[[0,0,0,1]],"texts":[["xyz[,2]"]],"cex":[[1]],"adj":[[0.5,0.5,0.5]],"centers":[["NaN",4,1]],"family":[["sans"]],"font":[[1]],"ignoreExtent":true,"flags":33808},"1697":{"id":1697,"type":"text","material":{"lit":false,"margin":2,"floating":true,"edge":[1,1,1]},"vertices":[["NaN",4,1]],"colors":[[0,0,0,1]],"texts":[["xyz[,3]"]],"cex":[[1]],"adj":[[0.5,0.5,0.5]],"centers":[["NaN",4,1]],"family":[["sans"]],"font":[[1]],"ignoreExtent":true,"flags":33808},"1698":{"id":1698,"type":"text","material":{"lit":false},"vertices":[[-0.0165022350847721,0.325173050165176,0.399703741073608],[1.741544008255,0.0694453716278076,-0.221697375178337],[0.543411493301392,1.49068033695221,-0.784249722957611],[1.24753499031067,-0.140793651342392,-1.70900797843933],[0.899816393852234,-0.641633331775665,0.507175028324127],[0.116094887256622,0.262625485658646,-2.12193417549133],[1.09585046768188,1.01582396030426,0.116599455475807],[-0.949470102787018,-0.422809720039368,1.83467650413513],[1.73623871803284,-0.38835084438324,0.576871693134308],[-0.746923089027405,1.27877962589264,0.450023144483566]],"colors":[[0,0,0,1]],"texts":[["1"],["2"],["3"],["4"],["5"],["6"],["7"],["8"],["9"],["10"]],"cex":[[1]],"adj":[[0.5,0.5,0.5]],"centers":[[-0.0165022350847721,0.325173050165176,0.399703741073608],[1.741544008255,0.0694453716278076,-0.221697375178337],[0.543411493301392,1.49068033695221,-0.784249722957611],[1.24753499031067,-0.140793651342392,-1.70900797843933],[0.899816393852234,-0.641633331775665,0.507175028324127],[0.116094887256622,0.262625485658646,-2.12193417549133],[1.09585046768188,1.01582396030426,0.116599455475807],[-0.949470102787018,-0.422809720039368,1.83467650413513],[1.73623871803284,-0.38835084438324,0.576871693134308],[-0.746923089027405,1.27877962589264,0.450023144483566]],"family":[["sans"]],"font":[[1]],"pos":[[2],[1],[2],[4],[4],[2],[3],[2],[3],[4]],"ignoreExtent":false,"flags":33808},"1690":{"id":1690,"type":"light","vertices":[[0,0,1]],"colors":[[1,1,1,1],[1,1,1,1],[1,1,1,1]],"viewpoint":true,"finite":false},"1691":{"id":1691,"type":"background","material":{"lit":false,"back":"lines"},"colors":[[1,1,1,1]],"centers":[[0,0,0]],"sphere":false,"fogtype":"none","fogscale":1,"flags":32768},"1694":{"id":1694,"type":"bboxdeco","material":{"front":"lines","back":"lines"},"vertices":[[-0.5,"NA","NA"],[0,"NA","NA"],[0.5,"NA","NA"],[1,"NA","NA"],[1.5,"NA","NA"],["NA",-0.5,"NA"],["NA",0,"NA"],["NA",0.5,"NA"],["NA",1,"NA"],["NA","NA",-2],["NA","NA",-1],["NA","NA",0],["NA","NA",1]],"colors":[[0,0,0,1]],"axes":{"mode":["pretty","pretty","pretty"],"step":[0.5,0.5,1],"nticks":[5,5,5],"marklen":[15,15,15],"expand":[1.02999997138977,1.02999997138977,1.02999997138977]},"draw_front":true},"1686":{"id":1686,"type":"subscene","par3d":{"antialias":8,"FOV":30,"ignoreExtent":false,"listeners":1686,"mouseMode":{"none":"none","left":"trackball","right":"zoom","middle":"fov","wheel":"pull"},"observer":[0,0,12.8189535140991],"modelMatrix":[[1.12393152713776,0,0,-0.445118397474289],[0,0.485128134489059,0.718320667743683,-0.102776743471622],[0,-1.33287858963013,0.261447340250015,-12.2155637741089],[0,0,0,1]],"projMatrix":[[3.73205089569092,0,0,0],[0,3.73205089569092,0,0],[0,0,-3.86370325088501,-46.2108459472656],[0,0,-1,0]],"skipRedraw":false,"userMatrix":[[1,0,0,0],[0,0.342020143325668,0.939692620785909,0],[0,-0.939692620785909,0.342020143325668,0],[0,0,0,1]],"userProjection":[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],"scale":[1.12393152713776,1.41841971874237,0.764420866966248],"viewport":{"x":0,"y":0,"width":1,"height":1},"zoom":1,"bbox":[-0.949470102787018,1.741544008255,-0.641633331775665,1.49068033695221,-2.12193417549133,1.83467650413513],"windowRect":[0,0,256,256],"family":"sans","font":1,"cex":1,"useFreeType":true,"fontname":"NULL","maxClipPlanes":2147483647,"glVersion":"NA","activeSubscene":0},"embeddings":{"viewport":"replace","projection":"replace","model":"replace","mouse":"replace"},"objects":[1691,1694,1693,1695,1696,1697,1698,1690],"subscenes":[],"flags":36112}},"crosstalk":{"key":[],"group":[],"id":[],"options":[]},"width":480,"height":480,"context":{"shiny":false,"rmarkdown":null},"players":[],"webGLoptions":{"preserveDrawingBuffer":true}},"evals":[],"jsHooks":[]}