目录
1.前言
本篇博客包含PTA题目集4(四边形)、5(五边形)以及其中考试的题目。
2.类
2.1 Point
attribute:
对于Point来说,含有两个属性x,y分别代表横坐标和纵坐标
function:
-
add(Point)
两个点的加法运算,对应坐标相加,并返回一个新的Points
-
inLine(Line)
判断点是否在直线上,返回true/false
-
print()
打印点的一些信息,用于debug
-
isSameTo(Point)
判断两个点是否一样,返回true/false
-
disToLine(Line)
求出点到直线的距离,使用距离公式,返回值double
-
disToPoint(Point)
求两点距离,返回double
-
sub(Point)
两个点的减法运算,对应坐标相减,返回新的Point
-
inLineSegment_close(Line)
判断点是否在线段之内,包括端点,返回true/false
-
inLineSegment(Line)
判断点是否在线段之内,不包括端点,返回true/false
对应类图:
code:
class Point{
public double x, y;
public Point(){
this.x = 0;
this.y = 0;
}
public Point(double a,double b){
this.x = a;
this.y = b;
}
public void print(){
String x = String.format("%.6f",this.x);
String y = String.format("%.6f",this.y);
x = x.replaceAll("0+?$", "");
y = y.replaceAll("0+?$", "");
System.out.printf("(%s , %s)\n",this.x,this.y);
}
//两点坐标相同
public boolean isSameTo(Point a){
return (this.x == a.x)&&(this.y == a.y);
}
//两点距离
public double disToPoint(Point another){
return Math.sqrt(Math.pow(this.x-another.x,2) + Math.pow(this.y-another.y,2));
}
//点到直线的垂直距离
public double disToLine(Line l){
return Math.abs(l.a*this.x+l.b*this.y+l.c) / Math.sqrt(Math.pow(l.a,2)+Math.pow(l.b,2));
}
//判断是否在直线之上
public boolean inLine(Line l){
return Math.abs(l.a*this.x + l.b*this.y + l.c) < 0.000001;
}
//判断是否在线段之内(包括端点)
public boolean inLineSegment_close(Line l){
if(!this.inLine(l)) return false;
double res = this.disToPoint(l.sta) + this.disToPoint(l.ed) - l.length();
return Math.abs(res) < 0.000001;
}
//判断是否在线段之内(不包括端点)
public boolean inLineSegment(Line l){
return this.inLineSegment_close(l) &&
(!this.isSameTo(l.sta)) &&
(!this.isSameTo(l.ed));
}
public Point deepCopy(){
Point res = new Point();
res.x = this.x;
res.y = this.y;
return res;
}
public Point add(Point another){
Point res = this.deepCopy();
res.x += another.x;
res.y += another.y;
return res;
}
public Point sub(Point another){
Point res = this.deepCopy();
res.x -= another.x;
res.y -= another.y;
return res;
}
//求点集重心
public static Point focusPoint(Point[] points ){
Point res = new Point(0,0);
for(Point item:points){
res = res.add(item);
}
res.x /= points.length;
res.y /= points.length;
return res;
}
}
2.2 Line
attribute:
采用一般式:$Ax+By+C=0$的形式描述直线
Point sta,ed 两者为直线上不同的两个点
Point vector 为sta-ed 代表向量
function:
-
isParallelTo(Line)
判断两条直线是否相互平行,返回true/false
-
LineSegmentIntersection(Line)
求两条线段的交点,返回Point,无交点则返回null
-
isVerticalTo(Line)
判断两直线是否相互垂直
-
vectorAngle(Line)
求vector属性的夹角,返回double
-
print()
打印直线的某些信息,用于debug
-
vectorMul(Line)
求vector属性的点乘,返回double
-
vectorCrossMul(Line)
求vectoe属性的叉乘,返回double
-
length()
求线段长度,返回double
-
getIntersection(Line)
求两条直线的交点,返回Point,无交点则返回null
-
slope()
求直线的斜率,返回double
-
isSameTo(Line)
判断两条直线是否平行,返回true/false
-
vectorLength(Line)
求vector属性的长度,返回double
对应类图:
code:
class Line{
public Point sta, ed;
public double a,b,c;
private final Point vector;
public Line(Point a,Point b){
this.sta = a;
this.ed = b;
this.a = (-(a.y-b.y));
this.b = (a.x-b.x);
this.c = (-this.a*this.sta.x-this.b*this.sta.y);
this.vector = ed.sub(sta);
}
public void print(){
System.out.printf("%fX + %fY + %f = 0\n",this.a,this.b,this.c);
}
//求线段长度
public double length(){
return this.sta.disToPoint(this.ed);
}
//判断是否平行
public boolean isParallelTo(Line another){
if(this.b==0 || another.b==0){
return (this.b == 0 && another.b == 0);
}
return (this.a*another.b == this.b*another.a);
}
//判断是否重合
public boolean isSameTo(Line another){
double x1,x2,x3,x4,y1,y2,y3,y4;
x1 = sta.x;x2 = ed.x;
y1 = sta.y;y2 = ed.y;
x3 = another.sta.x;x4 = another.ed.x;
y3 = another.sta.y;y4 = another.ed.y;
if(x1==x2&&x3==x4){
return x1==x3;
}
if(y1==y2){
return y1==y3&&y1==y4;
}
if(y3==y4){
return y3==y1&&y3==y2;
}
return (y2 - y1) * (x4 - x3) == (y4 - y3) * (x2 - x1) && (x2 * y1 - x1 * y2) * (x4 - x3) == (x4 * y3 - x3 * y4) * (x2 - x1);
}
//求两条直线交点
public Point getIntersection(Line another){
if(this.isParallelTo(another)) return null;
Point res = new Point();
res.y = (another.a*this.c-this.a*another.c) / (this.a*another.b-another.a*this.b);
res.x = (this.b*another.c-another.b*this.c) / (this.a*another.b-another.a*this.b);
return res;
}
//返回两条线段的交点
public Point LineSegmentInside(Line another){
Point res = this.getIntersection(another);
if(res == null) return res;
boolean ok = (res.inLineSegment_close(this) && res.inLineSegment_close(another));
return ok ? res:null;
}
//求向量模
public double vectorLength(){
return Math.sqrt( Math.pow(this.vector.x,2) + Math.pow(this.vector.y,2) );
}
//求向量点积
public double vectorMul(Line another){
return (this.vector.x * another.vector.x) + (this.vector.y * another.vector.y);
}
//求向量叉积
public double vectorCrossMul(Line another){
return (this.vector.x * another.vector.y) - (another.vector.x * this.vector.y);
}
//求两向量夹角(非0向量)
public double vectorAngle(Line another){
double cos_angle = this.vectorMul(another) / (this.vectorLength() * another.vectorLength());
return Math.acos(cos_angle);
}
}
2.3 Graphical
attribute:
-
对于三角形,四边形,五边形...这些多边形的父类---图形类,抽象出一些统一的属性:
构成图形的点 points[];
构成图形的线 lines[];
面积 area;
周长 sidelength;
凹凸性 isConvexGraphical;
function:
-
Graphical(Point[])
析构函数接受一个Points数组参数
-
area(Graphical)
对于求任意多边形的面积,同样是分割成不同的三角形然后求和,但是考虑到凹多边形特殊性求三角形面积采用向量的叉乘。
以原点为参考点O,相邻顶点P1,P2 -
sideLength(Graphical)
求周长,即将所有Line的长度求和返回
-
isConvexGraphical(Graphical)
我们知道向量叉乘是有正负的,对于下面的向量,我们求OP1 × OP2,结果是正,而反过来求叉乘则是负,直观来看就是:
P1在向量OP2的左侧则叉乘为正,P2在向量OP1的右侧则叉乘为负。假设当前连续的三个顶点分别是P1,P2,P3。计算向量(P1,P2),(P1,P3)的叉乘,也就是计算三角形P1P2P3的面积,得到的结果如果大于0,则表示P2点在线段P1和P3的右侧,多边形的顶点是逆时针序列。然后依次计算下一个前后所组成向量的叉乘,如果在计算时,出现负值,则此多边形时凹多边形,如果所有顶点计算完毕,其结果都是大于0,则多边形时凸多边形。
-
isContainPoint(Point)
判断图形是否包含某一个点
首先特判在边上的情况!
将图形分割成若干个不重合的三角形,记作$T_1,T_2,...,T_n$
然后判断该点是否在这$n$个三角形中(用面积法判断,这个之前的作业写过),只要处在某一个三角形的内部,则该点就在该图形的内部,否则处在图形的外部 -
isSeparatedFrom(Graphical)
判断两个图形是否完全分离
两个图形重叠面积为0 + 点都不在对方的边上 -
isContainGra(Graphical)
判断一个图形this是否完全包含另一个图形g
g图形的所有点都位于this图形内部或者边上 -
isSameTo(Graphical)
判断两个图形是否相同(所有对应点的坐标一致,即为相同的图形)
-
relationshipWith(Graphical)
判断两图形之间的关系
判断优先级:分离,完全重合,包含,被包含,连接,交错
其中前四者都有对应函数实现
判断连接还是交错,只需看有没有重叠面积就行 -
overlappingArea(Graphical)
求两个图形的重叠面积
对应类图:
code:
import java.util.Arrays;
class Graphical {
public int len=0,status=1; //多边形边数,状态
public Point[] points;
public Line[] lines;
public double sideLength = 0,area = 0; //边长,面积
public Graphical(Point[] points){
this.points = new Point[points.length];
points = this.removeMulti(points); //去除重复点
if(points.length <=2 ){
this.status = -1;
return;
}
//相邻边夹角0则去除中间点,夹角180则status:-1
for(int i=0;i<points.length;i++){
int first = i , second = (i+1)%points.length, third = (i+2)%points.length;
Line l1 = new Line(points[first],points[second]);
Line l2 = new Line(points[second],points[third]);
if( Math.abs(l1.vectorAngle(l2) - Math.PI) < 0.000001 ){ //夹角180
this.status = -1;
return;
}
else if(Math.abs(l1.vectorAngle(l2)) > 0.000001){ //夹角不为0
this.points[this.len++] = points[second].deepCopy();
}
}
this.points = Arrays.copyOf(this.points,this.len);
this.lines = new Line[this.len];
for(int i=0;i<this.len;i++){
int first = i, second = (i+1)%this.len;
this.lines[i] = new Line(this.points[first], this.points[second]);
}
//判断任意不相邻边(线段交点)是否有交点
checkEdge();
Graphical.Cal_S(this);
Graphical.Cal_C(this);
}
//判断和另一个图形完全分离(重叠面积为0,并且任意点都在this之外)
public boolean isSeparatedFrom(Graphical g){
boolean ok = true;
int[] check2 = new int[g.len];
for(int i=0;i<g.len;i++){
check2[i] = this.isContainPoint(g.points[i]);
}
for(int item:check2){
if(item != 1) ok = false;
}
if(this.overlappingArea(g) !=0) ok = false;
return ok;
}
//判断图形是否包含某个点返回值-1,0,1 (内部,边缘,外部)
public int isContainPoint(Point p){
for(int i=0;i<this.len;i++){ //位于边之上
if(p.inLineSegment_close(this.lines[i])) return 0;
}
double s = 0;
for(int i=0;i<this.len;i++){
s += Triangle.area(p,this.points[i], this.points[(i+1)%this.len]);
}
return Math.abs(s-this.area) < 0.000001 ? -1:1;
}
//判断两个图形是否一模一样(点完全重合)
public boolean isSameTo(Graphical g){
if(this.len != g.len) return false;
for(int i=0;i<this.len;i++){
boolean ok = false;
for(int j=0;j<g.len;j++){
if(this.points[i].isSameTo(g.points[j])) ok = true;
}
if(!ok) return false;
}
return true;
}
//判断完全包含另一个图形(任意点都在this之内)
public boolean isContainGra(Graphical g){
boolean ok = true;
int[] check2 = new int[g.len];
for(int i=0;i<g.len;i++){
check2[i] = this.isContainPoint(g.points[i]);
}
for(int item:check2){
if(item == 1) ok = false;
}
return ok;
}
public double overlappingArea(Graphical g){
Point[] intersection = new Point[100];
int intersection_len = 0;
for(Line item1:this.lines){ //求出两多边形的交点
for(Line item2: g.lines){
Point tmp = item1.LineSegmentInside(item2);
if(tmp != null){
intersection[intersection_len++] = tmp.deepCopy();
}
}
}
if(intersection_len == 0){ //特判包含
if(this.isContainGra(g)) return g.area;
if(g.isContainGra(this)) return this.area;
return 0;
}
if(this.isSameTo(g)) return this.area;
for(Point item:g.points){ //顶点包含在内部
if(this.isContainPoint(item) == -1) intersection[intersection_len++] = item.deepCopy();
}
for(Point item:this.points){ //顶点包含在内部
if(g.isContainPoint(item) == -1) intersection[intersection_len++] = item.deepCopy();
}
/*排序交点数组*/
intersection = Arrays.copyOf(intersection,intersection_len);
intersection = this.removeMulti(intersection);
Point focus = Point.focusPoint(intersection);
Point sta = intersection[0].deepCopy();
Arrays.sort(intersection,1,intersection.length, (o1, o2) -> {
try{
Line origin =new Line(focus,sta);
Line l1 = new Line(focus,o1);
Line l2 = new Line(focus,o2);
double angle1 = origin.vectorAngle(l1);
double angle2 = origin.vectorAngle(l2);
if(origin.vectorCrossMul(l1) < 0) angle1 = 2*Math.PI - angle1;
if(origin.vectorCrossMul(l2) < 0) angle2 = 2*Math.PI - angle2;
if(angle1-angle2 > 0.000001) return 1;
if(Math.abs(angle1-angle2) < 0.000001) return 0;
return -1;
}catch (Exception reason){}
return 0;
});
Graphical graphical = new Graphical(intersection);
return graphical.area;
}
//去除所有重复点
private Point[] removeMulti(Point[] points){
Point[] tmp_points = new Point[points.length];
int tmp_len = 0;
for(int i=0;i<points.length;i++){
boolean ok = true;
for(int j=0;j<tmp_len;j++){
if(points[i].isSameTo(tmp_points[j])){
ok = false;
break;
}
}
if(ok) tmp_points[tmp_len++] = points[i].deepCopy();
}
return Arrays.copyOf(tmp_points,tmp_len);
}
//判断不相邻边是否有交点
private void checkEdge(){
for(int i=0;i<this.len;i++){
for(int j=i+2;j<this.len;j++){
if(i==0&&j==this.len-1) continue;
Point p = this.lines[i].getIntersection(this.lines[j]);
if(p==null) continue;
if(p.inLineSegment_close(this.lines[i]) && p.inLineSegment_close(this.lines[j])){
this.status = -1;
return;
}
}
}
}
//多边形面积
private static void Cal_S(Graphical e){
double res = 0;
Point origin = new Point(0,0);
for(int i=0;i<e.len;i++){
Line l1 = new Line(origin,e.points[i]);
Line l2 = new Line(origin,e.points[(i+1)%e.len]);
res += 0.5 * l1.vectorCrossMul(l2);
}
e.area = Math.abs(res);
}
//多边形周长
private static void Cal_C(Graphical e){
double res = 0;
for(int i=0;i<e.len;i++){
res += e.points[i].disToPoint(e.points[(i+1)%e.len]);
}
e.sideLength = res;
}
}
2.4 Quadrilateral
attribute:
null
function:
-
isDiamond()
判断是否是菱形,平行四边形+四边长度相等 返回true/false
-
isParallelQuadrilateral()
判断是否是平行四边形,任意对边平行即可,返回true/false
-
isSquare()
判断是否是正方形,菱形+矩形,返回true/false
-
isRectangle()
判断是否是矩形,对角线长度相等,返回true/false
-
Quadrilatera(Points[])
构造函数,接受点集作为参数,先构造父类,根据父类的status和len属性判断是否可以构成四边形
不能构成四边形抛出异常
6、isContainPoint(Point)
判断四边形是否包含某点
对应类图:
code:
class Quadrilateral{
public Point[] points;
public Line[] lines;
public Quadrilateral(Point a,Point b,Point c,Point d){
this.points = new Point[4];
this.lines = new Line[4];
this.points[0] = a; this.points[1] = b;
this.points[2] = c; this.points[3] = d;
this.lines[0] = new Line(this.points[0], this.points[1]);
this.lines[1] = new Line(this.points[1], this.points[2]);
this.lines[2] = new Line(this.points[2], this.points[3]);
this.lines[3] = new Line(this.points[3], this.points[0]);
}
public boolean isQuadrilateral(){
Line l1,l2,l3,l4;
l1 = new Line(points[0],points[1]);
l2 = new Line(points[1],points[2]);
l3 = new Line(points[2],points[3]);
l4 = new Line(points[3],points[0]);
if(points[2].inLine(l1)){
return false;
}
if(points[3].inLine(l2)){
return false;
}
if(points[0].inLine(l3)){
return false;
}
if(points[1].inLine(l4)){
return false;
}
Point p1,p2;
p1 = lines[0].getIntersection(lines[2]);
p2 = lines[1].getIntersection(lines[3]);
if(p1!=null){
if(p1.inLineSegment_close(lines[0])&&p1.inLineSegment_close(lines[2]))return false;
}
if(p2!=null){
if(p2.inLineSegment_close(lines[1])&&p2.inLineSegment_close(lines[3]))return false;
}
return true;
}
//判断是否为平行四边形(对边分别平行)
public boolean isParallelQuadrilateral(){
return this.lines[0].isParallelTo(this.lines[2]) &&
this.lines[1].isParallelTo(this.lines[3]);
}
//判断是否为菱形(平行四边形 + 四边长度相等)
public boolean isDiamond(){
boolean v = this.lines[0].length() == this.lines[1].length() &&
this.lines[1].length() == this.lines[2].length() &&
this.lines[2].length() == this.lines[3].length();
return this.isParallelQuadrilateral() && v;
}
//判断是否为矩形(对角线相等)
public boolean isRectangle(){
return this.points[0].disToPoint(this.points[2]) == this.points[1].disToPoint(this.points[3]);
}
//判断是否为正方形(菱形 + 矩形)
public boolean isSquare(){
return this.isDiamond() && this.isRectangle();
}
//判断是否为凸四边形(面积公式)
public boolean isConvexQuadrilateral(){
double s1 = Triangle.area(points[0],points[1],points[2]);
double s2 = Triangle.area(points[2],points[3],points[0]);
double s3 = Triangle.area(points[1],points[2],points[3]);
double s4 = Triangle.area(points[3],points[0],points[1]);
double res = s1 + s2 - s3 - s4;
return Math.abs(res) < 0.000001;
}
//判断一个点是否落在(凸)四边形内部(0内,1边,2外)
//和Triangle类似,用面积法;
public int isContainPoint(Point p){
if(p.inLineSegment_close(this.lines[0]) || p.inLineSegment_close(this.lines[1])
|| p.inLineSegment_close(this.lines[2]) || p.inLineSegment_close(this.lines[3])){
return 1;
}
double s1 = Triangle.area(p,this.points[0],this.points[1]);
double s2 = Triangle.area(p,this.points[1],this.points[2]);
double s3 = Triangle.area(p,this.points[2],this.points[3]);
double s4 = Triangle.area(p,this.points[3],this.points[0]);
double res = s1+s2+s3+s4 - this.area();
if(Math.abs(res) < 0.000001) return 0;
return 2;
}
//四边形周长
public double sideLength(){
return this.lines[0].length() + this.lines[1].length() +this.lines[2].length() +this.lines[3].length();
}
//四边形面积(切分为两个三角形)
public double area(){
double s1 = Triangle.area(this.points[0], this.points[1], this.points[2]);
double s2 = Triangle.area(this.points[0], this.points[3], this.points[2]);
return s1+s2;
}
public void cal_Quadrilateral(Line l){
for(int i=0;i<4;i++){
if(l.isSameTo(lines[i])){
System.out.println("The line is coincide with one of the lines");
return;
}
}
int cnt = 4;
Point[] p = new Point[4];
p[0] = l.getIntersection(lines[0]);
p[1] = l.getIntersection(lines[1]);
p[2] = l.getIntersection(lines[2]);
p[3] = l.getIntersection(lines[3]);
for(int i=0;i<4;i++) {
if(p[i]!=null) {
p[i].x += 0.0;
p[i].y += 0.0;
}
else{
cnt--;
}
}
for(int i=0;i<4;i++){
for(int j=i+1;j<4;j++){
if(p[j]!=null&&p[i]!=null&&!p[j].isSameTo(new Point(999999., 999999.))&&p[j].isSameTo(p[i])){
p[j] = new Point(999999., 999999.);
cnt--;
}
}
}
for(int i=0;i<4;i++){
if(p[i]!=null&&!p[i].isSameTo(new Point(999999., 999999.))&&!(p[i].inLineSegment_close(lines[i])&&p[i].inLineSegment_close(l))){
p[i] = new Point(999999., 999999.);
cnt--;
}
}
if(cnt<2){
System.out.println(cnt);
return;
}
System.out.print(cnt+" ");
int p1=-1,p2=-1;
for(int i=0;i<4;i++){
if(p[i]!=null&&!p[i].isSameTo(new Point(999999., 999999.))){
if(p1==-1)p1=i;
else{
p2=i;
break;
}
}
}
double s1,s2,s;
s = area();
if(p1==0&&p2==1){
s1 = Triangle.area(p[p1], p[p2], points[1]);
}
else if(p1==0&&p2==2){
Quadrilateral q = new Quadrilateral(p[p1], points[1], points[2], p[p2]);
s1 = q.area();
}
else if(p1==0&&p2==3){
s1 = Triangle.area(p[p1], p[p2], points[0]);
}
else if(p1==1&&p2==2){
s1 = Triangle.area(p[p1], p[p2], points[2]);
}
else if(p1==1&&p2==3){
Quadrilateral q = new Quadrilateral(p[p1], p[p2], points[3], points[2]);
s1 = q.area();
}
else{
s1 = Triangle.area(p[p1], p[p2], points[3]);
}
s2 = s-s1;
if(s1<s2){
Main.print_Dec(s1);
System.out.print(" ");
Main.print_Dec(s2);
}
else{
Main.print_Dec(s2);
System.out.print(" ");
Main.print_Dec(s1);
}
}
}
2.5 Pentagon
attribute:
1、points[]代表构成五边形的数组
2、lines[]代表五边形的五条边
function:
-
Pentagon(points a,points b,point c,point d,point e)
构造函数,接受点集作为参数,先构造父类,根据父类的status和len属性判断是否可以构成四边形
不能构成五边形抛出异常
2、isConvexPentagon()判断是否为凸五边形
3、cal_S()计算五边形的面积
4、cal_C()计算五边形的周长
5、isPentagon()判断是否能构成五边形
对应类图:
code:
class pentagon{
public Point[] points;
public Line[] lines;
public pentagon(Point a,Point b,Point c,Point d, Point e){
this.points = new Point[5];
this.lines = new Line[5];
this.points[0] = a; this.points[1] = b;
this.points[2] = c; this.points[3] = d;
this.points[4] = e;
this.lines[0] = new Line(this.points[0], this.points[1]);
this.lines[1] = new Line(this.points[1], this.points[2]);
this.lines[2] = new Line(this.points[2], this.points[3]);
this.lines[3] = new Line(this.points[3], this.points[4]);
this.lines[4] = new Line(this.points[4], this.points[0]);
}
//2:0,0 2,0 3,1 1,0.5 -1,1
public boolean isPentagon(){
Line l1,l2,l3,l4,l5;
l1 = new Line(points[0],points[1]);
l2 = new Line(points[1],points[2]);
l3 = new Line(points[2],points[3]);
l4 = new Line(points[3],points[4]);
l5 = new Line(points[4],points[0]);
if(points[2].inLine(l1)){
return false;
}
if(points[3].inLine(l2)){
return false;
}
if(points[4].inLine(l3)){
return false;
}
if(points[0].inLine(l4)){
return false;
}
if(points[1].inLine(l5)){
return false;
}
Point p1,p2,p3,p4,p5,p6,p7,p8,p9,p10;
p1 = lines[0].getIntersection(lines[2]);
p2 = lines[1].getIntersection(lines[3]);
p3 = lines[2].getIntersection(lines[4]);
p4 = lines[3].getIntersection(lines[0]);
p5 = lines[4].getIntersection(lines[1]);
p6 = lines[0].getIntersection(lines[3]);
p7 = lines[1].getIntersection(lines[4]);
p8 = lines[2].getIntersection(lines[0]);
p9 = lines[3].getIntersection(lines[1]);
p10 = lines[4].getIntersection(lines[2]);
if(p1!=null){
if(p1.inLineSegment_close(lines[0])&&p1.inLineSegment_close(lines[2]))return false;
}
if(p2!=null){
if(p2.inLineSegment_close(lines[1])&&p2.inLineSegment_close(lines[3]))return false;
}
if(p3!=null){
if(p3.inLineSegment_close(lines[2])&&p3.inLineSegment_close(lines[4]))return false;
}
if(p4!=null){
if(p4.inLineSegment_close(lines[3])&&p4.inLineSegment_close(lines[0]))return false;
}
if(p5!=null){
if(p5.inLineSegment_close(lines[4])&&p5.inLineSegment_close(lines[1]))return false;
}
if(p6!=null){
if(p6.inLineSegment_close(lines[0])&&p6.inLineSegment_close(lines[3]))return false;
}
if(p7!=null){
if(p7.inLineSegment_close(lines[1])&&p7.inLineSegment_close(lines[4]))return false;
}
if(p8!=null){
if(p8.inLineSegment_close(lines[2])&&p8.inLineSegment_close(lines[0]))return false;
}
if(p9!=null){
if(p9.inLineSegment_close(lines[3])&&p9.inLineSegment_close(lines[1]))return false;
}
if(p10!=null){
if(p10.inLineSegment_close(lines[4])&&p10.inLineSegment_close(lines[2]))return false;
}
return true;
}
//判断是否为凸五边形(面积公式)
public boolean isConvexPentagon(){
Quadrilateral q1,q2,q3,q4,q5;
q1 = new Quadrilateral(points[0],points[1],points[2],points[3]);
q2 = new Quadrilateral(points[1],points[2],points[3],points[4]);
q3 = new Quadrilateral(points[2],points[3],points[4],points[0]);
q4 = new Quadrilateral(points[3],points[4],points[0],points[1]);
q5 = new Quadrilateral(points[4],points[0],points[1],points[2]);
return q1.isConvexQuadrilateral()&&q2.isConvexQuadrilateral()&&q3.isConvexQuadrilateral()&&q4.isConvexQuadrilateral()&&q5.isConvexQuadrilateral();
}
public double cal_S(){
Quadrilateral q;
Triangle t;
q = new Quadrilateral(points[0],points[1],points[2],points[3]);
t = new Triangle(points[0],points[3],points[4]);
return q.area()+t.area();
}
public double cal_C(){
return lines[0].length()+lines[1].length()+lines[2].length()+lines[3].length()+lines[4].length();
}
public void cal_Pentagon(Line l){
for(int i=0;i<5;i++){
if(l.isSameTo(lines[i])){
System.out.println("The line is coincide with one of the lines");
return;
}
}
//3:-6,0 -6,6 0,0 8,0 8,3 6,6 0,3
int cnt = 5;
Point[] p = new Point[5];
p[0] = l.getIntersection(lines[0]);
p[1] = l.getIntersection(lines[1]);
p[2] = l.getIntersection(lines[2]);
p[3] = l.getIntersection(lines[3]);
p[4] = l.getIntersection(lines[4]);
for(int i=0;i<5;i++) {
if(p[i]!=null) {
p[i].x += 0.0;
p[i].y += 0.0;
}
else{
p[i] = new Point(999999., 999999.);
cnt--;
}
}
for(int i=0;i<5;i++){
for(int j=i+1;j<5;j++){
if(p[i].isSameTo(new Point(999999., 999999.)))break;
if(!p[j].isSameTo(new Point(999999., 999999.))&&p[j].isSameTo(p[i])){
p[j] = new Point(999999., 999999.);
cnt--;
}
}
}
for(int i=0;i<5;i++){
if(!p[i].isSameTo(new Point(999999., 999999.))&&!(p[i].inLineSegment_close(lines[i]))){
p[i] = new Point(999999., 999999.);
cnt--;
}
}
if(cnt<2){
System.out.println(cnt);
return;
}
System.out.print(cnt+" ");
int p1=-1,p2=-1;
for(int i=0;i<5;i++){
if(!p[i].isSameTo(new Point(999999., 999999.))){
if(p1==-1)p1=i;
else{
p2=i;
break;
}
}
}
double s1,s2,s;
s = cal_S();
if(p1==0&&p2==1){
s1 = Triangle.area(p[p1], p[p2], points[1]);
}
else if(p1==0&&p2==2){
Quadrilateral q = new Quadrilateral(p[p1], points[1], points[2], p[p2]);
s1 = q.area();
}
else if(p1==0&&p2==3){
Quadrilateral q = new Quadrilateral(p[p1], p[p2], points[4], points[0]);
s1 = q.area();
}
else if(p1==0&&p2==4){
s1 = Triangle.area(p[p1], p[p2], points[0]);
}
else if(p1==1&&p2==2){
s1 = Triangle.area(p[p1], p[p2], points[2]);
}
else if(p1==1&&p2==3){
Quadrilateral q = new Quadrilateral(p[p1], p[p2], points[3], points[2]);
s1 = q.area();
}
else if(p1==1&&p2==4){
Quadrilateral q = new Quadrilateral(p[p1], p[p2], points[0], points[1]);
s1 = q.area();
}
else if(p1==2&&p2==3){
s1 = Triangle.area(p[p1], p[p2], points[3]);
}
else if(p1==2&&p2==4){
Quadrilateral q = new Quadrilateral(p[p1], p[p2], points[4], points[3]);
s1 = q.area();
}
else{
s1 = Triangle.area(p[p1], p[p2], points[4]);
}
s2 = s-s1;
if(s1<s2){
Main.print_Dec(s1);
System.out.print(" ");
Main.print_Dec(s2);
}
else{
Main.print_Dec(s2);
System.out.print(" ");
Main.print_Dec(s1);
}
}
}
3.设计与分析
3.1 点线形系列4-凸四边形的计算
题目描述:
用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
1:输入四个点坐标,判断是否是四边形、平行四边形,判断结果输出true/false,结果之间以一个英文空格符分隔。
2:输入四个点坐标,判断是否是菱形、矩形、正方形,判断结果输出true/false,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
3:输入四个点坐标,判断是凹四边形(false)还是凸四边形(true),输出四边形周长、面积,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
4:输入六个点坐标,前两个点构成一条直线,后四个点构成一个四边形或三角形,输出直线与四边形(也可能是三角形)相交的交点数量。如果交点有两个,再按面积从小到大输出四边形(或三角形)被直线分割成两部分的面积(不换行)。若直线与四边形或三角形的一条边线重合,输出"The line is coincide with one of the lines"。若后四个点不符合四边形或三角形的输入,输出"not a quadrilateral or triangle"。
后四个点构成三角形的情况:假设三角形一条边上两个端点分别是x、y,边线中间有一点z,另一顶点s:
1)符合要求的输入:顶点重复或者z与xy都相邻,如x x y s、x z y s、x y x s、s x y y。此时去除冗余点,保留一个x、一个y。
\2) 不符合要求的输入:z 不与xy都相邻,如z x y s、x z s y、x s z y
5:输入五个点坐标,输出第一个是否在后四个点所构成的四边形(限定为凸四边形,不考虑凹四边形)或三角形(判定方法见选项4)的内部(若是四边形输出in the quadrilateral/outof the quadrilateral,若是三角形输出in the triangle/outof the triangle)。如果点在多边形的某条边上,输出"on the triangle或者on the quadrilateral"。若后四个点不符合四边形或三角形,输出"not a quadrilateral or triangle"。
思路分析:
图一:
图二:凹四边形
图三:凸四边形:
-
cmd == 1: 判断能否构成四边形:
相邻三点不共线(重合也算共线),非相邻两边没有交点
不满足上述条件就无法构成四边形 -
cmd == 2:
- 菱形:四边形四条边长度相等
- 矩形:对角线长度相等
- 正方形:满足菱形 + 满足矩形
-
cmd == 3:
-
判断四边形是凸还是凹可根据四边形不同对角线分割出来的两三角形面积和是否相等判断
-
周长:求和即可
-
面积:由于题目只涉及到凸四边形,所以只需要将四边形分割为不重合的若干个三角形,再将这若干个三角形的面积求和即可
-
-
cmd == 4:
-
后者构成了四边形:
我是先求出直线与四边形四条边的交点(只有0,1,2三种情况),当交点个数为2时,再暴力if判断交点所在的边(这里可以判断出这两个交点跟哪个顶点构成三角形),然后计算出该三角形的面积,用大四边形的面积减去就得到剩余部分的面积 -
后者构成了三角形:
直接copy练习三
-
-
cmd == 5:
-
判断图形是否构成三角形或四边形,同上
-
将四边形分割成两个个不重合的三角形,记作$T_1,T_2$
然后判断该点是否在这2个三角形中(用面积法判断,这个之前的作业写过),只要处在某一个三角形的内部,则该点就在该图形的内部,否则处在图形的外部
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void print_Dec(double ans){
String res = String.format("%.3f",ans);
ans = Double.parseDouble(res);
System.out.print(ans);
}
public static double cal_dis(double x1,double y1,double x2,double y2){
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
public static double cal_dis2(double x1,double y1,double x2,double y2){
return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
public static double cal_S(double x1, double y1, double x2, double y2, double x3, double y3){
double d1,d2,d3,p;
d1=cal_dis2(x1,y1,x2,y2);
d2=cal_dis2(x2,y2,x3,y3);
d3=cal_dis2(x3,y3,x1,y1);
p=(d1+d2+d3)/2;
return Math.sqrt(p*(p-d1)*(p-d2)*(p-d3));
}
public static double cal_S2(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
double d1,d2,d3,d4,d5,p1,p2;
d1 = cal_dis2(x1,y1,x2,y2);
d2 = cal_dis2(x2,y2,x3,y3);
d3 = cal_dis2(x3,y3,x4,y4);
d4 = cal_dis2(x4,y4,x1,y1);
d5 = cal_dis2(x2,y2,x4,y4);
p1 = (d1+d4+d5)/2;
p2 = (d2+d3+d5)/2;
return Math.sqrt(p1*(p1-d1)*(p1-d4)*(p1-d5))+Math.sqrt(p2*(p2-d2)*(p2-d3)*(p2-d5));
}
public static double cal_C(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
return cal_dis2(x1,y1,x2,y2)+cal_dis2(x2,y2,x3,y3)+cal_dis2(x3,y3,x4,y4)+cal_dis2(x4,y4,x1,y1);
}
public static int choose_point(double[] p1, double[] p2, double x3, double y3, double x4, double y4, double x5, double y5){
double A,B,C;
A = p2[1]-p1[1];
B = p1[0]-p2[0];
C = p2[0]*p1[1]-p1[0]*p2[1];
if((x3*A+y3*B+C)*(x4*A+y4*B+C)>0)return 5;
if((x5*A+y5*B+C)*(x3*A+y3*B+C)>0)return 4;
return 3;
}
//判断是否有点重合
public static boolean check_coin(double[] x, double[] y){
for(int i=0;i<x.length;i++){
for(int j=i+1;j<x.length;j++){
if(x[i]==x[j] && y[i]==y[j]){
return true;
}
}
}
return false;
}
//判断是否有点重合
public static int[] cal_coin2(double[] x, double[] y){
for(int i=0;i<x.length;i++){
for(int j=i+1;j<x.length;j++){
if(x[i]==x[j] && y[i]==y[j]){
return new int[]{i,j};
}
}
}
return null;
}
//判断两条边是否平行
public static boolean check_parr(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
// double k1,b1,k2,b2;
if(x1==x2 || x3==x4){
if(x1==x2&&x3==x4&&x1!=x3){
return true;
}
return false;
}
return (y2 - y1) * (x4 - x3) == (y4 - y3) * (x2 - x1) && y1 * (x2 - x1) * (x4 - x3) - x1 * (y2 - y1) * (x4 - x3) != y3 * (x2 - x1) * (x4 - x3) - x3 * (y4 - y3) * (x2 - x1);
}
//判断三点是否共线
public static boolean check_collin(double x1, double y1, double x2, double y2, double x3, double y3){
double A,B,C;
A = y2-y1;
B = x1-x2;
C = x2*y1-x1*y2;
return Math.abs(A * x3 + B * y3 + C) < 0.001;
}
//判断两线是否重合
public static boolean check_coin2(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
if(x1==x2&&x3==x4){
return x1==x3;
}
if(y1==y2){
return y1==y3&&y1==y4;
}
if(y3==y4){
return y3==y1&&y3==y2;
}
return (y2 - y1) * (x4 - x3) == (y4 - y3) * (x2 - x1) && (x2 * y1 - x1 * y2) * (x4 - x3) == (x4 * y3 - x3 * y4) * (x2 - x1);
}
//判断两直线是否有交点
public static boolean check_intersect(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
double a1 = y2-y1, b1 = x1-x2, c1 = x1*y2-x2*y1;
double a2 = y4-y3, b2 = x3-x4, c2 = x3*y4-x4*y3;
double[] ans = new double[2];
ans[0] = (c1*b2-b1*c2)/(a1*b2-a2*b1);
ans[1] = (a1*c2-a2*c1)/(a1*b2-a2*b1);
if(ans[0]>=Math.min(x1,x2)&&ans[0]<=Math.max(x1,x2)&&ans[1]>=Math.min(y1,y2)&&ans[1]<=Math.max(y1,y2))return true;
return false;
}
//计算两直线交点
public static double[] cal_union(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
double a1 = y2-y1, b1 = x1-x2, c1 = x1*y2-x2*y1;
double a2 = y4-y3, b2 = x3-x4, c2 = x3*y4-x4*y3;
double[] ans = new double[2];
ans[0] = (c1*b2-b1*c2)/(a1*b2-a2*b1);
ans[1] = (a1*c2-a2*c1)/(a1*b2-a2*b1);
return ans;
}
//判断交点是否在线段内
public static boolean isInside(double[] ans, double x1, double y1, double x2, double y2){
if(ans[0]>Math.min(x1,x2)&&ans[0]<Math.max(x1,x2)&&ans[1]>Math.min(y1,y2)&&ans[1]<Math.max(y1,y2))return true;
return false;
}
//判断交点是否在线段内(含端点)
public static boolean isInside2(double[] ans, double x1, double y1, double x2, double y2){
if(ans[0]>=Math.min(x1,x2)&&ans[0]<=Math.max(x1,x2)&&ans[1]>=Math.min(y1,y2)&&ans[1]<=Math.max(y1,y2))return true;
return false;
}
//判断是否为菱形
public static boolean check_rhombus(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
double dis1,dis2,dis3,dis4;
dis1 = cal_dis(x1,y1,x2,y2);
dis2 = cal_dis(x2,y2,x3,y3);
dis3 = cal_dis(x3,y3,x4,y4);
dis4 = cal_dis(x4,y4,x1,y1);
return dis1==dis2&&dis2==dis3&&dis3==dis4;
}
//判断是否为矩形
public static boolean check_rectangle(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
double dis1,dis2,dis3,dis4;
double d1,d2;
dis1 = cal_dis(x1,y1,x2,y2);
dis2 = cal_dis(x2,y2,x3,y3);
dis3 = cal_dis(x3,y3,x4,y4);
dis4 = cal_dis(x1,y1,x4,y4);
d1 = cal_dis(x1,y1,x3,y3);
d2 = cal_dis(x2,y2,x4,y4);
if(Math.abs(dis1+dis2-d1)<=0.1&&Math.abs(dis2+dis3-d2)<=0.1&&Math.abs(dis3+dis4-d1)<=0.1&&Math.abs(dis4+dis1-d2)<=0.1)return true;
return false;
}
//判断是否为平行四边形
public static boolean check_parallelogram(double[] x, double[] y){
int cnt = 0;
if(check_parr(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]))cnt++;
if(check_parr(x[0],y[0],x[2],y[2],x[1],y[1],x[3],y[3]))cnt++;
if(check_parr(x[0],y[0],x[3],y[3],x[1],y[1],x[2],y[2]))cnt++;
return cnt>=2;
}
public static void cal_segment_S_3(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4, double x5, double y5, double x6, double y6){
double[][] ans = new double[3][];
int[] count = new int[3];
int cnt=0,choose;
if(!((x3==x5&&y3==y5&&!on_edge(x6,y6,new double[]{x3,x4},new double[]{y3,y4}))||
(x4==x6&&y4==y6&&!on_edge(x3,y3,new double[]{x4,x5},new double[]{y4,y5}))||
(x3==x4&&y3==y4&&!on_edge(x6,y6,new double[]{x3,x5},new double[]{y3,y5}))||
(x4==x5&&y4==y5&&!on_edge(x6,y6,new double[]{x3,x4},new double[]{y3,y4}))||
(x5==x6&&y5==y6&&!on_edge(x3,y3,new double[]{x4,x5},new double[]{y4,y5}))||
(x6==x3&&y6==y3&&!on_edge(x5,y5,new double[]{x3,x4},new double[]{y3,y4}))||
(check_collin(x3,y3,x4,y4,x5,y5)&&on_edge(x4,y4,new double[]{x3,x5},new double[]{y3,y5})&&x4>=Math.min(x3,x5)&&x4<=Math.max(x3,x5)&&y4>=Math.min(y3,y5)&&y4<=Math.max(y3,y5))||
(check_collin(x4,y4,x5,y5,x6,y6)&&on_edge(x5,y5,new double[]{x4,x6},new double[]{y4,y6})&&x5>=Math.min(x4,x6)&&x5<=Math.max(x4,x6)&&y5>=Math.min(y4,y6)&&y5<=Math.max(y4,y6))||
(check_collin(x5,y5,x6,y6,x3,y3)&&on_edge(x6,y6,new double[]{x5,x3},new double[]{y5,y3})&&x6>=Math.min(x3,x5)&&x6<=Math.max(x3,x5)&&y6>=Math.min(y3,y5)&&y6<=Math.max(y3,y5))||
(check_collin(x6,y6,x3,y3,x4,y4)&&on_edge(x3,y3,new double[]{x6,x4},new double[]{y6,y4})&&x3>=Math.min(x6,x4)&&x3<=Math.max(x6,x4)&&y3>=Math.min(y4,y6)&&y3<=Math.max(y4,y6)))
){
System.out.println("not a quadrilateral or triangle");
return;
}
if (check_coin(new double[]{x3, x4, x5, x6}, new double[]{y3, y4, y5, y6})) {
//将不重复的点存到(x3,y3)(x4,y4)(x5,y5)
int except;
int[] temp = cal_coin2(new double[]{x3, x4, x5, x6}, new double[]{y3, y4, y5, y6});
except = temp[1];
if(except == 0){
x3 = x4;y3 = y4;
x4 = x5;y4 = y5;
x5 = x6;y5 = y6;
}
else if(except == 1){
x4 = x5;y4 = y5;
x5 = x6;y5 = y6;
}
else if(except == 2){
x5 = x6;y5 = y6;
}
}
else{
int except;
if(check_collin(x3,y3,x4,y4,x5,y5)) except = 4;
else if(check_collin(x4,y4,x5,y5,x6,y6)) except = 5;
else if(check_collin(x5,y5,x6,y6,x3,y3)) except = 6;
else except = 3;
if(except == 3){
x3 = x4;y3 = y4;
x4 = x5;y4 = y5;
x5 = x6;y5 = y6;
}
else if(except == 4){
x4 = x5;y4 = y5;
x5 = x6;y5 = y6;
}
else if(except == 5){
x5 = x6;y5 = y6;
}
}
if (check_coin2(x1, y1, x2, y2, x3, y3, x4, y4)) {
System.out.println("The line is coincide with one of the lines");
return;
}
if(check_coin2(x1, y1, x2, y2, x4, y4, x5, y5)){
System.out.println("The line is coincide with one of the lines");
return;
}
if(check_coin2(x1, y1, x2, y2, x5, y5, x3, y3)){
System.out.println("The line is coincide with one of the lines");
return;
}
ans[0] = cal_union(x1,y1,x2,y2,x3,y3,x4,y4);
ans[1] = cal_union(x1,y1,x2,y2,x4,y4,x5,y5);
ans[2] = cal_union(x1,y1,x2,y2,x5,y5,x3,y3);
ans[0][0]+=0.0;ans[0][1]+=0.0;
ans[1][0]+=0.0;ans[1][1]+=0.0;
ans[2][0]+=0.0;ans[2][1]+=0.0;
if(!isInside2(ans[0],x3,y3,x4,y4))ans[0] = new double[]{999999.,999999.};
if(!isInside2(ans[1],x4,y4,x5,y5))ans[1] = new double[]{999999.,999999.};
if(!isInside2(ans[2],x5,y5,x3,y3))ans[2] = new double[]{999999.,999999.};
for(int i=1;i<3;i++){
for(int j=0;j<i;j++){
if(Arrays.equals(ans[i],new double[]{999999.,999999.})||Arrays.equals(ans[j],new double[]{999999.,999999.}))continue;
if(Arrays.equals(ans[i],ans[j]))count[i]++;
}
}
for(int i=0;i<3;i++){
if(count[i]==0&&!Arrays.equals(ans[i],new double[]{999999.,999999.}))cnt++;
}
if(cnt==0||cnt==1){
System.out.println(cnt);
}
else {
System.out.print("2 ");
double s1, s2, s;
int p1 = -1, p2 = -1;
for (int i = 0; i < 3; i++) {
if (count[i] == 0&&!Arrays.equals(ans[i],new double[]{999999.,999999.})) {
if (p1 == -1) p1 = i;
else p2 = i;
}
}
s = cal_S(x3, y3, x4, y4, x5, y5);
choose = choose_point(ans[p1], ans[p2], x3, y3, x4, y4, x5, y5);
if (choose == 3) {
s1 = cal_S(ans[p1][0], ans[p1][1], ans[p2][0], ans[p2][1], x3, y3);
} else if (choose == 4) {
s1 = cal_S(ans[p1][0], ans[p1][1], ans[p2][0], ans[p2][1], x4, y4);
} else {
s1 = cal_S(ans[p1][0], ans[p1][1], ans[p2][0], ans[p2][1], x5, y5);
}
s2 = s - s1;
if (s1 < s2) {
print_Dec(s1);
System.out.print(" ");
print_Dec(s2);
} else {
print_Dec(s2);
System.out.print(" ");
print_Dec(s1);
}
}
}
public static void cal_segment_S_4(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4, double x5, double y5,double x6,double y6){
if(check_coin2(x1,y1,x2,y2,x3,y3,x4,y4)){
System.out.println("The line is coincide with one of the lines");
return;
}
if(check_coin2(x1,y1,x2,y2,x4,y4,x5,y5)){
System.out.println("The line is coincide with one of the lines");
return;
}
if(check_coin2(x1,y1,x2,y2,x5,y5,x6,y6)){
System.out.println("The line is coincide with one of the lines");
return;
}
if(check_coin2(x1,y1,x2,y2,x6,y6,x3,y3)){
System.out.println("The line is coincide with one of the lines");
return;
}
double[][] ans = new double[4][];
int[] count = new int[4];
int cnt=0;
ans[0] = cal_union(x1,y1,x2,y2,x3,y3,x4,y4);
ans[1] = cal_union(x1,y1,x2,y2,x4,y4,x5,y5);
ans[2] = cal_union(x1,y1,x2,y2,x5,y5,x6,y6);
ans[3] = cal_union(x1,y1,x2,y2,x6,y6,x3,y3);
ans[0][0]+=0.0;ans[0][1]+=0.0;
ans[1][0]+=0.0;ans[1][1]+=0.0;
ans[2][0]+=0.0;ans[2][1]+=0.0;
ans[3][0]+=0.0;ans[3][1]+=0.0;
if(!isInside2(ans[0],x3,y3,x4,y4))ans[0] = new double[]{999999.,999999.};
if(!isInside2(ans[1],x4,y4,x5,y5))ans[1] = new double[]{999999.,999999.};
if(!isInside2(ans[2],x5,y5,x6,y6))ans[2] = new double[]{999999.,999999.};
if(!isInside2(ans[3],x6,y6,x3,y3))ans[3] = new double[]{999999.,999999.};
for(int i=1;i<4;i++){
for(int j=0;j<i;j++){
if(Arrays.equals(ans[i],new double[]{999999.,999999.})||Arrays.equals(ans[j],new double[]{999999.,999999.}))continue;
if(Arrays.equals(ans[i],ans[j]))count[i]++;
}
}
for(int i=0;i<4;i++){
if(count[i]==0&&!Arrays.equals(ans[i],new double[]{999999.,999999.})){
cnt++;
}
}
if(cnt==0||cnt==1){
System.out.println(cnt);
}
else{
System.out.print("2 ");
double s1,s2,s3,s;
int p1=-1,p2=-1;
for(int i=0;i<4;i++){
if(count[i]==0&&!Arrays.equals(ans[i],new double[]{999999.,999999.})){
if(p1==-1)p1=i;
else p2=i;
}
}
s = cal_S2(x3,y3,x4,y4,x5,y5,x6,y6);
if(p1+1==p2||(p1==0&&p2==3)){
if(p1==0&&p2==1){
s1 = cal_S(ans[p1][0],ans[p1][1],ans[p2][0],ans[p2][1],x4,y4);
}
else if(p1==1&&p2==2){
s1 = cal_S(ans[p1][0],ans[p1][1],ans[p2][0],ans[p2][1],x5,y5);
}
else if(p1==2&&p2==3){
s1 = cal_S(ans[p1][0],ans[p1][1],ans[p2][0],ans[p2][1],x6,y6);
}
else{
s1 = cal_S(ans[p1][0],ans[p1][1],ans[p2][0],ans[p2][1],x3,y3);
}
s2 = s-s1;
if(s1<s2){
print_Dec(s1);
System.out.print(" ");
print_Dec(s2);
}
else{
print_Dec(s2);
System.out.print(" ");
print_Dec(s1);
}
return;
}
if(p1==0){
s1 = cal_S(ans[p1][0],ans[p1][1],x4,y4,x5,y5);
s2 = cal_S(ans[p1][0],ans[p1][1],ans[p2][0],ans[p2][1],x5,y5);
}
else{
s1 = cal_S(ans[p1][0],ans[p1][1],x5,y5,x6,y6);
s2 = cal_S(ans[p1][0],ans[p1][1],ans[p2][0],ans[p2][1],x6,y6);
}
s3 = s-s1-s2;
if(s1+s2<s3) {
print_Dec(s1 + s2);
System.out.print(" ");
print_Dec(s3);
}
else{
print_Dec(s3);
System.out.print(" ");
print_Dec(s1 + s2);
}
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
if(!s.matches("^[1-5][:](([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))[,]([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))\\s?)+")){
System.out.println("Wrong Format");
return;
}
String a[] = s.split(":");
String[] points = a[1].split(" ");
int op = Integer.parseInt(a[0]);
String[] num;
if(op==1){
if(points.length!=4){
System.out.println("wrong number of points");
return;
}
double x1,y1,x2,y2,x3,y3,x4,y4;
num = points[0].split(",");
x1 = Double.parseDouble(num[0]);
y1 = Double.parseDouble(num[1]);
num = points[1].split(",");
x2 = Double.parseDouble(num[0]);
y2 = Double.parseDouble(num[1]);
num = points[2].split(",");
x3 = Double.parseDouble(num[0]);
y3 = Double.parseDouble(num[1]);
num = points[3].split(",");
x4 = Double.parseDouble(num[0]);
y4 = Double.parseDouble(num[1]);
if(check_coin(new double[]{x1,x2,x3,x4}, new double[]{y1,y2,y3,y4})){
System.out.println("points coincide");
return;
}
boolean flag1 = false,flag2 = false;
flag1 |= check_collin(x1,y1,x2,y2,x3,y3);
flag1 |= check_collin(x2,y2,x3,y3,x4,y4);
flag1 |= check_collin(x3,y3,x4,y4,x1,y1);
flag1 |= check_collin(x4,y4,x1,y1,x2,y2);
flag2 |= check_intersect(x1,y1,x2,y2,x3,y3,x4,y4);
flag2 |= check_intersect(x2,y2,x3,y3,x4,y4,x1,y1);
flag2 |= check_intersect(x3,y3,x4,y4,x1,y1,x2,y2);
flag2 |= check_intersect(x4,y4,x1,y1,x2,y2,x3,y3);
if(flag1||flag2){
System.out.println("false false");
}
else{
System.out.print("true ");
System.out.println(check_parallelogram(new double[]{x1,x2,x3,x4}, new double[]{y1,y2,y3,y4}));
}
}
else if(op==2){
if(points.length!=4){
System.out.println("wrong number of points");
return;
}
double x1,y1,x2,y2,x3,y3,x4,y4;
num = points[0].split(",");
x1 = Double.parseDouble(num[0]);
y1 = Double.parseDouble(num[1]);
num = points[1].split(",");
x2 = Double.parseDouble(num[0]);
y2 = Double.parseDouble(num[1]);
num = points[2].split(",");
x3 = Double.parseDouble(num[0]);
y3 = Double.parseDouble(num[1]);
num = points[3].split(",");
x4 = Double.parseDouble(num[0]);
y4 = Double.parseDouble(num[1]);
boolean flag1 = false,flag2 = false;
flag1 |= check_collin(x1,y1,x2,y2,x3,y3);
flag1 |= check_collin(x2,y2,x3,y3,x4,y4);
flag1 |= check_collin(x3,y3,x4,y4,x1,y1);
flag1 |= check_collin(x4,y4,x1,y1,x2,y2);
flag2 |= check_intersect(x1,y1,x2,y2,x3,y3,x4,y4);
flag2 |= check_intersect(x2,y2,x3,y3,x4,y4,x1,y1);
flag2 |= check_intersect(x3,y3,x4,y4,x1,y1,x2,y2);
flag2 |= check_intersect(x4,y4,x1,y1,x2,y2,x3,y3);
if(flag1||flag2){
System.out.println("not a quadrilateral");
return;
}
if(check_coin(new double[]{x1,x2,x3,x4}, new double[]{y1,y2,y3,y4})){
System.out.println("points coincide");
return;
}
if(!check_parallelogram(new double[]{x1,x2,x3,x4}, new double[]{y1,y2,y3,y4})) {
System.out.println("false false false");
return;
}
boolean f1;
if(check_rhombus(x1,y1,x2,y2,x3,y3,x4,y4)) {
System.out.print("true ");
f1 = true;
}
else{
System.out.print("false ");
f1 = false;
}
if(check_rectangle(x1,y1,x2,y2,x3,y3,x4,y4)) {
if(f1)System.out.print("true true");
else System.out.println("true false");
}
else {
System.out.print("false false");
}
}
else if(op==3){
if(points.length!=4){
System.out.println("wrong number of points");
return;
}
double x1,y1,x2,y2,x3,y3,x4,y4;
num = points[0].split(",");
x1 = Double.parseDouble(num[0]);
y1 = Double.parseDouble(num[1]);
num = points[1].split(",");
x2 = Double.parseDouble(num[0]);
y2 = Double.parseDouble(num[1]);
num = points[2].split(",");
x3 = Double.parseDouble(num[0]);
y3 = Double.parseDouble(num[1]);
num = points[3].split(",");
x4 = Double.parseDouble(num[0]);
y4 = Double.parseDouble(num[1]);
if(check_coin(new double[]{x1,x2,x3,x4}, new double[]{y1,y2,y3,y4})){
System.out.println("points coincide");
return;
}
boolean flag1 = false;
flag1 |= check_collin(x1,y1,x2,y2,x3,y3);
flag1 |= check_collin(x2,y2,x3,y3,x4,y4);
flag1 |= check_collin(x3,y3,x4,y4,x1,y1);
flag1 |= check_collin(x4,y4,x1,y1,x2,y2);
if(flag1){
System.out.println("not a quadrilateral");
return;
}
double[] ans;
boolean flag=false;
int c1=0,c2=0,c3=0,c4=0;
ans = cal_union(x1,y1,x2,y2,x3,y3,x4,y4);
if(isInside(ans,x3,y3,x4,y4)){
flag = true;
c1++;
c2++;
}
ans = cal_union(x2,y2,x3,y3,x4,y4,x1,y1);
if(isInside(ans,x4,y4,x1,y1)){
flag = true;
c2++;
c3++;
}
ans = cal_union(x3,y3,x4,y4,x1,y1,x2,y2);
if(isInside(ans,x1,y1,x2,y2)){
flag = true;
c3++;
c4++;
}
ans = cal_union(x4,y4,x1,y1,x2,y2,x3,y3);
if(isInside(ans,x2,y2,x3,y3)){
flag = true;
c4++;
c1++;
}
if(flag) System.out.print("false ");
else System.out.print("true ");
print_Dec(cal_C(x1,y1,x2,y2,x3,y3,x4,y4));
System.out.print(" ");
if(c1==2) {
print_Dec(cal_S(x2, y2, x3, y3, x1, y1) + cal_S(x1, y1, x3, y3, x4, y4));
}
else if(c2==2){
print_Dec(cal_S(x2, y2, x1, y1, x4, y4) + cal_S(x2, y2, x3, y3, x4, y4));
}
else if(c3==2){
print_Dec(cal_S(x2, y2, x3, y3, x1, y1) + cal_S(x1, y1, x3, y3, x4, y4));
}
else{
print_Dec(cal_S(x2, y2, x3, y3, x4, y4) + cal_S(x1, y1, x2, y2, x4, y4));
}
}
else if(op==4){
if(points.length!=6){
System.out.println("wrong number of points");
return;
}
double x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6;
num = points[0].split(",");
x1 = Double.parseDouble(num[0]);
y1 = Double.parseDouble(num[1]);
num = points[1].split(",");
x2 = Double.parseDouble(num[0]);
y2 = Double.parseDouble(num[1]);
num = points[2].split(",");
x3 = Double.parseDouble(num[0]);
y3 = Double.parseDouble(num[1]);
num = points[3].split(",");
x4 = Double.parseDouble(num[0]);
y4 = Double.parseDouble(num[1]);
num = points[4].split(",");
x5 = Double.parseDouble(num[0]);
y5 = Double.parseDouble(num[1]);
num = points[5].split(",");
x6 = Double.parseDouble(num[0]);
y6 = Double.parseDouble(num[1]);
if(x1==x2&&y1==y2){
System.out.println("points coincide");
return;
}
boolean flag1 = false, flag2 = false;
flag1 |= check_intersect(x3,y3,x4,y4,x5,y5,x6,y6);
flag1 |= check_intersect(x3,y3,x6,y6,x4,y4,x5,y5);
flag2 |= check_collin(x3,y3,x4,y4,x5,y5);
flag2 |= check_collin(x4,y4,x5,y5,x6,y6);
flag2 |= check_collin(x5,y5,x6,y6,x3,y3);
flag2 |= check_collin(x6,y6,x3,y3,x4,y4);
//无法构成四边形
if(flag1||flag2) {
cal_segment_S_3(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6);
}
//可以构成四边形
else{
cal_segment_S_4(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6);
}
}
else{
if(points.length!=5){
System.out.println("wrong number of points");
return;
}
double x1,y1,x2,y2,x3,y3,x4,y4,x5,y5;
num = points[0].split(",");
x1 = Double.parseDouble(num[0]);
y1 = Double.parseDouble(num[1]);
num = points[1].split(",");
x2 = Double.parseDouble(num[0]);
y2 = Double.parseDouble(num[1]);
num = points[2].split(",");
x3 = Double.parseDouble(num[0]);
y3 = Double.parseDouble(num[1]);
num = points[3].split(",");
x4 = Double.parseDouble(num[0]);
y4 = Double.parseDouble(num[1]);
num = points[4].split(",");
x5 = Double.parseDouble(num[0]);
y5 = Double.parseDouble(num[1]);
boolean flag1 = false, flag2 = false;
flag1 |= check_intersect(x2,y2,x3,y3,x4,y4,x5,y5);
flag1 |= check_intersect(x2,y2,x5,y5,x3,y3,x4,y4);
flag2 |= check_collin(x2,y2,x3,y3,x4,y4);
flag2 |= check_collin(x3,y3,x4,y4,x5,y5);
flag2 |= check_collin(x4,y4,x5,y5,x2,y2);
flag2 |= check_collin(x5,y5,x2,y2,x3,y3);
//无法构成四边形
if(flag1||flag2) {
check_triangle(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5);
}
//可以构成四边形
else{
check_quadrilateral(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5);
}
}
}
public static void check_quadrilateral(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4,double x5,double y5){
//2,3,4
//2,4,5
if((on_edge(x1,y1,new double[]{x2,x3},new double[]{y2,y3})&&x1>=Math.min(x2,x3)&&x1<=Math.max(x2,x3)&&y1>=Math.min(y2,y3)&&y1<=Math.max(y2,y3))||(on_edge(x1,y1,new double[]{x3,x4},new double[]{y3,y4})&&x1>=Math.min(x3,x4)&&x1<=Math.max(x3,x4)&&y1>=Math.min(y3,y4)&&y1<=Math.max(y3,y4))||(on_edge(x1,y1,new double[]{x4,x5},new double[]{y4,y5})&&x1>=Math.min(x4,x5)&&x1<=Math.max(x4,x5)&&y1>=Math.min(y4,y5)&&y1<=Math.max(y4,y5))||(on_edge(x1,y1,new double[]{x2,x5},new double[]{y2,y5})&&x1>=Math.min(x2,x5)&&x1<=Math.max(x2,x5)&&y1>=Math.min(y2,y5)&&y1<=Math.max(y2,y5))){
System.out.println("on the quadrilateral");
return;
}
double s1,s2,s3;
double s4,s5,s6;
s1 = cal_S(x1,y1,x2,y2,x3,y3);
s2 = cal_S(x1,y1,x3,y3,x4,y4);
s3 = cal_S(x1,y1,x2,y2,x4,y4);
s4 = cal_S(x1,y1,x2,y2,x5,y5);
s5 = cal_S(x1,y1,x4,y4,x5,y5);
s6 = cal_S(x1,y1,x2,y2,x4,y4);
if(Math.abs(s1+s2+s3-cal_S(x2,y2,x3,y3,x4,y4))<0.001||Math.abs(s4+s5+s6-cal_S(x2,y2,x4,y4,x5,y5))<0.001){
System.out.println("in the quadrilateral");
}
else{
System.out.println("outof the quadrilateral");
}
}
public static void check_triangle(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4,double x5,double y5){
if(!((x2==x4&&y2==y4&&!on_edge(x5,y5,new double[]{x2,x3},new double[]{y2,y3}))||
(x3==x5&&y3==y5&&!on_edge(x2,y2,new double[]{x3,x4},new double[]{y3,y4}))||
(x2==x3&&y2==y3&&!on_edge(x5,y5,new double[]{x2,x4},new double[]{y2,y4}))||
(x3==x4&&y3==y4&&!on_edge(x5,y5,new double[]{x2,x3},new double[]{y2,y3}))||
(x4==x5&&y4==y5&&!on_edge(x2,y2,new double[]{x3,x4},new double[]{y3,y4}))||
(x5==x2&&y5==y2&&!on_edge(x4,y4,new double[]{x2,x3},new double[]{y2,y3}))||
(check_collin(x2,y2,x3,y3,x4,y4)&&on_edge(x3,y3,new double[]{x2,x4},new double[]{y2,y4})&&x3>=Math.min(x2,x4)&&x3<=Math.max(x2,x4)&&y3>=Math.min(y2,y4)&&y3<=Math.max(y2,y4))||
(check_collin(x3,y3,x4,y4,x5,y5)&&on_edge(x4,y4,new double[]{x3,x5},new double[]{y3,y5})&&x4>=Math.min(x3,x5)&&x4<=Math.max(x3,x5)&&y4>=Math.min(y3,y5)&&y4<=Math.max(y3,y5))||
(check_collin(x4,y4,x5,y5,x2,y2)&&on_edge(x5,y5,new double[]{x4,x2},new double[]{y4,y2})&&x5>=Math.min(x4,x2)&&x5<=Math.max(x4,x2)&&y5>=Math.min(y4,y2)&&y5<=Math.max(y4,y2))||
(check_collin(x5,y5,x2,y2,x3,y3)&&on_edge(x2,y2,new double[]{x5,x3},new double[]{y5,y3})&&x2>=Math.min(x5,x3)&&x2<=Math.max(x5,x3)&&y2>=Math.min(y5,y3)&&y2<=Math.max(y5,y3)))
){
System.out.println("not a quadrilateral or triangle");
return;
}
if (check_coin(new double[]{x2, x3, x4, x5}, new double[]{y2, y3, y4, y5})) {
//将不重复的点存到(x3,y3)(x4,y4)(x5,y5)
//将不重复的点存到(x3,y3)(x4,y4)(x5,y5)
int except;
int[] temp = cal_coin2(new double[]{x2, x3, x4, x5}, new double[]{y2, y3, y4, y5});
except = temp[1];
if(except == 0){
x2 = x3;y2 = y3;
x3 = x4;y3 = y4;
x4 = x5;y4 = y5;
}
else if(except == 1){
x3 = x4;y3 = y4;
x4 = x5;y4 = y5;
}
else if(except == 2){
x4 = x5;y4 = y5;
}
}
else{
int except;
if(check_collin(x2,y2,x3,y3,x4,y4)) except = 3;
else if(check_collin(x3,y3,x4,y4,x5,y5)) except = 4;
else if(check_collin(x4,y4,x5,y5,x2,y2)) except = 5;
else except = 2;
if(except == 2){
x2 = x3;y2 = y3;
x3 = x4;y3 = y4;
x4 = x5;y4 = y5;
}
else if(except == 3){
x3 = x4;y3 = y4;
x4 = x5;y4 = y5;
}
else if(except == 4){
x4 = x5;y4 = y5;
}
}
if((on_edge(x1,y1,new double[]{x2,x3},new double[]{y2,y3})&&x1>=Math.min(x2,x3)&&x1<=Math.max(x2,x3))||(on_edge(x1,y1,new double[]{x3,x4},new double[]{y3,y4})&&x1>=Math.min(x3,x4)&&x1<=Math.max(x3,x4))||(on_edge(x1,y1,new double[]{x2,x4},new double[]{y2,y4})&&x1>=Math.min(x2,x4)&&x1<=Math.max(x2,x4))){
System.out.println("on the triangle");
return;
}
double s1,s2,s3;
s1 = cal_S(x1,y1,x2,y2,x3,y3);
s2 = cal_S(x1,y1,x3,y3,x4,y4);
s3 = cal_S(x1,y1,x2,y2,x4,y4);
if(Math.abs(s1+s2+s3-cal_S(x2,y2,x3,y3,x4,y4))<0.01){
System.out.println("in the triangle");
}
else{
System.out.println("outof the triangle");
}
}
public static boolean on_edge(double x0, double y0, double[] x, double[] y){
double A,B,C;
A = y[1]-y[0];
B = x[0]-x[1];
C = y[0]*(x[1]-x[0])-x[0]*(y[1]-y[0]);
return x0 * A + B * y0 + C == 0.0;
}
}
3.2 点线形系列5-凸五边形的计算
题目描述:[两次作业一起]
用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
1:输入五个点坐标,判断是否是五边形,判断结果输出true/false。
2:输入五个点坐标,判断是凹五边形(false)还是凸五边形(true),如果是凸五边形,则再输出五边形周长、面积,结果之间以一个英文空格符分隔。 若五个点坐标无法构成五边形,输出"not a pentagon"
3:输入七个点坐标,前两个点构成一条直线,后五个点构成一个凸五边形、凸四边形或凸三角形,输出直线与五边形、四边形或三角形相交的交点数量。如果交点有两个,再按面积从小到大输出被直线分割成两部分的面积(不换行)。若直线与多边形形的一条边线重合,输出"The line is coincide with one of the lines"。若后五个点不符合五边形输入,若前两点重合,输出"points coincide"。4:输入十个点坐标,前、后五个点分别构成一个凸多边形(三角形、四边形、五边形),判断它们两个之间是否存在包含关系(一个多边形有一条或多条边与另一个多边形重合,其他部分都包含在另一个多边形内部,也算包含)。
两者存在六种关系:1、分离(完全无重合点) 2、连接(只有一个点或一条边重合) 3、完全重合 4、被包含(前一个多边形在后一个多边形的内部)5、交错 6、包含(后一个多边形在前一个多边形的内部)。
各种关系的输出格式如下:
1、no overlapping area between the previous triangle/quadrilateral/ pentagon and the following triangle/quadrilateral/ pentagon
2、the previous triangle/quadrilateral/ pentagon is connected to the following triangle/quadrilateral/ pentagon
3、the previous triangle/quadrilateral/ pentagon coincides with the following triangle/quadrilateral/ pentagon
4、the previous triangle/quadrilateral/ pentagon is inside the following triangle/quadrilateral/ pentagon
5、the previous triangle/quadrilateral/ pentagon is interlaced with the following triangle/quadrilateral/ pentagon
6、the previous triangle/quadrilateral/ pentagon contains the following triangle/quadrilateral/ pentagon5:输入十个点坐标,前、后五个点分别构成一个凸多边形(三角形、四边形、五边形),输出两个多边形公共区域的面积。注:只考虑每个多边形被另一个多边形分割成最多两个部分的情况,不考虑一个多边形将另一个分割成超过两个区域的情况。
6:输入六个点坐标,输出第一个是否在后五个点所构成的多边形(限定为凸多边形,不考虑凹多边形),的内部(若是五边形输出in the pentagon/outof the pentagon,若是四边形输出in the quadrilateral/outof the quadrilateral,若是三角形输出in the triangle/outof the triangle)。输入入错存在冗余点要排除,冗余点的判定方法见选项5。如果点在多边形的某条边上,输出"on the triangle/on the quadrilateral/on the pentagon"。
以上4、5、6选项输入的五个点坐标可能存在冗余,假设多边形一条边上两个端点分别是x、y,边线中间有一点z,另一顶点s:
1)符合要求的输入:顶点重复或者z与xy都相邻,如:x x y s、x z y s、x y x s、s x y y。此时去除冗余点,保留一个x、一个y。
\2) 不符合要求的输入:z不与xy都相邻,如:z x y s、x z s y、x s z y
思路分析:
-
cmd == 1
如果相邻三点不共线(重合算共线),非相邻两边没有交点则可以构成五边形,否则不能 -
cmd ==2
将五边形分割成若干个四边形,调用四边形判断凹凸性的方法来判断这若干个四边形是否为凸,若都为凸则为凸五边形,否则为凹五边形 -
cmd == 3
-
后者构成了五边形
我是先求出直线与五边形四条边的交点(只有0,1,2三种情况),当交点个数为2时,再暴力if判断交点所在的边(这里可以判断出这两个交点跟哪个顶点构成三角形),然后计算出该三角形的面积,用大五边形的面积减去就得到剩余部分的面积 -
后者构成了四边形:
直接copy练习四 -
后者构成了三角形:
直接copy练习三
-
-
cmd == 4
实例化两个Graphical对象
调用relationshipWith函数 -
cmd == 5
实例化一个Graphical对象
调用overlappingArea函数 -
cmd == 6
实例化一个Graphical对象
调用isContainPoint函数
code:
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Main {
public static void print_Dec(double ans){
String res = String.format("%.3f",ans);
ans = Double.parseDouble(res);
System.out.print(ans);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
if(!s.matches("^[1-6][:](([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))[,]([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))\\s?)+")){
System.out.println("Wrong Format");
return;
}
String a[] = s.split(":");
String[] points = a[1].split(" ");
int op = Integer.parseInt(a[0]);
String[] num;
if(op==1){
if(points.length!=5){
System.out.println("wrong number of points");
return;
}
Point p1,p2,p3,p4,p5;
num = points[0].split(",");
p1 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[1].split(",");
p2 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[2].split(",");
p3 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[3].split(",");
p4 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[4].split(",");
p5 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
pentagon p = new pentagon(p1,p2,p3,p4,p5);
System.out.println(p.isPentagon());
}
else if(op==2){
if(points.length!=5){
System.out.println("wrong number of points");
return;
}
Point p1,p2,p3,p4,p5;
num = points[0].split(",");
p1 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[1].split(",");
p2 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[2].split(",");
p3 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[3].split(",");
p4 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[4].split(",");
p5 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
pentagon p = new pentagon(p1,p2,p3,p4,p5);
if(!p.isPentagon_()){
System.out.println("not a pentagon");
return;
}
if(p.isConvexPentagon()){
System.out.print("true ");
print_Dec(p.cal_C());
System.out.print(" ");
print_Dec(p.cal_S());
}
else{
System.out.println("false");
}
}
else if(op==3){
if(points.length!=7){
System.out.println("wrong number of points");
return;
}
Point p1,p2,p3,p4,p5,p6,p7;
num = points[0].split(",");
p1 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[1].split(",");
p2 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[2].split(",");
p3 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[3].split(",");
p4 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[4].split(",");
p5 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[5].split(",");
p6 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[6].split(",");
p7 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
Line l = new Line(p1,p2);
pentagon p = new pentagon(p3,p4,p5,p6,p7);
if(p1.isSameTo(p2)){
System.out.println("points coincide");
return;
}
if(p.isPentagon()){
p.cal_Pentagon(l);
}
else{
if(p4.inLineSegment_close(new Line(p3,p5))){
p4=p5;p5=p6;p6=p7;
}
else if(p5.inLineSegment_close(new Line(p4,p6))){
p5=p6;p6=p7;
}
else if(p6.inLineSegment_close(new Line(p5,p7))){
p6=p7;
}
else if(p3.inLineSegment_close(new Line(p7,p4))){
p3=p4;p4=p5;p5=p6;p6=p7;
}
Quadrilateral q = new Quadrilateral(p3,p4,p5,p6);
if(q.isQuadrilateral()){
q.cal_Quadrilateral(l);
}
else{
if(p4.inLineSegment_close(new Line(p3,p5))){
p4=p5;p5=p6;
}
else if(p5.inLineSegment_close(new Line(p4,p6))){
p5=p6;
}
else if(p3.inLineSegment_close(new Line(p4,p6))){
p3=p4;p4=p5;p5=p6;
}
Triangle t = new Triangle(p3,p4,p5);
if(t.is_Triangle()){
t.cal_Triangle(l);
}
else{
System.out.println("not a pentagon");
}
}
}
}
else if(op==4){
if(points.length!=10){
System.out.println("wrong number of points");
return;
}
Point p1,p2,p3,p4,p5,p6,p7,p8,p9,p10;
num = points[0].split(",");
p1 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[1].split(",");
p2 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[2].split(",");
p3 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[3].split(",");
p4 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[4].split(",");
p5 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[5].split(",");
p6 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[6].split(",");
p7 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[7].split(",");
p8 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[8].split(",");
p9 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[9].split(",");
p10 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
Graphical g1 = new Graphical(new Point[]{p1,p2,p3,p4,p5}), g2 = new Graphical(new Point[]{p6,p7,p8,p9,p10});
if(g1.status==-1||g2.status==-1){
System.out.println("not a polygon");
}
String[] name = new String[]{"triangle", "quadrilateral", "pentagon"};
//分离
if(g1.isSeparatedFrom(g2)){
System.out.println("no overlapping area between the previous "+name[g1.len-3]+ " and the following "+name[g2.len-3]);
return;
}
//完全重合
if(g1.isSameTo(g2)) {
System.out.println("the previous " + name[g1.len - 3] + " coincides with the following " + name[g2.len - 3]);
return;
}
//包含
if(g1.isContainGra(g2)){
System.out.println("the previous "+name[g1.len-3]+ " contains the following "+name[g2.len-3]);
return;
}
//被包含
if(g2.isContainGra(g1)){
System.out.println("the previous "+name[g1.len-3]+ " is inside the following "+name[g2.len-3]);
return;
}
//连接
if(g1.overlappingArea(g2) == 0){
System.out.println("the previous "+name[g1.len-3]+ " is connected to the following "+name[g2.len-3]);
return;
}
//交错
System.out.println("the previous "+name[g1.len-3]+ " is interlaced with the following "+name[g2.len-3]);
}
else if(op==5){
if(points.length!=10){
System.out.println("wrong number of points");
return;
}
Point p1,p2,p3,p4,p5,p6,p7,p8,p9,p10;
num = points[0].split(",");
p1 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[1].split(",");
p2 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[2].split(",");
p3 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[3].split(",");
p4 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[4].split(",");
p5 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[5].split(",");
p6 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[6].split(",");
p7 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[7].split(",");
p8 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[8].split(",");
p9 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[9].split(",");
p10 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
Graphical g1 = new Graphical(new Point[]{p1,p2,p3,p4,p5}), g2 = new Graphical(new Point[]{p6,p7,p8,p9,p10});
if(g1.status==-1||g2.status==-1){
System.out.println("not a polygon");
}
System.out.println(g1.overlappingArea(g2));
}
else{
if(points.length!=6){
System.out.println("wrong number of points");
return;
}
Point p1,p2,p3,p4,p5,p6;
num = points[0].split(",");
p1 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[1].split(",");
p2 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[2].split(",");
p3 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[3].split(",");
p4 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[4].split(",");
p5 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
num = points[5].split(",");
p6 = new Point(Double.parseDouble(num[0]), Double.parseDouble(num[1]));
Graphical g = new Graphical(new Point[]{p2,p3,p4,p5,p6});
if(g.status==-1){
System.out.println("not a polygon");
}
if(g.len==3){
if(g.isContainPoint(p1)==-1){
System.out.println("in the triangle");
}
else if(g.isContainPoint(p1)==0){
System.out.println("on the triangle");
}
else{
System.out.println("outof the triangle");
}
}
else if(g.len==4){
if(g.isContainPoint(p1)==-1){
System.out.println("in the quadrilateral");
}
else if(g.isContainPoint(p1)==0){
System.out.println("on the quadrilateral");
}
else{
System.out.println("outof the quadrilateral");
}
}
else{
if(g.isContainPoint(p1)==-1){
System.out.println("in the pentagon");
}
else if(g.isContainPoint(p1)==0){
System.out.println("on the pentagon");
}
else{
System.out.println("outof the pentagon");
}
}
}
}
}
class Point{
public double x, y;
public Point(){
this.x = 0;
this.y = 0;
}
public Point(double a,double b){
this.x = a;
this.y = b;
}
public void print(){
String x = String.format("%.6f",this.x);
String y = String.format("%.6f",this.y);
x = x.replaceAll("0+?$", "");
y = y.replaceAll("0+?$", "");
System.out.printf("(%s , %s)\n",this.x,this.y);
}
//两点坐标相同
public boolean isSameTo(Point a){
return (this.x == a.x)&&(this.y == a.y);
}
//两点距离
public double disToPoint(Point another){
return Math.sqrt(Math.pow(this.x-another.x,2) + Math.pow(this.y-another.y,2));
}
//点到直线的垂直距离
public double disToLine(Line l){
return Math.abs(l.a*this.x+l.b*this.y+l.c) / Math.sqrt(Math.pow(l.a,2)+Math.pow(l.b,2));
}
//判断是否在直线之上
public boolean inLine(Line l){
return Math.abs(l.a*this.x + l.b*this.y + l.c) < 0.000001;
}
//判断是否在线段之内(包括端点)
public boolean inLineSegment_close(Line l){
if(!this.inLine(l)) return false;
double res = this.disToPoint(l.sta) + this.disToPoint(l.ed) - l.length();
return Math.abs(res) < 0.000001;
}
//判断是否在线段之内(不包括端点)
public boolean inLineSegment(Line l){
return this.inLineSegment_close(l) &&
(!this.isSameTo(l.sta)) &&
(!this.isSameTo(l.ed));
}
public Point add(Point another){
Point res = this.deepCopy();
res.x += another.x;
res.y += another.y;
return res;
}
public Point sub(Point another){
Point res = this.deepCopy();
res.x -= another.x;
res.y -= another.y;
return res;
}
//求点集重心
public static Point focusPoint(Point[] points ){
Point res = new Point(0,0);
for(Point item:points){
res = res.add(item);
}
res.x /= points.length;
res.y /= points.length;
return res;
}
}
class Line{
public Point sta, ed;
public double a,b,c;
private final Point vector;
public Line(Point a,Point b){
this.sta = a;
this.ed = b;
this.a = (-(a.y-b.y));
this.b = (a.x-b.x);
this.c = (-this.a*this.sta.x-this.b*this.sta.y);
this.vector = ed.sub(sta);
}
public void print(){
System.out.printf("%fX + %fY + %f = 0\n",this.a,this.b,this.c);
}
//求线段长度
public double length(){
return this.sta.disToPoint(this.ed);
}
//判断是否平行
public boolean isParallelTo(Line another){
if(this.b==0 || another.b==0){
return (this.b == 0 && another.b == 0);
}
return (this.a*another.b == this.b*another.a);
}
//判断是否重合
public boolean isSameTo(Line another){
// return this.isParallelTo(another) && (this.c==another.c);
double x1,x2,x3,x4,y1,y2,y3,y4;
x1 = sta.x;x2 = ed.x;
y1 = sta.y;y2 = ed.y;
x3 = another.sta.x;x4 = another.ed.x;
y3 = another.sta.y;y4 = another.ed.y;
if(x1==x2&&x3==x4){
return x1==x3;
}
if(y1==y2){
return y1==y3&&y1==y4;
}
if(y3==y4){
return y3==y1&&y3==y2;
}
return (y2 - y1) * (x4 - x3) == (y4 - y3) * (x2 - x1) && (x2 * y1 - x1 * y2) * (x4 - x3) == (x4 * y3 - x3 * y4) * (x2 - x1);
}
//求两条直线交点
public Point getIntersection(Line another){
if(this.isParallelTo(another)) return null;
Point res = new Point();
res.y = (another.a*this.c-this.a*another.c) / (this.a*another.b-another.a*this.b);
res.x = (this.b*another.c-another.b*this.c) / (this.a*another.b-another.a*this.b);
return res;
}
//返回两条线段的交点
public Point LineSegmentInside(Line another){
Point res = this.getIntersection(another);
if(res == null) return res;
boolean ok = (res.inLineSegment_close(this) && res.inLineSegment_close(another));
return ok ? res:null;
}
//求向量模
public double vectorLength(){
return Math.sqrt( Math.pow(this.vector.x,2) + Math.pow(this.vector.y,2) );
}
//求向量点积
public double vectorMul(Line another){
return (this.vector.x * another.vector.x) + (this.vector.y * another.vector.y);
}
//求向量叉积
public double vectorCrossMul(Line another){
return (this.vector.x * another.vector.y) - (another.vector.x * this.vector.y);
}
//求两向量夹角(非0向量)
public double vectorAngle(Line another){
double cos_angle = this.vectorMul(another) / (this.vectorLength() * another.vectorLength());
return Math.acos(cos_angle);
}
}
class Triangle extends Graphical {
public Triangle(Point[] points){
super(points);
}
//求三个点围成的图形面积(三点可能共线,面积为0)
public static double area(Point a, Point b, Point c){
double len1 = a.disToPoint(b);
double len2 = b.disToPoint(c);
double len3 = c.disToPoint(a);
double p = (len1+len2+len3) / 2;
return Math.sqrt(p*(p-len1)*(p-len2)*(p-len3));
}
}
class Graphical {
public int len=0,status=1; //多边形边数,状态
public Point[] points;
public Line[] lines;
public double sideLength = 0,area = 0; //边长,面积
public Graphical(Point[] points){
this.points = new Point[points.length];
points = this.removeMulti(points); //去除重复点
if(points.length <=2 ){
this.status = -1;
return;
}
//相邻边夹角0则去除中间点,夹角180则status:-1
for(int i=0;i<points.length;i++){
int first = i , second = (i+1)%points.length, third = (i+2)%points.length;
Line l1 = new Line(points[first],points[second]);
Line l2 = new Line(points[second],points[third]);
if( Math.abs(l1.vectorAngle(l2) - Math.PI) < 0.000001 ){ //夹角180
this.status = -1;
return;
}
else if(Math.abs(l1.vectorAngle(l2)) > 0.000001){ //夹角不为0
this.points[this.len++] = points[second].deepCopy();
}
}
this.points = Arrays.copyOf(this.points,this.len);
this.lines = new Line[this.len];
for(int i=0;i<this.len;i++){
int first = i, second = (i+1)%this.len;
this.lines[i] = new Line(this.points[first], this.points[second]);
}
//判断任意不相邻边(线段交点)是否有交点
checkEdge();
Graphical.Cal_S(this);
Graphical.Cal_C(this);
}
//判断和另一个图形完全分离(重叠面积为0,并且任意点都在this之外)
public boolean isSeparatedFrom(Graphical g){
boolean ok = true;
int[] check2 = new int[g.len];
for(int i=0;i<g.len;i++){
check2[i] = this.isContainPoint(g.points[i]);
}
for(int item:check2){
if(item != 1) ok = false;
}
if(this.overlappingArea(g) !=0) ok = false;
return ok;
}
//判断图形是否包含某个点返回值-1,0,1 (内部,边缘,外部)
public int isContainPoint(Point p){
for(int i=0;i<this.len;i++){ //位于边之上
if(p.inLineSegment_close(this.lines[i])) return 0;
}
double s = 0;
for(int i=0;i<this.len;i++){
s += Triangle.area(p,this.points[i], this.points[(i+1)%this.len]);
}
return Math.abs(s-this.area) < 0.000001 ? -1:1;
}
//判断两个图形是否一模一样(点完全重合)
public boolean isSameTo(Graphical g){
if(this.len != g.len) return false;
for(int i=0;i<this.len;i++){
boolean ok = false;
for(int j=0;j<g.len;j++){
if(this.points[i].isSameTo(g.points[j])) ok = true;
}
if(!ok) return false;
}
return true;
}
//判断完全包含另一个图形(任意点都在this之内)
public boolean isContainGra(Graphical g){
boolean ok = true;
int[] check2 = new int[g.len];
for(int i=0;i<g.len;i++){
check2[i] = this.isContainPoint(g.points[i]);
}
for(int item:check2){
if(item == 1) ok = false;
}
return ok;
}
public double overlappingArea(Graphical g){
Point[] intersection = new Point[100];
int intersection_len = 0;
for(Line item1:this.lines){ //求出两多边形的交点
for(Line item2: g.lines){
Point tmp = item1.LineSegmentInside(item2);
if(tmp != null){
intersection[intersection_len++] = tmp.deepCopy();
}
}
}
if(intersection_len == 0){ //特判包含
if(this.isContainGra(g)) return g.area;
if(g.isContainGra(this)) return this.area;
return 0;
}
if(this.isSameTo(g)) return this.area;
for(Point item:g.points){ //顶点包含在内部
if(this.isContainPoint(item) == -1) intersection[intersection_len++] = item.deepCopy();
}
for(Point item:this.points){ //顶点包含在内部
if(g.isContainPoint(item) == -1) intersection[intersection_len++] = item.deepCopy();
}
/*排序交点数组*/
intersection = Arrays.copyOf(intersection,intersection_len);
intersection = this.removeMulti(intersection);
Point focus = Point.focusPoint(intersection);
Point sta = intersection[0].deepCopy();
Arrays.sort(intersection,1,intersection.length, (o1, o2) -> {
try{
Line origin =new Line(focus,sta);
Line l1 = new Line(focus,o1);
Line l2 = new Line(focus,o2);
double angle1 = origin.vectorAngle(l1);
double angle2 = origin.vectorAngle(l2);
if(origin.vectorCrossMul(l1) < 0) angle1 = 2*Math.PI - angle1;
if(origin.vectorCrossMul(l2) < 0) angle2 = 2*Math.PI - angle2;
if(angle1-angle2 > 0.000001) return 1;
if(Math.abs(angle1-angle2) < 0.000001) return 0;
return -1;
}catch (Exception reason){}
return 0;
});
Graphical graphical = new Graphical(intersection);
return graphical.area;
}
//去除所有重复点
private Point[] removeMulti(Point[] points){
Point[] tmp_points = new Point[points.length];
int tmp_len = 0;
for(int i=0;i<points.length;i++){
boolean ok = true;
for(int j=0;j<tmp_len;j++){
if(points[i].isSameTo(tmp_points[j])){
ok = false;
break;
}
}
if(ok) tmp_points[tmp_len++] = points[i].deepCopy();
}
return Arrays.copyOf(tmp_points,tmp_len);
}
//判断不相邻边是否有交点
private void checkEdge(){
for(int i=0;i<this.len;i++){
for(int j=i+2;j<this.len;j++){
if(i==0&&j==this.len-1) continue;
Point p = this.lines[i].getIntersection(this.lines[j]);
if(p==null) continue;
if(p.inLineSegment_close(this.lines[i]) && p.inLineSegment_close(this.lines[j])){
this.status = -1;
return;
}
}
}
}
//多边形面积
private static void Cal_S(Graphical e){
double res = 0;
Point origin = new Point(0,0);
for(int i=0;i<e.len;i++){
Line l1 = new Line(origin,e.points[i]);
Line l2 = new Line(origin,e.points[(i+1)%e.len]);
res += 0.5 * l1.vectorCrossMul(l2);
}
e.area = Math.abs(res);
}
//多边形周长
private static void Cal_C(Graphical e){
double res = 0;
for(int i=0;i<e.len;i++){
res += e.points[i].disToPoint(e.points[(i+1)%e.len]);
}
e.sideLength = res;
}
}
3.3 期中考试
-
第一题只需封装好Point,Line两个类即可
-
第二题在第一题的基础上,加入了Plane类,增加了Point,Line,Plane的父类Element
-
第三题在第二题的基础上,加入了GeometryObject容器类,用于存放Element
Point extends Element:
属性:x,y
方法:对x,y的get 和 set P2P(点到点的距离) , display
Line extends Element:
属性:point1 , point2 , color
方法:对属性的get 和 set getDistance(point1和point2的距离) , display
Plane extends Element:
属性:color
方法:对属性的get 和 set display
Element:
方法:display
GeometryObject:
属性:list
方法:getList , add(向list添加元素) , remove(移除链表末尾元素)
对应类图:
类code:
Point extends Element:
class Point extends Element{
double x,y;
public Point(){
}
public Point(double x,double y){
setX(x);
setY(y);
}
public double getX(){
return this.x;
}
public double P2P(Point p){
return Math.sqrt((p.x-x)*(p.x-x)+(p.y-y)*(p.y-y));
}
public void setX(double x){
this.x=x;
}
public double getY(){
return this.y;
}
public void setY(double y){
this.y=y;
}
public void display(){
System.out.println("("+String.format("%.2f", this.x)+","+String.format("%.2f", this.y)+")");
}
}
Line extends Element:
class Line extends Element{
Point p1,p2;
String color;
public Line(){
}
public Line(Point p1,Point p2,String color){
setP1(p1);
setP2(p2);
setColor(color);
}
public Point getP1(){
return this.p1;
}
public void setP1(Point p1){
this.p1=p1;
}
public Point getP2(){
return this.p2;
}
public void setP2(Point p2){
this.p2=p2;
}
public String getColor(){
return this.color;
}
public void setColor(String color){
this.color=color;
}
public double getDistance(){
return p1.P2P(p2);
}
public void display(){
System.out.println("The line's color is:"+color);
System.out.println("The line's begin point's Coordinate is:");
p1.display();
System.out.println("The line's end point's Coordinate is:");
p2.display();
System.out.println("The line's length is:"+String.format("%.2f", getDistance()));
}
}
Plane extends Element:
class Plane extends Element{
String color;
public Plane(){
}
public Plane(String color){
setColor(color);
}
public String getColor(){
return this.color;
}
public void setColor(String color){
this.color=color;
}
public void display(){
System.out.println("The Plane's color is:"+this.color);
}
}
Element:
abstract class Element{
public void display(){
}
}
GeometryObject:
import java.util.ArrayList;
class GeometryObject{
ArrayList<Element> List = new ArrayList<>();
public GeometryObject(){
}
public void add(Element element){
this.List.add(element);
}
public void remove(int index){
this.List.remove(index);
}
public ArrayList<Element> getList(){
return this.List;
}
}
实现code:
code1:
import java.util.Scanner;
public class Main {
public static boolean Check(double x){
return x > 0 && x <= 200;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
double x1,y1,x2,y2;
String color;
Line line;
x1 = Double.parseDouble(in.next());
y1 = Double.parseDouble(in.next());
x2 = Double.parseDouble(in.next());
y2 = Double.parseDouble(in.next());
in.nextLine();
if(!Check(x1)||!Check(y1)||!Check(x2)||!Check(x2)||!Check(y2)){
System.out.println("Wrong Format");
return;
}
color = in.nextLine();
line = new Line(new Point(x1,y1), new Point(x2,y2), color);
line.display();
}
}
class Point{
double x,y;
public Point(){
}
public Point(double x,double y){
setX(x);
setY(y);
}
public double getX(){
return this.x;
}
public double P2P(Point p){
return Math.sqrt((p.x-x)*(p.x-x)+(p.y-y)*(p.y-y));
}
public void setX(double x){
this.x=x;
}
public double getY(){
return this.y;
}
public void setY(double y){
this.y=y;
}
public void display(){
System.out.println("("+String.format("%.2f", this.x)+","+String.format("%.2f", this.y)+")");
}
}
class Line{
Point p1,p2;
String color;
public Line(){
}
public Line(Point p1,Point p2,String color){
setP1(p1);
setP2(p2);
setColor(color);
}
public Point getP1(){
return this.p1;
}
public void setP1(Point p1){
this.p1=p1;
}
public Point getP2(){
return this.p2;
}
public void setP2(Point p2){
this.p2=p2;
}
public String getColor(){
return this.color;
}
public void setColor(String color){
this.color=color;
}
public double getDistance(){
return p1.P2P(p2);
}
public void display(){
System.out.println("The line's color is:"+color);
System.out.println("The line's begin point's Coordinate is:");
p1.display();
System.out.println("The line's end point's Coordinate is:");
p2.display();
System.out.println("The line's length is:"+String.format("%.2f", getDistance()));
}
}
code2:
import java.util.Scanner;
public class Main {
public static boolean Check(double x){
return x > 0 && x <= 200;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
double x1,y1,x2,y2;
String color;
x1 = Double.parseDouble(in.next());
y1 = Double.parseDouble(in.next());
x2 = Double.parseDouble(in.next());
y2 = Double.parseDouble(in.next());
in.nextLine();
if(!Check(x1)||!Check(y1)||!Check(x2)||!Check(x2)||!Check(y2)){
System.out.println("Wrong Format");
return;
}
color = in.nextLine();
Element element;
element = new Point(x1,y1);
element.display();
element = new Point(x2,y2);
element.display();
element = new Line(new Point(x1,y1),new Point(x2,y2),color);
element.display();
element = new Plane(color);
element.display();
}
}
abstract class Element{
public void display(){
}
}
class Point extends Element{
double x,y;
public Point(){
}
public Point(double x,double y){
setX(x);
setY(y);
}
public double getX(){
return this.x;
}
public double P2P(Point p){
return Math.sqrt((p.x-x)*(p.x-x)+(p.y-y)*(p.y-y));
}
public void setX(double x){
this.x=x;
}
public double getY(){
return this.y;
}
public void setY(double y){
this.y=y;
}
public void display(){
System.out.println("("+String.format("%.2f", this.x)+","+String.format("%.2f", this.y)+")");
}
}
class Line extends Element{
Point p1,p2;
String color;
public Line(){
}
public Line(Point p1,Point p2,String color){
setP1(p1);
setP2(p2);
setColor(color);
}
public Point getP1(){
return this.p1;
}
public void setP1(Point p1){
this.p1=p1;
}
public Point getP2(){
return this.p2;
}
public void setP2(Point p2){
this.p2=p2;
}
public String getColor(){
return this.color;
}
public void setColor(String color){
this.color=color;
}
public double getDistance(){
return p1.P2P(p2);
}
public void display(){
System.out.println("The line's color is:"+color);
System.out.println("The line's begin point's Coordinate is:");
p1.display();
System.out.println("The line's end point's Coordinate is:");
p2.display();
System.out.println("The line's length is:"+String.format("%.2f", getDistance()));
}
}
class Plane extends Element{
String color;
public Plane(){
}
public Plane(String color){
setColor(color);
}
public String getColor(){
return this.color;
}
public void setColor(String color){
this.color=color;
}
public void display(){
System.out.println("The Plane's color is:"+this.color);
}
}
code3:
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static boolean Check(double x){
return x > 0 && x <= 200;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
double x1,y1,x2,y2;
String color;
Point p;
Line l;
Plane pl;
GeometryObject geometryObject = new GeometryObject();
int choice = Integer.parseInt(in.nextLine());
while(choice != 0) {
switch(choice) {
case 1:
x1 = Double.parseDouble(in.nextLine());
y1 = Double.parseDouble(in.nextLine());
p = new Point(x1,y1);
geometryObject.add(p);
break;
case 2:
x1 = Double.parseDouble(in.nextLine());
y1 = Double.parseDouble(in.nextLine());
x2 = Double.parseDouble(in.nextLine());
y2 = Double.parseDouble(in.nextLine());
color = in.nextLine();
l = new Line(new Point(x1,y1),new Point(x2,y2),color);
geometryObject.add(l);
break;
case 3:
color = in.nextLine();
pl = new Plane(color);
geometryObject.add(pl);
break;
case 4:
int index = Integer.parseInt(in.nextLine());
if(index>geometryObject.List.size())break;
geometryObject.remove(index-1);
}
choice = Integer.parseInt(in.nextLine());
}
for(Element e:geometryObject.List){
e.display();
}
}
}
abstract class Element{
public void display(){
}
}
class Point extends Element{
double x,y;
public Point(){
}
public Point(double x,double y){
setX(x);
setY(y);
}
public double getX(){
return this.x;
}
public double P2P(Point p){
return Math.sqrt((p.x-x)*(p.x-x)+(p.y-y)*(p.y-y));
}
public void setX(double x){
this.x=x;
}
public double getY(){
return this.y;
}
public void setY(double y){
this.y=y;
}
public void display(){
System.out.println("("+String.format("%.2f", this.x)+","+String.format("%.2f", this.y)+")");
}
}
class Line extends Element{
Point p1,p2;
String color;
public Line(){
}
public Line(Point p1,Point p2,String color){
setP1(p1);
setP2(p2);
setColor(color);
}
public Point getP1(){
return this.p1;
}
public void setP1(Point p1){
this.p1=p1;
}
public Point getP2(){
return this.p2;
}
public void setP2(Point p2){
this.p2=p2;
}
public String getColor(){
return this.color;
}
public void setColor(String color){
this.color=color;
}
public double getDistance(){
return p1.P2P(p2);
}
public void display(){
System.out.println("The line's color is:"+color);
System.out.println("The line's begin point's Coordinate is:");
p1.display();
System.out.println("The line's end point's Coordinate is:");
p2.display();
System.out.println("The line's length is:"+String.format("%.2f", getDistance()));
}
}
class Plane extends Element{
String color;
public Plane(){
}
public Plane(String color){
setColor(color);
}
public String getColor(){
return this.color;
}
public void setColor(String color){
this.color=color;
}
public void display(){
System.out.println("The Plane's color is:"+this.color);
}
}
class GeometryObject{
ArrayList<Element> List = new ArrayList<>();
public GeometryObject(){
}
public void add(Element element){
this.List.add(element);
}
public void remove(int index){
this.List.remove(index);
}
public ArrayList<Element> getList(){
return this.List;
}
}
复杂度分析
四边形:
五边形:
期中考试题:
4.踩坑心得
- 题干关于构成多边形的合法性条件看了好久都没理解,还是后面问了同学才总结出来一个通用的判断条件
- 考试的时候用Scanner类的nextLine方法读入无法处理数据与数据之间有多个空格或换行的情况,应该要用next方法来读入数据
5.改进建议
- 代码重构得还是有点乱,写博客的时候发现第三第四次作业的代码好像是完全独立的,没有继承的关系,到了第五次作业才涉及到
6.总结
- 这个系列最后涉及到好多计算几何的算法,急于完成作业没有对算法进行深入的探讨,之后抽空一定要好好学习一下相关的算法
- 设计类的属性、方法时没有考虑private和protected,全都是无脑public...