<SOLVED> How to plot a sphere as wireframe with back view hidden, in R? - r

Using R, I would like to plot a sphere with latitude and longitude lines, but without any visibility of hidden part of the sphere. And, ideally, I'd like to have the initial view start out with a specific tilt (but that's down the road).
This matlab question gets to the idea
Plotting a wireframe sphere in Python hidding backward meridians and parallels
... but it's matlab. The closest solution that stackoverflow suggested
Plot Sphere with custom gridlines in R
doesn't help with the hidden line aspect.
The closest I got was editting a sphereplot routine:
library(sphereplot)
matt.rgl.sphgrid <- function (radius = 1, col.long = "red", col.lat = "blue", deggap = 15,
longtype = "H", add = FALSE, radaxis = TRUE, radlab = "Radius")
{
if (add == F) {
open3d(userMatrix = rotationMatrix((90)*pi/180, 1, 0, 0)) #changed
}
for (lat in seq(-90, 90, by = deggap)) {
if (lat == 0) {
col.grid = "grey50"
}
else {
col.grid = "grey"
}
#create an array here using the sph2car call below, then rotate those and
#set the appropriate ones to NA before passing that array to this call
#ditto for the next plot3d call as well
plot3d(sph2car(long = seq(0, 360, len = 100), lat = lat,
radius = radius, deg = T),
col = col.grid, add = T,
type = "l")
}
for (long in seq(0, 360 - deggap, by = deggap)) {
if (long == 0) {
col.grid = "grey50"
}
else {
col.grid = "grey"
}
plot3d(sph2car(long = long, lat = seq(-90, 90, len = 100),
radius = radius, deg = T),
col = col.grid, add = T,
type = "l")
}
if (longtype == "H") {
scale = 15
}
if (longtype == "D") {
scale = 1
}
# rgl.sphtext(long = 0, lat = seq(-90, 90, by = deggap), radius = radius,
# text = seq(-90, 90, by = deggap), deg = TRUE, col = col.lat)
# rgl.sphtext(long = seq(0, 360 - deggap, by = deggap), lat = 0,
# radius = radius, text = seq(0, 360 - deggap, by = deggap)/scale,
# deg = TRUE, col = col.long)
}
matt.rgl.sphgrid(radaxis=FALSE)
But I can't figure out how to hide the lines.
Any pointers or examples I've overlooked?
SOLUTION: Just prior to the plot3d calls, set any negative values in "y" (in this case, given a first rotation of 90 degrees) to NA

Related

How to move object across axis?

