Problem: Iterating across network display algorithms provides updates to each nodes' XYZ coordinate. Trying to graph this in a smooth way does not seem to be able to avoid the wireframe reloading, leading to a strobing effect. Codebase and video attached.
Description:
Current example is a ring network, meaning an adjacency matrix where each node is connected to the two nodes ahead and behind. Nodes begin in a random XYZ coordinate of consistent radius from (0,0,0), and then undergo the sorting algorithm that updates each nodes' xyz location.
Current best solution:
Using the RGL package, the network_plot3d function is careful to only open one RGL object and to not clear3d the whole graph. Options are to either use [rgl.pop3d(type="shapes") to try to clear the graph without the wireframe reloading, or to use the deprecated rgl.clear() and to suppress the warnings.
Is there a way to smoothly update only the objects on the screen and not the wireframe? is there another package
Attached is code and video.
Video - https://youtu.be/0EAFZiIyRXg
-
- Network_Plot3d - trying to update the graph without clearing the whole graph.
-
- Sort.surface.sort - the updater.
Network_plot3d<-function(attr, edgelist, layout.par = "layout.par") {
# This function will use 'plot3d' to display networks.
# First, it plots the points as spheres. Radius of
# spheres can be related to the number of links (hubs are big)
# The 'natural' sphere size is '3' or 1/20th of the plot.
# df<-update_vertex_count(df,layout.par) #sets size according to degree distribution
lines <- layout.par["lines"]
if (rgl.cur() == 0) {
open3d() # opens the rgl window the first time.
} else {
if (nrow(rgl.ids()) > 0) {
#print("deleting stuff")
rgl.clear()
#print(nrow(rgl.ids(type="shapes")))
}
}
plot3d(attr[, 1:3],
col = attr[, 7],
type = "s",
size = attr[, 8],
xlim = c(-layout.par["xlim"], layout.par["xlim"]),
ylim = c(-layout.par["ylim"], layout.par["ylim"]),
zlim = c(-layout.par["zlim"], layout.par["zlim"])
)
# Now that the points are graphed, we need to get an edgelist
if (lines == TRUE) {
edges <- edge_locations(attr, edgelist)
lines3d(edges)
}
}
sort.surface.sort <- function(attr,edges,layout.par,mod=0){ #This is the original. All nodes go to the average of their neighbors,
#then the nodes blow out from the geometric mean of the network. Result is always a full sphere.
if (mod==0){mod<-layout.par["iterations"]+1} #This sets the mods to the layout.par value, if nothing is given. This controls how often in the iterations to graph.
iterations<-layout.par["iterations"] #sets how many times to run the algorithm
lines<-layout.par["lines"] #should it include lines or only nodes in the final graph?
layout.par["lines"]<-FALSE #turns off lines during the intermediate graphs
nw<-network(edges, directed = layout.par["directed"]) #Uses the provided edgelist, and network package to interpret the edgelist.
hood_list<-get_neighborhoods(nw) #Generates a neighborhood list for all nodes. This happens inside the sort command to allow for network manipulations to exist later -
loud <-layout.par["verbose"] #turns on or off most print messages.
#sort will automatically regenerate from a newly provided edgelist.
attr<-degree_scaler(attr,layout.par) #degree_scaler generates a radius number, with major hubs getting close to zero. however, I'm not sure THIS script actually uses this.
if (loud == 1) # note that TRUE was stored in layout.par["verbose"] as a 1
(print("first it recenters and normalizes everyone to their proper radius"))
attr<-recenter(attr)
attr<-normalize_subjective(attr,target_list=1:nrow(attr),layout.par)
if (loud == 1) (print("Then it moves everyone to their geometric mean - do in order by hubs?"))
for (i in 1:iterations){
if (loud == 1) (print(i))
attr<-geo_mean(hood_list,attr,batch=TRUE,target_list=1:nrow(attr))
attr<-recenter(attr)
attr<-normalize_subjective(attr,target_list=1:nrow(attr),layout.par)
if (i%%mod==0){network_plot3d(attr,edges,layout.par)}
}
#df<-pendulums(df,layout.par,FALSE)
layout.par["lines"]<-lines
pop3d(type="shapes")
#resize(attr,layout.par)
network_plot3d(attr,edges,layout.par)
return(attr)
}
To avoid the strobing, use
save <- par3d(skipRedraw = TRUE)before any changes, andpar3d(save)when they are done. Then the only update will be from the old display to the new one, with nothing drawn in between.