机器人技术第二次作业(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("/////////////////////////////////////////////////////");

 

    }

}

 

运行效果图:

测试图的数据均按给出的测试数据排列

直线与直线交点测试数据:三组

  1. -x+y+1=0 和 -x+y-1=0 平行
  2. 两个2x+2y+2=0 重合
  3. x+y+1=0和-x+y=0 交点应为(-0.5,-0.5)

 

直线与矩形的测试数据:

一、三组,其中矩形的四个点为(0,0)(0,2)(2,0)(2,2) 即边垂直于XY轴的矩形。

  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 无数交点

 

 

直线与圆的测试数据:三组  给定圆心为(0,0),半径为1的圆。

  1. 直线 x-1=0  相切(-1,0)
  2. 直线 -x+y=0 相交于(根号二,根号二),(负根号二,负根号二)
  3. 直线 x+y+10=0 相离

 

所用公式及备注

备注:

求交点时,实例化一个Geometry对象,调用三个方法即可

  1. PrintLineAndLine  直线与直线 返回Point对象
  2. PrintLineAndRecSp   直线与边垂直于XY轴的矩形  返回Point对象数组或null
  3. PrintLineAndCircle  直线与矩形  返回Point对象数组或null
  4. PrintLineAndRecGen   直线与不边垂直于XY轴的矩形或平行四边形  返回Point对象数组或null

 

 

posted @ 2020-04-26 09:05  HaiTianChen  阅读(385)  评论(0)    收藏  举报