I have an interactive plot and I want to move topoplot position across the x-axis according to the slider (or red vertical bar) position.
How can I do that?
In an ideal situation, the topoplot moves until some border (so it would be partially out of the screen).
Also, is it possible to put a line connecting the topolot with a red vertical line?
This is my script with prerequisite functions:
using Makie
using GLMakie
using PyMNE
using JLD2 # loading data
using TopoPlots
using StatsBase # mean/std
using Pipe
using ColorSchemes
using Colors
using LinearAlgebra
function eegHeadMatrix(positions, center, radius)
oldCenter = mean(positions)
oldRadius, _ = findmax(x-> LinearAlgebra.norm(x .- oldCenter),
positions)
radF = radius/oldRadius
return Makie.Mat4f(radF, 0, 0, 0,
0, radF, 0, 0,
0, 0, 1, 0,
center[1]-oldCenter[1]*radF, center[2]-
oldCenter[2]*radF, 0, 1)
end
struct NullInterpolator <: TopoPlots.Interpolator
end
function (ni::NullInterpolator)(
xrange::LinRange, yrange::LinRange,
positions::AbstractVector{<: Point{2}}, data::AbstractVector{<:Number})
return zeros(length(xrange),length(yrange))
end
function posToColor(pos)
cx = 0.5 - pos[1]
cy = 0.5 - pos[2]
rx = cx * 0.7071068 + cy * 0.7071068
ry = cx * -0.7071068 + cy * 0.7071068
b = 1.0 - (2*sqrt(cx^2+cy^2))^2
return RGB(0.5 - rx*1.414, 0.5 - ry*1.414, b)
end
This is the main function
f = Figure(backgroundcolor = RGBf(0.98, 0.98, 0.98), resolution = (1500, 700))
# interaction
xs = range(-0.3, length=size(dat_e, 2), step=1 ./ 128)
sg = SliderGrid(f[4, 1:2],
(label="time", range=xs, format = "{:.3f} ms", startvalue = 0),
)
time = sg.sliders[1].value
str = lift(t -> "[$(round(t, digits = 3)) ms]", time)
topo_slice = lift((t, data) -> mean(data[1:30, indexin(t, xs), :], dims=2)[:,1], time, dat_e)
# butterfly plot
ax = Axis(f[2:3, 1:2], xlabel = "Time [s]", ylabel = "Voltage amplitude [µV]")
N = 1:length(pos) #1:4
hidespines!(ax, :t, :r)
GLMakie.xlims!(-0.3, 1.2)
hlines!(0, color = :gray, linewidth = 1)
vlines!(0, color = :gray, linewidth = 1)
times = range(-0.3, length=size(dat_e,2), step=1 ./ 128)
specialColors = ColorScheme(vcat(RGB(1,1,1.),[posToColor(pos) for pos in pos[N]]...))
for i in N
mean_trial = mean(dat_e[i,:,:], dims=2)[:,1]
lines!(times, mean_trial, color = specialColors[i])
end
hidedecorations!(ax, label = false, ticks = false, ticklabels = false)
# text
vlines!(time, color = :red, linewidth = 1)
text!(time, 8, text = str, align = (:center, :center))
# topoplot
topo_axis = Axis(f[1, 1:2], width = 178, height = 178, aspect = DataAspect())
Makie.xlims!(low = -0.2, high = 1.2)
Makie.ylims!(low = -0.2, high = 1.2)
topoMatrix = eegHeadMatrix(pos[N], (0.5, 0.5), 0.5)
topo = eeg_topoplot!(topo_axis, topo_slice, # averaging all trial of 30 participants on Xth msec
raw.ch_names[1:30];
positions=pos, # produced automatically from ch_names
#interpolation=DelaunayMesh(),
enlarge=1,
extrapolation=GeomExtrapolation(enlarge=1.0, geometry=Circle),
label_text=false)
hidedecorations!(current_axis())
hidespines!(current_axis())
f

How can i have more than three gauge sectors in flexdashboard?

Flexdashboard allows to specify three sectors for its gauges: "danger", "warning" and "success". I want to use 5 gauge sectors to show in which interval my observed value lies. I calculated confidence intervals with alpha 0.2 (80 %) and 0.01 (99 %) and use this to define 5 sectors:
Sector 1 = c(min(value),lower_90_ci)
Sector 2 = c(lower_90_ci,lower_80_ci)
Sector 3 = c(lower_80_ci, upper_80_ci)
Sector 4 = c(upper_80_ci, upper_90_ci)
Sector 5 = c(upper_90_ci, max(value))
This is a standard-gauge in flexdashboard:
library(flexdashboard)
gauge(42, min = 0, max = 100, symbol = '%', gaugeSectors(
success = c(80, 100), warning = c(40, 79), danger = c(0, 39)
))
If the intention is to have optimum range in the middle with warning and danger on both higher and lower sides, I tried this:
gauge(value = 95, # For example
min = 0,
max = 100,
sectors = gaugeSectors(
success = c(20, 80),
warning = c(10, 90),
danger = c(0, 100)
)
)
You may want to make sure that the sectors covers the whole range (min-max). Any value within the range but not belonging to any sector will use default color (success).
I don't think it can be done out of the box. Digging into the resolveSectors function shows that it expects three sectors and is quite inflexible:
function (sectors, min, max)
{
if (is.null(sectors)) {
sectors = sectors(success = c(min, max), warning = NULL,
danger = NULL, colors = c("success", "warning", "danger"))
}
if (is.null(sectors$success) && is.null(sectors$warning) &&
is.null(sectors$danger)) {
sectors$success <- c(min, max)
}
if (is.null(sectors$colors))
sectors$colors <- c("success", "warning", "danger")
customSectors <- list()
addSector <- function(sector, color) {
if (!is.null(sector)) {
if (!is.numeric(sector) || length(sector) != 2)
stop("sectors must be numeric vectors of length 2",
call. = FALSE)
customSectors[[length(customSectors) + 1]] <<- list(lo = sector[[1]],
hi = sector[[2]], color = color)
}
}
sectors$colors <- rep_len(sectors$colors, 3)
addSector(sectors$success, sectors$colors[[1]])
addSector(sectors$warning, sectors$colors[[2]])
addSector(sectors$danger, sectors$colors[[3]])
customSectors
}
<environment: namespace:flexdashboard>
Nevertheless, you could build your own gauge function that uses a custom built resolveSectors function (using the current function as a template) that expects five sectors.

