簡體   English   中英

需要一些幫助為Java創建Triangle類

[英]Need some assistance creating a Triangle class for Java

我應該在學校為自己的項目制作自己的Java Triangle類。 新的三角形從左到右依次獲取3個點的(x,y)坐標。 我主要關心的是我制作sideAB,sideBC和sideAC實例變量並在構造函數中初始化它們的方式。 另外,maxAngle和minAngle看起來像一團糟,我希望它具有與我的側面相似的angleA和angleC變量。 另外,我不確定我的任何變量是否應該是靜態的。 抱歉,如果我的代碼確實是noobie,但這是我上課的第一個Java項目。

這就是我所擁有的。 它有效,但我認為我沒有以正確的方式做所有事情:

public class Triangle {
    private double ax;
    private double ay;
    private double bx;
    private double by;
    private double cx;
    private double cy;
    //added these variables because I use them so frequently when calculating angles, area, perimeter, etc.
    private double sideAB;
    private double sideBC;
    private double sideAC;

    public Triangle(double x1, double y1, double x2, double y2, double x3, double y3)
    {
        ax = x1;
        ay = y1;
        bx = x2;
        by = y2;
        cx = x3;
        cy = y3;
        sideAB= Math.abs(Math.sqrt(Math.pow(bx-ax,  2)+Math.pow(by-ay, 2)));
        sideBC= Math.abs(Math.sqrt(Math.pow(cx-bx,  2)+Math.pow(cy-by, 2)));
        sideAC= Math.abs(Math.sqrt(Math.pow(cx-ax,  2)+Math.pow(cy-ay, 2)));
    }
    public double getPerimeter()
    {
        //add the 3 sides together for the perimeter
        double perimeter = sideAB + sideBC + sideAC;
        return perimeter;
    }
    public double getArea()
    {
        //used Heron's formula to find the area of the triangle
        double s = (sideAB + sideBC + sideAC)/2;
        double area = Math.sqrt(s*(s - sideAB)*(s - sideBC)*(s - sideAC));
        return area;
    }
    public double getSideAB()
    {
        return sideAB;
    }
    public double getSideBC()
    {
        return sideBC;
    }
    public double getSideAC()
    {
        return sideAC;
    }
    public double getAngleC()
    {
        //Law of cosines to find the angle
        double a2 = Math.pow(sideAB, 2);
        double b2 = Math.pow(sideBC, 2);
        double c2 = Math.pow(sideAC, 2);
        double cosC = ((b2 + c2)-a2)/((2*sideBC)*sideAC);
        double angleC = Math.acos(cosC);
        angleC = Math.toDegrees(angleC);
        return angleC;
    }
    public double getAngleB()
    {
        double a2 = Math.pow(sideAB, 2);
        double b2 = Math.pow(sideBC, 2);
        double c2 = Math.pow(sideAC, 2);
        double cosB = ((a2+b2-c2)/(2*sideAB*sideBC));
        double angleB = Math.acos(cosB);
        angleB = Math.toDegrees(angleB);
        return angleB;
    }
    public double getAngleA()
    {
        double a2 = Math.pow(sideAB, 2);
        double b2 = Math.pow(sideBC, 2);
        double c2 = Math.pow(sideAC, 2);
        double cosA = ((a2+c2-b2)/(2*sideAB*sideAC));
        double angleA = Math.acos(cosA);
        angleA = Math.toDegrees(angleA);
        return angleA;
    }
    public double maxSide()
    {
        //if-else if-else statements for max and min sides functions
        if (sideAB >= sideBC && sideAB >= sideAC)
        {
            return sideAB;
        }
        else if(sideBC >= sideAB && sideBC >= sideAC)
        {
            return sideBC;
        }
        else
        {
            return sideAC;
        }
    }
    public double minSide()
    {
        if (sideAB <= sideBC && sideAB <= sideAC)
        {
            return sideAB;
        }
        else if(sideBC <= sideAB && sideBC <= sideAC)
        {
            return sideBC;
        }
        else
        {
            return sideAC;
        }
    }
    public double maxAngle()
    {
        double a2 = Math.pow(sideAB, 2);
        double b2 = Math.pow(sideBC, 2);
        double c2 = Math.pow(sideAC, 2);
        double cosC = ((b2 + c2)-a2)/((2*sideBC)*sideAC);
        double angleC = Math.acos(cosC);
        angleC = Math.toDegrees(angleC);
        double cosB = ((a2+b2-c2)/(2*sideAB*sideBC));
        double angleB = Math.acos(cosB);
        angleB = Math.toDegrees(angleB);
        double cosA = ((a2+c2-b2)/(2*sideAB*sideAC));
        double angleA = Math.acos(cosA);
        angleA = Math.toDegrees(angleA);
        if (angleA >= angleB && angleA >= angleC)
        {
            return angleA;
        }
        else if(angleB >= angleA && angleB >= angleC)
        {
            return angleB;
        }
        else
        {
            return angleC;
        }       
    }
    public double minAngle()
    {
        double a2 = Math.pow(sideAB, 2);
        double b2 = Math.pow(sideBC, 2);
        double c2 = Math.pow(sideAC, 2);
        double cosC = ((b2 + c2)-a2)/((2*sideBC)*sideAC);
        double angleC = Math.acos(cosC);
        angleC = Math.toDegrees(angleC);
        double cosB = ((a2+b2-c2)/(2*sideAB*sideBC));
        double angleB = Math.acos(cosB);
        angleB = Math.toDegrees(angleB);
        double cosA = ((a2+c2-b2)/(2*sideAB*sideAC));
        double angleA = Math.acos(cosA);
        angleA = Math.toDegrees(angleA);
        if (angleA <= angleB && angleA <= angleC)
        {
            return angleA;
        }
        else if(angleB <= angleA && angleB <= angleC)
        {
            return angleB;
        }
        else
        {
            return angleC;
        }       
    }
}

