首页 > 编程语言 > 详细

C++ Rectangle类的实现

时间:2021-03-27 12:36:28      阅读:46      评论:0      收藏:0      [点我收藏+]

C++:Rectangle---一个经典练习题

1.实现项目Rectangle :main.cpp 、Rectangle.cpp 、 Rectangle.h

  首先我们需要表示出Rectangle的四个角【即四个x,y坐标】

  这一步我们可以使用pair<double,double>实现,也可以自己写一个Point类

  为了方便,我使用pair

 

2.实现功能:

 (1)计算length 、 width 、 area 

 (2)判断是不是square、rectangle

 (3)打印图像

 (4)旋转图像

 (5)放缩图像

 

3.步骤分析:

 (1)步骤简单,略过

 (2)那么直接进入如何判断rectangle

  条件一:一个矩形,它的对角线必然相等

  条件二:一个矩形,它的对边相等

  条件三:它不能是一条线

bool MyRectangle::Rectangle::isRectangle( ) const
{
    // 判断对角线是否相等 and 对边是否相等
    bool ans = distance(point[0],point[3]) == distance(point[1],point[2]);
    ans &= distance(point[2],point[0]) == distance(point[3],point[1]);
    ans &= distance(point[2],point[3]) == distance(point[1],point[0]);
    for(int i = 0;i < 3;i++){//判断是不是有重合点
        if(point[i].fi==point[i+1].fi&&point[i].se==point[i+1].se)
            return false;
    }
    return ans;
}

 判断正方形直接加上邻边相等条件即可!

 (3)打印图像

  首先想到,打印循环的点都是int类型的,但是矩形是double类型的,那么必然会导致显示不完全的情况,在此说明了。

  对于一个双重for循环打印,我们考虑对于每一个{i,j}赋予一个属性:在/不在 矩形内部

  所以我写了一个inRectangle的判断函数,这个判断函数也是很好写的。

  【详见https://blog.csdn.net/dapengbusi/article/details/50516126

  就是利用向量的叉乘判断一个点是不是在举行外部【特判四个角的情况】

bool MyRectangle::Rectangle::inRectangle(float x,float y) const
{
    const double eps = 0.3; // 这个精度控制真的难受。。。。
    for(PFF it:point){
        if(fabs(x-it.fi) < eps && fabs(y-it.se) < 1e-4)
            return true;
    }
    PFF p = make_pair(x,y);
    for(int i = 0;i < 4;i++)
    {
        if( cross(point[i+1]-point[i],p-point[i]) > eps )
        return false;
    }
    return true;
}

 (4)旋转嘛,也很简单,就是一个旋转公式。

  【详细请见https://blog.csdn.net/qq_36797743/article/details/85680195

void MyRectangle::Rectangle::rotateRectangle(float deg)
{
    vector<PFF>temp;
    for(PFF&it:point){
        //旋转公式
        float y = ( (it.se-o.se)*cos(deg) + (it.fi-o.fi)*sin(deg) ) + o.se;
        float x = ( (it.fi-o.fi)*cos(deg) - (it.se-o.se)*sin(deg) ) + o.fi;
        if(x < 0 || x > 25 || y < 0 || y >25){
            cerr<<"旋转失败"<<endl;
            return ;
        }
        temp.push_back(make_pair(x,y));
    }
    point.clear();
    point = temp;
}

 (5)放缩,添加一个比例变量,但是很难做到定点放缩【暂且不谈了吧】

 

4.错误总结

 (1)实现过程中发现光标很烦人地闪来闪去。于是加了一段代码隐藏光标,但是windows.h头文件与Rectangle类是冲突的,那么我们怎么办呢?

  为Rectangle加一个命名空间即可,但是这样的话,在命名空间外部定义的函数,也需要加上一个MyRectangle::作用域符号,然后创建对象时也需要加一个MyRectangle::

 (2)极角排序还需要加强练习啊!

 

文件:

技术分享图片
#include <iostream>
#include <windows.h>
#include "Rectangle.h"
using namespace std;

#define mp make_pair

