lmlin  

前言:

四边形的计算和五边形的计算确实很复杂,尤其是五边形,挺多测试点的,

其中如何判断四边形和五边形大同小异,判断它们的凹凸性方法同根同源。

都用面积法来做。其他的点,虽然做法相似,比如一条直线分割四边形或

五边形,分割面积按从小到大输出,但是五边形的情况远比四边形复杂的

多。

期中测试的话,难度不大,但需要速度与细心。考的是在点与线类的基础

上增加父类、抽象类等考点。问题不大

第四次大作业:

7-2 点线形系列4-凸四边形的计算

分数 70

作者 蔡轲
单位 南昌航空大学

用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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"。

输入格式:

基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。

输出格式:

基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
注意:输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0

选项1、2、3中,若四边形四个点中有重合点,输出"points coincide"。
选项4中,若前两个输入线的点重合,输出"points coincide"。

输入样例1:

选项1,点重合。例如:

1:-1,-1 -1,-1 1,2 1,-2
 

输出样例:

在这里给出相应的输出。例如:

points coincide
 

输入样例2:

不符合基本格式。例如:

1:-1,-1 1,2 -1,1 ++1,0
 

输出样例:

在这里给出相应的输出。例如:

Wrong Format
 

输入样例3:

选项1,输入点数量不对。例如:

1:-1,-1 -1,2 
 

输出样例:

在这里给出相应的输出。例如:

wrong number of points
 

输入样例4:

选项1,正确输入判断。例如:

1:-1,-1 -1,1 1,2 1,-2
 

输出样例:

在这里给出相应的输出。例如:

true false
 

输入样例5:

选项2,输入点不构成四边形。例如:

2:10,10 1,1 0,0 1,20
 

输出样例:

在这里给出相应的输出。例如:

not a quadrilateral
 

输入样例6:

选项2,正方形。例如:

2:0,0 0,80 80,80 80,0
 

输出样例:

在这里给出相应的输出。例如:

true true true
 

输入样例7:

选项2。例如:

2:0,0 -10,80 0,160 -10,80
 

输出样例:

在这里给出相应的输出。例如:

not a quadrilateral
 

输入样例8:

选项3,凸四边形。例如:

3:-1,-1 -1,1 1,2 1,-2
 

输出样例:

在这里给出相应的输出。例如:

true 10.472 6.0
 

输入样例9:

选项3,。例如:

3:0,0 -10,100 0,99 10,100
 

输出样例:

在这里给出相应的输出。例如:

false 221.097 990.0

