1

我正在开发一个 R 包,它允许用户通过单击和拖动图表上的点来编辑时间序列。

我需要在图表上始终显示 6 条线,尽管只有一条线是“活动的”并且可以用鼠标进行编辑。

现在可以正常工作了,但是因为当“单击和拖动”功能处于活动状态时,我要绘制很多线并每秒绘制多次,所以屏幕闪烁很多,这对眼睛很不利。

我想用非活动系列制作一个图,然后将此图另存为图像,然后将图像写入设备并在事件循环的其余部分在图像上绘制“活动”线。据我估计,这会将图表中的“层”数量从 6 降低到 2。

评论中的一些人说一些真实的代码会有所帮助。这是我的代码:

near.point<-function(point,x.vec,y.vec){   #this function takes 'point' which is an x,y val and then finds the point in x.vec, y.vec which is nearby, and returns it
    dis.vec<- sqrt(abs(x.vec/(max(x.vec)-min(x.vec))-point[1]/(max(x.vec)-min(x.vec)))^2 + abs(y.vec/(max(y.vec)-min(y.vec))-point[2]/(max(y.vec)-min(y.vec)))^2) #vector of total distances of #pointer click from line points
    return(which(dis.vec==min(dis.vec)) )
}

savepar <- par(ask=FALSE)
picker.mover <- function(bl,scenarios,date.labs,target,name) { #this function allows one to edit #line points with the mouse

#plot the baseline (the first time series)
plot(unlist(bl),col="black",type="l",lwd=2,xaxt="n",main=name,xlab="",
     ylab="Add function to bring in units, later",sub=paste(paste("S",target,sep=""),"active",sep=" "),ylim=c(.96*min(scenarios),1.04*max(scenarios)))
axis(1,at=seq(1,length(date.labs),12),labels=date.labs[seq(1,length(date.labs),12)])
#plot the nontarget scenarios, the other lines to show in the graph but not be edited with mouse
for(i in c(1:6)[-which(c(1:6)==target)]){ #this 'which' structure returns a sequence from #1 to 6 excluding the target scenario     
    lines(scenarios[,i],col=(i),pch=5,lwd=1)
    }
    #plot the target scenario
    lines(unlist(scenarios[,target]),type="b",col="blue",lwd=3)
    #####legend structure###################################################
    l.widths <-rep(1,7);l.widths[target+1] <-3 
    l.colors<-c("black",1:6);l.colors[target+1]<-"blue" 
    legend("bottomright",c("BL","S1","S2","S3","S4","S5","S6"),lty=c(1,1,1,1,1,1,1),lwd=l.widths,col=l.colors)
        ####End legend structure###############################################    

#some graphics events functions, Frankensteined from the getGrapnicsEven R help example

devset <- function()
    if (dev.cur() != eventEnv$which) dev.set(eventEnv$which)

dragmousedown <- function(buttons, x, y) { #what happens when we click
    start.x <- grconvertX(x,"ndc","user") #<<- super assignment
    start.y <- grconvertY(y,"ndc","user")
    #devset()

    temp.point<<-near.point(c(start.x,start.y),
        1:length(unlist(bl)),scenarios[,target])
    points(temp.point,scenarios[temp.point,target],col="Red"
       ,pch=21,bg="red",lwd=2)

          eventEnv$onMouseMove <- dragmousemove
    NULL
}

dragmousemove <- function(buttons, x, y) { #what happens when we move after clicking
    #devset()


    y.scaled<-grconvertY(y,"ndc","user")
    scenarios[temp.point,target]<<-y.scaled

#och plotta hela grej igen
#plot the baseline
plot(unlist(bl),col="black",type="l",lwd=2,xaxt="n",xlab="",
     ylab="Add function to bring in units, later",sub=paste(paste("S",target,sep=""),"active",sep=" "),main=name,ylim=c(.96*min(scenarios),1.04*max(scenarios)))
      axis(1,at=seq(1,length(date.labs),12),labels=date.labs[seq(1,length(date.labs),12)])

#plot the nontarget scenarios
for(i in c(1:6)[-which(c(1:6)==target)]){ #this 'which' structure returns a sequence from 1 to 6 excluding the target scenario      
    lines(scenarios[,i],col=(i),pch=5,lwd=1)
    }
    #plot the target scenario
    lines(unlist(scenarios[,target]),type="b",col="blue",lwd=3)
    ####legend structure###################################################
    l.widths <-rep(1,7);l.widths[target+1] <-3 
    l.colors<-c("black",1:6);l.colors[target+1]<-"blue" 
    legend("bottomright",c("BL","S1","S2","S3","S4","S5","S6"),lty=c(1,1,1,1,1,1,1),lwd=l.widths,col=l.colors)
        ####End legend structure###############################################

    points(temp.point,scenarios[temp.point,target],col="Red"
       ,pch=21,bg="red",lwd=2)

  temp.text<- paste(as.character(date.labs[temp.point]),":",sep="") #report date
temp.text <- paste(temp.text,paste(round(100*(scenarios[temp.point,target]/unlist(bl)[temp.point]-1),3),"%",sep=""),sep=" ")
temp.text<- paste(temp.text,"from BL")
legend("topleft",temp.text)
    NULL
}

mouseup <- function(buttons, x, y) {    
    eventEnv$onMouseMove <- NULL
}   

keydown <- function(key) {
    if (key == "q") return(invisible(1))
    eventEnv$onMouseMove <- NULL
    NULL
}

setGraphicsEventHandlers(prompt="Click and drag, hit q to quit",
                 onMouseDown = dragmousedown,
                 onMouseUp = mouseup,
                 onKeybd = keydown)
eventEnv <- getGraphicsEventEnv()
}

我的datas数据框很大,但假装它只有时间序列向量。

第一个 col 是日期,然后 col 2 是“基线”预测,3 到 8 是替代方案。

我只是使用下面的行来测试,我还有另一个函数来运行整个事情

picker.mover(bl=datas[,2],scenarios=datas[,3:8],date.labs=datas[,1],target=1,name=colnames(datas)[2])
getGraphicsEvent()
par(savepar)
4

1 回答 1

0

您可能想查看http://www.image.ucar.edu/GSP/Software/Fields/Help/add.image.html - 原则上应该可以将图像添加到绘图中,因此您可以保存图像,然后创建一个以它为背景的新图形并在其上绘制。但是,您将遇到缩放等问题。

于 2012-10-02T21:13:49.467 回答