int main()
{
    //隐藏光标
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); // 得到控制台的句柄
    CONSOLE_CURSOR_INFO CursorInfo;                  // 建立光标对象
    GetConsoleCursorInfo(handle,&CursorInfo);        // 得到光标对象的信息
    CursorInfo.bVisible = false;                     // 设置bvisible为 false
    SetConsoleCursorInfo(handle,&CursorInfo);        // 然后设置即可!

    //Rectangle r({1,1},{15,1},{1,15},{14,14});
    //最后一个点错误,不能形成矩形
    const float pi = acos(-1);

    //隐藏光标之后,发现windows与Rectangle类起冲突
    //只能使用命名空间解决问题了【代码量加大。。】

    MyRectangle::Rectangle R(mp(1,1),mp(10,1),mp(1,15),mp(10,15));
    R.print();
    R.rotateRectangle();
    system("pause");
    R.print();

    for(int i = 1;i < 10;i++)
    {
        R.rotateRectangle();
        R.print();
    }


    const double deg = 45.0/180.0*pi;//转45°,转换成rad单位,效果最好


    R.setRectangle(mp(10,10),mp(15,10),mp(10,11),mp(15,11));
    R.print();
    R.rotateRectangle();
    system("pause");
    R.print();
    for(int i = 1;i < 10;i++)
    {
        R.rotateRectangle(deg);
        R.print();
    }

    //斜着的
    R.setRectangle(mp(1,3),mp(3,1),mp(4,2),mp(2,4));
    R.print();



    //角度不宜太小,否则可能显示同一个图形 / 或者图像显示不全
    for(int i = 1;i < 10;i++)
    {
        R.rotateRectangle(deg);
        R.print();
    }

    return 0;
}
main.cpp
技术分享图片
/*
 作者:Pigeon
 时间:2021
 功能:作业
 实现方法:写 C++
 */

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdexcept>
using namespace std;
#include "Rectangle.h"

typedef pair<float,float> PFF;
#define fi first
#define se second
// the pre definition

//三个辅助函数
float distance(PFF a,PFF b)
{
    float dx = a.fi - b.fi;
    float dy = a.se - b.se;
    return sqrt(dx*dx+dy*dy);
}

//为了方便,写一个pair<float,float>中的operator-运算符
PFF operator-(PFF a,PFF b)
{
    return {a.fi-b.fi,a.se-b.se};
}

float cross(PFF a,PFF b)//传入两个向量
{
    return ( b.se * a.fi ) - ( a.se * b.fi );
}