设计与分析:

 我的代码:

  1 import java.util.*;
  2 import java.text.DecimalFormat;
  3 public class Main{
  4     //控制小数点
  5     public static void main(String[] args){
  6         //Point p1=new Point();
  7 
  8         Scanner input=new Scanner(System.in);
  9         String x=input.nextLine();//输入点
 10         String coor[]=x.split(" |[,]|[:]");//提出每个点的坐标x,y
 11         String coor1[]=x.split(" |,");
 12         String coor2[]=x.split(" |:");
 13         //判断格式是否合法,不合法则结束
 14         if(!x.matches("^[1-5][:](([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))[,]([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))\\s?)+$")){
 15             System.out.println("Wrong Format");
 16             return;
 17         }
 18 
 19     if(coor[0].equalsIgnoreCase("1")||coor[0].equalsIgnoreCase("2")||coor[0].equalsIgnoreCase("3")){
 20         if(coor.length!=9){
 21             System.out.println("wrong number of points");
 22                 return;
 23        }
 24     }
 25     if(coor[0].equalsIgnoreCase("4")){
 26         if(coor.length!=13){
 27             System.out.println("wrong number of points");
 28                 return;
 29        }
 30     }
 31     if(coor[0].equalsIgnoreCase("5")){
 32         if(coor.length!=11){
 33             System.out.println("wrong number of points");
 34                 return;
 35        }
 36     }
 37         double x1=Double.valueOf(coor[1]);
 38         double y1=Double.valueOf(coor[2]);
 39         double x2=Double.valueOf(coor[3]);
 40         double y2=Double.valueOf(coor[4]);
 41         double x3=Double.valueOf(coor[5]);
 42         double y3=Double.valueOf(coor[6]);
 43         double x4=Double.valueOf(coor[7]);
 44         double y4=Double.valueOf(coor[8]);
 45         Point a=new Point(x1,y1);
 46         Point b=new Point(x2,y2);
 47         Point c=new Point(x3,y3);
 48         Point d=new Point(x4,y4);
 49 //         Line l1=new Line(a,b);
 50 //         Line l2=new Line(b,c);
 51 //         Line l3=new Line(c,d);
 52 //         Line l4=new Line(d,a);
 53 //          Quadrilateral q = new Quadrilateral(a,b,c,d);
 54 if(coor[0].equalsIgnoreCase("1")){
 55     
 56     try{
 57         Quadrilateral q = new Quadrilateral(a,b,c,d);
 58         if(q.isCoincide()){
 59             System.out.println("points coincide");
 60         return;
 61         }
 62         System.out.printf("true %s\n",q.isParallelQuadrilateral());
 63         }catch (Exception e){
 64             if(e.getMessage().equals("not a quadrilateral"))
 65                 System.out.println("false false");
 66             else System.out.println(e.getMessage());
 67         }
 68 }
 69 
 70     
 71 if(coor[0].equalsIgnoreCase("2")){
 72 
 73     try{
 74         Quadrilateral q = new Quadrilateral(a,b,c,d);
 75         if(q.isCoincide()){
 76             System.out.println("points coincide");
 77             return;
 78         }
 79             System.out.printf("%s %s %s\n",q.isDiamond(),q.isRectangle(),q.isSquare());
 80         }catch (Exception e){
 81             System.out.println("not a quadrilateral");
 82         }
 83      }
 84         
 85         
 86 if(coor[0].equalsIgnoreCase("3")){
 87     try{
 88         Quadrilateral q = new Quadrilateral(a,b,c,d);
 89         if(q.isCoincide()){
 90             System.out.println("points coincide");
 91             return;
 92             }
 93              System.out.printf("%s ",q.isConvexQuadrilateral());
 94              change(q.sideLength());
 95              System.out.print(" ");
 96              change(q.area());       
 97             
 98             }catch (Exception e){
 99                 System.out.println(e.getMessage());
100             }
101 }
102      
103 if(coor[0].equalsIgnoreCase("4")){
104         double x5=Double.valueOf(coor[9]);
105         double y5=Double.valueOf(coor[10]);
106         double x6=Double.valueOf(coor[11]);
107         double y6=Double.valueOf(coor[12]);
108         Point f=new Point(x5,y5);
109         Point g=new Point(x6,y6);
110     Line l=null;
111             Quadrilateral q=null;
112             try{
113                 l=new Line(a,b);
114             }catch (Exception e){   //不构成直线
115                 System.out.println(e.getMessage());
116                 return;
117             }
118     try{
119         q = new Quadrilateral(c,d,f,g);
120         solve(l,q);
121         
122         return;
123     }catch (Exception e){   //可能构成三角形
124                 try{    //保证以下代码正确,捕获异常并吞并
125                   
126                     //以g号点作为顶点
127                     if(!c.isSameTo(f)){   //c,f点不重合
128                         Line ll = new Line(c,f);
129                         //d在ll之上,g在ll之外
130                         if(d.inLineSegment_close(ll) && !g.inLineSegment_close(ll)){
131                             Trianges tr = new Trianges(c,f,g);
132                             solve(l,tr);
133                             return;
134                         }
135                     }
136                     else{   //c,f点重合
137                         if(!c.isSameTo(d)){   //但是c,d点不重合
138                             Line ll = new Line(c,d);
139                             if(!g.inLineSegment_close(ll)){  //g点在ll线之外
140                                 Trianges tr = new Trianges(c,d,g);
141                                 solve(l,tr);
142                                 return;
143                             }
144                         }
145                     }
146                     //以c点作为顶点
147                     if(!d.isSameTo(g)){//d,g点不重合
148                         Line ll = new Line(d,g);
149                         if(f.inLineSegment_close(ll) && !c.inLine(ll)){
150                             Trianges tr = new Trianges(c,d,g);
151                             solve(l,tr);
152                             return;
153                         }
154                     }
155                     else{
156                         if(!d.isSameTo(f)){
157                             Line ll = new Line(d,f);
158                             if(!c.inLineSegment_close(ll)){
159                                 Trianges tr = new Trianges(c,d,f);
160                                 solve(l,tr);
161                                 return;
162                             }
163                         }
164                     }
165                     
166                     //以f点作为顶点
167                     if(!d.isSameTo(g)){
168                         Line ll = new Line(d,g);
169                         if(c.inLineSegment_close(ll) && !f.inLine(ll)){
170                             Trianges tr = new Trianges(d,f,g);
171                            
172                            solve(l,tr);
173                             return;
174                         }
175                     }
176                     else{
177                         if(!d.isSameTo(c)){
178                             Line ll = new Line(d,c);
179                             if(!f.inLineSegment_close(ll)){
180                                 Trianges tr = new Trianges(c,d,f);
181                                 solve(l,tr);
182                                 return;
183                             }
184                         }
185                     }
186                     //以d点作为顶点
187                     if(!c.isSameTo(f)){
188                         Line ll = new Line(c,f);
189                         if(g.inLineSegment_close(ll) && !d.inLine(ll)){
190                             Trianges tr = new Trianges(c,d,f);
191                             solve(l,tr);
192                             return;
193                         }
194                     }
195                     else{
196                         if(!g.isSameTo(f)){
197                             Line ll = new Line(g,f);
198                             if(!d.inLineSegment_close(ll)){
199                                 Trianges tr = new Trianges(f,d,g);
200                                 solve(l,tr);
201                                 return;
202                             }
203                         }
204                     }
205 
206 
207 
208                     //不构成三角形
209                     System.out.println("not a quadrilateral or triangle");
210 
211 
212                 }catch(Exception ee){}
213 
214 
215             }
216     
217     }
218 if(coor[0].equalsIgnoreCase("5")){
219        double x5=Double.valueOf(coor[9]);
220         double y5=Double.valueOf(coor[10]);
221         Point f=new Point(x5,y5);
222     try{
223         Quadrilateral q = new Quadrilateral(b,c,d,f);
224         int flag=q.isContainPoint(a);
225         if(flag==0)
226             System.out.println("in the quadrilateral");
227         else if(flag==1)
228             System.out.println("on the quadrilateral");
229         else
230             System.out.println("outof the quadrilateral");
231         return;
232      }catch(Exception e){    //不构成四边形,待确定是否构成三角形
233             try{    
234                 //以b点作为顶点
235                 if(!c.isSameTo(f)){   //c,f点不重合
236                     Line Lcf = new Line(c,f);
237                     if(d.inLineSegment_close(Lcf)&&!b.inLineSegment_close(Lcf)){ //d在Lcf之上,b在Lcf之外
238                         Trianges tr=new Trianges(b,c,f);
239                         isInTriangle(tr,a);
240                         return;
241                     }
242                 }
243                 else{
244                     //c,f点重合
245                     if(!d.isSameTo(c)){   //但是c,d点不重合
246                         Line Lcd = new Line(d,c);
247                         if(!b.inLineSegment_close(Lcd)){  //b点在Lcd线之外
248                             Trianges tr=new Trianges(b,c,d);
249                             isInTriangle(tr,a);
250                             return;
251                         }
252                     }
253                 }
254                  //以f点作为顶点
255                 if(!b.isSameTo(d)){   //b,d点不重合
256                     Line Lbd = new Line(b,d);
257                     if(c.inLineSegment_close(Lbd)&&!f.inLineSegment_close(Lbd)){ //c在Lbd之上,f在Lbd之外
258                         Trianges tr=new Trianges(b,d,f);
259                         isInTriangle(tr,a);
260                         return;
261                     }
262                 }
263                 else{
264                     //b,d点重合
265                     if(!b.isSameTo(c)){   //但是b,c点不重合
266                         Line Lbc = new Line(b,c);
267                         if(!f.inLineSegment_close(Lbc)){  //f点在Lbc线之外
268                             Trianges tr=new Trianges(b,c,f);
269                             isInTriangle(tr,a);
270                             return;
271                         }
272                     }
273                 }
274                  //以c点作为顶点
275                 if(!b.isSameTo(d)){   //b,d点不重合
276                     Line Lbd=new Line(b,d);
277                     if(f.inLineSegment_close(Lbd)&&!c.inLineSegment_close(Lbd)){ //f在Lbd之上,c在Lbd之外
278                         Trianges tr=new Trianges(b,c,d);
279                         isInTriangle(tr,a);
280                         return;
281                     }
282                 }
283                 else{
284                     //b,d点重合
285                     if(!f.isSameTo(d)){   //但是f,d点不重合
286                         Line Ldf=new Line(f,d);
287                         if(!c.inLineSegment_close(Ldf)){  //d点在Ldf线之外
288                             Trianges tr=new Trianges(f,c,d);
289                             isInTriangle(tr,a);
290                             return;
291                         }
292                     }
293                 }
294                  //以d点作为顶点
295                 if(!c.isSameTo(f)){   //c,f点不重合
296                     Line Lcf = new Line(c,f);
297                     if(b.inLineSegment_close(Lcf)&&!d.inLineSegment_close(Lcf)){ //d在Lbd之上,b在Lbd之外
298                         Trianges tr=new Trianges(d,c,f);
299                         isInTriangle(tr,a);
300                         return;
301                     }
302                 }
303                  else{
304                     //c,f点重合
305                     if(!b.isSameTo(c)){   //但是b,c点不重合
306                         Line Lbc=new Line(b,c);
307                         if(!d.inLineSegment_close(Lbc)){  //d点在Lbc线之外
308                             Trianges tr=new Trianges(b,c,d);
309                             isInTriangle(tr,a);
310                             return;
311                         }
312                     }
313                 }
314                 System.out.println("not a quadrilateral or triangle");
315             }catch(Exception ee){}
316 
317     }
318         
319 }
320     }
321     public static void change(double num){
322 //         if((num*1000)%10<0.0001)//这里不能写==0,double的精度问题
323 //             System.out.printf("%.1f",num);
324 //         else
325 //             System.out.printf("%.3f",num);
326     DecimalFormat d=new DecimalFormat();
327     String style="#.###";
328     d.applyPattern(style);
329     System.out.print(Double.parseDouble(d.format((Double)num)));
330         
331   }
332     public static void isInTriangle(Trianges tr,Point a){
333         int flag=tr.isContainPoint(a);
334         if(flag==0)
335             System.out.println("in the triangle");
336         else if(flag==1)
337             System.out.println("on the triangle");
338         else
339             System.out.println("outof the triangle");
340         return;
341     }
342     public static void pr_ans(Trianges t, Point a,Point b,Point c){
343         double[] ans = new double[2];
344         ans[0] = Trianges.area(a,b,c);
345         ans[1] = t.getArea() - ans[0];
346         Arrays.sort(ans);
347         System.out.printf("2 ");
348         change(ans[0]);
349         System.out.print(" ");
350         change(ans[1]);
351          System.out.println();
352     }
353     public static void pr_ans(Quadrilateral q,Point a,Point b,Point c){
354         double[] ans = new double[2];
355         ans[0] = Trianges.area(a,b,c);
356         ans[1] = q.area() - ans[0];
357         Arrays.sort(ans);
358         System.out.printf("2 ");
359         change(ans[0]);
360         System.out.print(" ");
361         change(ans[1]);  
362     }
363     
364     //三角形交点情况
365    public static void solve(Line l,Trianges t){
366        
367         //与任意一条边重合
368         if(l.isSameTo(t.L1) || l.isSameTo(t.L2) || l.isSameTo(t.L3)){
369         System.out.println("The line is coincide with one of the lines");
370         return;
371         }
372         
373         //与三条边的交点(值可能为null,即平行)
374         Point p_ab = l.getIntersection(t.L1);
375         Point p_ac = l.getIntersection(t.L3);
376         Point p_bc = l.getIntersection(t.L2);
377 
378 
379         //三交点是否位于边之内
380         boolean p_ab_in=false, p_ac_in =false, p_bc_in=false;
381         if(p_ab != null)  p_ab_in = p_ab.inLineSegment(t.L1);
382         if(p_ac != null)  p_ac_in = p_ac.inLineSegment(t.L3);
383         if(p_bc != null)  p_bc_in = p_bc.inLineSegment(t.L2);
384 
385 
386         //任一角在直线之上(特判三角形的角)
387         if(t.p1.inLine(l)){
388         //与另一条边无交点或者交点在边之外
389         if(p_bc == null || !p_bc.inLineSegment_close(t.L2)){
390         System.out.println("1");
391         }
392         else pr_ans(t,t.p1,t.p2,p_bc);
393         return;
394         }
395         if(t.p2.inLine(l)){
396         if(p_ac == null || !p_ac.inLineSegment_close(t.L3)){
397         System.out.println("1");
398         }
399         else pr_ans(t,t.p1,t.p2,p_ac);
400         return;
401         }
402         if(t.p3.inLine(l)){
403         if(p_ab == null || !p_ab.inLineSegment_close(t.L1)){
404         System.out.println("1");
405         }
406         else pr_ans(t,t.p1,t.p3,p_ab);
407         return;
408         }
409 
410         //两个交点
411         if(p_ab_in && p_bc_in){ pr_ans(t,t.p2,p_ab,p_bc);return;}
412         if(p_ab_in && p_ac_in){ pr_ans(t,t.p1,p_ab,p_ac);return;}
413         if(p_bc_in && p_ac_in){ pr_ans(t,t.p3,p_bc,p_ac);return;}
414         //无交点
415         System.out.println("0");
416 
417         }
418 
419         //四边形交点情况
420         public static void solve(Line l,Quadrilateral q){
421         //与任意一条边重合
422         if(l.isSameTo(q.l1)||l.isSameTo(q.l2)||l.isSameTo(q.l3)||l.isSameTo(q.l4)){
423         System.out.println("The line is coincide with one of the lines");
424         return;
425         }
426         //与四条边的交点,可能为null;
427         Point pt0 = l.getIntersection(q.l1);
428         Point pt1 = l.getIntersection(q.l2);
429         Point pt2 = l.getIntersection(q.l3);
430         Point pt3 = l.getIntersection(q.l4);
431 
432         //判断交点是否在边之上
433         boolean p0_in = false,p1_in = false,p2_in = false,p3_in = false;
434         if(pt0 != null) p0_in = pt0.inLineSegment(q.l1);
435         if(pt1 != null) p1_in = pt1.inLineSegment(q.l2);
436         if(pt2 != null) p2_in = pt2.inLineSegment(q.l3);
437         if(pt3 != null) p3_in = pt3.inLineSegment(q.l4);
438 
439         //任一角在直线l之上
440         if(q.p1.inLine(l)){
441         //它的对角也在边之上
442         if(q.p3.inLine(l)){
443         pr_ans(q,q.p1,q.p2,q.p3);
444         }
445         //对角的邻边任一与直线有交点
446         else if (p2_in){    //邻边之一
447         pr_ans(q,q.p1,pt2,q.p4);
448         }
449         else if (p1_in){    //邻边之二
450         pr_ans(q,q.p1,pt1,q.p2);
451         }
452         else{
453         System.out.println("1");
454         }
455         return;
456         }
457         else if(q.p2.inLine(l)){
458         //它的对角也在边之上
459         if(q.p4.inLine(l)){
460         pr_ans(q,q.p2,q.p3,q.p4);
461         }
462         //对角的邻边任一与直线有交点
463         else if (p2_in){    //邻边之一
464         pr_ans(q,q.p2,pt2,q.p3);
465         }
466         else if (p3_in){    //邻边之二
467         pr_ans(q,q.p2,pt3,q.p1);
468         }
469         else{
470         System.out.println("1");
471         }
472         return;
473         }
474         else if (q.p3.inLine(l)) {
475         //它的对角也在边之上
476         if(q.p1.inLine(l)){
477         pr_ans(q,q.p3,q.p4,q.p1);
478         }
479         //对角的邻边任一与直线有交点
480         else if (p3_in){    //邻边之一
481         pr_ans(q,q.p3,pt3,q.p4);
482         }
483         else if (p0_in){    //邻边之二
484         pr_ans(q,q.p3,pt0,q.p2);
485         }
486         else{
487         System.out.println("1");
488         }
489         return;
490         }
491         else if (q.p4.inLine(l)) {
492         //它的对角也在边之上
493         if(q.p2.inLine(l)){
494         pr_ans(q,q.p4,q.p1,q.p2);
495         }
496         //对角的邻边任一与直线有交点
497         else if (p0_in){    //邻边之一
498         pr_ans(q,q.p4,pt0,q.p1);
499         }
500         else if (p1_in){    //邻边之二
501         pr_ans(q,q.p4,pt1,q.p3);
502         }
503         else{
504         System.out.println("1");
505         }
506         return;
507         }
508 
509         //两个交点(邻边)
510         if(p0_in && p1_in){pr_ans(q,pt0,pt1,q.p2);return;}
511         if(p1_in && p2_in){pr_ans(q,pt1,pt2,q.p3);return;}
512         if(p2_in && p3_in){pr_ans(q,pt2,pt3,q.p4);return;}
513         if(p3_in && p0_in){pr_ans(q,pt3,pt0,q.p1);return;}
514         //对边
515         if(p0_in && p2_in){
516         double[] ans = new double[2];
517         ans[0] = Trianges.area(q.p1,pt0,pt2) + Trianges.area(pt0,pt2,q.p4);
518         ans[1] = Trianges.area(q.p2,pt0,pt2) + Trianges.area(pt0,pt2,q.p3);
519         Arrays.sort(ans);
520         System.out.printf("2 ");
521         change(ans[0]);
522         System.out.print(" ");
523         change(ans[1]);  
524         return;
525         }
526         if(p1_in && p3_in){
527         double[] ans = new double[2];
528         ans[0] = Trianges.area(q.p2,pt1,pt3) + Trianges.area(pt1,pt3,q.p1);
529         ans[1] = Trianges.area(q.p3,pt1,pt3) + Trianges.area(pt1,pt3,q.p4);
530         Arrays.sort(ans);
531        System.out.printf("2 ");
532         change(ans[0]);
533         System.out.print(" ");
534         change(ans[1]);  
535         return;
536         }
537         //0交点
538         System.out.println("0");
539 
540         }
541        
542 
543 
544 }
545 class Point{
546     double x;
547     double y;
548     public Point(){
549         this.x = 0;
550         this.y = 0;
551     }
552     public Point(double x,double y){
553         this.x=x;
554         this.y=y;
555     }
556     //斜率是否存在
557     public boolean vertical(Point b){
558         if((this.x==b.x)&&(this.y!=b.y))
559             return true;//不存在
560         else
561             return false;
562     }
563     //两点的斜率
564     public double getSlope(Point b){
565         return (this.y-b.y)/(this.x-b.x);
566     }
567     //两点坐标相同
568     public boolean isSameTo(Point a){
569         return (this.x == a.x)&&(this.y == a.y);
570     }
571     //计算两点距离
572     public double getDistance(Point b){
573         return Math.sqrt(Math.pow(b.x-this.x,2)+Math.pow(b.y-this.y,2));
574     }
575      //判断是否在直线之上
576     public boolean inLine(Line l){
577         return Math.abs(l.A*this.x + l.B*this.y + l.C) < 0.000001;
578     }
579     //判断是否在线段之内(包括端点)
580     public boolean inLineSegment_close(Line l){
581         if(!this.inLine(l)) 
582             return false;
583         else{
584         double res = this.getDistance(l.a) + this.getDistance(l.b)-l.GetLength();
585             return Math.abs(res) < 0.000001;
586         }
587     }
588     //判断是否在线段之内(不包括端点)
589     public boolean inLineSegment(Line l){
590         return this.inLineSegment_close(l) &&
591                 (!this.isSameTo(l.a)) &&
592                 (!this.isSameTo(l.b));
593     }
594 }
595 class Line{
596     Point a;
597     Point b;
598     double A,B,C;
599     public Line(Point m,Point n){
600         this.a=m;
601         this.b=n;
602        
603             this.A = this.b.y-this.a.y;
604             this.B = this.a.x-this.b.x;
605 //             this.C = this.b.x*this.a.y-this.a.x*this.b.y;
606             this.C = (-this.A*this.a.x-this.B*this.a.y);
607        
608 
609     }
610 
611     //斜率是否存在
612     public boolean vertical(){
613 
614         return (this.a.x != this.b.x) || (this.a.y == this.b.y);
615     }
616 
617     //线的斜率
618     public double getSlope(){
619         return (this.a.y-this.b.y)/(this.a.x-this.b.x);
620     }
621     //判断两直线是否平行
622     public boolean isParallelTo(Line l){
623         if(this.B==0 || l.B==0){
624             return (this.B == 0 && l.B == 0);
625         }
626         return ((this.A / this.B) == (l.A / l.B));
627     }
628     //判断两直线是否重合
629     public boolean isSameTo(Line another){
630         return this.isParallelTo(another) && (this.C==another.C);
631     }
632     //判断两直线是否垂直
633     public boolean isVerticalTo(Line another){
634          return this.A * another.A + this.B * another.B == 0;
635     }
636     //点到直线的距离
637     public double distance(Point a){
638         return Math.abs((this.a.y-this.b.y)*a.x+(this.b.x-this.a.x)*a.y+this.a.x*this.b.y-this.a.y*this.b.x)/Math.sqrt((this.a.y-this.b.y)*(this.a.y-this.b.y)+(this.a.x-this.b.x)*(this.a.x-this.b.x));
639     }
640     //判断三点是否一线
641     boolean threeline(Point c) {
642         return this.distance(c) == 0;
643     }
644 
645     //线段长度
646     public double GetLength(){
647         return Math.sqrt(Math.pow(this.b.x-this.a.x,2)+Math.pow(this.b.y-this.a.y,2));
648     }
649     //判断两线长度是否相等
650     public boolean isEqulength(Line l){
651         if(this.GetLength()==l.GetLength())
652             return true;
653         else
654             return false;
655     }
656     //求两条直线交点
657     public Point getIntersection(Line another){
658         if(this.isParallelTo(another)) return null;
659         Point res = new Point();
660         res.y = (another.A*this.C-this.A*another.C) / (this.A*another.B-another.A*this.B);
661         res.x = (this.B*another.C-another.B*this.C) / (this.A*another.B-another.A*this.B);
662         return res;
663     }
664     
665 
666 }
667 class Trianges
668 {
669     Point p1,p2,p3;
670     Line L1,L2,L3;
671     double J1,J2,J3;
672     public Trianges(Point point1,Point point2,Point point3)throws Exception
673     {
674         try{
675         this.p1 = point1;
676         this.p2 = point2;
677         this.p3 = point3;
678         this.L1 = new Line(point1,point2);
679         this.L2 = new Line(point2,point3);
680         this.L3 = new Line(point1,point3);
681         if(this.L1.isParallelTo(this.L2)){
682                 throw new Exception("not a triangle");
683             }
684         }catch(Exception e){
685             throw e;
686         }   
687     }
688     //是否等边三角形,返回(true/false)
689     public boolean isDengbian()    
690     {
691         return (this.L1.GetLength() == this.L2.GetLength()&&this.L2.GetLength() == this.L3.GetLength());
692     }
693     //是否等腰三角形,返回(true/false)
694     public boolean isDengyao()
695     {
696         return (this.L1.GetLength() == this.L2.GetLength()||this.L2.GetLength() == this.L3.GetLength()||this.L1.GetLength() == this.L3.GetLength());
697     }
698     //计算三角形周长,返回三角形周长(double)
699     public double getGirth()        
700     {
701         return (this.L1.GetLength()+this.L2.GetLength()+this.L3.GetLength());
702     }
703     //计算三角形面积,返回三角形面积(double)
704     public double getArea()            
705     {
706         return (this.L1.GetLength()*this.L1.distance(this.p3))/2;
707     }
708     //求三个点围成的图形面积(三点可能共线,面积为0)
709     public static double area(Point a,Point b,Point c){
710         double l1 = a.getDistance(b);
711         double l2 = b.getDistance(c);
712         double l3 = a.getDistance(c);
713         double p = (l1+l2+l3)/2;
714         return Math.sqrt(p*(p-l1)*(p-l2)*(p-l3));
715     }
716     //求三角形的重心,返回重心点(Points)
717     public Point getCenter()
718     {
719         Point Z = new Point((this.p1.x+this.p2.x+this.p3.x)/3,(this.p1.y+this.p2.y+this.p3.y)/3);
720         return Z;
721     }
722     //是否是钝角三角形,,返回(true/false)
723     public boolean isDunjiao()
724     {
725         double l12 = this.L1.GetLength()*this.L1.GetLength();
726         double l22 = this.L2.GetLength()*this.L2.GetLength();
727         double l32 = this.L3.GetLength()*this.L3.GetLength();
728         return ((l12+l22-l32+1e-6<0)||(l12+l32-l22+1e-6<0)||(l22+l32-l12+1e-6<0));
729     }
730     //是否是直角三角形,返回(true/false)
731     public boolean isZhijiao()
732     {
733         return (Math.abs(J1-90)<=1e-6||Math.abs(J2-90)<=1e-6||Math.abs(J3-90)<=1e-6);
734     }
735     //是否是锐角三角形,返回(true/false)
736     public boolean isRuijiao()
737     {
738         return (!(this.isDunjiao()||this.isZhijiao()));
739     }
740     //线是否与三角形的其中一条边重合
741     public boolean LineEquTriangesLine(Line l)
742     {
743         return ((L1.distance(l.a)==0&&L1.distance(l.b)==0)||(L2.distance(l.a)==0)&&L2.distance(l.b)==0||(L3.distance(l.a)==0&&L3.distance(l.b)==0));
744     }
745 
746     // 判断某点是否在三角形之内,(0内,1边,2外);
747     //面积法
748     public int isContainPoint(Point p){
749         //特判在边上的情况
750         if(p.inLineSegment_close(this.L1) || p.inLineSegment_close(this.L2)
751                 || p.inLineSegment_close(this.L3)){
752             return 1;
753         }
754         double a1 = Trianges.area(p,this.p1,this.p2);
755         double a2 = Trianges.area(p,this.p2,this.p3);
756         double a3 = Trianges.area(p,this.p3,this.p1);
757         double res = a1+a2+a3 - this.getArea();
758         if(Math.abs(res) < 0.000001) 
759             return 0;
760         return 2;
761     }
762 
763 }
764 class Quadrilateral{
765     Point p1,p2,p3,p4;
766     Line l1,l2,l3,l4,diagonaL1,diagonaL2;
767     public Quadrilateral(Point a,Point b,Point c,Point d)throws Exception{
768      try{
769         this.p1 = a;
770         this.p2 = b;
771         this.p3 = c;
772         this.p4 = d;
773         this.l1 = new Line(a,b);
774         this.l2 = new Line(b,c);
775         this.l3 = new Line(c,d);
776         this.l4 = new Line(d,a);
777         diagonaL1 = new Line(this.p1,this.p3);
778         diagonaL2 = new Line(this.p2,this.p4);
779         if(this.l1.isParallelTo(this.l2) || this.l1.isParallelTo(this.l4)){
780                 throw new Exception("not a quadrilateral");
781             }
782             if(this.l3.isParallelTo(this.l2) || this.l3.isParallelTo(this.l4)){
783                 throw new Exception("not a quadrilateral");
784             }
785             Point P1 = this.l1.getIntersection(this.l3);
786             Point P2 = this.l2.getIntersection(this.l4);
787             if(P1 != null && P1.inLineSegment_close(this.l1) && P1.inLineSegment_close(this.l3)) throw new Exception("not a quadrilateral");
788             if(P2 != null && P2.inLineSegment_close(this.l2) && P2.inLineSegment_close(this.l4)) throw new Exception("not a quadrilateral");
789         }catch (Exception e){
790             throw e;
791          }
792     }
793     //判断是否是四边形
794     public boolean isQuadrilateral1(){
795         if((this.l1.isParallelTo(this.l2))||(this.l2.isParallelTo(this.l3)))
796             return false;
797         else if((this.l3.isParallelTo(this.l4))||(this.l4.isParallelTo(this.l1)))
798             return false;
799         else
800             return true;
801     }
802     public boolean isQuadrilateral2(){
803         Point P1 = this.l1.getIntersection(this.l3);
804         Point P2 = this.l2.getIntersection(this.l4);
805         if(P1 != null && P1.inLineSegment_close(this.l1) && P1.inLineSegment_close(this.l3)) 
806             return false;
807         else if(P2 != null && P2.inLineSegment_close(this.l2) && P2.inLineSegment_close(this.l4)) 
808             return false;
809         else 
810             return true;
811     }
812     
813     //判断是否是平行四边形
814     public boolean isParallelQuadrilateral(){
815         if((this.l1.isParallelTo(this.l3))&&(this.l2.isParallelTo(this.l4)))
816             return true;
817         else
818             return false;
819     }
820     //判断是否为菱形(平行四边形 + 四边长度相等)
821     public boolean isDiamond(){
822         boolean H = this.l1.GetLength() == this.l2.GetLength()&&
823                 this.l2.GetLength() == this.l3.GetLength()&&
824                 this.l3.GetLength() == this.l4.GetLength();
825         return this.isParallelQuadrilateral() && H;
826     }
827     //判断是否是矩形
828     public boolean isRectangle(){
829         if(this.diagonaL1.isEqulength(this.diagonaL2))
830             return true;
831         else
832             return false;
833     }
834     //判断是否为正方形(菱形 + 矩形)
835     public boolean isSquare(){
836         return this.isDiamond() && this.isRectangle();
837     }
838     //判断四个点是否有重合
839     public boolean isCoincide(){
840         if((this.p1.x==this.p2.x)&&(this.p1.y==this.p2.y))
841             return true;
842         else if((this.p1.x==this.p3.x)&&(this.p1.y==this.p3.y))
843             return true;
844         else if((this.p1.x==this.p4.x)&&(this.p1.y==this.p4.y))
845             return true;
846         else if((this.p2.x==this.p3.x)&&(this.p2.y==this.p3.y))
847             return true;
848         else if((this.p2.x==this.p4.x)&&(this.p2.y==this.p4.y))
849             return true;
850         else if((this.p3.x==this.p4.x)&&(this.p3.y==this.p4.y))
851             return true;
852         else
853             return false;
854     }
855     //判断是否为凸四边形(面积公式)
856     public boolean isConvexQuadrilateral(){
857         double s1 = Trianges.area(p1,p2,p3);
858         double s2 = Trianges.area(p1,p3,p4);
859         double s3 = Trianges.area(p2,p4,p3);
860         double s4 = Trianges.area(p2,p4,p1);
861         double res = s1+s2-s3-s4;
862         return Math.abs(res) < 0.000001;
863     }
864     //四边形周长
865     public double sideLength(){
866         return this.l1.GetLength() + this.l2.GetLength() +this.l3.GetLength() +this.l4.GetLength();
867     }
868 
869     //四边形面积(切分为两个三角形)
870     public double area(){
871         double s1 = Trianges.area(this.p1, this.p2, this.p3);
872         double s2 = Trianges.area(this.p1, this.p3, this.p4);
873 
874 
875         double s3 = Trianges.area(this.p2, this.p4, this.p1);
876         double s4 = Trianges.area(this.p2, this.p4, this.p3);
877 
878 
879         return Math.min(s1+s2, s3+s4);
880     }
881 
882     //判断一个点是否落在(凸)四边形内部(0内,1边,2外)面积法
883     public int isContainPoint(Point p){
884         if(p.inLineSegment_close(this.l1) || p.inLineSegment_close(this.l2))
885             return 1;
886         else if(p.inLineSegment_close(this.l3) || p.inLineSegment_close(this.l4))
887             return 1;
888         else{
889         double s1 = Trianges.area(p,this.p1,this.p2);
890         double s2 = Trianges.area(p,this.p2,this.p3);
891         double s3 = Trianges.area(p,this.p3,this.p4);
892         double s4 = Trianges.area(p,this.p4,this.p1);
893         double res = s1+s2+s3+s4-this.area();
894         if(Math.abs(res) < 0.000001) 
895             return 0;
896         return 2;
897         }
898     }
899 
900 
901 }
View Code