Error of self edges in hive plot

Absolutely cannot figure out why the error is coming even though there are no self edges.
Below is a reproducible code. Any help would be great
library(HiveR)
nodes = data.frame(id = 1:9, lab = c("A","B","C","E","F","G","H","I","J"),
axis = c(1,1,1,2,3,2,2,2,3), radius = rep(50,9),size = rep(10,9),
color = c("yellow","yellow","yellow", "green","red","green","green","green","red"))
edges = data.frame(id1 = c(1,2,3,4,5,4,1,9,8,6,1),id2 = c(2,3,4,1,9,9,9,8,7,7,6),
weight = rep(1,11),
color = c(rep("green",7), rep("red",4)))
test3 <- ranHiveData(nx = 3)
test3$nodes = nodes
test3$edges = edges
test3$edges$color <- as.character(test3$edges$color)
test3$edges$id1 <- as.integer(test3$edges$id1)
test3$edges$id2 <- as.integer(test3$edges$id2)
test3$nodes$color <- as.character(test3$nodes$color)
test3$nodes$lab <- as.character(test3$nodes$lab)
test3$nodes$axis = as.integer(test3$nodes$axis)
test3$nodes$id = as.integer(test3$nodes$id)
test3$nodes$radius = as.numeric(test3$nodes$radius)
test3$nodes$size = as.numeric(test3$nodes$size)
test3$edges$weight = as.numeric(test3$edges$weight)
test3$desc = "3 axes --9 nodes -- 11 edges"
sumHPD(test3, chk.sm.pt = TRUE)
The code is giving self edges and the the plot is not rendering plotHive(test3) showing
Error in calcCurveGrob(x,x$debug) : end points must not be identical
In your code the position of the nodes of the axis (radius) are all set to 50. Hence there are overlapping points (3 on axis 1, 4 on axes 2 and 2 on axis 3).
A correct definition of radius solves the problem.
library(HiveR)
# radius has been changed !
nodes = data.frame(id = 1:9, lab = c("A","B","C","E","F","G","H","I","J"),
axis = c(1,1,1,2,3,2,2,2,3), radius = c(1,2,3,1,1,2,3,4,2),size = rep(1,9),
color = c("yellow","yellow","yellow", "green","red","green","green","green","red"))
edges = data.frame(id1 = c(1,2,3,4,5,4,1,9,8,6,1),id2 = c(2,3,4,1,9,9,9,8,7,7,6),
weight = rep(1,11),
color = c(rep("green",7), rep("red",4)))
test3 <- ranHiveData(nx = 3)
test3$nodes = nodes
test3$edges = edges
test3$edges$color <- as.character(test3$edges$color)
test3$edges$id1 <- as.integer(test3$edges$id1)
test3$edges$id2 <- as.integer(test3$edges$id2)
test3$nodes$color <- as.character(test3$nodes$color)
test3$nodes$lab <- as.character(test3$nodes$lab)
test3$nodes$axis = as.integer(test3$nodes$axis)
test3$nodes$id = as.integer(test3$nodes$id)
test3$nodes$radius = as.numeric(test3$nodes$radius)
test3$nodes$size = as.numeric(test3$nodes$size)
test3$edges$weight = as.numeric(test3$edges$weight)
test3$desc = "3 axes --9 nodes -- 11 edges"
sumHPD(test3, chk.sm.pt = TRUE)
plotHive(test3)

how to write text inside a rectangle in R

