我应该为我在学校的项目制作自己的Java Triangle课程。新的三角形从左到右依次取3个点的(x,y)坐标。我关心的主要是我制作sideAB,sideBC和sideAC实例变量的方式,以及它们在构造函数中初始化它们的方式。此外,maxAngle和minAngle看起来像一团糟,我希望它有angleA angleB和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;
}
}
}
答案 0 :(得分:2)
三角形的显着特性(至少在二维欧几里德空间中)是它的三个点。
就是这样,你需要存储所有。其他所有东西都可以从中计算出来。你不需要边的长度或顶点的角度,它们都可以从这三个点得出。
我的建议是简单地创建一个Point
类型,然后从其中三个类型中构建您的Triangle
类型。
如果你确定这些派生值的计算过于昂贵,那么只有那时,你应该考虑缓存这些信息。但我怀疑情况会是这样。如果确实结果是这种情况,那么(至少)有两种方法。
首先是每当非派生值改变时计算派生值。这样做的好处是,每当您更改某些内容并简化代码时,所有值都是最新的(每个setSomething()
方法,而构造函数只需调用calcAllDerivedValues()
方法)。
其次,无论何时更改非派生值,都可以将派生值标记为脏。然后,无论何时需要派生数据,计算它的方法都可以检查它们是否脏,然后再计算(并缓存)它们。
如果他们不脏,他们只返回缓存的值。这有点复杂但可以删除不必要的计算,特别是如果每个派生值都有一个脏标志 - 你只需要在需要时计算你需要的东西。
并且,对于static
上的特定问题,如果它们在所有实例之间共享,则只使用静态类级变量。由于边的角度或长度特定于一个实例,因此它们不应是静态的。
以下是我的开始。首先,Point
类有x
和y
成员(以及它们的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->b
,b->c
和a->c
之间的距离(使用Point
类getDistance()
方法完成)然后添加它们来获取周长。 Point
类getAngle()
(例如)a->b
和a->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); }
答案 1 :(得分:1)
在大多数情况下,代码是正确的。
但最大的问题是,您编写的代码可以多次执行相同的操作。例如,这种方法:
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();
}
答案 2 :(得分:0)
如果性能很重要,则应预先计算所有值(假设不能改变三角形的任何一点),尤其是角度,如果它们被多次访问。
不,你绝对不应该使用任何静态变量,因为这些变量将由Triangle类的每个实例共享。
答案 3 :(得分:0)
您的代码中可以进行的一些修改是: -
创建角度类来查找和存储所有角度..
现在,您不必在一个班级中创建所有内容,而是可以在各自的班级中计算它们。只需从那里获取..
EG: - 让特定的 Angle
实例找出自己的角度,你就可以得到从那里开始的角度。所以,你不必写逻辑来创造角度三倍..
您可以将 findMaxSide()
和 findMinSide()
代码移至 Side 类。因为理想情况下,您的方法应位于您的方法正在使用的class containing the information
..
findMaxAngle()
和 findMinAngle()
移至您的角度类。所以,我在这里给你Angle
课程你可以使用..你可以自己创建Coordinate
和Side
课程: -
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;
}
}
side1
和side2
是您想要找到角度的边......
您可以使用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 **/
}
我刚刚展示了构造函数,显示了如何设置三角类的所有三个属性..
我认为这些信息可以帮助您继续创造一个好的设计。