圈复杂度分析图:

由上图可知:Max complexity(最大复杂度)过大,原因是某个函数(最复杂的函数)设计中if-else语句用的太多。还有Avg Depth过大,说明我的函数中分支嵌套的层数过多,导致平均其值过大。

踩坑心得:

(1)注意异常四边形、凹四边形和凸四边形。异常四边形:不相邻的两条边交叉(不算四边形哦,判断是否为四边形时候记得不要漏掉此情况)。凹凸四边形大家都认识,我就不说了,懂得都懂。

(2)判断凹凸四边形建议用面积法,就是用对角线分割成两个三角形求面积和,看两条对角线分割后求的四边形面积是否相等。相等为凸四边形,否则为凹四边形。

(3)判断输出第一个是否在后四个点所构成的四边形(限定为凸四边形,不考虑凹四边形)或三角形的内部。建议这里使用面积法。假设为m点,判断m分别与四边形的每条边组成的三角形面积之和是否等于该四边形。相等即在内部,否则在外部。前提是判断m点不在四边形上。

改进建议:

把那些if-else判断语句还是写成一个函数吧,太复杂了,减少圈复杂度。

 

第五次大作业:

7-1 点线形系列5-凸五边形的计算-1
分数 50
作者 蔡轲
单位 南昌航空大学

