第十二週上機項目4 點,圓的關係

【項目4 - 點、圓的關係】
(1)先建立一個Point(點)類,包含數據成員x,y(座標點);
(2)以Point爲基類,派生出一個Circle(圓)類,增加數據成員(半徑),基類的成員表示圓心;
(3)編寫上述兩類中的構造、析構函數及必要運算符重載函數(本項目主要是輸入輸出);

(4)定義友元函數int locate,判斷點p與圓的位置關係(返回值<0圓內,==0圓上,>0 圓外);

int main( )  
{  
    Circle c1(3,2,4),c2(4,5,5);      //c2應該大於c1  
    Point p1(1,1),p2(3,-2),p3(7,3);  //分別位於c1內、上、外  
  
  
    cout<<"圓c1: "<<c1;  
   
    cout<<"點p1: "<<p1;  
    cout<<"點p1在圓c1之"<<((locate(p1, c1)>0)?"外":((locate(p1, c1)<0)?"內":"上"))<<endl;  
   
    cout<<"點p2: "<<p2;  
    cout<<"點p2在圓c1之"<<((locate(p2, c1)>0)?"外":((locate(p2, c1)<0)?"內":"上"))<<endl;  
   
    cout<<"點p3: "<<p3;  
    cout<<"點p3在圓c1之"<<((locate(p3, c1)>0)?"外":((locate(p3, c1)<0)?"內":"上"))<<endl;  
    return 0;  
}  

/*
* Copyright (c) 2015,煙臺大學計算機學院
* All right reserved.
* 作者:曹莉萍
* 文件:Demo.cpp
* 完成時間:2015年05月31日
* 版本號:v1.0
*/
#include <iostream>
#include<Cmath>
using namespace std;
class Point
{
public:
    Point(double a=0,double b=0):x(a),y(b) {} //構造函數
    double distance(const Point &p) const;  //求距離
    friend ostream & operator<<(ostream &,const Point &);//重載運算符“<<”
protected:    //受保護成員
    double x,y;
};

double Point::distance(const Point &p) const    //求距離
{
    double dx = x-p.x;
    double dy = y-p.y;
    return sqrt(dx*dx+dy*dy);
}

ostream & operator<<(ostream &output,const Point &p)
{
    output<<"["<<p.x<<","<<p.y<<"]"<<endl;
    return output;
}

class Circle:public Point //circle是Point類的公用派生類
{
public:
    Circle(double a=0,double b=0,double r=0) :Point(a,b),radius(r) { }; //構造函數
    friend ostream &operator<<(ostream &,const Circle &);//重載運算符“<<”
    friend int locate(const Point &p, const Circle &c); //判斷點p在圓上、圓內或圓外,返回值:<0圓內,==0圓上,>0 圓外
protected:
    double radius;
};

//重載運算符“<<”,使之按規定的形式輸出圓的信息
ostream &operator<<(ostream &output,const Circle &c)
{
    output<<"Center=["<<c.x<<", "<<c.y<<"], r="<<c.radius<<endl;
    return output;
}

//判斷點p在圓內、圓c內或圓c外
int locate(const Point &p, const Circle &c)
{
    const Point cp(c.x,c.y); //圓心
    double d = cp.distance(p);
    if (abs(d - c.radius) < 1e-7)
        return 0;  //相等
    else if (d < c.radius)
        return -1;  //圓內
    else
        return 1;  //圓外
}

int main( )
{
    Circle c1(3,2,4);
    Point p1(1,1),p2(3,-2),p3(7,3);  //分別位於c1內、上、外

    cout<<"圓c1: "<<c1;

    cout<<"點p1: "<<p1;
    cout<<"點p1在圓c1之"<<((locate(p1, c1)>0)?"外":((locate(p1, c1)<0)?"內":"上"))<<endl;

    cout<<"點p2: "<<p2;
    cout<<"點p2在圓c1之"<<((locate(p2, c1)>0)?"外":((locate(p2, c1)<0)?"內":"上"))<<endl;

    cout<<"點p3: "<<p3;
    cout<<"點p3在圓c1之"<<((locate(p3, c1)>0)?"外":((locate(p3, c1)<0)?"內":"上"))<<endl;
    return 0;
}



(5)在圓類上重載關係運算符(6種),使之能夠按圓的面積比較兩個圓的大小。自編main函數完成測試。

/*
* Copyright (c) 2015,煙臺大學計算機學院
* All right reserved.
* 作者:曹莉萍
* 文件:Demo.cpp
* 完成時間:2015年05月31日
* 版本號:v1.0
*/
#include <iostream>
#include<Cmath>
using namespace std;
class Point
{
public:
    Point(double a=0,double b=0):x(a),y(b) {}       //構造函數
protected:                                       //受保護成員
    double x,y;
};