三角形(至少在二維歐幾里得空間中)的顯着特性是其三個點。

就這樣,這就是您需要存儲的全部 其他一切都可以從中計算出來。 您不需要邊的長度或頂點的角度,它們都可以從這三個點導出。

我的建議是簡單地創建一個Point類型,然后從其中的三個中構建您的Triangle類型。

如果您確定這些派生值的計算過於昂貴,那么只有這樣,應該考慮緩存該信息。 但我懷疑情況會如此。 如果確實如此,則有(至少)兩種方法。

首先是在非派生值發生變化時計算派生值。 這樣做的好處是,每當您更改某些內容並簡化代碼時,都確保所有值都是最新的(每個setSomething()方法和構造函數都只需調用calcAllDerivedValues()方法)。

其次,只要更改非衍生值,就可以將衍生值標記為臟值。 然后,無論何時需要派生數據,計算數據的方法都可以檢查它們是否臟,然后計算(並緩存)它們。

如果它們臟,它們僅返回緩存的值。 這稍微復雜一點,但是可以刪除不必要的計算,尤其是如果每個派生值只有一個臟標志時,僅在需要時才計算需要的值。

並且,對於您對static的特定問題,如果它們在所有實例之間共享,則僅使用靜態的類級變量。 由於側面的角度或長度特定於一種情況,因此它們不應為靜態。


這就是我的開始方式。 首先,一個Point類,它具有xy成員(以及它們的getter和setter),並且能夠算出到另一個點的距離和角度(相對於“筆直”等固定角度),例如:

private double x, y;

public double getX();
public double getY();
public void setX(double newX);
public void setY(double newY);
public void setXY(double newX, double newY);
public double getDistance (Point other);
public double getAngle (Point other);

然后,您的Triangle類需要其中三點:

private Point a, b, c;

以及適當的setter和getter,以及計算所需的派生屬性所需的任何函數。

就像這樣:

  • 通過計算a->bb->ca->c之間的距離(使用Point類的getDistance()方法完成)來獲得周長,然后將它們相加。
  • 使用相同的信息(三個線長)來獲取面積。
  • 根據PointgetAngle()對於a->ba->c (對於A角)的結果之間的差來獲取角度。 如果該角度大於180,則顯然是三角形的外部 ,您應該從360中減去該角度以獲得內角。

而且您無需針對每種情況重復所有代碼。 例如,您希望能夠計算出三個頂點中任意一個的角度。 並不需要復制的所有智能代碼為每一個。

只需編寫一次復雜的代碼,然后以三種不同的方式進行調用。

我的意思是這樣的:

// Can just call Point stuff directly for distances (simple code).
double getDistAB() { return a.getDistance (b); }
double getDistAC() { return a.getDistance (c); }
double getDistBC() { return b.getDistance (c); }

double getPerimeter() { return getDistAB() + getDistAC() + getDistBC(); }

// Returns the angle inside triangle at the first vertex (complex code).
double getAngleAtPointX (Point x, Point y, Point z) {
    double angle = x.getAngle (y) - x.getAngle (z);
    if (angle < 0)
        angle = -angle;
    if (angle > 180)
        angle = 360 - angle;
    return angle;
}

// Then just call that with different arguments.
double getAngleA() { return getAngleAtPoint (a, b, c); }
double getAngleB() { return getAngleAtPoint (b, a, c); }
double getAngleC() { return getAngleAtPoint (c, a, b); }

在大多數情況下,代碼是正確的。

但是,最大的問題是您編寫的代碼多次執行相同的操作。 例如此方法:

