机器人技术第二次作业(HFUT)

简单的几何计算。
java源码:
package robathomework2;
//点类,后面求出交点后,返回一个点对象
class Point {
private double x;
private double y;
private int condition;
// 因为后面求交点的函数返回的都是Point对象,为了区分直线与其他无交点,有交点,有无数交点的情况
// 需要引入 condition ,当值为0 1 2 时分别对应,有有限个交点,无交点,有无数交点的情况。
// 初始化一个点的时候,condition默认为0
Point() {
this.condition = 0;
this.x = 0;
this.y = 0;
}
Point(int condititon) {
this.condition = condititon;
this.x = 0;
this.y = 0;
}
Point(double x, double y) {
this.x = x;
this.y = y;
this.condition = 0;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public void printXandY() {
System.out.print("(" + String.format("%.4f", x) + "," + String.format("%.4f", y) + ")");
}
public int getCondition() {
return condition;
}
public void setCondition(int condition) {
this.condition = condition;
}
}
//线类
//储存了 abc三个系数,即每一个线对象就对应一个直线一般方程 ax + by + c = 0
class Line {
private double a;
private double b;
private double c;
Line(double a, double b, double c) {
this.a = a;
this.b = b;
this.c = c;
}
public double getA() {
return a;
}
public void setA(double a) {
this.a = a;
}
public double getB() {
return b;
}
public void setB(double b) {
this.b = b;
}
public double getC() {
return c;
}
public void setC(double c) {
this.c = c;
}
public void printLine() {
System.out.println(a + "x " + "+ " + b + "y + " + "(" + c + ")" + " = 0");
}
}
//矩形类
//边垂直于XY轴的矩形只要给出对角两个点便可以确定一个矩形
//边不垂直于XY轴的矩形需要按顺时针顺序给出四个点。
//矩形的四条边可用四个直线方程表示,在后面计算交点的时候再限制范围即可
class Rectangle {
private Line[] lines;
public Line[] getLines() {
return lines;
}
public void setLines(Line[] lines) {
this.lines = lines;
}
public Point[] getPoints() {
return points;
}
public void setPoints(Point[] points) {
this.points = points;
}
private Point points[];
// 矩形,只需要给出对角的两个点的坐标即可。
// 注意,参数的顺序
Rectangle(double x1, double x2, double y1, double y2) {
try {
this.lines = new Line[4];
this.lines[0] = new Line(1, 0, -x1);
this.lines[1] = new Line(1, 0, -x2);
this.lines[2] = new Line(0, 1, -y1);
this.lines[3] = new Line(0, 1, -y2);
} catch (Exception e) {
System.out.println("矩形初始化失败!");
}
}
// 注意,这里要按照顺时针顺序输入点。
// 对于可能的各边不分别垂直于XY轴的矩形,用这个初始化。
Rectangle(Point p1, Point p2, Point p3, Point p4) {
try {
this.points = new Point[4];
points[0] = p1;
points[1] = p2;
points[2] = p3;
points[3] = p4;
this.lines = new Line[4];
this.lines[0] = new Line(p2.getY() - p1.getY(), p1.getX() - p2.getX(),
p2.getX() * p1.getY() - p1.getX() * p2.getY());
this.lines[1] = new Line(p3.getY() - p2.getY(), p2.getX() - p3.getX(),
p3.getX() * p2.getY() - p2.getX() * p3.getY());
this.lines[2] = new Line(p4.getY() - p3.getY(), p3.getX() - p4.getX(),
p4.getX() * p3.getY() - p3.getX() * p4.getY());
this.lines[3] = new Line(p4.getY() - p1.getY(), p1.getX() - p4.getX(),
p4.getX() * p1.getY() - p1.getX() * p4.getY());
} catch (Exception e) {
System.out.println("矩形初始化失败!");
}
}
}
//圆类,给出圆心和半径即可确定唯一一个圆
class Circle {
private Point centerPoint;
private double radius;
public Point getCenterPoint() {
return centerPoint;
}
public void setCenterPoint(Point centerPoint) {
this.centerPoint = centerPoint;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
Circle(Point cen, double r) {
this.centerPoint = cen;
this.radius = r;
}
}
//几何工具类,即求交点的类,包含了各种求交点的方法和其他辅助方法。
class Geometry {
//1.求直线与直线交点
//利用了直线与直线交点公式,公式会附在作业后面
public Point LineAndLine(Line line1, Line line2) {
if (line1.getA() * line2.getB() == line2.getA() * line1.getB()) {
if ((line1.getA() * line2.getC() == line1.getC() * line2.getA())
&& (line1.getB() * line2.getC() == line1.getC() * line2.getB())) {
return new Point(2);
} else {
return new Point(1);
}
} else {
double x = (line1.getB() * line2.getC() - line2.getB() * line1.getC())
/ (line1.getA() * line2.getB() - line2.getA() * line1.getB());
double y = (line2.getA() * line1.getC() - line1.getA() * line2.getC())
/ (line1.getA() * line2.getB() - line2.getA() * line1.getB());
return new Point(x, y);
}
}
//2. 方法1是确定有交点后求交点的方法,而本方法对直线有无交点
// 是否有有限个交点进行判定,并且对输出进行了美化,使用了两直线是否平行、重合的判定公式(附在后面)
public Point PrintLineAndLine(Line line1, Line line2) {
Point tempPoint = LineAndLine(line1, line2);
if (tempPoint.getCondition() == 0) {
System.out.print("直线1:");
line1.printLine();
System.out.print("直线2:");
line2.printLine();
System.out.print("交点:");
tempPoint.printXandY();
System.out.println();
return tempPoint;
} else if (tempPoint.getCondition() == 1) {
System.out.print("直线1:");
line1.printLine();
System.out.print("直线2:");
line2.printLine();
System.out.println("平行,无交点 ");
return tempPoint;
} else {
System.out.print("直线1:");
line1.printLine();
System.out.print("直线2:");
line2.printLine();
System.out.println("重合,有无数交点");
return tempPoint;
}
}
//3. 求直线与矩形交点并输出的方法
// 实际上,就是四条限定范围的直线与一条直线求交点。
public Point[] PrintLineAndRecSp(Line line1, Rectangle r1) {
Point[] tempPoints = new Point[4];
Line[] tempLines = r1.getLines();
tempPoints[0] = LineAndLine(line1, tempLines[0]);
tempPoints[1] = LineAndLine(line1, tempLines[1]);
tempPoints[2] = LineAndLine(line1, tempLines[2]);
tempPoints[3] = LineAndLine(line1, tempLines[3]);
Point[] points = new Point[4];
int count = 0;
int flag = 0;
double xmax = Math.max(-tempLines[0].getC(), -tempLines[1].getC());
double xmin = Math.min(-tempLines[0].getC(), -tempLines[1].getC());
double ymax = Math.max(-tempLines[2].getC(), -tempLines[3].getC());
double ymin = Math.min(-tempLines[2].getC(), -tempLines[3].getC());
for (int i = 0; i < 4; i++) {
if (tempPoints[i].getCondition() == 0) {
if ((i == 0 || i == 1) && (tempPoints[i].getX() < xmax) && (tempPoints[i].getX() > xmin)
&& (tempPoints[i].getY() <= ymax) && (tempPoints[i].getY() >= ymin)) {
points[count++] = tempPoints[i];
System.out.println("直线与矩形的边:");
tempLines[i].printLine();
System.out.print("有交点:");
tempPoints[i].printXandY();
System.out.println("");
}
if ((i == 2 || i == 3) && (tempPoints[i].getY() <= ymax) && (tempPoints[i].getY() >= ymin)
&& (tempPoints[i].getX() <= xmax) && (tempPoints[i].getX() >= xmin)) {
points[count++] = tempPoints[i];
System.out.println("直线与矩形的边:");
tempLines[i].printLine();
System.out.print("有交点:");
tempPoints[i].printXandY();
System.out.println("");
}
} else if (tempPoints[i].getCondition() == 1) {
// System.out.println("直线与矩形的边:");
// tempLines[i].printLine();
// System.out.print("平行无交点");
} else {
System.out.println("直线与矩形的边:");
tempLines[i].printLine();
flag = 1;
System.out.println("有无数交点");
}
}
if (count == 0 && flag == 0) {
System.out.println("直线与矩形没有交点");
}
return points;
}
//4. 实际上是方法3的 一般形式,可以求解任意平行四边形,或者不垂直于XY轴的矩形。
// 但是要注意参数的四个点需要按照顺时针顺序输入。
public Point[] PrintLineAndRecGen(Line line1, Rectangle r1) {
Point[] tempPoints = new Point[4];
Line[] tempLines = r1.getLines();
tempPoints[0] = LineAndLine(line1, tempLines[0]);
tempPoints[1] = LineAndLine(line1, tempLines[1]);
tempPoints[2] = LineAndLine(line1, tempLines[2]);
tempPoints[3] = LineAndLine(line1, tempLines[3]);
Point[] points = new Point[4];
int count = 0;
int flag = 0;
for (int i = 0; i < 4; i++) {
if (tempPoints[i].getCondition() == 0) {
double xmax = Math.max(r1.getPoints()[i].getX(), r1.getPoints()[(i + 1) % 4].getX());
double xmin = Math.min(r1.getPoints()[i].getX(), r1.getPoints()[(i + 1) % 4].getX());
double ymax = Math.max(r1.getPoints()[i].getY(), r1.getPoints()[(i + 1) % 4].getY());
double ymin = Math.min(r1.getPoints()[i].getY(), r1.getPoints()[(i + 1) % 4].getY());
if ((i == 0 || i == 2) && (tempPoints[i].getX() < xmax) && (tempPoints[i].getX() > xmin)
&& (tempPoints[i].getY() < ymax) && (tempPoints[i].getY() > ymin)) {
points[count++] = tempPoints[i];
System.out.println("直线与矩形的边:");
tempLines[i].printLine();
System.out.print("有交点:");
tempPoints[i].printXandY();
System.out.println("");
}
if ((i == 1 || i == 3) && (tempPoints[i].getY() <= ymax) && (tempPoints[i].getY() >= ymin)
&& (tempPoints[i].getX() <= xmax) && (tempPoints[i].getX() >= xmin)) {
points[count++] = tempPoints[i];
System.out.println("直线与矩形的边:");
tempLines[i].printLine();
System.out.print("有交点:");
tempPoints[i].printXandY();
System.out.println("");
}
} else if (tempPoints[i].getCondition() == 1) {
// System.out.println("直线与矩形的边:");
// tempLines[i].printLine();
// System.out.print("平行无交点");
} else {
System.out.println("直线与矩形的边:");
tempLines[i].printLine();
flag = 1;
System.out.println("有无数交点");
}
}
if (count == 0 && flag == 0) {
System.out.println("直线与矩形没有交点");
}
return points;
}
//5. 判断圆与直线位置关系的方法
// 如果相离返回0,相切返回1,相交返回2
public int PositionLC(Line line, Circle circle) {
double dist = Math.abs(line.getA() * circle.getCenterPoint().getX()
+ line.getB() * circle.getCenterPoint().getY() + line.getC());
if (dist < circle.getRadius()) {
return 2;// 有两个交点
} else if (dist == circle.getRadius()) {
return 1;// 有一个交点
} else {
return 0;// 没有交点
}
}
//6. 求圆与直线的交点,其中直线不垂直X轴
// 利用直线的点斜式和圆的一般方程,化成一元二次方程即可。
public Point[] calBnotZero(Line line, Circle circle) {
double m, c, D, E, F;
m = -line.getA() / line.getB();
c = -line.getC() / line.getB();
D = -2 * circle.getCenterPoint().getX();
E = -2 * circle.getCenterPoint().getY();
F = Math.pow(circle.getCenterPoint().getX(), 2) + Math.pow(circle.getCenterPoint().getY(), 2)
- Math.pow(circle.getRadius(), 2);
double coe1 = 1 + m * m;
double coe2 = 2 * m * c + D + E * m;
double coe3 = c * c + E * c + F;
double x1 = (-coe2 + Math.sqrt(coe2 * coe2 - 4 * coe1 * coe3)) / (2 * coe1);
double x2 = (-coe2 - Math.sqrt(coe2 * coe2 - 4 * coe1 * coe3)) / (2 * coe1);
double y1 = m * x1 + c;
double y2 = m * x2 + c;
Point[] points = new Point[2];
points[0] = new Point(x1, y1);
points[1] = new Point(x2, y2);
return points;
}
//7. 求圆与直线的交点,直线垂直X轴
// 本方法与方法5共同组成了求圆与直线交点的方法。
public Point[] calBisZero(Line line, Circle circle) {
double D, E, F;
D = -2 * circle.getCenterPoint().getX();
E = -2 * circle.getCenterPoint().getY();
F = Math.pow(circle.getCenterPoint().getX(), 2) + Math.pow(circle.getCenterPoint().getY(), 2)
- Math.pow(circle.getRadius(), 2);
double coe1 = 1;
double coe2 = E;
double coe3 = (-line.getC() * D) / line.getA() + line.getC() * line.getC() / (line.getA() * line.getA()) + F;
double y1 = (-coe2 + Math.sqrt(coe2 * coe2 - 4 * coe1 * coe3)) / (2 * coe1);
double y2 = (-coe2 - Math.sqrt(coe2 * coe2 - 4 * coe1 * coe3)) / (2 * coe1);
double x1 = -line.getC() / line.getA();
double x2 = x1;
Point[] points = new Point[2];
points[0] = new Point(x1, y1);
points[1] = new Point(x2, y2);
return points;
}
//8. 求圆与直线的交点的方法
// 本方法考虑到直线与圆的位置关系,直线的形式等,求直线与圆的时候直接调用本方法即可。
public Point[] PrintLineAndCircle(Line line, Circle circle) {
if (PositionLC(line, circle) == 0) {
System.out.println("直线与圆相离,没有交点");
return null;
} else if (PositionLC(line, circle) == 1) {
Point[] Points = new Point[1];
if (line.getB() != 0) {
Points[0] = calBnotZero(line, circle)[0];
} else {
Points[0] = calBisZero(line, circle)[0];
}
System.out.print("直线与圆相切,交点为:");
Points[0].printXandY();
System.out.println();
return Points;
} else {
Point[] points = new Point[2];
if (line.getB() != 0) {
points = calBnotZero(line, circle);
} else {
points = calBisZero(line, circle);
}
System.out.print("直线与圆相交,两个交点为:");
points[0].printXandY();
System.out.print(" ");
points[1].printXandY();
System.out.println();
return points;
}
}
}
public class RobatHomework2 {
public static void main(String args[]) {
// 直线与直线交点测试数据。
System.out.println("/////////////////////////////////////////////////////");
System.out.println("直线与直线交点测试数据:");
System.out.println("*****************************************************");
Geometry geometry = new Geometry();
// -x+y+1=0 和 -x+y-1=0 平行
Line line1 = new Line(-1, 1, 1);
Line line2 = new Line(-1, 1, -1);
geometry.PrintLineAndLine(line1, line2);
System.out.println("*****************************************************");
// 2x+2y+2=0 重合
Line line3 = new Line(2, 2, 2);
Line line4 = new Line(2, 2, 2);
geometry.PrintLineAndLine(line3, line4);
System.out.println("*****************************************************");
// x+y+1=0和-x+y=0 交点应为(-0.5,-0.5)
Line line5 = new Line(1, 1, 1);
Line line6 = new Line(-1, 1, 0);
geometry.PrintLineAndLine(line5, line6);
System.out.println("*****************************************************");
System.out.println("/////////////////////////////////////////////////////");
System.out.println("直线与矩形交点测试数据(一):");
// 直线与矩形的测试数据
// 一 .矩形四个点为(0,0)(0,2)(2,0)(2,2)
// 直线取三种
// 1.-x+y=0 两个交点 (0,0)(2,2)
// 2. x-3=0 无交点
// 3. y-2=0 无数交点
// 二.矩形取(1,0)(0,1)(0,-1)(-1,0) 即边非垂直于XY轴的矩形
// 直线取三种
// 1.-x+y=0 两个交点(0.5,0.5)(-0.5,-0.5)
// 2. x+y+10=0 无交点
// 3. x+y+1-=0 无数交点
Rectangle r1 = new Rectangle(0, 2, 0, 2);
Line line7 = new Line(1, 0, -3);
Line line8 = new Line(0, 1, -2);
System.out.println("*****************************************************");
geometry.PrintLineAndRecSp(line6, r1);
System.out.println("*****************************************************");
geometry.PrintLineAndRecSp(line7, r1);
System.out.println("*****************************************************");
geometry.PrintLineAndRecSp(line8, r1);
System.out.println("*****************************************************");
System.out.println("直线与矩形交点测试数据(二):");
Rectangle r2 = new Rectangle(new Point(0, 1), new Point(1, 0), new Point(0, -1), new Point(-1, 0));
Line line11 = new Line(1, -1, 0);
Line line12 = new Line(1, 1, 10);
Line line13 = new Line(1, 1, 1);
System.out.println("*****************************************************");
geometry.PrintLineAndRecGen(line11, r2);
System.out.println("*****************************************************");
geometry.PrintLineAndRecGen(line12, r2);
System.out.println("*****************************************************");
geometry.PrintLineAndRecGen(line13, r2);
System.out.println("*****************************************************");
System.out.println("/////////////////////////////////////////////////////");
System.out.println("直线与圆交点测试数据:");
// 给定圆心为(0,0),半径为1的圆。
// 直线 x-1=0 相切(-1,0)
// 直线 -x+y=0 相交于(根号二,根号二),(负根号二,负根号二)
// 直线 x+y+10=0 相离
Circle circle = new Circle(new Point(0, 0), 1);
Line line9 = new Line(1, 0, -1);
Line line10 = new Line(1, 1, 10);
System.out.println("*****************************************************");
geometry.PrintLineAndCircle(line9, circle);
System.out.println("*****************************************************");
geometry.PrintLineAndCircle(line6, circle);
System.out.println("*****************************************************");
geometry.PrintLineAndCircle(line10, circle);
System.out.println("/////////////////////////////////////////////////////");
}
}
运行效果图:
测试图的数据均按给出的测试数据排列
直线与直线交点测试数据:三组
- -x+y+1=0 和 -x+y-1=0 平行
- 两个2x+2y+2=0 重合
- x+y+1=0和-x+y=0 交点应为(-0.5,-0.5)
直线与矩形的测试数据:
一、三组,其中矩形的四个点为(0,0)(0,2)(2,0)(2,2) 即边垂直于XY轴的矩形。
- -x+y=0 两个交点 (0,0)(2,2)
- x-3=0 无交点
- y-2=0 无数交点
二、三组,其中矩形的四个点为(1,0)(0,1)(0,-1)(-1,0) 即边非垂直于XY轴的矩形
- -x+y=0 两个交点(0.5,0.5)(-0.5,-0.5)
- x+y+10=0 无交点
- x+y+1-=0 无数交点
直线与圆的测试数据:三组 给定圆心为(0,0),半径为1的圆。
- 直线 x-1=0 相切(-1,0)
- 直线 -x+y=0 相交于(根号二,根号二),(负根号二,负根号二)
- 直线 x+y+10=0 相离
所用公式及备注
备注:
求交点时,实例化一个Geometry对象,调用三个方法即可
- PrintLineAndLine 直线与直线 返回Point对象
- PrintLineAndRecSp 直线与边垂直于XY轴的矩形 返回Point对象数组或null
- PrintLineAndCircle 直线与矩形 返回Point对象数组或null
- PrintLineAndRecGen 直线与不边垂直于XY轴的矩形或平行四边形 返回Point对象数组或null


浙公网安备 33010602011771号