用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
1:输入五个点坐标,判断是否是五边形,判断结果输出true/false。
2:输入五个点坐标,判断是凹五边形(false)还是凸五边形(true),如果是凸五边形,则再输出五边形周长、面积,结果之间以一个英文空格符分隔。 若五个点坐标无法构成五边形,输出"not a pentagon"
3:输入七个点坐标,前两个点构成一条直线,后五个点构成一个凸五边形、凸四边形或凸三角形,输出直线与五边形、四边形或三角形相交的交点数量。如果交点有两个,再按面积从小到大输出被直线分割成两部分的面积(不换行)。若直线与多边形形的一条边线重合,输出"The line is coincide with one of the lines"。若后五个点不符合五边形输入,若前两点重合,输出"points coincide"。

以上3选项中,若输入的点无法构成多边形,则输出"not a polygon"。输入的五个点坐标可能存在冗余,假设多边形一条边上两个端点分别是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

输入格式:

基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。

输出格式:

基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
注意:输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0

输入样例1:

选项1,点重合。例如:

1:-1,-1 1,2 -1,1 1,0
 

输出样例:

在这里给出相应的输出。例如:

wrong number of points

之前的就不再重复写,主要贴出五边形的类和判断五边形的交点情况。

设计与分析:

这里我就不给全部代码了,太冗长了

五边形的类:

  1 class Pentagon{
  2     public Point[] p;
  3     public Point p1,p2,p3,p4,p5;
  4     public Line[] l;
  5     public Line l1,l2,l3,l4,l5;
  6 
  7      public  String message = "init";
  8      public Pentagon ( Point p1,Point p2,Point p3,Point p4,Point p5){
  9         this.p = new Point[5];
 10         this.l = new Line[5];
 11         this.p[0] = p1;
 12         this.p[1] = p2;
 13         this.p[2] = p3;
 14         this.p[3] = p4;
 15         this.p[4] = p5;
 16         this.l[0] = new Line(p1,p2);
 17         this.l[1] = new Line(p2,p3);
 18         this.l[2] = new Line(p3,p4);
 19         this.l[3] = new Line(p4,p5);
 20         this.l[4] = new Line(p5,p1);
 21         this.p1 = p1;
 22         this.p2 = p2;
 23         this.p3 = p3;
 24         this.p4 = p4;
 25         this.p5 = p5;
 26         this.l1 = new Line(p1,p2);
 27         this.l2 = new Line(p2,p3);
 28         this.l3 = new Line(p3,p4);
 29         this.l4 = new Line(p4,p5);
 30         this.l5 = new Line(p5,p1);
 31          
 32     }
 33     
 34     public boolean isxj(){
 35     Point P1 = this.l[0].getIntersection(this.l[2]);
 36     Point P2 = this.l[0].getIntersection(this.l[3]);
 37     Point P3 = this.l[1].getIntersection(this.l[3]);
 38     Point P4 = this.l[1].getIntersection(this.l[4]);
 39     Point P5 = this.l[2].getIntersection(this.l[4]);
 40     if(P1 != null && P1.inLineSegment_close(this.l[0]) && P1.inLineSegment_close(this.l[2])) 
 41         return true;
 42     else if(P2 != null && P2.inLineSegment_close(this.l[0]) && P2.inLineSegment_close(this.l[3])) 
 43         return true;
 44     else if(P3 != null && P3.inLineSegment_close(this.l[1]) && P3.inLineSegment_close(this.l[3])) 
 45         return true;
 46     else if(P4 != null && P4.inLineSegment_close(this.l[1]) && P1.inLineSegment_close(this.l[4])) 
 47         return true;
 48     else if(P5 != null && P5.inLineSegment_close(this.l[2]) && P1.inLineSegment_close(this.l[4])) 
 49         return true;
 50     else 
 51         return false;
 52     }
 53  public boolean isThree(){
 54     if(this.l[0].isParallelTo(this.l[1]) || this.l[1].isParallelTo(this.l[2])){
 55         return true;
 56     }
 57     else if(this.l[2].isParallelTo(this.l[3]) || this.l[3].isParallelTo(this.l[4])){
 58         return true;
 59     }
 60     else if(this.l[4].isParallelTo(this.l[0])){
 61          return true;
 62      }
 63     else
 64         return false;
 65 }
 66  public boolean isCoincide(){
 67         if((this.p[0].x==this.p[1].x)&&(this.p[0].y==this.p[1].y))
 68             return true;
 69         else if((this.p[0].x==this.p[2].x)&&(this.p[0].y==this.p[2].y))
 70             return true;
 71         else if((this.p[0].x==this.p[3].x)&&(this.p[0].y==this.p[3].y))
 72             return true;
 73         else if((this.p[0].x==this.p[4].x)&&(this.p[0].y==this.p[4].y))
 74             return true;
 75         else if((this.p[1].x==this.p[2].x)&&(this.p[1].y==this.p[2].y))
 76             return true;
 77         else if((this.p[1].x==this.p[3].x)&&(this.p[1].y==this.p[3].y))
 78             return true;
 79         else if((this.p[1].x==this.p[4].x)&&(this.p[1].y==this.p[4].y))
 80             return true;
 81         else if((this.p[2].x==this.p[3].x)&&(this.p[2].y==this.p[3].y))
 82             return true;
 83         else if((this.p[2].x==this.p[4].x)&&(this.p[2].y==this.p[4].y))
 84             return true;
 85         else if((this.p[3].x==this.p[4].x)&&(this.p[3].y==this.p[4].y))
 86             return true;
 87         else
 88             return false;
 89     }
 90 
 91 public boolean isPentagon(){
 92     if(this.isCoincide()){
 93        return false;
 94 }else{
 95     if(this.isThree()){
 96         return false;
 97     }else{
 98         if(this.isxj()){
 99         return false;
100         }else{
101         return true;
102         }
103     }
104 
105 }
106     
107 }
108   //判断是凹五边形还是凸五边形
109  public boolean checkConvex(){
110     int flag=0;
111     for(int i=0;i<4;){
112         if(l[i].Chacheng(l[i+1])>0){
113             i++;
114             flag++;
115         }else
116             flag=0;
117     }
118      if(l[4].Chacheng(l[1])>0)
119          flag++;
120      else
121          flag=0;
122      if(flag==0)
123            return false;
124      else 
125            return true;      
126            }
127     //判断是否为凸五边形(面积公式)
128     public boolean isConvexQuadrilateral(){
129         double s1 = Trianges.area(this.p[0], this.p[1], this.p[2]);
130         double s2 = Trianges.area(this.p[0], this.p[2], this.p[3]);
131         double s3 = Trianges.area(this.p[0], this.p[3], this.p[4]);
132         double s4 = Trianges.area(this.p[1], this.p[2], this.p[3]);
133         double s5 = Trianges.area(this.p[1], this.p[3], this.p[4]);
134         double s6 = Trianges.area(this.p[1], this.p[0], this.p[4]);
135         double res = s1+s2+s3-(s4+s5+s6);
136         return Math.abs(res) < 0.000001;
137     }
138   //五边形面积
139 public double area(){
140     double s1 = Trianges.area(this.p[0], this.p[1], this.p[2]);
141     double s2 = Trianges.area(this.p[0], this.p[2], this.p[3]);
142     double s3 = Trianges.area(this.p[0], this.p[3], this.p[4]);
143     return s1+s2+s3;
144 }
145     //五边形周长
146     public double sideLength(){
147         return this.l[0].GetLength() + this.l[1].GetLength() +this.l[2].GetLength() +this.l[3].GetLength()+this.l[4].GetLength();
148     }
149  
150 
151 }
View Code