MyRectangle::Rectangle::Rectangle(PFF a,PFF b,PFF c,PFF d):rectChar(.),borderChar(#)
{
    setRectangle(a,b,c,d);
    //ctor
}

void MyRectangle::Rectangle::setRectangle(PFF a,PFF b,PFF c,PFF d)
{
    point.clear();// 必须要清空之前的点
    point.push_back(a);
    point.push_back(b);
    point.push_back(c);
    point.push_back(d);
    sort(point.begin(),point.end());

    //判断是不是在 0~20内
    const float eps = 1e-9;//精度损失
    for(PFF it:point){
        if(it.fi > 20 || it.fi < eps)
            throw invalid_argument(" invalid x coordinate , x must be 0~20 !");
        if(it.se > 20 || it.se < eps)
            throw invalid_argument(" invalid y coordinate , y must be 0~20 !");
    }
    if(this->isRectangle() == 0){
        throw invalid_argument(" invalid x,y coordinate , can‘t make a rectangle!");
    }

    //确认是一个矩形,完成后续初始化
    //对角线中心
    o = make_pair((point[0].fi+point[3].fi)/2,(point[0].se+point[3].se)/2);
    //冒泡排序进行极角排序

    for(int i = 0;i < 4;i++)
    {
        for(int j = i;j+1 < 4;j++)
        {
            if(cross(point[j]-o,point[j+1]-o) > 0)
            swap(point[j],point[j+1]);
        }
    }
    point.push_back(point[0]);

    //初始化宽 、 长
    width = min(distance(point[0],point[1]),distance(point[1],point[3]));
    length = max(distance(point[0],point[1]),distance(point[1],point[3]));
}

bool MyRectangle::Rectangle::isRectangle( ) const
{
    // 判断对角线是否相等 and 对边是否相等
    bool ans = distance(point[0],point[3]) == distance(point[1],point[2]);
    ans &= distance(point[2],point[0]) == distance(point[3],point[1]);
    ans &= distance(point[2],point[3]) == distance(point[1],point[0]);
    for(int i = 0;i < 3;i++){
        if(point[i].fi==point[i+1].fi&&point[i].se==point[i+1].se)
            return false;
    }
    return ans;
}

bool MyRectangle::Rectangle::isSquare( ) const
{
    if( isRectangle( ) && getWidth() == getLength() )//是矩形而且边长相等
        return true;
    return false;
}

float MyRectangle::Rectangle::getWidth( ) const // 短轴距离
{
     return width;
}

float MyRectangle::Rectangle::getLength( ) const // 长轴距离
{
    return length;
}

float MyRectangle::Rectangle::getArea( ) const
{
    return getLength()*getWidth();
}

void MyRectangle::Rectangle::setFillCharacter( const char&ch )
{
    rectChar = ch;
}

void MyRectangle::Rectangle::setPerimeterCharacter( const char&ch )
{
    borderChar = ch;
}

bool MyRectangle::Rectangle::inRectangle(float x,float y) const
{
    const double eps = 0.3; // 这个精度控制真的难受。。。。
    for(PFF it:point){
        if(fabs(x-it.fi) < eps && fabs(y-it.se) < 1e-4)
            return true;
    }
    PFF p = make_pair(x,y);
    for(int i = 0;i < 4;i++)
    {
        if( cross(point[i+1]-point[i],p-point[i]) > eps )
        return false;
    }
    return true;
}

bool MyRectangle::Rectangle::onBorder(float x,float y)const
{
    const float eps = 1e-7;
    return( fabs(x) < eps ||
            fabs(y) < eps ||
            fabs(y-25) < eps ||
            fabs(x-25) < eps );
}

void MyRectangle::Rectangle::print( ) const
{
    system("cls");
    for(int i = 0;i <= 25;i++)
    {
        for(int j = 0;j <= 25;j++)
        {
            if(onBorder(i,j))cout<<borderChar<<" ";
            else if(inRectangle(i,j))cout<<rectChar<<" ";
            else cout<<"  ";
        }
        cout<<endl;
    }
}

void MyRectangle::Rectangle::rotateRectangle(float deg)
{
    vector<PFF>temp;
    for(PFF&it:point){
        //旋转公式
        float y = ( (it.se-o.se)*cos(deg) + (it.fi-o.fi)*sin(deg) ) + o.se;
        float x = ( (it.fi-o.fi)*cos(deg) - (it.se-o.se)*sin(deg) ) + o.fi;
        if(x < 0 || x > 25 || y < 0 || y >25){
            cerr<<"旋转失败"<<endl;
            return ;
        }
        temp.push_back(make_pair(x,y));
    }
    point.clear();
    point = temp;
}

MyRectangle::Rectangle::~Rectangle()
{
    //dtor
}
Rectangle.cpp
技术分享图片
#ifndef RECTANGLE_H
#define RECTANGLE_H

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

namespace MyRectangle
{
typedef pair<float,float> PFF;

class Rectangle
{
public:
    Rectangle(
        PFF L1 = {1,1},PFF L2 = {1,20},
        PFF R1 = {20,1}, PFF R2 = {20,20}
    );
    virtual ~Rectangle( );

    //check function
    bool isRectangle( ) const;
    bool isSquare( ) const;
    bool inRectangle(float, float) const;//检验这个点在不在矩形内
    bool onBorder(float, float) const;  //检验这个点是不是边界

    //get function
    float getWidth( ) const;
    float getLength( ) const;
    float getArea( ) const;

    //set Function
    void setRectangle(PFF,PFF,PFF,PFF);
    void setFillCharacter(const char&);
    void setPerimeterCharacter(const char&);

    //print function
    void print( ) const;

    //加分函数
    void rotateRectangle(float = 1.570796326794896619);//默认旋转: pi/2
    /*
    *   支持旋转一定角度
    *   默认 “定点” 为对角线交点
    *   确定旋转的 “定点”
    *   先检验转换之后 矩形是否合法 再进行旋转
    *   所有点根据 “定点” 来旋转
    */


private:
    vector<PFF> point;
    PFF o;// 对角线交点
    float width , length;
    char rectChar , borderChar;
};

}

#endif // RECTANGLE_H
Rectangle.h

 

C++ Rectangle类的实现

原文:https://www.cnblogs.com/guanjinquan/p/14585221.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!