public double maxAngle()
{
    double a2 = Math.pow(sideAB, 2);
    double b2 = Math.pow(sideBC, 2);
    double c2 = Math.pow(sideAC, 2);
    double cosC = ((b2 + c2)-a2)/((2*sideBC)*sideAC);
    double angleC = Math.acos(cosC);
    angleC = Math.toDegrees(angleC);
    double cosB = ((a2+b2-c2)/(2*sideAB*sideBC));
    double angleB = Math.acos(cosB);
    angleB = Math.toDegrees(angleB);
    double cosA = ((a2+c2-b2)/(2*sideAB*sideAC));
    double angleA = Math.acos(cosA);
    angleA = Math.toDegrees(angleA);
    if (angleA >= angleB && angleA >= angleC)
    {
        return angleA;
    }
    else if(angleB >= angleA && angleB >= angleC)
    {
        return angleB;
    }
    else
    {
        return angleC;
    }       
}

計算最大角度,但是您可以使用已經實現的方法getAngleA()getAngleB()getAngleC()編寫如下代碼:

public double maxAngle() {
  if(getAngleA() => getAngleB() && getAngleA() => getAngleC())
    return getAngleA();
  if(getAngleB() => getAngleA() && getAngleB() => getAngleC())
    return getAngleB();
  return getAngleC();
}

如果性能很重要,則應該預先計算所有值(假設一個值不能更改三角形的任何點),尤其是角度(如果多次訪問)。

不,您絕對不應使用任何靜態變量,因為這些變量將由Triangle類的每個實例共享。

可以在代碼中進行的一些修改是:-

  • 創建一個Coordinate類來存儲三個三角形坐標的x和y坐標。
  • 創建一個Side類來存儲所有三個面。
  • 創建一個Angle類以查找和存儲所有角度。

  • 現在,您不必在一個類中創建所有內容,而可以在各自的類中對其進行計算。然后從那里獲取。

  • EG:-讓一個特定的Angle實例找出自己的angle ,然后就可以從那里獲取角度了。因此,您不必編寫邏輯來創建角度三次。

  • 您可以將findMaxSide()findMinSide()代碼移動到Side類。.因為理想情況下,您的方法應該位於class containing the information您的方法正在使用class containing the informationclass containing the information

  • 同樣,將findMaxAngle()findMinAngle()移到您的Angle類。

因此,在這里,我為您提供了可以使用的Angle類。您可以自己創建CoordinateSide類:-

public class Angle {

    private double angle;

    public Angle() {

    }

    public double getAngle() {
        return this.angle;
    }

    public void setAngle(Side side1, Side side2, Side side3) {

        double a2 = Math.pow(side1.getLength(), 2);
        double b2 = Math.pow(side2.getLength(), 2);
        double c2 = Math.pow(side3.getLength(), 2);
        double cosB = ((a2+b2-c2)/(2*side1.getLength()*side2.getLength()));

        double tempAngle = Math.acos(cosB);

        this.angle = Math.toDegrees(tempAngle);
    }

    public Angle maxAngle(Angle angle1, Angle angle2) {

        Angle temp = angle1.getAngle() > angle2.getAngle() ? angle1 : angle2;
        return temp.getAngle() > this.getAngle() ? temp : this;
    }

    public Angle minAngle(Angle angle1, Angle angle2) {

        Angle temp = angle1.getAngle() < angle2.getAngle() ? angle1 : angle2;
        return temp.getAngle() < this.getAngle() ? temp : this;
    }
}

side1side2是它們之間要找到角邊..

您可以從Triangle類中使用該類,如下所示:-

public class Triangle {

    private Coordinate a;
    private Coordinate b;
    private Coordinate c;
    //added these variables because I use them so frequently when calculating angles, area, perimeter, etc.

    private Side sideAB;
    private Side sideBC;
    private Side sideAC;

    private Angle angleA = new Angle();
    private Angle angleB = new Angle();
    private Angle angleC = new Angle();

    public Triangle(double x1, double y1, double x2, double y2, double x3, double y3)
    {

        a = new Coordinate(x1, y1);
        b = new Coordinate(x2, y2);
        c = new Coordinate(x3, y3);

        sideAB= new Side(a, b);
        sideBC= new Side(b, c);
        sideAC= new Side(a, c);

        angleA.setAngle(sideAB, sideAC, sideBC);
        angleB.setAngle(sideAB, sideBC, sideAC);
        angleC.setAngle(sideAC, sideBC, sideAB);
    }

    /** Your other methods to calculate Perimeter and Area **/
}

我剛剛顯示了構造函數,該構造函數顯示了如何設置三角形類的所有三個屬性。

我認為這些信息將幫助您繼續前進,以創建一個好的設計。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM