|
66 | 66 | ## and we loop |
67 | 67 | box <- matrix(0, nrow(xy), 2) |
68 | 68 | for (i in seq_len(nrow(xy))) { |
69 | | - box[i,1] <- strwidth(labels[i], cex = cex[i], font = font[i]) + |
70 | | - strwidth("m", cex = cex[i], font = font[i]) |
71 | | - box[i,2] <- strheight(labels[i], cex = cex[i], font = font[i]) + |
72 | | - strheight("x", cex = cex[i], font = font[i]) |
| 69 | + box[i,1] <- strwidth(labels[i], cex = cex[i], font = font[i]) + em/1.5 |
| 70 | + box[i,2] <- strheight(labels[i], cex = cex[i], font = font[i]) + ex/1.5 |
73 | 71 | } |
74 | 72 | ## offset: 1 up, 2..4 sides, 5..8 corners |
75 | 73 | makeoff <- function(pos, lab) { |
|
78 | 76 | } |
79 | 77 | ## amount of overlap |
80 | 78 | overlap <- function(xy1, off1, xy2, off2) { |
81 | | - pmax(0, pmin(xy1[,1] + off1[,1]/2, xy2[,1] + off2[,1]/2) |
82 | | - -pmax(xy1[,1] - off1[,1]/2, xy2[,1] - off2[,1]/2)) * |
83 | | - pmax(0, pmin(xy1[,2] + off1[,2]/2, xy2[,2] + off2[,2]/2) |
84 | | - -pmax(xy1[,2] - off1[,2]/2, xy2[,2] - off2[,2]/2)) |
| 79 | + pmax.int(0, pmin.int(xy1[,1] + off1[,1]/2, xy2[,1] + off2[,1]/2) |
| 80 | + -pmax.int(xy1[,1] - off1[,1]/2, xy2[,1] - off2[,1]/2)) * |
| 81 | + pmax.int(0, pmin.int(xy1[,2] + off1[,2]/2, xy2[,2] + off2[,2]/2) |
| 82 | + -pmax.int(xy1[,2] - off1[,2]/2, xy2[,2] - off2[,2]/2)) |
85 | 83 | } |
86 | 84 | ## indices of overlaps in lower triangular matrix |
87 | 85 | n <- nrow(xy) |
88 | 86 | j <- as.vector(as.dist(row(matrix(0, n, n)))) |
89 | 87 | k <- as.vector(as.dist(col(matrix(0, n, n)))) |
90 | 88 | ## Find labels that may overlap... |
91 | | - maylap <- overlap(xy[j,], 2*box[j,], xy[k,], 2*box[k,]) > 0 |
| 89 | + maylap <- overlap(xy[j,], 2*box[j,] - c(em,ex)/1.5, |
| 90 | + xy[k,], 2*box[k,] - c(em,ex)/1.5) > 0 |
92 | 91 | ## ... and work only with those |
93 | 92 | j <- j[maylap] |
94 | 93 | k <- k[maylap] |
95 | 94 | jk <- sort(unique(c(j,k))) |
96 | | - ## SANN: no. of iterations & starting positions |
97 | | - nit <- min(64 * length(jk), 10000) |
| 95 | + ## SANN: starting values & starting positions. nit is the number |
| 96 | + ## of iterations, temp is the starting temperature, tmax the |
| 97 | + ## number of evaluations at the same temperature. Hotter |
| 98 | + ## temperatures allow worse moves in the beginning. The "idea" |
| 99 | + ## behind 0.791: if you try n positions for n points, you try |
| 100 | + ## 0.632*n labels, and if you try 0.791*n, you try half of labels |
| 101 | + ## (some repeatedly). |
| 102 | + nit <- min(64 * length(jk), 10000) # default 10000 |
| 103 | + temp <- 5 # default 10 |
| 104 | + tmax <- ceiling(0.791 * length(jk)) # default 10 |
98 | 105 | pos <- ifelse(xy[,2] > 0, 1, 3) |
99 | 106 | ## Criterion: overlap + penalty for moving towards origin and also |
100 | 107 | ## for corners. Penalty is mild: max 1 ltr and one-character |
|
118 | 125 | } |
119 | 126 | ## Simulated annealing |
120 | 127 | sol <- optim(par = pos, fn = fn, gr = gr, method="SANN", |
121 | | - control=list(maxit=nit)) |
| 128 | + control=list(maxit=nit, tmax=tmax, temp=temp)) |
122 | 129 | lab <- xy + makeoff(sol$par, box) |
123 | 130 | dev.hold() |
124 | 131 | on.exit(dev.flush()) |
125 | 132 | ## draw optional lab background first so it does not cover points |
126 | 133 | if (!missing(bg)) { |
127 | 134 | for(i in seq_len(nrow(lab))) { |
128 | | - polygon(lab[i,1] + c(-1,1,1,-1)*box[i,1]/2.2, |
129 | | - lab[i,2] + c(-1,-1,1,1)*box[i,2]/2.2, |
| 135 | + polygon(lab[i,1] + c(-1,1,1,-1)*box[i,1]/2, |
| 136 | + lab[i,2] + c(-1,-1,1,1)*box[i,2]/2, |
130 | 137 | col = fill[i], border = col[i], xpd = TRUE) |
131 | 138 | ordiArgAbsorber(lab[i,1], lab[i,2], labels = labels[i], |
132 | 139 | col = col[i], cex = cex[i], font = font[i], |
|
0 commit comments