I want each rectangle to contain a number, so that the first plotted rectangle would contain : rect 1 the second rect 2 and so on, but i don't know how to insert text inside rectangles.
require(grDevices)
## set up the plot region:
plot(c(0, 250), c(0, 250), type = "n",
main = "Exercise 1: R-Tree Index Question C")
rect(0.0,0.0,40.0,35.0, , text= "transparent")
rect(10.0,210.0,45.0,230.0)
rect(170.0,50.0,240.0,150.0)
rect(75.0,110.0,125.0,125.0)
rect(50.0,130.0,65.0,160.0)
rect(15.0,140.0,30.0,150.0)
rect(100.0,50.0,130.0,90.0)
rect(150.0,40.0,155.0,60.0)
rect(52.0,80.0,75.0,90.0)
rect(62.0,65.0,85.0,75.0)
rect(20.0,75.0,25.0,80.0)
rect(30.0,40.0,50.0,80.0)
rect(102.0,155.0,113.0,217.0)
par(op)
Like the other answers mention, you can use the coordinates that you give to rect to place the text somewhere relative.
plot(c(0, 250), c(0, 250), type = "n",
main = "Exercise 1: R-Tree Index Question C")
rect(0.0,0.0,40.0,35.0)
center <- c(mean(c(0, 40)), mean(c(0, 35)))
text(center[1], center[2], labels = 'hi')
You can easily put this into a function to save yourself some typing/errors
recttext <- function(xl, yb, xr, yt, text, rectArgs = NULL, textArgs = NULL) {
center <- c(mean(c(xl, xr)), mean(c(yb, yt)))
do.call('rect', c(list(xleft = xl, ybottom = yb, xright = xr, ytop = yt), rectArgs))
do.call('text', c(list(x = center[1], y = center[2], labels = text), textArgs))
}
Use it like this
recttext(50, 0, 100, 35, 'hello',
rectArgs = list(col = 'red', lty = 'dashed'),
textArgs = list(col = 'blue', cex = 1.5))
You need to use text() as a separate graphics call.
coords <- matrix(
c(0.0,0.0,40.0,35.0,
10.0,210.0,45.0,230.0,
170.0,50.0,240.0,150.0,
75.0,110.0,125.0,125.0,
50.0,130.0,65.0,160.0,
15.0,140.0,30.0,150.0,
100.0,50.0,130.0,90.0,
150.0,40.0,155.0,60.0,
52.0,80.0,75.0,90.0,
62.0,65.0,85.0,75.0,
20.0,75.0,25.0,80.0,
30.0,40.0,50.0,80.0,
102.0,155.0,113.0,217.0),
ncol=4,byrow=TRUE)
plot(c(0, 250), c(0, 250), type = "n",
main = "Exercise 1: R-Tree Index Question C")
rfun <- function(x,i) {
do.call(rect,as.list(x))
}
apply(coords,1,rfun)
text((coords[,1]+coords[,3])/2,
(coords[,2]+coords[,4])/2,
seq(nrow(coords)))
text( (0.0+40.0)/2, (0.0+35.0)/2 , 'transparent')
where we chose x,y to be the centroid of your rectangle. You could define a function to draw the rect then place the text at its centroid.
Note: these coords are large; this will display outside your normal view. So you'll either need to zoom to see it, or scale coords to the range 0.0..1.0
By the way, read 12.2 Low-level plotting commands

How to draw gauge chart in R?

