问题描述
多段线(polyline)通常有多个点对象构成,2D空间中的多段线由2D空间中的点构成,这些点依次链接,在二维平面上构成一条多段线,请编写的点类、利用动态内存申请的形式,编写polyline类。
要求:
1.二维点类;
2.多段线中存储的点个数用户可以指定;
3.能够计算多段线的长度;
4.能够计算这些2D空间点所构成的AABB包围盒的左下角点和右上角点。
目录
思路
- 要求1说明点的数据成员至少有x,y作为坐标
- 对于要求2则是创建多个点类,这在主函数中实现、
- 要求3的实现可以先求两个点之间的距离,再依次相加,写成函数,则是调用一个点的成员函数,传另一个点的值,这样就写成了成员函数
- 要求4可以先在两点之间比较坐标值,然后获取满足条件的坐标值,同样可以在类中实现,倒不如说在类与对象这章,也只有“调用”这种操作——即调用该类创建对象,调用类中的函数等不在类中实现,后续无论多少参数,多少函数都应该在类中实现
- 该问题较为简单,析构函数用默认的就行,构造函数中默认坐标为(0,0),距离为0
步骤
第一步——构造类以及确定创建的对象的个数
先写个模板,通过分析确定类里的数据成员为x,y作为坐标,_len作为距离。函数成员有1.获取坐标,2.显示坐标(用来在控制台输出),2.求两点之间的距离,3.计算“AABB”盒左下角点和右下角点(考虑到输出问题,这俩分开写)
class polyline
{
public:
polyline() :_x(0), _y(0), _len(0)
{
} //构造函数
void setline();//设置各个点的坐标
void show_line();//显示坐标
void left_down_line(polyline &p);//输出AABB左下角点
void right_up_line(polyline &p);
double gain_line(polyline p);//多线段的长度
private:
double _x, _y;//点的坐标
double _len;//多线段的长度
};
主函数中,输入对象的个数,并设置一个变量来记录各距离之和,用动态数组接收这n个对象
注意个数一定是整数,坐标值以及长度可能是小数所以用double类型
int main() {
int n;//确定有多少个对象
double len=0;//用来相加所有的对象中的距离的值
cin >> n;
polyline* p = new polyline[n];//用动态数组接收这n个对象
}
第二步——各函数的细节实现
接下来实现成员函数中的细节,获取坐标用cin直接输入即可,显示坐标直接cout输出即可,比较简单
获取坐标函数的实现:
void polyline::setline() {
cin >> _x;
cin >> _y;
}
求长度就是两点之间距离问题,点坐标差的平方和开根号
求距离函数的实现:
double polyline::gain_line(polyline p)
{
_len=sqrt((this->_x - p._x) * (this->_x - p._x) + (this->_y - p._y) * (this->_y - p._y));
return _len;
}
sqrt是求根函数,需要头文件<cmath>,表达式比较长但实际上只会写这一次所以不需要取别名做简化
在主函数中的“调用”实现:
for (int i = 0; i < n; i++) {
(p + i)->setline();
}
for (int i = 0; i < n; i++) {
if (i == n - 1) {
cout << len << endl;
break;
}
len += (p + i)->gain_line(*(p + i + 1));
}
输出“AABB”左下角点实际上就是找到这n个对象中x和y的最小值并输出,这里的思路是调用一个对象A的成员函数,传B的参数进去,两者的x,y分别进行比较,如果A的x比B小,那就交换,A的y比较小,那就交换,反之则不换,最终B的x和y一定是两者中的更小值,然后再使B和下一个进行比较,找右上角点也是同理。当然,这样做显而易见地可能改变了所有对象的值,但就解决这个问题所有要求本身而言并无大碍。而因为值改变了,所以需要用&进行值传递
求左下角点函数的实现:
void polyline::left_down_line(polyline &p)
{
if (this->_x < p._x) {
double m;
m = p._x;
p._x = this->_x;
this->_x = m;
}
if (this->_y < p._y) {
double m;
m = p._y;
p._y = this->_y;
this->_y = m;
}
}
需要注意的是如果在参数里不用&,那么个对象的值是不会发生改变的,也就是说这个函数就没用了
在主函数中“调用”的实现:
for (int i = 0; i < n; i++) {
if (i == n - 1) {
(p + n - 1)->show_line();
cout << endl;
break;
}
(p + i)->left_down_line(*(p + i + 1));
}
求右上角点的实现,只要把上面的成员函数<号改成>号就行了,其他一样。在这里为了展示的完整性就重写了一个求右上角点函数
总代码
#include<iostream>
#include<cmath>
using namespace std;
class polyline
{
public:
polyline() :_x(0), _y(0), _len(0)
{
} //构造函数
void setline();//设置各个点的坐标
void show_line();//显示坐标
void left_down_line(polyline &p);//输出AABB左下角点
void right_up_line(polyline &p);
double gain_line(polyline p);//多线段的长度
private:
double _x, _y;//点的坐标
double _len;//多线段的长度
};
void polyline::setline() {
cin >> _x;
cin >> _y;
}
void polyline::show_line()
{
cout << _x << " " << _y;
}
void polyline::left_down_line(polyline &p)
{
if (this->_x < p._x) {
double m;
m = p._x;
p._x = this->_x;
this->_x = m;
}
if (this->_y < p._y) {
double m;
m = p._y;
p._y = this->_y;
this->_y = m;
}
}
void polyline::right_up_line(polyline &p)
{
if (this->_x > p._x) {
double m;
m = p._x;
p._x = this->_x;
this->_x = m;
}
if (this->_y > p._y) {
double m;
m = p._y;
p._y = this->_y;
this->_y = m;
}
}
double polyline::gain_line(polyline p)
{
_len=sqrt((this->_x - p._x) * (this->_x - p._x) + (this->_y - p._y) * (this->_y - p._y));
return _len;
}
int main() {
int n;//确定有多少个对象
double len=0;//用来相加所有的对象中的距离的值
cin >> n;
polyline* p = new polyline[n];//用动态数组接收这n个对象
for (int i = 0; i < n; i++) {
(p + i)->setline();
}
for (int i = 0; i < n; i++) {
if (i == n - 1) {
cout << len << endl;
break;
}
len += (p + i)->gain_line(*(p + i + 1));
}
for (int i = 0; i < n; i++) {
if (i == n - 1) {
(p + n - 1)->show_line();
cout << endl;
break;
}
(p + i)->left_down_line(*(p + i + 1));
}
for (int i = 0; i < n; i++) {
if (i == n - 1) {
(p + n - 1)->show_line();
break;
}
(p + i)->right_up_line(*(p + i + 1));
}
}
虽然看着行数很多,但实际上并不复杂,对类的定义及声明占主要部分,当然代码也有可优化部分,比如只保留求左下角点的函数,构造一个新函数用来将“<”改成“>”,在需要求右上角点的时候调用该函数即可,再比如一些地方最好加上const修饰等。类的定义与声明部分一般是单独存放的,需要时直接调用即可。
同样的,在主函数里的代码也有可以优化的地方,比如求左下角点和右上角点可以放在一个for循环里循环两遍输出,第一遍输出左下角点,第二遍输出右上角点,总之代码的优化之路恒久且远
另外,对于要求中的“AABB”盒,如果认为一个点形成的"AABB"盒左下角点和右上角点都是它本身那没问题,而如果认为只有一个点是形成不了"AABB"盒,那么对于这种只有一个点的“特例”,只需要在输出里特地表达出遇到特例的默认输出值就可以了
标签:函数,对象,double,void,练习,点类,polyline,._,line From: https://blog.csdn.net/ftgchtcju/article/details/144565926