class Circle:public Point //circle是Point類的公用派生類
{
public:
    Circle(double a=0,double b=0,double r=0): Point(a,b),radius(r) { }//構造函數
    double area ( ) const; //計算圓面積
    friend ostream &operator<<(ostream &,const Circle &);//重載運算符“<<”
    //重載關係運算符運算符,使之能夠按圓的面積比較兩個圓的大小;
    bool operator>(const Circle &);
    bool operator<(const Circle &);
    bool operator>=(const Circle &);
    bool operator<=(const Circle &);
    bool operator==(const Circle &);
    bool operator!=(const Circle &);
protected:
    double radius;
};

//計算圓面積
double Circle::area( ) const
{
    return 3.14159*radius*radius;
}

//重載運算符“<<”,使之按規定的形式輸出圓的信息
ostream &operator<<(ostream &output,const Circle &c)
{
    output<<"Center=["<<c.x<<", "<<c.y<<"], r="<<c.radius;
    return output;
}

//重載關係運算符(種)運算符,使之能夠按圓的面積比較兩個圓的大小;
bool Circle::operator>(const Circle &c)
{
    return (this->radius - c.radius) > 1e-7;
}

bool Circle::operator<(const Circle &c)
{
    return (c.radius - this->radius) > 1e-7;
}

bool Circle::operator>=(const Circle &c)
{
    return !(*this < c);
}

bool Circle::operator<=(const Circle &c)
{
    return !(*this > c);
}

bool Circle::operator==(const Circle &c)
{
    return abs(this->radius - c.radius) < 1e-7;
}

bool Circle::operator!=(const Circle &c)
{
    return abs(this->radius - c.radius) > 1e-7;
}

int main( )
{
    Circle c1(3,2,4),c2(4,5,5);      //c2應該大於c1
    cout<<"圓c1( "<<c1<<" )的面積是 "<<c1.area()<<endl;
    cout<<"圓c2( "<<c2<<" )的面積是 "<<c2.area()<<endl;
    cout<<"圓c1 ";
    if(c1>c2) cout<<"大於, ";
    if(c1<c2) cout<<"小於, ";
    if(c1>=c2) cout<<"大於等於, ";
    if(c1<=c2) cout<<"小於等於, ";
    if(c1==c2) cout<<"等於, ";
    if(c1!=c2) cout<<"不等於, ";
    cout<<"圓c2"<<endl;

    return 0;
}



6)與圓心相連的直線:給定一點p,其與圓心相連成的直線,會和圓有兩個交點,如圖。在上面定義的Point(點)類和Circle(圓)類基礎上,設計一種方案,輸出這兩點的座標。

方法1:用引用類型參數

/*
* Copyright (c) 2015,煙臺大學計算機學院
* All right reserved.
* 作者:曹莉萍
* 文件:Demo.cpp
* 完成時間:2015年05月31日
* 版本號:v1.0
*/
#include <iostream>
#include<Cmath>
using namespace std;
class Circle;  //由於在Point中聲明友元函數crossover_point中參數中用了Circle,需要提前聲明
class Point
{
public:
    Point(double a=0,double b=0):x(a),y(b) {}       //構造函數
    friend ostream & operator<<(ostream &,const Point &);//重載運算符“<<”
    friend void crossover_point(Point &p,Circle &c, Point &p1,Point &p2 ) ;  //求交點的友元函數
protected:                                       //受保護成員
    double x,y;
};
ostream & operator<<(ostream &output,const Point &p)
{
    output<<"["<<p.x<<","<<p.y<<"]";
    return output;
}

class Circle:public Point //circle是Point類的公用派生類
{
public:
    Circle(double a=0,double b=0,double r=0):Point(a,b),radius(r) { } //構造函數
    friend ostream &operator<<(ostream &,const Circle &);//重載運算符“<<”
    friend void crossover_point(Point &p,Circle &c, Point &p1,Point &p2 ) ;  //求交點的友元函數
protected:
    double radius;
};

//重載運算符“<<”,使之按規定的形式輸出圓的信息
ostream &operator<<(ostream &output,const Circle &c)
{
    output<<"Center=["<<c.x<<", "<<c.y<<"], r="<<c.radius;
    return output;
}

