Comments (10)
This is one of the things I’ll be working on. You’re welcome to try with a PR
from ggraph.
@thomasp85 Is this high up on your list? I have fiddled a bit with this issue.
The function below allows to create a parallel line of an edge between midpoints of nodes.
the shift parameter controls the distance.
edge_shift <- function(x1,y1,x2,y2,shift){
v <- c(x2 - x1,y2 - y1)
v <- v/sqrt((v[1]^2 + v[2]^2))
v_perp <- c( -v[2], v[1] )
return(c(x1 + shift*vperp[1],y1 + shift*vperp[2],
x2 + shift*vperp[1],y2 + shift*vperp[2]))
}
of course this is no proper geom yet (ggproto is still mostly a mystery to me...) but if this is low priority for you I'll try to get my hands dirty on this.
from ggraph.
I want something that keeps the edge distance constant when resizing I think
from ggraph.
All right maybe I use this as an excuse to learn ggproto and see how far I can get
from ggraph.
I’ll help you through it. Just start a PR early on and I can come with suggestions
from ggraph.
Ok I got something, but not yet PR worthy due to some major issue outlined further down.
# function to create parallel edges ----
create_parallels <- function(data,params) {
data$origID <- 1:nrow(data)
data$.id <- paste(pmin(data$from, data$to), pmax(data$from, data$to), sep = '-')
data <- data %>% arrange(.id)
medge <- data %>%
group_by(.id) %>%
dplyr::summarise(medge=n()) %>%
ungroup() %>%
transmute(medge)
medge <- medge$medge
medge_shift <- unlist(sapply(medge,dseq,spread=params$spread))
data$shift <- medge_shift*ifelse(data$from<data$to,1,-1)
shifted <- t(apply(data[,c("x","y","xend","yend","shift")],1,
function(x) edge_shift(x[1],x[2],x[3],x[4],x[5])))
data[,c("x","y","xend","yend")] <- shifted
data <- data %>% arrange(origID)
data[["shift"]] <- NULL
data[["origID"]] <- NULL
data[[".id"]] <- NULL
data[["from"]] <- NULL
data[["to"]] <- NULL
data
}
dseq <- function(n,spread){
seq(-(n-1)*spread/2,(n-1)*spread/2,by=spread)
}
edge_shift <- function(x1,y1,x2,y2,shift){
v <- c(x2 - x1,y2 - y1)
v <- v/sqrt((v[1]^2 + v[2]^2))
v_perp <- c( -v[2], v[1] )
return(c(x1 + shift*v_perp[1],y1 + shift*v_perp[2],
x2 + shift*v_perp[1],y2 + shift*v_perp[2]))
}
#Stat Function ----
StatEdgeParallel <- ggproto('StatEdgeParallel', StatLink,
setup_data = function(data, params) {
if (any(names(data) == 'filter')) {
if (!is.logical(data$filter)) {
stop('filter must be logical')
}
data <- data[data$filter, names(data) != 'filter']
}
data <- create_parallels(data,params)
StatLink$setup_data(data, params)
},
default_aes = aes(filter = TRUE),
extra_params = c("na.rm","n",'spread')
)
#geom ----
geom_edge_parallel <- function(mapping = NULL, data = get_edges(),
position = "identity", arrow = NULL, spread = 0.02,
n = 100,
lineend = "butt", linejoin = "round", linemitre = 1,
label_colour = 'black', label_alpha = 1,
label_parse = FALSE, check_overlap = FALSE,
angle_calc = 'rot', force_flip = TRUE,
label_dodge = NULL, label_push = NULL,
show.legend = NA, ...) {
mapping <- complete_edge_aes(mapping)
mapping <- aes_intersect(mapping, aes_(x=~x, y=~y, xend=~xend, yend=~yend,
from=~from, to=~to))
layer(data = data, mapping = mapping, stat = StatEdgeParallel,
geom = GeomEdgePath, position = position, show.legend = show.legend,
inherit.aes = FALSE,
params = expand_edge_aes(
list(arrow = arrow, lineend = lineend, linejoin = linejoin,
linemitre = linemitre, na.rm = FALSE, spread = spread, n = n,
interpolate = FALSE,
label_colour = label_colour, label_alpha = label_alpha,
label_parse = label_parse, check_overlap = check_overlap,
angle_calc = angle_calc, force_flip = force_flip,
label_dodge = label_dodge, label_push = label_push, ...)
)
)
}
The only real new thing is the create_parallels call in StatEdgeParallel. Otherwise it is pretty much the same as for geom_edge_link.
g <- graph.full(3)
g <- add.edges(g,c(1,2,2,3,2,1))
E(g)$col <- c("a","a","a","b","b","c")
ggraph(g,"stress")+geom_edge_parallel(aes(col=col),spread=0.01)+geom_node_point(size=7)
#> Warning: Ignoring unknown aesthetics: from, to
Pretty sure that removing the warning would be easy. I added "from" and "to" in aes_intersect because I needed it to find edges between the same nodes. Don't know how to remove the warning though. The spread parameter controls the distance between the edges and here is where the biggest issue is when all nodes have the same y coordinate (or x for that matter)
gr <- graph_from_data_frame(data.frame(
from = c(1, 1, 1, 1, 1, 2, 2, 2,2,2,2),
to = c(2, 2, 2, 2, 2, 1, 1, 1,3,3,3),
class = sample(letters[1:3], 11, TRUE)
))
xy <- cbind(c(1,2,3),c(0,0,0))
ggraph(gr, 'manual',node.positions=data.frame(x=xy[,1],y=xy[,2])) +
geom_edge_parallel(spread=0.002)+
geom_node_point(size=7)
#> Warning: Ignoring unknown aesthetics: from, to
of course it is fixable with scale_y_continuous.
ggraph(gr, 'manual',node.positions=data.frame(x=xy[,1],y=xy[,2])) +
geom_edge_parallel(spread=0.002)+
geom_node_point(size=7)+scale_y_continuous(limits=c(-0.2,0.2))
#> Warning: Ignoring unknown aesthetics: from, to
But that can not be a desired feature. So I am wondering how one would go about to draw parallel lines in this case. I assume that requires some deeper dive into grid
? simply adjusting coordinates seems to not work in this special case. This might also be related to your comment "I want something that keeps the edge distance constant when resizing" I assume
from ggraph.
yeah... this is what I meant with constant edge distances... This needs to be done in a new makeContent method when the size of the viewport is known
it is going to get hairy :-)
from ggraph.
lol and here I am thinking I accomplished something. Guess that means I need to dig deeper into grid
.
from ggraph.
You've absolutely accomplished something. The main computations just need to be moved closer to draw time :-)
I'm fine with taking your code and moving it around, but you are also welcome to play with grid... Have a look at how path capping is achieved in cappedPath.R
if you dare ;-)
from ggraph.
well thanks :). I am gonna look into it. If I fail in the next two days, I'll send a PR with what I currently have
from ggraph.
Related Issues (20)
- labels are cut off on the sides HOT 2
- Revdep check failure with upcoming ggplot2 3.5.0
- -e HOT 1
- Release ggraph 2.2.0
- algorythmn is arranging circles in wrong manner HOT 1
- Accessing Package From Network without Internet
- ```collapse = "all"``` for get_edges not working
- Documentation on geom_edge_link incomplete HOT 6
- Failing installations of ggraph 2.2.0 with R versions 3.6 and 4.0 HOT 15
- ggraph unable to collate and parse R files for package ‘ggraph’ HOT 1
- System crash with line cutter HOT 5
- geom_conn_bundle_text HOT 1
- Preserve tip lengths in dendrogram (similarly to `plot.hclust()`) HOT 2
- Feature request: Support additional "arrowhead" types
- Some stats fail when the filter selects no data
- Allow different end_shapes to be passed to geom_edge_span
- Problem on edge colour geom_edge_link colour and node colour geom_node_point HOT 1
- Cannot use color aes in geom_edge_bundle_force HOT 2
- linetype in geom_node_circle not being mapped correctly
- question: having an absolute location custom layout.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ggraph.