判断五边形的交点情况的方法:

//五边形交点情况
   public static void solve(Line l,Pentagon q){
        //与任意一条边重合
        if(l.isSameTo(q.l1)||l.isSameTo(q.l2)||l.isSameTo(q.l3)||l.isSameTo(q.l4)||l.isSameTo(q.l5)){
        System.out.println("The line is coincide with one of the lines");
        return;
        }
        //与五条边的交点,可能为null;
        Point pt0 = l.getIntersection(q.l1);
        Point pt1 = l.getIntersection(q.l2);
        Point pt2 = l.getIntersection(q.l3);
        Point pt3 = l.getIntersection(q.l4);
        Point pt4 = l.getIntersection(q.l5);
        //判断交点是否在边之上
        boolean p0_in = false,p1_in = false,p2_in = false,p3_in = false,p4_in = false;
        if(pt0 != null) p0_in = pt0.inLineSegment(q.l1);
        if(pt1 != null) p1_in = pt1.inLineSegment(q.l2);
        if(pt2 != null) p2_in = pt2.inLineSegment(q.l3);
        if(pt3 != null) p3_in = pt3.inLineSegment(q.l4);
        if(pt4 != null) p4_in = pt4.inLineSegment(q.l5);
       
        //任一角在直线l之上
        if(q.p1.inLine(l)){
        //它的不相邻对角也在边之上
        if(q.p3.inLine(l)){
        pr_ans(q,q.p1,q.p2,q.p3);
        }
        //它的另不相邻对角也在边之上
        else if(q.p4.inLine(l)){
        pr_ans(q,q.p1,q.p4,q.p5);
        }    
        //对角的邻边任一与直线有交点
        else if (p3_in){    //邻边之一
        pr_ans(q,q.p1,pt3,q.p5);
        }
        else if (p1_in){    //邻边之二
        pr_ans(q,q.p1,pt1,q.p2);
        }
        else if (p2_in){    //对边
        double[] ans = new double[2];
        ans[0]=Trianges.area(q.p1,q.p2,q.p3)+Trianges.area(q.p1,pt2,q.p3);
        ans[1] = q.area() - ans[0];
        Arrays.sort(ans);
        System.out.printf("2 ");
        change(ans[0]);
        System.out.print(" ");
        change(ans[1]);  
        
//         pr_ans(q,q.p1,pt2,q.p3);
//         pr_ans(q,q.p1,q.p3,q.p2);
        }
        else{
        System.out.println("1");
        }
        return;
        }
        else if(q.p2.inLine(l)){
        //它的对角也在边之上
        if(q.p4.inLine(l)){
        pr_ans(q,q.p2,q.p3,q.p4);
        }
        //它的另一不相邻对角也在边之上
        else if(q.p5.inLine(l)){
        pr_ans(q,q.p2,q.p4,q.p5);
        }    
        //对角的邻边任一与直线有交点
        else if (p2_in){    //邻边之一
        pr_ans(q,q.p2,pt2,q.p3);
        }
        else if (p4_in){    //邻边之二
        pr_ans(q,q.p2,pt4,q.p1);
        }
        else if (p3_in){    //对边
        double[] ans = new double[2];
        ans[0]=Trianges.area(q.p2,q.p3,q.p4)+Trianges.area(q.p2,pt3,q.p4);
        ans[1] = q.area() - ans[0];
        Arrays.sort(ans);
        System.out.printf("2 ");
        change(ans[0]);
        System.out.print(" ");
        change(ans[1]);  
        }
        else{
        System.out.println("1");
        }
        return;
        }
        else if (q.p3.inLine(l)) {
        //它的对角也在边之上
        if(q.p1.inLine(l)){
        pr_ans(q,q.p3,q.p2,q.p1);
        }
        //它的另一不相邻对角也在边之上
        else if(q.p5.inLine(l)){
        pr_ans(q,q.p3,q.p4,q.p5);
        }    
        //对角的邻边任一与直线有交点
        else if (p3_in){    //邻边之一
        pr_ans(q,q.p3,pt3,q.p4);
        }
        else if (p0_in){    //邻边之二
        pr_ans(q,q.p3,pt0,q.p2);
        }
        else if (p4_in){    //对边
        double[] ans = new double[2];
        ans[0]=Trianges.area(q.p3,q.p4,q.p5)+Trianges.area(q.p3,pt4,q.p5);
        ans[1] = q.area() - ans[0];
        Arrays.sort(ans);
        System.out.printf("2 ");
        change(ans[0]);
        System.out.print(" ");
        change(ans[1]);  
        }
        else{
        System.out.println("1");
        }
        return;
        }
        else if (q.p4.inLine(l)) {
        //它的对角也在边之上
        if(q.p2.inLine(l)){
        pr_ans(q,q.p4,q.p3,q.p2);
        }
        //它的另一不相邻对角也在边之上
        else if(q.p1.inLine(l)){
        pr_ans(q,q.p4,q.p5,q.p1);
        }    
        //对角的邻边任一与直线有交点
        else if (p4_in){    //邻边之一
        pr_ans(q,q.p4,pt4,q.p5);
        }
        else if (p1_in){    //邻边之二
        pr_ans(q,q.p4,pt1,q.p3);
        }
        else if (p0_in){    //对边
        double[] ans = new double[2];
        ans[0]=Trianges.area(q.p4,q.p5,q.p1)+Trianges.area(q.p4,pt0,q.p1);
        ans[1] = q.area() - ans[0];
        Arrays.sort(ans);
        System.out.printf("2 ");
        change(ans[0]);
        System.out.print(" ");
        change(ans[1]);  
        }
        else{
        System.out.println("1");
        }
        return;
        }
        else if (q.p5.inLine(l)) {
        //它的对角也在边之上
        if(q.p3.inLine(l)){
        pr_ans(q,q.p5,q.p4,q.p3);
        }
        //它的另一不相邻对角也在边之上
        else if(q.p2.inLine(l)){
        pr_ans(q,q.p5,q.p1,q.p2);
        }    
        //对角的邻边任一与直线有交点
        else if (p0_in){    //邻边之一
        pr_ans(q,q.p5,pt0,q.p1);
        }
        else if (p2_in){    //邻边之二
        pr_ans(q,q.p5,pt2,q.p4);
        }
        else if (p1_in){    //对边
        double[] ans = new double[2];
        ans[0]=Trianges.area(q.p5,q.p1,q.p2)+Trianges.area(q.p5,pt1,q.p2);
        ans[1] = q.area() - ans[0];
        Arrays.sort(ans);
        System.out.printf("2 ");
        change(ans[0]);
        System.out.print(" ");
        change(ans[1]);  
        }
        else{
        System.out.println("1");
        }
        return;
        }
       
        //两个交点(邻边)
        if(p0_in && p1_in){pr_ans(q,pt0,pt1,q.p2);return;}
        if(p1_in && p2_in){pr_ans(q,pt1,pt2,q.p3);return;}
        if(p2_in && p3_in){pr_ans(q,pt2,pt3,q.p4);return;}
        if(p3_in && p4_in){pr_ans(q,pt3,pt4,q.p5);return;}
        if(p4_in && p0_in){pr_ans(q,pt4,pt0,q.p1);return;}
        //对边
        if(p0_in && p2_in){
        double[] ans = new double[2];
        ans[0] = Trianges.area(q.p3,pt0,pt2) + Trianges.area(pt0,q.p2,q.p3);
        ans[1] = q.area() - ans[0];
        Arrays.sort(ans);
        System.out.printf("2 ");
        change(ans[0]);
        System.out.print(" ");
        change(ans[1]);  
        return;
        }
        if(p0_in && p3_in){
        double[] ans = new double[2];
        ans[0] = Trianges.area(q.p5,pt0,pt3) + Trianges.area(pt0,q.p1,q.p5);
        ans[1] = q.area() - ans[0];
        Arrays.sort(ans);
        System.out.printf("2 ");
        change(ans[0]);
        System.out.print(" ");
        change(ans[1]);  
        return;
        }
        if(p1_in && p3_in){
        double[] ans = new double[2];
        ans[0] = Trianges.area(q.p4,pt1,pt3) + Trianges.area(pt1,q.p3,q.p4);
        ans[1] = q.area() - ans[0];
        Arrays.sort(ans);
        System.out.printf("2 ");
        change(ans[0]);
        System.out.print(" ");
        change(ans[1]);  
        return;
        }
        if(p1_in && p4_in){
        double[] ans = new double[2];
        ans[0] = Trianges.area(q.p1,pt1,pt4) + Trianges.area(pt1,q.p1,q.p2);
        ans[1] = q.area() - ans[0];
        Arrays.sort(ans);
        System.out.printf("2 ");
        change(ans[0]);
        System.out.print(" ");
        change(ans[1]);  
        return;
        }
        if(p2_in && p4_in){
        double[] ans = new double[2];
        ans[0] = Trianges.area(q.p5,pt2,pt4) + Trianges.area(pt2,q.p5,q.p4);
        ans[1] = q.area() - ans[0];
        Arrays.sort(ans);
        System.out.printf("2 ");
        change(ans[0]);
        System.out.print(" ");
        change(ans[1]);  
        return;
        }
        //0交点
        System.out.println("0");

        }
       
View Code

 圈复杂度分析图:

 

 

 由上图可知:Avg Depth过大,很大的原因是部分函数中if-else语句(分支嵌套层数)用的太多。而Avg Stmts/Method过大,说明我的函数有部分语句过多,导致平均每个函数包含的语句数过大。 

踩坑心得:

这道题很难,我是菜狗,我没做出来,部分正确。判断凹凸四边形建议用面积法。

