关于坐标轴刻度取值的问题
由于工作原因,需要画图表,但在图表的该度的取值上就出现了问题,但现在关于图表的控件已经很多了,那应该也有成熟的算法了,经过在网上努力寻找前人们是足迹,算给我找到了这编文章,问题总算解决了!!!---故记。
(1)步长规范化是关键
一般地,我们在标定坐标轴时,给出的参数是:起点、终点和刻度数,因为我们程序设计人员对在一个多大的区域面积内绘制多少个刻度比较美观有直观感觉,相反,而对多大步长则印象较浅。当然,知道刻度数和起点与终点值求步长是很容易 的,如下式:
CorStep=(CorMax一CorMin)/CorNumber
式中,CorMax、CorMin、CorNmnber分别对应 起点、终点和刻度数。 步长求出后。我们只要将步长求以lO为底的 对数,即可获得步长的数量级,见下式:
Temp=Log(corStep)/Log(10)
或者
Temp=Log(CorStep)/Log(10)+1
式中,Log代表自然对数。至于取哪个公式,需 要根据CorStep是否是lO的整数次幂而定。
进而将步长其规范化到0到1的范围内,方法如下: NewCopStep=CorStep/(10^Temp)
式中,符号“^”代表取幂的意思。
然后根据新的步长取值范围,将新的取值定位 在:0.1、O.2、0.25、0.5、1几个常规步长上,称为StardardStep.最后,再根据数量级将规范的步长恢复 到本来的数量级上,见下式:
FinalStep=StardardStp*Temp
(2)起点的规范化
一般说来.我们的起点应该是小于等于原来的 起点,同时,起点坐标是步长的整数倍比较符合人 们的习惯。这一点容易做到,见下式:
NewCorMin=(Int(CorMin/FinalStep))*Finalste
其中,Int是取整函数。
(3)终点的规范化
按惯例,我们的终点应该是大于等于原来的终点,同样,终点坐标是步长的整数倍比较符合人们的习惯,见下式:
NewC0rMax= (Int(CorMax/FinalStep)+1)十FinaIStep
其中,Int是取整函数。
(4)最后的修正
我们按上面的公式确定完参数后,新确定的步长、起点、终点值有可能使得刻度数与原来刻度数不等。这里是否需要调整呢?如果需要,我们应该如何调整呢?笔者认为,如果新算得的刻度数大于等于原来设定的刻度数,就不应该调整了。如果新算得的刻度数小于原来设定的刻度数,就应该将其 调整为原来的刻度数。同时,在步长不动的情况下,分别将起点与终点进行再次修正。
下面是对应的程序:
注:源文为VB代码,由于工作需要,转为javascript代码。
function standard(cormax,cormin,cornumber){
var tmpmax,tmpmin, corstep,tmpstep,tmpnumber,temp,extranumber;
if(cormax<=cormin)
return ;
corstep=(cormax-cormin)/cornumber;
if(Math.pow(10,parseInt(Math.log(corstep)/Math.log(10)))==corstep){
temp = Math.pow(10,parseInt(Math.log(corstep)/Math.log(10)));
}else{
temp = Math.pow(10,(parseInt(Math.log(corstep)/Math.log(10))+1));
}
tmpstep = (corstep/temp).toFixed(6);
//选取规范步长
if(tmpstep>=0&&tmpstep<=0.1){
tmpstep = 0.1;
}else if(tmpstep>=0.100001&&tmpstep<=0.2){
tmpstep = 0.2;
}else if(tmpstep>=0.200001&&tmpstep<=0.25){
tmpstep = 0.25;
}else if(tmpstep>=0.250001&&tmpstep<=0.5){
tmpstep = 0.5
}else{
tmpstep = 1;
}
tmpstep = tmpstep * temp;
if(parseInt(cormin/tmpstep)!=(cormin/tmpstep)){
if(cormin<0){
cormin = (-1) * Math.ceil(Math.abs(cormin/tmpstep))*tmpstep;
}else{
cormin = parseInt(Math.abs(cormin/tmpstep))*tmpstep;
}
}
if(parseInt(cormax/tmpstep)!=(cormax/tmpstep)){
cormax = parseInt(cormax/tmpstep+1)*tmpstep;
}
tmpnumber = (cormax-cormin)/tmpstep;
if(tmpnumber<cornumber){
extranumber = cornumber - tmpnumber;
tmpnumber = cornumber;
if(extranumber%2 == 0){
cormax = cormax + tmpstep*parseInt(extranumber/2);
}else{
cormax = cormax + tmpstep*parseInt(extranumber/2+1);
}
cormin = cormin - tmpstep*parseInt(extranumber/2);
}
cornumber = tmpnumber;
return [cormax,cormin,cornumber];
}
---------------文章摘抄于《坐标轴刻度的规范化标定处理》