How can I draw the following plot in R?
Red = 30
Yellow = 40
Green = 30
Needle at 52.
So here's a fully ggplot solution.
Note: Edited from the original post to add numeric indicator and labels at the gauge breaks which seems to be what OP is asking for in their comment. If indicator is not needed, remove the annotate(...) line. If labels are not needed, remove geom_text(...) line.
gg.gauge <- function(pos,breaks=c(0,30,70,100)) {
require(ggplot2)
get.poly <- function(a,b,r1=0.5,r2=1.0) {
th.start <- pi*(1-a/100)
th.end <- pi*(1-b/100)
th <- seq(th.start,th.end,length=100)
x <- c(r1*cos(th),rev(r2*cos(th)))
y <- c(r1*sin(th),rev(r2*sin(th)))
return(data.frame(x,y))
}
ggplot()+
geom_polygon(data=get.poly(breaks[1],breaks[2]),aes(x,y),fill="red")+
geom_polygon(data=get.poly(breaks[2],breaks[3]),aes(x,y),fill="gold")+
geom_polygon(data=get.poly(breaks[3],breaks[4]),aes(x,y),fill="forestgreen")+
geom_polygon(data=get.poly(pos-1,pos+1,0.2),aes(x,y))+
geom_text(data=as.data.frame(breaks), size=5, fontface="bold", vjust=0,
aes(x=1.1*cos(pi*(1-breaks/100)),y=1.1*sin(pi*(1-breaks/100)),label=paste0(breaks,"%")))+
annotate("text",x=0,y=0,label=pos,vjust=0,size=8,fontface="bold")+
coord_fixed()+
theme_bw()+
theme(axis.text=element_blank(),
axis.title=element_blank(),
axis.ticks=element_blank(),
panel.grid=element_blank(),
panel.border=element_blank())
}
gg.gauge(52,breaks=c(0,35,70,100))
## multiple guages
library(gridExtra)
grid.newpage()
grid.draw(arrangeGrob(gg.gauge(10),gg.gauge(20),
gg.gauge(52),gg.gauge(90),ncol=2))
You will likely need to tweak the size=... parameter to geom_text(...) and annotate(...) depending on the actual size of your gauge.
IMO the segment labels are a really bad idea: they clutter the image and defeat the purpose of the graphic (to indicate at a glance if the metric is in "safe", "warning", or "danger" territory).
Here's a very quick and dirty implementation using grid graphics
library(grid)
draw.gauge<-function(x, from=0, to=100, breaks=3,
label=NULL, axis=TRUE, cols=c("red","yellow","green")) {
if (length(breaks)==1) {
breaks <- seq(0, 1, length.out=breaks+1)
} else {
breaks <- (breaks-from)/(to-from)
}
stopifnot(length(breaks) == (length(cols)+1))
arch<-function(theta.start, theta.end, r1=1, r2=.5, col="grey", n=100) {
t<-seq(theta.start, theta.end, length.out=n)
t<-(1-t)*pi
x<-c(r1*cos(t), r2*cos(rev(t)))
y<-c(r1*sin(t), r2*sin(rev(t)))
grid.polygon(x,y, default.units="native", gp=gpar(fill=col))
}
tick<-function(theta, r, w=.01) {
t<-(1-theta)*pi
x<-c(r*cos(t-w), r*cos(t+w), 0)
y<-c(r*sin(t-w), r*sin(t+w), 0)
grid.polygon(x,y, default.units="native", gp=gpar(fill="grey"))
}
addlabel<-function(m, theta, r) {
t<-(1-theta)*pi
x<-r*cos(t)
y<-r*sin(t)
grid.text(m,x,y, default.units="native")
}
pushViewport(viewport(w=.8, h=.40, xscale=c(-1,1), yscale=c(0,1)))
bp <- split(t(embed(breaks, 2)), 1:2)
do.call(Map, list(arch, theta.start=bp[[1]],theta.end=bp[[2]], col=cols))
p<-(x-from)/(to-from)
if (!is.null(axis)) {
if(is.logical(axis) && axis) {
m <- round(breaks*(to-from)+from,0)
} else if (is.function(axis)) {
m <- axis(breaks, from, to)
} else if(is.character(axis)) {
m <- axis
} else {
m <- character(0)
}
if(length(m)>0) addlabel(m, breaks, 1.10)
}
tick(p, 1.03)
if(!is.null(label)) {
if(is.logical(label) && label) {
m <- x
} else if (is.function(label)) {
m <- label(x)
} else {
m <- label
}
addlabel(m, p, 1.15)
}
upViewport()
}
This function can be used to draw one gauge
grid.newpage()
draw.gauge(100*runif(1))
or many gauges
grid.newpage()
pushViewport(viewport(layout=grid.layout(2,2)))
for(i in 1:4) {
pushViewport(viewport(layout.pos.col=(i-1) %/%2 +1, layout.pos.row=(i-1) %% 2 + 1))
draw.gauge(100*runif(1))
upViewport()
}
popViewport()
It's not too fancy so it should be easy to customize.
You can now also add a label
draw.gauge(75, label="75%")
I've added another update to allow for drawing an "axis". You can set it to TRUE to use default values, or you can pass in a character vector to give whatever labels you want, or you can pass in a function that will take the breaks (scaled 0-1) and the from/to values and should return a character value.
grid.newpage()
draw.gauge(100*runif(1), breaks=c(0,30,70,100), axis=T)
Flexdashboard has a simple function for guage chart. For details take a look at https://rdrr.io/cran/flexdashboard/man/gauge.html
You can plot the chart using a simple call like:
gauge(42, min = 0, max = 100, symbol = '%',
gaugeSectors(success = c(80, 100), warning = c(40, 79), danger = c(0, 39)))
I found this solution from Gaston Sanchez's blog:
library(googleVis)
plot(gvisGauge(data.frame(Label=”UserR!”, Value=80),
options=list(min=0, max=100,
yellowFrom=80, yellowTo=90,
redFrom=90, redTo=100)))
Here is the function created later:
# Original code by Gaston Sanchez http://www.r-bloggers.com/gauge-chart-in-r/
#
dial.plot <- function(label = "UseR!", value = 78, dial.radius = 1
, value.cex = 3, value.color = "black"
, label.cex = 3, label.color = "black"
, gage.bg.color = "white"
, yellowFrom = 75, yellowTo = 90, yellow.slice.color = "#FF9900"
, redFrom = 90, redTo = 100, red.slice.color = "#DC3912"
, needle.color = "red", needle.center.color = "black", needle.center.cex = 1
, dial.digets.color = "grey50"
, heavy.border.color = "gray85", thin.border.color = "gray20", minor.ticks.color = "gray55", major.ticks.color = "gray45") {
whiteFrom = min(yellowFrom, redFrom) - 2
whiteTo = max(yellowTo, redTo) + 2
# function to create a circle
circle <- function(center=c(0,0), radius=1, npoints=100)
{
r = radius
tt = seq(0, 2*pi, length=npoints)
xx = center[1] + r * cos(tt)
yy = center[1] + r * sin(tt)
return(data.frame(x = xx, y = yy))
}
# function to get slices
slice2xy <- function(t, rad)
{
t2p = -1 * t * pi + 10*pi/8
list(x = rad * cos(t2p), y = rad * sin(t2p))
}
# function to get major and minor tick marks
ticks <- function(center=c(0,0), from=0, to=2*pi, radius=0.9, npoints=5)
{
r = radius
tt = seq(from, to, length=npoints)
xx = center[1] + r * cos(tt)
yy = center[1] + r * sin(tt)
return(data.frame(x = xx, y = yy))
}
# external circle (this will be used for the black border)
border_cir = circle(c(0,0), radius=dial.radius, npoints = 100)
# open plot
plot(border_cir$x, border_cir$y, type="n", asp=1, axes=FALSE,
xlim=c(-1.05,1.05), ylim=c(-1.05,1.05),
xlab="", ylab="")
# gray border circle
external_cir = circle(c(0,0), radius=( dial.radius * 0.97 ), npoints = 100)
# initial gage background
polygon(external_cir$x, external_cir$y,
border = gage.bg.color, col = gage.bg.color, lty = NULL)
# add gray border
lines(external_cir$x, external_cir$y, col=heavy.border.color, lwd=18)
# add external border
lines(border_cir$x, border_cir$y, col=thin.border.color, lwd=2)
# yellow slice (this will be used for the yellow band)
yel_ini = (yellowFrom/100) * (12/8)
yel_fin = (yellowTo/100) * (12/8)
Syel = slice2xy(seq.int(yel_ini, yel_fin, length.out = 30), rad= (dial.radius * 0.9) )
polygon(c(Syel$x, 0), c(Syel$y, 0),
border = yellow.slice.color, col = yellow.slice.color, lty = NULL)
# red slice (this will be used for the red band)
red_ini = (redFrom/100) * (12/8)
red_fin = (redTo/100) * (12/8)
Sred = slice2xy(seq.int(red_ini, red_fin, length.out = 30), rad= (dial.radius * 0.9) )
polygon(c(Sred$x, 0), c(Sred$y, 0),
border = red.slice.color, col = red.slice.color, lty = NULL)
# white slice (this will be used to get the yellow and red bands)
white_ini = (whiteFrom/100) * (12/8)
white_fin = (whiteTo/100) * (12/8)
Swhi = slice2xy(seq.int(white_ini, white_fin, length.out = 30), rad= (dial.radius * 0.8) )
polygon(c(Swhi$x, 0), c(Swhi$y, 0),
border = gage.bg.color, col = gage.bg.color, lty = NULL)
# calc and plot minor ticks
minor.tix.out <- ticks(c(0,0), from=5*pi/4, to=-pi/4, radius=( dial.radius * 0.89 ), 21)
minor.tix.in <- ticks(c(0,0), from=5*pi/4, to=-pi/4, radius=( dial.radius * 0.85 ), 21)
arrows(x0=minor.tix.out$x, y0=minor.tix.out$y, x1=minor.tix.in$x, y1=minor.tix.in$y,
length=0, lwd=2.5, col=minor.ticks.color)
# coordinates of major ticks (will be plotted as arrows)
major_ticks_out = ticks(c(0,0), from=5*pi/4, to=-pi/4, radius=( dial.radius * 0.9 ), 5)
major_ticks_in = ticks(c(0,0), from=5*pi/4, to=-pi/4, radius=( dial.radius * 0.77 ), 5)
arrows(x0=major_ticks_out$x, y0=major_ticks_out$y, col=major.ticks.color,
x1=major_ticks_in$x, y1=major_ticks_in$y, length=0, lwd=3)
# calc and plot numbers at major ticks
dial.numbers <- ticks(c(0,0), from=5*pi/4, to=-pi/4, radius=( dial.radius * 0.70 ), 5)
dial.lables <- c("0", "25", "50", "75", "100")
text(dial.numbers$x, dial.numbers$y, labels=dial.lables, col=dial.digets.color, cex=.8)
# Add dial lables
text(0, (dial.radius * -0.65), value, cex=value.cex, col=value.color)
# add label of variable
text(0, (dial.radius * 0.43), label, cex=label.cex, col=label.color)
# add needle
# angle of needle pointing to the specified value
val = (value/100) * (12/8)
v = -1 * val * pi + 10*pi/8 # 10/8 becuase we are drawing on only %80 of the cir
# x-y coordinates of needle
needle.length <- dial.radius * .67
needle.end.x = needle.length * cos(v)
needle.end.y = needle.length * sin(v)
needle.short.length <- dial.radius * .1
needle.short.end.x = needle.short.length * -cos(v)
needle.short.end.y = needle.short.length * -sin(v)
needle.side.length <- dial.radius * .05
needle.side1.end.x = needle.side.length * cos(v - pi/2)
needle.side1.end.y = needle.side.length * sin(v - pi/2)
needle.side2.end.x = needle.side.length * cos(v + pi/2)
needle.side2.end.y = needle.side.length * sin(v + pi/2)
needle.x.points <- c(needle.end.x, needle.side1.end.x, needle.short.end.x, needle.side2.end.x)
needle.y.points <- c(needle.end.y, needle.side1.end.y, needle.short.end.y, needle.side2.end.y)
polygon(needle.x.points, needle.y.points, col=needle.color)
# add central blue point
points(0, 0, col=needle.center.color, pch=20, cex=needle.center.cex)
# add values 0 and 100
}
par(mar=c(0.2,0.2,0.2,0.2), bg="black", mfrow=c(2,2))
dial.plot ()
dial.plot (label = "Working", value = 25, dial.radius = 1
, value.cex = 3.3, value.color = "white"
, label.cex = 2.7, label.color = "white"
, gage.bg.color = "black"
, yellowFrom = 73, yellowTo = 95, yellow.slice.color = "gold"
, redFrom = 95, redTo = 100, red.slice.color = "red"
, needle.color = "red", needle.center.color = "white", needle.center.cex = 1
, dial.digets.color = "white"
, heavy.border.color = "white", thin.border.color = "black", minor.ticks.color = "white", major.ticks.color = "white")
dial.plot (label = "caffeine", value = 63, dial.radius = .7
, value.cex = 2.3, value.color = "white"
, label.cex = 1.7, label.color = "white"
, gage.bg.color = "black"
, yellowFrom = 80, yellowTo = 93, yellow.slice.color = "gold"
, redFrom = 93, redTo = 100, red.slice.color = "red"
, needle.color = "red", needle.center.color = "white", needle.center.cex = 1
, dial.digets.color = "white"
, heavy.border.color = "black", thin.border.color = "lightsteelblue4", minor.ticks.color = "orange", major.ticks.color = "tan")
dial.plot (label = "Fun", value = 83, dial.radius = .7
, value.cex = 2.3, value.color = "white"
, label.cex = 1.7, label.color = "white"
, gage.bg.color = "black"
, yellowFrom = 20, yellowTo = 75, yellow.slice.color = "olivedrab"
, redFrom = 75, redTo = 100, red.slice.color = "green"
, needle.color = "red", needle.center.color = "white", needle.center.cex = 1
, dial.digets.color = "white"
, heavy.border.color = "black", thin.border.color = "lightsteelblue4", minor.ticks.color = "orange", major.ticks.color = "tan")

Resources