(1)注意异常五边形、凹四边形和凸四边形。非五边形的情况:异常五边形:不相邻的两条边交叉、三点共线、任意两点重合。

(2)判断凹凸五边形建议用面积法,就是选定任意两个顶点分别将五边形分割成三个三角形求面积和,看二者分割后求的五边形面积是否相等。相等为凸五边形,否则为凹五边形。

(3)判断输出第一个是否在后五个点所构成的四边形(限定为凸五边形,不考虑凹五边形)或三角形的内部。建议这里使用面积法。假设为m点,判断m分别与四边形的每条边组成的三角形面积之和是否等于该四边形。相等即在内部,否则在外部。前提是判断m点不在四边形上。

改进建议:

同上一题一样,把那些if-else判断语句还是写成一个函数吧,太复杂了,减少圈复杂度。

7-2 点线形系列5-凸五边形的计算-2

分数 50
作者 蔡轲
单位 南昌航空大学

用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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/ pentagon

5:输入十个点坐标,前、后五个点分别构成一个凸多边形(三角形、四边形、五边形),输出两个多边形公共区域的面积。注:只考虑每个多边形被另一个多边形分割成最多两个部分的情况,不考虑一个多边形将另一个分割成超过两个区域的情况。
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

输入格式:

基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。

输出格式:

输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0

输入样例:

在这里给出一组输入。例如:

4:0,0 6,0 7,1 8,3 6,6 0,0 6,0 7,1 8,3 6,6
 

输出样例:

在这里给出相应的输出。例如:

the previous pentagon coincides with the following pentagon

设计与分析:

父类:Grahical类

  1 class Graphical {
  2     public int len=0,status=1;    //多边形边数,状态
  3     public Point[] points;
  4     public Line[] lines;
  5     public double sideLength = 0,area = 0;   //边长,面积
  6     public boolean isConvexGraphical = true;
  7     public  String message = "init"; //信息
  8 
  9     public Graphical(Point[] points){
 10         this.points = new Point[points.length];
 11 
 12         points = this.removeMulti(points);  //去除重复点
 13         if(points.length <=2 ){
 14             this.status = -1;
 15             this.message = "Not enough points";
 16             return;
 17         }
 18 
 19         //相邻边夹角0则去除中间点,夹角180则status:-1
 20         for(int i=0;i<points.length;i++){
 21             int first = i , second = (i+1)%points.length, third = (i+2)%points.length;
 22             try{
 23                 Line l1 = new Line(points[first],points[second]);
 24                 Line l2 = new Line(points[second],points[third]);
 25                 if( Math.abs(l1.vectorAngle(l2) - Math.PI) < 0.000001 ){    //夹角180
 26                     this.status = -1;
 27                     this.message = "lines reverse coincidence";
 28                     return;
 29                 }
 30                 else if(Math.abs(l1.vectorAngle(l2)) > 0.000001){   //夹角不为0
 31                     this.points[this.len++] = points[second].deepCopy();
 32                 }
 33             }catch (Exception e){}
 34         }
 35 
 36         this.points = Arrays.copyOf(this.points,this.len);
 37         this.lines = new Line[this.len];
 38 
 39         //初始化边
 40         for(int i=0;i<this.len;i++){
 41             try {
 42                 int first = i, second = (i+1)%this.len;
 43                 this.lines[i] = new Line(this.points[first], this.points[second]);
 44             }catch (Exception e){}
 45         }
 46 
 47         //判断任意不相邻边(线段交点)是否有交点
 48         checkEdge();
 49 
 50         Graphical.area(this);
 51         Graphical.sideLength(this);
 52         Graphical.checkConvex(this);
 53     }
 54     public void print(){
 55         if(this.status == -1){
 56             System.out.println(this.message);
 57             return;
 58         }
 59         System.out.println("点数为:"+this.len);
 60         for(int i=0;i<this.len;i++){
 61             this.points[i].print();
 62         }
 63         for(int i=0;i<this.len;i++){
 64             this.lines[i].print();
 65         }
 66         System.out.println("周长为:"+this.sideLength);
 67         System.out.println("面积为:"+this.area);
 68         System.out.println("凹凸性:"+this.isConvexGraphical);
 69     }
 70     //判断图形是否包含某个点返回值-1,0,1 (内部,边缘,外部)
 71     //由于只考虑凸多边形,用面积法就行
 72     public int isContainPoint(Point p){
 73         for(int i=0;i<this.len;i++){    //位于边之上
 74             if(p.inLineSegment_close(this.lines[i])) return 0;
 75         }
 76 
 77         double s = 0;
 78         for(int i=0;i<this.len;i++){
 79             s += Triangle.area(p,this.points[i], this.points[(i+1)%this.len]);
 80         }
 81         return Math.abs(s-this.area) < 0.000001 ? -1:1;
 82     }
 83     //判断两个图形类之间的关系()
 84     public String relationshipWith(Graphical g){
 85         String[] name = new String[]{"triangle", "quadrilateral", "pentagon"};
 86         //分离
 87         if(this.isSeparatedFrom(g)){
 88             return "no overlapping area between the previous "+name[this.len-3]+ " and the following "+name[g.len-3];
 89         }
 90         //完全重合
 91         if(this.isSameTo(g))
 92             return "the previous "+name[this.len-3]+ " coincides with the following "+name[g.len-3];
 93         //包含
 94         if(this.isContainGra(g)){
 95             return "the previous "+name[this.len-3]+ " contains the following "+name[g.len-3];
 96         }
 97         //被包含
 98         if(g.isContainGra(this)){
 99             return "the previous "+name[this.len-3]+ " is inside the following "+name[g.len-3];
100         }
101 
102         //连接
103         if(this.overlappingArea(g) == 0){
104             return "the previous "+name[this.len-3]+ " is connected to the following "+name[g.len-3];
105         }
106 
107         //交错
108         return "the previous "+name[this.len-3]+ " is interlaced with the following "+name[g.len-3];
109 
110     }
111 
112     //判断和另一个图形完全分离(重叠面积为0,并且任意点都在this之外)
113     public boolean isSeparatedFrom(Graphical g){
114         boolean ok = true;
115         int[] check2 = new int[g.len];
116         for(int i=0;i<g.len;i++){
117             check2[i] = this.isContainPoint(g.points[i]);
118         }
119         for(int item:check2){
120             if(item != 1) ok = false;
121         }
122         if(this.overlappingArea(g) !=0) ok = false;
123         return ok;
124     }
125     //判断完全包含另一个图形(任意点都在this之内)
126     public boolean isContainGra(Graphical g){
127         boolean ok = true;
128         int[] check2 = new int[g.len];
129         for(int i=0;i<g.len;i++){
130             check2[i] = this.isContainPoint(g.points[i]);
131         }
132         for(int item:check2){
133             if(item == 1) ok = false;
134         }
135         return ok;
136     }
137 
138     //判断两个图形是否一模一样(点完全重合)
139     public boolean isSameTo(Graphical g){
140         if(this.len != g.len) return false;
141         for(int i=0;i<this.len;i++){
142             boolean ok = false;
143             for(int j=0;j<g.len;j++){
144                 if(this.points[i].isSameTo(g.points[j])) ok = true;
145             }
146             if(!ok) return false;
147         }
148         return true;
149     }
150 
151     //计算两个图形的重叠面积(交点加内部顶点构成重叠多边形)
152     public double overlappingArea(Graphical g){
153         Point[] intersection = new Point[100];
154         int intersection_len = 0;
155 
156 
157         for(Line item1:this.lines){   //求出两多边形的交点
158             for(Line item2: g.lines){
159                 Point tmp = item1.lsi(item2);
160                 if(tmp != null){
161                     intersection[intersection_len++] = tmp.deepCopy();
162                 }
163             }
164         }
165 
166 
167         for(Point item:g.points){   //顶点包含在内部
168             if(this.isContainPoint(item) == -1) intersection[intersection_len++] = item.deepCopy();
169         }
170         for(Point item:this.points){   //顶点包含在内部
171             if(g.isContainPoint(item) == -1) intersection[intersection_len++] = item.deepCopy();
172         }
173 
174         //if(intersection_len == 0) return 0;    //交点为0,分离
175         //-2分
176 
177         /*排序交点数组*/
178         intersection = Arrays.copyOf(intersection,intersection_len);
179         intersection = this.removeMulti(intersection);
180         Point focus = Point.focusPoint(intersection);
181         Point sta = intersection[0].deepCopy();
182 
183         Arrays.sort(intersection,1,intersection.length, new Comparator<Point>()  {
184             @Override
185             public int compare(Point o1, Point o2) {
186                 try{
187                     Line origin =new Line(focus,sta);
188                     Line l1 = new Line(focus,o1);
189                     Line l2 = new Line(focus,o2);
190                     double angle1 = origin.vectorAngle(l1);
191                     double angle2 = origin.vectorAngle(l2);
192                     if(origin.vectorCrossMul(l1) < 0) angle1 = 2*Math.PI - angle1;
193                     if(origin.vectorCrossMul(l2) < 0) angle2 = 2*Math.PI - angle2;
194                     if(angle1-angle2 > 0.000001) return 1;
195                     if(Math.abs(angle1-angle2) < 0.000001) return 0;
196                     return -1;
197                 }catch (Exception reason){}
198                 return 0;
199             }
200         });
201 
202         Graphical graphical = new Graphical(intersection);
203         return  graphical.area;
204 
205     }
206 
207     //去除所有重复点
208     private Point[] removeMulti(Point[] points){
209         Point[] tmp_points = new Point[points.length];
210         int tmp_len = 0;
211 
212         for(int i=0;i<points.length;i++){
213             boolean ok = true;
214             for(int j=0;j<tmp_len;j++){
215                 if(points[i].isSameTo(tmp_points[j])){
216                     this.message = "points coincide";
217                     ok = false;
218                     break;
219                 }
220             }
221             if(ok) tmp_points[tmp_len++] = points[i].deepCopy();
222         }
223         return Arrays.copyOf(tmp_points,tmp_len);
224     }
225     //判断不相邻边是否有交点
226     private void checkEdge(){
227         for(int i=0;i<this.len;i++){
228             for(int j=i+2;j<this.len;j++){
229                 if(i==0&&j==this.len-1) continue;
230                 Point p = this.lines[i].getIntersection(this.lines[j]);
231                 if(p==null) continue;
232 
233                 if(p.inLineSegment_close(this.lines[i]) && p.inLineSegment_close(this.lines[j])){
234                     this.status = -1;
235                     this.message = "Non adjacent edges have intersections";
236                     return;
237                 }
238             }
239         }
240     }
241     //多边形面积
242     private static void area(Graphical e){
243         double res = 0;
244         Point origin = new Point(0,0);
245         for(int i=0;i<e.len;i++){
246             try{
247                 Line l1 = new Line(origin,e.points[i]);
248                 Line l2 = new Line(origin,e.points[(i+1)%e.len]);
249                 res += 0.5 * l1.vectorCrossMul(l2);
250             }catch (Exception reason){}
251 
252         }
253         e.area = Math.abs(res);
254     }
255     //多边形周长
256     private static void sideLength(Graphical e){
257         double res = 0;
258         for(int i=0;i<e.len;i++){
259             res += e.points[i].disToPoint(e.points[(i+1)%e.len]);
260         }
261         e.sideLength = res;
262     }
263     //多边形凹凸性
264     private static void checkConvex(Graphical e){
265         if(e.len == 3) return;
266         int v = 0;
267         for(int i=0;i<e.len;i++){
268             int first = i, second = (i+1)%e.len, thrid = (i+2)%e.len;
269             try{
270                 Line l1 = new Line(e.points[first], e.points[second]);
271                 Line l2 = new Line(e.points[first], e.points[thrid]);
272                 if(v==0){
273                     if(l1.vectorCrossMul(l2) > 0) v = 1;
274                     else v = -1;
275                 }
276                 if(v == 1 && l1.vectorCrossMul(l2) < 0) e.isConvexGraphical = false;
277                 if(v == -1 && l1.vectorCrossMul(l2) > 0) e.isConvexGraphical = false;
278             }catch (Exception reason){}
279         }
280     }
281     //是否一样
282 
283 }
View Code

 圈复杂度分析图:

 

 

 由上图可知:Max complexity(最大复杂度)过大,原因是某个函数(最复杂的函数)设计中if-else语句用的太多。不用说,这几道题我都是if-else语句过多,真是头大,能力不够。

