博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自制绘图之坐标轴
阅读量:6983 次
发布时间:2019-06-27

本文共 6227 字,大约阅读时间需要 20 分钟。

写代码之前得先了解坐标轴的一些属性,坐标轴有范围,每隔多少显示一条数值信息。然而间隔信息有时并不确定,一旦设置不准确,图形会乱掉。最好的方法是使用另一个参数:分隔符总数。这样可以利用坐标范围计算出间隔。

首先需要定义范围:

1 template 
2 class DataRange 3 { 4 public: 5 DataRange(const T& minValue, const T& maxValue): itsMinValue(minValue), itsMaxValue(maxValue){} 6 DataRange(){} 7 T itsMinValue; 8 T itsMaxValue; 9 T Length() const { return itsMaxValue - itsMinValue ;}10 };

先写测试代码:

1 void TestPicture::TestCoordSimple()2 {3     CoordinateAttribute
ca;4 ca.itsNumSeparate = 10;5 ca.itsGivenDataRange = DataRange
(0.0,2.4);6 ca.CalcCoordinate();7 assert(0.24==ca.itsSeparateLength);8 }

通过这一测试很简单只需一个除法就搞定了。代码如下:

1 template 
2 class CoordinateAttribute 3 { 4 public: 5 CoordinateAttribute(){} 6 //attribute 7 int itsNumSeparate; 8 DataRange
itsGivenDataRange; 9 T itsSeparateLength;10 //operators11 void CalcCoordinate()12 {13 //calculate separate length14 itsSeparateLength = itsGivenDataRange.Length() / itsNumSeparate;15 }16 };

有个问题就是如果坐标轴的范围不能被分隔符整除,显示出来的坐标将带有很多小数位,往往不是我们所想要的。于是还需要另一个参数给坐标轴,那就是最小刻度。比如有些情况下需要显示的都是整数,有时需要保留一位小数。

1 void TestPicture::TestCoordSimple2()2 {3     CoordinateAttribute
ca;4 ca.itsNumSeparate = 10;5 ca.itsGivenDataRange = DataRange
(0.0,2.4);6 ca.itsMinScale = 0.1;7 ca.CalcCoordinate();8 assert(0.3==ca.itsSeparateLength);9 }

修改代码为:

1 template 
2 class CoordinateAttribute 3 { 4 public: 5 CoordinateAttribute(){} 6 //attribute 7 int itsNumSeparate; 8 DataRange
itsGivenDataRange; 9 T itsMinScale;10 T itsSeparateLength;11 //operators12 void CalcCoordinate()13 {14 //calculate separate length15 T temp = itsGivenDataRange.Length() / itsNumSeparate;16 itsSeparateLength = itsMinScale * ceil((double)temp / itsMinScale);17 }18 };

这个坐标轴的计算方法先做到这,下面来测试其效果。坐标轴的信息需要给图形,最简洁的方法是告诉图形在坐标轴的什么位置显示多少坐标值,由于坐标轴对图形是未知的,其位置可以使用百分比来表示,在C++中可以使用std::map<double,std::string>来传递坐标轴的信息。

在CoordinateAttribute加入一个FillToAxisMap函数

1 void FillToAxisMap(std::map
& sm) 2 { 3 sm.clear(); 4 T iT = itsGivenDataRange.itsMinValue; 5 for (int i = 0; i <= itsNumSeparate; i++,iT += itsSeparateLength) 6 { 7 double dIndex = iT - itsGivenDataRange.itsMinValue ; 8 dIndex /= itsCalculateDataRange.Length(); 9 sm.insert(std::make_pair(dIndex,ConvertToString
(iT)));10 }11 }

其中ConvertToString函数如下:

1 template 
2 std::string ConvectToString(const T& v)3 {4 std::strstream str;5 str<
<<'\0';6 return str.str();7 }

写个输出函数来看我们的结果。

测试函数:

1     map
CoordInfo;2 ca.FillToAxisMap(CoordInfo);3 for (map
::iterator it = CoordInfo.begin();it != CoordInfo.end(); ++it)4 {5 cout << endl << it->first << " ---- " << it->second ;6 }

运行结果:

0 ---- 00.1 ---- 0.30.2 ---- 0.60.3 ---- 0.90.4 ---- 1.20.5 ---- 1.50.6 ---- 1.80.7 ---- 2.10.8 ---- 2.40.9 ---- 2.71 ---- 3

  

可以看到,其结果还是在我们的意料之中的,有一点不好,我们给的范围是0~2.4,而现在的范围变成了0~3了。先不做改动,再做下一次测试。

1     CoordinateAttribute
ca;2 ca.itsNumSeparate = 10;3 ca.itsGivenDataRange = DataRange
(0.0,2.4);4 ca.itsMinScale = 0.5;5 ca.CalcCoordinate();

其输出结果为:

0 ---- 00.1 ---- 0.50.2 ---- 10.3 ---- 1.50.4 ---- 20.5 ---- 2.50.6 ---- 30.7 ---- 3.50.8 ---- 40.9 ---- 4.51 ---- 5

问题更严重了,计算出的范围比之前我们给的大很多。其实这是由于所给参数不合理导致的。既然itsMinScale设了0.5,那么itsNumSeparate设为10显然不正确,这时最好由程序自己来调整。

理想的输出结果是:

0 ---- 00.2 ---- 0.50.4 ---- 10.6 ---- 1.50.8 ---- 21 ---- 2.5

修改代码如下:

1 template 
2 class CoordinateAttribute 3 { 4 public: 5 CoordinateAttribute(){} 6 //the param user give 7 int itsNumSeparate; 8 DataRange
itsGivenDataRange; 9 T itsMinScale;10 //the param calculate11 T itsSeparateLength;12 DataRange
itsCalculateDataRange;13 14 //operators15 void CalcCoordinate()16 {17 //adjust its min value18 itsCalculateDataRange.itsMinValue = itsMinScale * floor((double)itsGivenDataRange.itsMinValue / itsMinScale);19 //calculate separate length20 itsCalculateDataRange.itsMaxValue = itsGivenDataRange.itsMaxValue;21 T temp = itsCalculateDataRange.Length() / itsNumSeparate;22 itsSeparateLength = itsMinScale * ceil((double)temp / itsMinScale);23 //calculate its max value24 itsCalculateDataRange.itsMaxValue = itsCalculateDataRange.itsMinValue + itsSeparateLength * itsNumSeparate;25 //delete unused value26 while( itsCalculateDataRange.itsMaxValue - itsSeparateLength > itsGivenDataRange.itsMaxValue)27 {28 itsCalculateDataRange.itsMaxValue -= itsSeparateLength;29 itsNumSeparate--;30 }31 }32 };

这里加了itsCalculateDataRange,用来记录计算后的数据范围,对max和min的范围进行了调整。

测试如下:

1     ca.itsNumSeparate = 7; 2     ca.itsMinScale = 0.1; 3     ca.itsGivenDataRange = DataRange
(0.0,2.34); 4 ca.CalcCoordinate(); 5 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.4,ca.itsSeparateLength,0.01); 6 CPPUNIT_ASSERT_DOUBLES_EQUAL(2.4,ca.itsCalculateDataRange.itsMaxValue,0.01); 7 ca.itsNumSeparate = 5; 8 ca.CalcCoordinate(); 9 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.5,ca.itsSeparateLength,0.01);10 CPPUNIT_ASSERT_DOUBLES_EQUAL(2.5,ca.itsCalculateDataRange.itsMaxValue,0.01);11 ca.itsNumSeparate = 10;12 ca.itsMinScale = 0.1;13 ca.CalcCoordinate();14 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.3,ca.itsSeparateLength,0.001);15 CPPUNIT_ASSERT_DOUBLES_EQUAL(2.4,ca.itsCalculateDataRange.itsMaxValue,0.001);16 ca.itsGivenDataRange.itsMinValue = 0.14;17 ca.itsMinScale = 0.01;18 ca.itsNumSeparate = 10;19 ca.CalcCoordinate();20 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.22,ca.itsSeparateLength,0.001);21 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.14,ca.itsCalculateDataRange.itsMinValue,0.001);22 CPPUNIT_ASSERT_DOUBLES_EQUAL(2.34,ca.itsCalculateDataRange.itsMaxValue,0.001);