//給定一點p,求出該點與圓c的圓心相連成的直線與圓的兩個交點p1和p2
//關鍵問題是求得的交點如何返回
//方案1:利用引用類型的形式參數,注意,下面的p1和p2將“帶回”求得的結果
//crossover_point函數已經聲明爲Point和Circle類的友元函數,類中私有成員可以直接訪問
void crossover_point(Point &p, Circle &c, Point &p1,Point &p2 )
{
    p1.x = (c.x + sqrt(c.radius*c.radius/(1+((c.y-p.y)/(c.x-p.x))*((c.y-p.y)/(c.x-p.x)))));
    p2.x = (c.x - sqrt(c.radius*c.radius/(1+((c.y-p.y)/(c.x-p.x))*((c.y-p.y)/(c.x-p.x)))));
    p1.y = (p.y + (p1.x -p.x)*(c.y-p.y)/(c.x-p.x));
    p2.y = (p.y + (p2.x -p.x)*(c.y-p.y)/(c.x-p.x));
}

int main( )
{
    Circle c1(3,2,4);
    Point p1(1,1),p2,p3;

    crossover_point(p1,c1, p2, p3);

    cout<<"點p1: "<<p1<<endl;
    cout<<"與圓c1: "<<c1<<endl;
    cout<<"的圓心相連,與圓交於兩點,分別是:"<<endl;
    cout<<"交點1: "<<p2<<endl;
    cout<<"交點2: "<<p3<<endl;
    return 0;
}

方法2:結構體(定義兩個包含兩個點的結構體,用於返回值)

/*
* Copyright (c) 2015,煙臺大學計算機學院
* All right reserved.
* 作者:曹莉萍
* 文件:Demo.cpp
* 完成時間:2015年05月31日
* 版本號:v1.0
*/
#include <iostream>
#include<Cmath>
using namespace std;
class Circle;  //由於在Point中聲明友元函數crossover_point中參數中用了Circle,需要提前聲明
struct DoublePoint;  //也先聲明,Point中聲明友元函數crossover_point中要用到
class Point
{
public:
    Point(double a=0,double b=0):x(a),y(b) {}       //構造函數
    friend ostream & operator<<(ostream &,const Point &);//重載運算符“<<”
    friend DoublePoint crossover_point(Point &p,Circle &c) ;  //求交點的友元函數
protected:                                       //受保護成員
    double x,y;
};
ostream & operator<<(ostream &output,const Point &p)
{
    output<<"["<<p.x<<","<<p.y<<"]";
    return output;
}

class Circle:public Point //circle是Point類的公用派生類
{
public:
    Circle(double a=0,double b=0,double r=0):Point(a,b),radius(r) { } //構造函數
    friend ostream &operator<<(ostream &,const Circle &);//重載運算符“<<”
    friend DoublePoint crossover_point(Point &p,Circle &c) ;  //求交點的友元函數
protected:
    double radius;
};

//重載運算符“<<”,使之按規定的形式輸出圓的信息
ostream &operator<<(ostream &output,const Circle &c)
{
    output<<"Center=["<<c.x<<", "<<c.y<<"], r="<<c.radius;
    return output;
}

struct DoublePoint   //專門用於返回值的結構體類型
{
    Point p1;
    Point p2;
};

//給定一點p,求出該點與圓c的圓心相連成的直線與圓的兩個交點
//方案2:結果返回到DoublePoint類型的結構體中
//crossover_point函數已經聲明爲Point和Circle類的友元函數,類中私有成員可以直接訪問
DoublePoint crossover_point(Point &p, Circle &c)
{
    DoublePoint pp;
    pp.p1.x = (c.x + sqrt(c.radius*c.radius/(1+((c.y-p.y)/(c.x-p.x))*((c.y-p.y)/(c.x-p.x)))));
    pp.p2.x = (c.x - sqrt(c.radius*c.radius/(1+((c.y-p.y)/(c.x-p.x))*((c.y-p.y)/(c.x-p.x)))));
    pp.p1.y = (p.y + (pp.p1.x -p.x)*(c.y-p.y)/(c.x-p.x));
    pp.p2.y = (p.y + (pp.p2.x -p.x)*(c.y-p.y)/(c.x-p.x));
    return pp;
}

int main( )
{
    Circle c1(3,2,4);
    Point p1(1,1);
    DoublePoint pp;

    pp = crossover_point(p1,c1);

    cout<<"點p1: "<<p1<<endl;
    cout<<"與圓c1: "<<c1<<endl;
    cout<<"的圓心相連,與圓交於兩點,分別是:"<<endl;
    cout<<"交點1: "<<pp.p1<<endl;
    cout<<"交點2: "<<pp.p2<<endl;
    return 0;
}



好複雜的項目4,千辛萬苦弄完以後竟然有種字符搬家的感覺。

趕快吸收爲自己的吧。

加油加油!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章