踩坑心得:

这道题很难,我是菜狗,我没做出来,部分正确。

(1)判断输出第一个是否在后五个点所构成的四边形(限定为凸五边形,不考虑凹五边形)或四边形或三角形的内部。判断是否在五边形内部建议这里使用面积法。假设为m点,判断m分别与五边形的每条边组成的三角形面积之和是否等于该五边形。相等即在内部,否则在外部。前提是判断m点不在五边形上。

改进建议:

没写完,速度太慢了,下次写快点。嵌套层次太多了,想办法改进吧。还是多用用类吧。

 

7-1 点与线(类设计)

分数 20
作者 段喜龙
单位 南昌航空大学
  • 设计一个类表示平面直角坐标系上的点Point,私有属性分别为横坐标x与纵坐标y,数据类型均为实型数,除构造方法以及属性的getter与setter方法外,定义一个用于显示信息的方法display(),用来输出该坐标点的坐标信息,格式如下:(x,y),数值保留两位小数。为简化题目,其中,坐标点的取值范围设定为(0,200]。若输入有误,系统则直接输出Wrong Format

  • 设计一个类表示平面直角坐标系上的线Line,私有属性除了标识线段两端的点point1、point2外,还有一个字符串类型的color,用于表示该线段的颜色,同样,除构造方法以及属性的getter与setter方法外,定义一个用于计算该线段长度的方法getDistance(),还有一个用于显示信息的方法display(),用来输出线段的相关信息,输出格式如下:

      ```
          The line's color is:颜色值
          The line's begin point's Coordinate is:
          (x1,y1)
          The line's end point's Coordinate is:
          (x2,y2)
          The line's length is:长度值
      ```
    
     

    其中,所有数值均保留两位小数,建议可用String.format("%.2f", data)方法。

      设计类图如下图所示。
    
     

1641304523(1).jpg

** 题目要求:在主方法中定义一条线段对象,从键盘输入该线段的起点坐标与终点坐标以及颜色,然后调用该线段的display()方法进行输出。**

  • 以下情况为无效作业
    • 无法运行
    • 设计不符合所给类图要求
    • 未通过任何测试点测试
    • 判定为抄袭

输入格式:

分别输入线段的起点横坐标、纵坐标、终点的横坐标、纵坐标以及颜色,中间可用一个或多个空格、tab或者回车分隔。

输出格式:

The line's color is:颜色值
The line's begin point's Coordinate is:
(x1,y1)
The line's end point's Coordinate is:
(x2,y2)
The line's length is:长度值
 

输入样例1:

在这里给出一组输入。例如:

5
9.4
12.3
84
Red
 

输出样例1:

在这里给出相应的输出。例如:

The line's color is:Red
The line's begin point's Coordinate is:
(5.00,9.40)
The line's end point's Coordinate is:
(12.30,84.00)
The line's length is:74.96
 

输入样例2:

在这里给出一组输入。例如:

80.2356
352.12
24.5
100
Black
 

输出样例2:

在这里给出相应的输出。例如:

Wrong Format

我的代码:

  1 import java.util.*;
  2 import java.text.DecimalFormat;
  3 public class Main{
  4     //控制小数点
  5     public static void main(String[] args){
  6         //Point p1=new Point();
  7 
  8         Scanner input=new Scanner(System.in);
  9         double x1=input.nextDouble();
 10         double y1=input.nextDouble();
 11         double x2=input.nextDouble();
 12         double y2=input.nextDouble();
 13         String color=input.next();
 14         Point p1=new Point(x1,y1);
 15         Point p2=new Point(x2,y2);
 16         Line L=new Line(p1,p2,color);
 17         if((x1<=0||x1>200)||(y1<=0||y1>200)||(x2<=0||x2>200)||(y2<=0||y2>200)){
 18             System.out.println("Wrong Format");
 19             return;
 20         }
 21         else{
 22             L.display();
 23         }
 24         
 25     }
 26 }
 27 class Point{
 28     private double x;
 29     private double y;
 30     public Point(){
 31         this.x = 0;
 32         this.y = 0;
 33     }
 34     public Point(double x,double y){
 35         this.x=x;
 36         this.y=y;
 37     }
 38     public double getX(){
 39         return this.x;
 40     }
 41     public void setX(double x){
 42         this.x=x;
 43     }
 44      public double getY(){
 45         return this.y;
 46     }
 47     public void setY(double y){
 48         this.x=y;
 49     }
 50     public void display(){
 51           System.out.print("(");
 52           System.out.printf("%.2f",this.x);
 53           System.out.print(",");
 54           System.out.printf("%.2f",this.y);
 55           System.out.println(")");
 56       }
 57 }
 58 class Line{
 59     private Point point1;
 60     private Point point2;
 61     String color;
 62     public Line(){
 63         this.point1=point1;
 64         this.point2=point2;
 65         this.color="";
 66     }
 67     public Line(Point point1,Point point2,String color){
 68         this.point1=point1;
 69         this.point2=point2;
 70         this.color=color;
 71     }
 72     public Point getPoint1() {
 73           return point1;
 74       }
 75       public void setPoint1(Point point1) {
 76           this.point1=point1;
 77       }
 78       public Point getPoint2() {
 79           return point2;
 80       }
 81       public void setPoint2(Point point2) {
 82           this.point2=point2;
 83       }
 84       public String getColor() {
 85           return color;
 86       }
 87       public void setColor(String color) {
 88           this.color=color;
 89       }
 90     //线段长度
 91       public double getDistance(){ 
 92           return Math.sqrt(Math.pow(this.point2.getX()-this.point1.getX(),2)+Math.pow(this.point2.getY()-this.point1.getY(),2));
 93     }
 94     public void display(){
 95           System.out.println("The line's color is:"+this.color);
 96           System.out.println("The line's begin point's Coordinate is:");
 97           this.point1.display();
 98           System.out.println("The line's end point's Coordinate is:");
 99           this.point2.display();
100           System.out.print("The line's length is:");
101           System.out.printf("%.2f",getDistance());
102       }
103 }
View Code

圈复杂分析图:

 由上图可得:圈复杂度在合理范围之内

踩坑心得:

这里注意Point类中的x,y是private,在Line类的方法不能直接调用x,y,需要使用getX(),getY()的方法。其次注意输入值范围设定为(0,200]。

改进建议:

Point类中dispalay()中的输出方法可以简化为:

System.out.printf("(%.2f,%.2f)\n",this.x,this.y);

7-2 点线面问题重构(继承与多态)

分数 40
作者 段喜龙
单位 南昌航空大学

在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。

  • 对题目中的点Point类和线Line类进行进一步抽象,定义一个两个类的共同父类Element(抽象类),将display()方法在该方法中进行声明(抽象方法),将Point类和Line类作为该类的子类。
  • 再定义一个Element类的子类面Plane,该类只有一个私有属性颜色color,除了构造方法和属性的getter、setter方法外,display()方法用于输出面的颜色,输出格式如下:The Plane's color is:颜色
  • 在主方法内,定义两个Point(线段的起点和终点)对象、一个Line对象和一个Plane对象,依次从键盘输入两个Point对象的起点、终点坐标和颜色值(Line对象和Plane对象颜色相同),然后定义一个Element类的引用,分别使用该引用调用以上四个对象的display()方法,从而实现多态特性。示例代码如下:
          element = p1;//起点Point
          element.display();
          
          element = p2;//终点Point
          element.display();
          
          element = line;//线段
          element.display();
          
          element = plane;//面
          element.display();
    
     
    类结构如下图所示。

1641340607(1).jpg

其中,所有数值均保留两位小数,建议可用String.format("%.2f", data)方法。

  • 以下情况为无效作业
    • 无法运行
    • 设计不符合所给类图要求
    • 未通过任何测试点测试
    • 判定为抄袭

输入格式:

分别输入线段的起点横坐标、纵坐标、终点的横坐标、纵坐标以及颜色,中间可用一个或多个空格、tab或者回车分隔。

输出格式:

(x1,y1)
(x2,y2)
The line's color is:颜色值
The line's begin point's Coordinate is:
(x1,y1)
The line's end point's Coordinate is:
(x2,y2)
The line's length is:长度值
The Plane's color is:颜色值
 

输入样例1:

在这里给出一组输入。例如:

5
9.4
12.3
84
Red
 

输出样例1:

在这里给出相应的输出。例如:

(5.00,9.40)
(12.30,84.00)
The line's color is:Red
The line's begin point's Coordinate is:
(5.00,9.40)
The line's end point's Coordinate is:
(12.30,84.00)
The line's length is:74.96
The Plane's color is:Red
 

输入样例2:

在这里给出一组输入。例如:

5
9.4
12.3
845
Black
 

输出样例2:

在这里给出相应的输出。例如:

Wrong Format