转载于:https://www.cnblogs.com/zhangyonghugo/archive/2012/05/04/2482613.html

你可能感兴趣的文章
Golang web之http标准库简析
查看>>
PowerShell删除故障群集节点
查看>>
一个数组实现两个栈
查看>>
Fedora 27 命令行提示符修改
查看>>
Erlang 简易安装和卸载
查看>>
Windows Server 2012 R2 DirectAccess功能测试(3)—App2服务器安装及配置
查看>>
Shell 十三问学习笔记2
查看>>
Juniper-R&S-BGP(1):一些写在前头的基础知识
查看>>
python flaskfeng封装跨域请求头和封装json格式
查看>>
【搜索引擎基础知识2】网络爬虫
查看>>
Aptana Studio 3 汉化
查看>>
phonegap+jquerymobile开发android的心得(4)
查看>>
python 使用PyTesser--安装
查看>>
无需编译,1分钟安装Ubuntu官方构建的最新版Linux内核
查看>>
解压即用,Ubuntu上Nginx/Apache/PHP编译打包
查看>>
table设置border没有空隙
查看>>
Maven的setting.xml 配置详解
查看>>
Python3.7源码在windows(VS2015)下的编译和安装
查看>>
10_css选择符类型1.html
查看>>
修改 liteide 的 godoc 文档样式
查看>>