跳到内容

从 0.5.1 版本开始,igraph 在绘制图形时支持不同的顶点形状。

用法

shapes(shape = NULL)

shape_noclip(coords, el, params, end = c("both", "from", "to"))

shape_noplot(coords, v = NULL, params)

add_shape(shape, clip = shape_noclip, plot = shape_noplot, parameters = list())

参数

shape

字符标量,顶点形状的名称。如果对于 shapes()NULL,则返回所有已定义的顶点形状的名称。

coords, el, params, end, v

请参阅下面剪裁/绘图函数的参数。

clip

一个 R 函数对象,剪裁函数。

plot

一个 R 函数对象,绘图函数。

parameters

命名列表,附加的绘图/顶点/边参数。名为 define 的元素定义新参数,元素本身定义其默认值。顶点参数应具有前缀“vertex.”,边参数应具有前缀“edge.”。其他通用绘图参数应具有前缀“plot.”。请参阅下面的详细信息。

如果 shape 参数为 NULLshapes() 返回一个字符向量。它返回一个命名列表,其中包含名为“clip”和“plot”的条目,它们都是 R 函数。

add_shape() 返回 TRUE,不可见。

shape_noclip() 返回其 coords 参数的相应列。

详细信息

在 igraph 中,顶点形状由两个函数定义:1) 提供有关形状大小的信息,用于剪裁边;2) 如果需要,绘制形状。在本文档页面的其余部分中,这些函数称为“形状函数”。第一个是剪裁函数,第二个是绘图函数。

剪裁函数具有以下参数

coords

一个四列矩阵,包含 el 参数中提供的边列表的顶点的坐标。

el

一个两列矩阵,一些端点将被剪裁的边。它应具有与 coords 相同的行数。

params

这是一个可以调用的函数对象,用于查询顶点/边/绘图图形参数。该函数的第一个参数是“vertex”、“edge”或“plot”,以确定参数的类型,第二个参数是给出参数名称的字符串。例如 params("vertex", "size")

end

字符串,给出将使用哪个端点。可能的值为“both”、“from”和“to”。如果为“from”,则该函数应剪裁 el 边列表中的第一列,“to”选择第二列,“both”选择两列。

剪裁函数应返回一个矩阵,该矩阵具有与 el 参数相同的行数。如果 endboth,则该矩阵必须具有四列,否则为两列。该矩阵包含修改后的坐标,其中应用了剪裁。

绘图函数具有以下参数

coords

顶点的坐标,一个两列矩阵。

v

要绘制的顶点的 ID。它应与 coords 参数中的行数匹配。

params

与剪裁函数相同,请参见上文。

不使用绘图函数的返回值。

可以通过调用 shapes() 而不带参数或将 shape 参数设置为 NULL 来列出所有已安装的顶点形状的名称。如果给出了形状名称,则该形状的剪裁和绘图函数将在一个命名列表中返回。

add_shape() 可用于将新的顶点形状添加到 igraph。为此,必须给出新形状的剪裁和绘图函数。还可以列出绘图/顶点/边参数(在 parameters 参数中),剪裁和/或绘图函数可以使用这些参数。一个示例是一个通用的正多边形形状,它可以具有边数的参数。

shape_noclip() 是一个非常简单的剪裁函数,用户可以在其自己的形状定义中使用它。它不进行剪裁,边将绘制到列出的顶点位置坐标为止。

shape_noplot() 是一个非常简单(可能不是很有用)的绘图函数,它不绘制任何内容。

示例

# all vertex shapes, minus "raster", that might not be available
shapes <- setdiff(shapes(), "")
g <- make_ring(length(shapes))
set.seed(42)
plot(g,
  vertex.shape = shapes, vertex.label = shapes, vertex.label.dist = 1,
  vertex.size = 15, vertex.size2 = 15,
  vertex.pie = lapply(shapes, function(x) if (x == "pie") 2:6 else 0),
  vertex.pie.color = list(heat.colors(5))
)


# add new vertex shape, plot nothing with no clipping
add_shape("nil")
plot(g, vertex.shape = "nil")


#################################################################
# triangle vertex shape
mytriangle <- function(coords, v = NULL, params) {
  vertex.color <- params("vertex", "color")
  if (length(vertex.color) != 1 && !is.null(v)) {
    vertex.color <- vertex.color[v]
  }
  vertex.size <- params("vertex", "size")
  if (length(vertex.size) != 1 && !is.null(v)) {
    vertex.size <- vertex.size[v]
  }

  symbols(
    x = coords[, 1], y = coords[, 2], bg = vertex.color,
    stars = cbind(vertex.size, vertex.size, vertex.size),
    add = TRUE, inches = FALSE
  )
}
# clips as a circle
add_shape("triangle",
  clip = shapes("circle")$clip,
  plot = mytriangle
)
plot(g,
  vertex.shape = "triangle", vertex.color = rainbow(vcount(g)),
  vertex.size = seq(10, 20, length.out = vcount(g))
)


#################################################################
# generic star vertex shape, with a parameter for number of rays
mystar <- function(coords, v = NULL, params) {
  vertex.color <- params("vertex", "color")
  if (length(vertex.color) != 1 && !is.null(v)) {
    vertex.color <- vertex.color[v]
  }
  vertex.size <- params("vertex", "size")
  if (length(vertex.size) != 1 && !is.null(v)) {
    vertex.size <- vertex.size[v]
  }
  norays <- params("vertex", "norays")
  if (length(norays) != 1 && !is.null(v)) {
    norays <- norays[v]
  }

  mapply(coords[, 1], coords[, 2], vertex.color, vertex.size, norays,
    FUN = function(x, y, bg, size, nor) {
      symbols(
        x = x, y = y, bg = bg,
        stars = matrix(c(size, size / 2), nrow = 1, ncol = nor * 2),
        add = TRUE, inches = FALSE
      )
    }
  )
}
# no clipping, edges will be below the vertices anyway
add_shape("star",
  clip = shape_noclip,
  plot = mystar, parameters = list(vertex.norays = 5)
)
plot(g,
  vertex.shape = "star", vertex.color = rainbow(vcount(g)),
  vertex.size = seq(10, 20, length.out = vcount(g))
)

plot(g,
  vertex.shape = "star", vertex.color = rainbow(vcount(g)),
  vertex.size = seq(10, 20, length.out = vcount(g)),
  vertex.norays = rep(4:8, length.out = vcount(g))
)