我的代码:

  1 import java.util.*;
  2 import java.text.DecimalFormat;
  3 public class Main{
  4     //控制小数点
  5     public static void main(String[] args){
  6         //Point p1=new Point();
  7 
  8         Scanner input=new Scanner(System.in);
  9         double x1=input.nextDouble();
 10         double y1=input.nextDouble();
 11         double x2=input.nextDouble();
 12         double y2=input.nextDouble();
 13         String color=input.next();
 14         Point p1=new Point(x1,y1);
 15         Point p2=new Point(x2,y2);
 16         Line L=new Line(p1,p2,color);
 17         Plane P=new Plane(color);
 18         Element element;
 19         if((x1<=0||x1>200)||(y1<=0||y1>200)||(x2<=0||x2>200)||(y2<=0||y2>200)){
 20             System.out.println("Wrong Format");
 21             return;
 22         }
 23         else{
 24             
 25               element = p1;//起点Point
 26               element.display();
 27 
 28               element = p2;//终点Point
 29               element.display();
 30 
 31               element = L;//线段
 32               element.display();
 33 
 34               element = P;//
 35               element.display();
 36 
 37         }
 38         
 39     }
 40 }
 41 class Element{
 42      public void display(){
 43  }
 44 }
 45 class Point extends Element{
 46     private double x;
 47     private double y;
 48     public Point(){
 49         this.x = 0;
 50         this.y = 0;
 51     }
 52     public Point(double x,double y){
 53         this.x=x;
 54         this.y=y;
 55     }
 56     public double getX(){
 57         return this.x;
 58     }
 59     public void setX(double x){
 60         this.x=x;
 61     }
 62      public double getY(){
 63         return this.y;
 64     }
 65     public void setY(double y){
 66         this.x=y;
 67     }
 68     public void display(){
 69           System.out.print("(");
 70           System.out.printf("%.2f",this.x);
 71           System.out.print(",");
 72           System.out.printf("%.2f",this.y);
 73           System.out.println(")");
 74       }
 75 }
 76 class Line extends Element{
 77     private Point point1;
 78     private Point point2;
 79     String color;
 80     public Line(){
 81         this.point1=point1;
 82         this.point2=point2;
 83         this.color="";
 84     }
 85     public Line(Point point1,Point point2,String color){
 86         this.point1=point1;
 87         this.point2=point2;
 88         this.color=color;
 89     }
 90     public Point getPoint1() {
 91           return point1;
 92       }
 93       public void setPoint1(Point point1) {
 94           this.point1=point1;
 95       }
 96       public Point getPoint2() {
 97           return point2;
 98       }
 99       public void setPoint2(Point point2) {
100           this.point2=point2;
101       }
102       public String getColor() {
103           return color;
104       }
105       public void setColor(String color) {
106           this.color=color;
107       }
108     //线段长度
109       public double getDistance(){ 
110           return Math.sqrt(Math.pow(this.point2.getX()-this.point1.getX(),2)+Math.pow(this.point2.getY()-this.point1.getY(),2));
111     }
112     public void display(){
113           System.out.println("The line's color is:"+this.color);
114           System.out.println("The line's begin point's Coordinate is:");
115           this.point1.display();
116           System.out.println("The line's end point's Coordinate is:");
117           this.point2.display();
118           System.out.print("The line's length is:");
119           System.out.printf("%.2f\n",getDistance());
120       }
121 }
122 class Plane extends Element{
123     private String color;
124     public Plane(String color) {
125                  super();
126                  this.color=color;
127     }
128     public String getColor() {
129          return color;
130      }
131 
132      public void setColor(String color) {
133      this.color=color;
134      }
135 
136      public void display() {
137          System.out.println("The Plane's color is:"+this.color);
138        
139      }
140 }
View Code
圈复杂分析图:

 

由上图可得:圈复杂度在合理范围之内

踩坑心得:

这道题是在上一题的基础上,加了一个抽象类,注意在抽象父类中的display()方法也要用抽象方法来实现。这道题比较简单,注意格式就行。

改进建议:

 同上一题一样,输出可以改进一下,这道题比较简单,不需要花费太大的心思。

7-3 点线面问题再重构(容器类)

分数 40
作者 段喜龙
单位 南昌航空大学

在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。

  • 在原有类设计的基础上,增加一个GeometryObject容器类,其属性为ArrayList<Element>类型的对象(若不了解泛型,可以不使用<Element>
  • 增加该类的add()方法及remove(int index)方法,其功能分别为向容器中增加对象及删除第index - 1(ArrayList中index>=0)个对象
  • 在主方法中,用户循环输入要进行的操作(choice∈[0,4]),其含义如下:
    • 1:向容器中增加Point对象
    • 2:向容器中增加Line对象
    • 3:向容器中增加Plane对象
    • 4:删除容器中第index - 1个数据,若index数据非法,则无视此操作
    • 0:输入结束
    示例代码如下:
       choice = input.nextInt();
        while(choice != 0) {
            switch(choice) {
            case 1://insert Point object into list 
              ...
                break;
            case 2://insert Line object into list
                ...
                break;
            case 3://insert Plane object into list
                ...
                break;
            case 4://delete index - 1 object from list
                int index = input.nextInt();
                ...
            }
            choice = input.nextInt();
        }
    
     
    输入结束后,按容器中的对象顺序分别调用每个对象的display()方法进行输出。
    类图如下所示:

classdiagram.jpg

  • 以下情况为无效作业
    • 无法运行
    • 设计不符合所给类图要求
    • 未通过任何测试点测试
    • 判定为抄袭

输入格式:

switch(choice) {
            case 1://insert Point object into list 
              输入“点”对象的x,y值
                break;
            case 2://insert Line object into list
                输入“线”对象两个端点的x,y值
                break;
            case 3://insert Plane object into list
                输入“面”对象的颜色值
                break;
            case 4://delete index - 1 object from list
                输入要删除的对象位置(从1开始)
                ...
            }
 

输出格式:

  • Point、Line、Plane的输出参考题目2
  • 删除对象时,若输入的index超出合法范围,程序自动忽略该操作

输入样例:

在这里给出一组输入。例如:

1
3.4
5.6
2
4.4
8.0
0.98
23.888
Red
3
Black
1
9.8
7.5
3
Green
4
3
0
 

输出样例:

在这里给出相应的输出。例如:

(3.40,5.60)
The line's color is:Red
The line's begin point's Coordinate is:
(4.40,8.00)
The line's end point's Coordinate is:
(0.98,23.89)
The line's length is:16.25
(9.80,7.50)
The Plane's color is:Green

设计与分析:

 

我的代码:

  1 import java.util.*;
  2 import java.text.DecimalFormat;
  3 public class Main{
  4     //控制小数点
  5     public static void main(String[] args){
  6         //Point p1=new Point();
  7 
  8         Scanner input=new Scanner(System.in);
  9         
 10         GeometryObject ge = new GeometryObject();
 11         while(true) {
 12        
 13                 int choice = input.nextInt();
 14                 if(choice==0) {
 15                  break;
 16             }
 17         switch(choice) {
 18         case 1://insert Point object into list 
 19             double x1=input.nextDouble();
 20             double y1=input.nextDouble();
 21             Point p1=new Point(x1,y1);
 22             ge.add(new Point(x1,y1));
 23             break;
 24         case 2://insert Line object into list
 25             double x2=input.nextDouble();
 26             double y2=input.nextDouble();
 27             double x3=input.nextDouble();
 28             double y3=input.nextDouble();
 29             String color=input.next();
 30             Point p2=new Point(x2,y2);
 31             Point p3=new Point(x2,y2);
 32             Line L=new Line(p2,p3,color);
 33             if((x2<=0||x2>200)||(y2<=0||y2>200)||(x3<=0||x3>200)||(y3<=0||y3>200)){
 34             System.out.println("Wrong Format");
 35             ge.add(L);
 36             return;
 37         }
 38             break;
 39         case 3://insert Plane object into list
 40             String plcolor = input.next();
 41             Plane plane = new Plane(plcolor);
 42             ge.add(plane);
 43             break;
 44         case 4://delete index - 1 object from list
 45             int index = input.nextInt();
 46             ge.remove(index);
 47         default:
 48             break;
 49         }
 50         for(Element element:ge.getList()){
 51              element.display();
 52         }
 53     }
 54 
 55 
 56         
 57     }
 58 }
 59 class Element{
 60      public void display(){
 61  }
 62 }
 63 class Point extends Element{
 64     private double x;
 65     private double y;
 66     public Point(){
 67         this.x = 0;
 68         this.y = 0;
 69     }
 70     public Point(double x,double y){
 71         this.x=x;
 72         this.y=y;
 73     }
 74     public double getX(){
 75         return this.x;
 76     }
 77     public void setX(double x){
 78         this.x=x;
 79     }
 80      public double getY(){
 81         return this.y;
 82     }
 83     public void setY(double y){
 84         this.x=y;
 85     }
 86     public void display(){
 87           System.out.print("(");
 88           System.out.printf("%.2f",this.x);
 89           System.out.print(",");
 90           System.out.printf("%.2f",this.y);
 91           System.out.println(")");
 92       }
 93 }
 94 class Line extends Element{
 95     private Point point1;
 96     private Point point2;
 97     String color;
 98     public Line(){
 99         this.point1=point1;
100         this.point2=point2;
101         this.color="";
102     }
103     public Line(Point point1,Point point2,String color){
104         this.point1=point1;
105         this.point2=point2;
106         this.color=color;
107     }
108     public Point getPoint1() {
109           return point1;
110       }
111       public void setPoint1(Point point1) {
112           this.point1=point1;
113       }
114       public Point getPoint2() {
115           return point2;
116       }
117       public void setPoint2(Point point2) {
118           this.point2=point2;
119       }
120       public String getColor() {
121           return color;
122       }
123       public void setColor(String color) {
124           this.color=color;
125       }
126     //线段长度
127       public double getDistance(){ 
128           return Math.sqrt(Math.pow(this.point2.getX()-this.point1.getX(),2)+Math.pow(this.point2.getY()-this.point1.getY(),2));
129     }
130     public void display(){
131           System.out.println("The line's color is:"+this.color);
132           System.out.println("The line's begin point's Coordinate is:");
133           this.point1.display();
134           System.out.println("The line's end point's Coordinate is:");
135           this.point2.display();
136           System.out.print("The line's length is:");
137           System.out.printf("%.2f\n",getDistance());
138       }
139 }
140 class Plane extends Element{
141     private String color;
142     public Plane(String color) {
143                  super();
144                  this.color=color;
145     }
146     public String getColor() {
147          return color;
148      }
149 
150      public void setColor(String color) {
151      this.color=color;
152      }
153 
154      public void display() {
155          System.out.println("The Plane's color is:"+this.color);
156        
157      }
158 }
159 class GeometryObject {
160     private ArrayList<Element> list=new ArrayList<>();
161     public void add(Element element){
162         list.add(element);
163     }
164      public void remove(int index){
165         if(index<=list.size())
166             list.remove(index-1);
167      }
168      public ArrayList<Element> getList(){
169          return list;
170      }
171     
172 }
View Code

 圈复杂分析图:

 

 由上图可得知:圈复杂度在合理范围之内,没啥好说的。

踩坑心得:

这一题是在前两题的基础上做了修改。这里需要定义一个ArrayList<Element>的容器(不会的小伙伴记得找相关资料搞定),要通过add()和remove()进行添加和删除的工作。还有注意每一种情况都要判断输入值是否合法,

改进建议:

我没有每一种情况都判断输入值是否合法,没得满分,这里需要改进。

总结:

通过这几次实验,对于类的运用更加熟练,也学会的使用继承关系来简化代码。但是速度太慢,思考也不够深度,总感觉浮于表面,感觉有些地方似懂非懂。第五次大作业完成的不是很好,很多点没有想到或者想到了,写出来的代码却又问题,找bug又找不出来,很难受。只能说还需要加强练习。

 

 

 

 
 
posted on 2022-10-25 17:45  余语于玉  阅读(119)  评论(0)    收藏  举报