From 3a624b9d6114bfafa3586c13ab4742c54512e61d Mon Sep 17 00:00:00 2001 From: Daniel Tsada Yosief Date: Tue, 22 Feb 2022 12:05:30 +0100 Subject: [PATCH 1/3] #5 add branch coverage analysis tool --- .../LineSegmentLineSegmentIntersection.java | 87 ++++++++++++++++--- 1 file changed, 76 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java b/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java index d8b6768e8..236ece636 100644 --- a/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java +++ b/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java @@ -15,6 +15,7 @@ import static java.lang.Math.min; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class LineSegmentLineSegmentIntersection { @@ -38,13 +39,25 @@ public boolean equals(Pt pt) { // Finds the intersection point(s) of two line segments. Unlike regular line // segments, segments which are points (x1 = x2 and y1 = y2) are allowed. - public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4) { + public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4, int[] bc) { // No intersection. - if (!segmentsIntersect(p1, p2, p3, p4)) return new Pt[] {}; + if (!segmentsIntersect(p1, p2, p3, p4)) { + bc[0]++; + return new Pt[] {}; + } + else { + bc[1]++; + } // Both segments are a single point. - if (p1.equals(p2) && p2.equals(p3) && p3.equals(p4)) return new Pt[] {p1}; + if (p1.equals(p2) && p2.equals(p3) && p3.equals(p4)) { + bc[2]++; + return new Pt[] {p1}; + } + else { + bc[3]++; + } List endpoints = getCommonEndpoints(p1, p2, p3, p4); int n = endpoints.size(); @@ -53,22 +66,46 @@ public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4 // NOTE: checking only n == 1 is insufficient to return early // because the solution might be a sub segment. boolean singleton = p1.equals(p2) || p3.equals(p4); - if (n == 1 && singleton) return new Pt[] {endpoints.get(0)}; + if (n == 1 && singleton) { + bc[4]++; + return new Pt[] {endpoints.get(0)}; + } + else { + bc[5]++; + } // Segments are equal. - if (n == 2) return new Pt[] {endpoints.get(0), endpoints.get(1)}; + if (n == 2) { + bc[6]++; + return new Pt[] {endpoints.get(0), endpoints.get(1)}; + } + else { + bc[7]++; + } boolean collinearSegments = (orientation(p1, p2, p3) == 0) && (orientation(p1, p2, p4) == 0); // The intersection will be a sub-segment of the two // segments since they overlap each other. if (collinearSegments) { - + bc[8]++; // Segment #2 is enclosed in segment #1 - if (pointOnLine(p1, p2, p3) && pointOnLine(p1, p2, p4)) return new Pt[] {p3, p4}; + if (pointOnLine(p1, p2, p3) && pointOnLine(p1, p2, p4)) { + bc[9]++; + return new Pt[] {p3, p4}; + } + else { + bc[10]++; + } // Segment #1 is enclosed in segment #2 - if (pointOnLine(p3, p4, p1) && pointOnLine(p3, p4, p2)) return new Pt[] {p1, p2}; + if (pointOnLine(p3, p4, p1) && pointOnLine(p3, p4, p2)) { + bc[11]++; + return new Pt[] {p1, p2}; + } + else { + bc[12]++; + } // The subsegment is part of segment #1 and part of segment #2. // Find the middle points which correspond to this segment. @@ -76,26 +113,43 @@ public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4 Pt midPoint2 = pointOnLine(p3, p4, p1) ? p1 : p2; // There is actually only one middle point! - if (midPoint1.equals(midPoint2)) return new Pt[] {midPoint1}; + if (midPoint1.equals(midPoint2)) { + bc[13]++; + return new Pt[] {midPoint1}; + } + else { + bc[14]++; + } return new Pt[] {midPoint1, midPoint2}; } + else { + bc[15]++; + } /* Beyond this point there is a unique intersection point. */ // Segment #1 is a vertical line. if (abs(p1.x - p2.x) < EPS) { + bc[16]++; double m = (p4.y - p3.y) / (p4.x - p3.x); double b = p3.y - m * p3.x; return new Pt[] {new Pt(p1.x, m * p1.x + b)}; } + else { + bc[17]++; + } // Segment #2 is a vertical line. if (abs(p3.x - p4.x) < EPS) { + bc[18]++; double m = (p2.y - p1.y) / (p2.x - p1.x); double b = p1.y - m * p1.x; return new Pt[] {new Pt(p3.x, m * p3.x + b)}; } + else { + bc[19]++; + } double m1 = (p2.y - p1.y) / (p2.x - p1.x); double m2 = (p4.y - p3.y) / (p4.x - p3.x); @@ -179,6 +233,7 @@ private static List getCommonEndpoints(Pt p1, Pt p2, Pt p3, Pt p4) { } public static void main(String[] args) { + int[] bc = new int[20]; //Branch coverage array containing number of branch hits for each branch // Segment #1 is (p1, p2), segment #2 is (p3, p4) Pt p1, p2, p3, p4; @@ -187,7 +242,7 @@ public static void main(String[] args) { p2 = new Pt(3, 3); p3 = new Pt(0, 0); p4 = new Pt(2, 4); - Pt[] points = lineSegmentLineSegmentIntersection(p1, p2, p3, p4); + Pt[] points = lineSegmentLineSegmentIntersection(p1, p2, p3, p4, bc); Pt point = points[0]; // Prints: (1.636, 3.273) @@ -197,10 +252,20 @@ public static void main(String[] args) { p2 = new Pt(+10, 0); p3 = new Pt(-5, 0); p4 = new Pt(+5, 0); - points = lineSegmentLineSegmentIntersection(p1, p2, p3, p4); + points = lineSegmentLineSegmentIntersection(p1, p2, p3, p4, bc); Pt point1 = points[0], point2 = points[1]; // Prints: (-5.000, 0.000) (5.000, 0.000) System.out.printf("(%.3f, %.3f) (%.3f, %.3f)\n", point1.x, point1.y, point2.x, point2.y); + + //Branch coverage + int count = 0; + for (int j : bc) { + if (j != 0) { + count++; + } + } + System.out.printf("Branch coverage = %.1f%% (%d/%d)%n",((double)count/bc.length)*100, count, bc.length); + System.out.println(Arrays.toString(bc)); } } From 8d543732e08f19b89691529a949c024918db1f2a Mon Sep 17 00:00:00 2001 From: Daniel Tsada Yosief Date: Wed, 23 Feb 2022 12:01:48 +0100 Subject: [PATCH 2/3] Closes #18 This adds comments showing the branch coverage of the function, LineSegmentLineSegmentIntersectiongiven, given the tests in main. --- .../LineSegmentLineSegmentIntersection.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java b/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java index 236ece636..ff42c941d 100644 --- a/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java +++ b/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java @@ -43,19 +43,23 @@ public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4 // No intersection. if (!segmentsIntersect(p1, p2, p3, p4)) { + // This branch is currently not covered, given the tests in main bc[0]++; return new Pt[] {}; } else { + // This branch is covered, given the tests in main bc[1]++; } // Both segments are a single point. if (p1.equals(p2) && p2.equals(p3) && p3.equals(p4)) { + // This branch is currently not covered, given the tests in main bc[2]++; return new Pt[] {p1}; } else { + // This branch is covered, given the tests in main bc[3]++; } @@ -67,19 +71,23 @@ public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4 // because the solution might be a sub segment. boolean singleton = p1.equals(p2) || p3.equals(p4); if (n == 1 && singleton) { + // This branch is currently not covered, given the tests in main bc[4]++; return new Pt[] {endpoints.get(0)}; } else { + // This branch is covered, given the tests in main bc[5]++; } // Segments are equal. if (n == 2) { + // This branch is currently not covered, given the tests in main bc[6]++; return new Pt[] {endpoints.get(0), endpoints.get(1)}; } else { + // This branch is covered, given the tests in main bc[7]++; } @@ -88,22 +96,27 @@ public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4 // The intersection will be a sub-segment of the two // segments since they overlap each other. if (collinearSegments) { + // This branch is covered, given the tests in main bc[8]++; // Segment #2 is enclosed in segment #1 if (pointOnLine(p1, p2, p3) && pointOnLine(p1, p2, p4)) { + // This branch is covered, given the tests in main bc[9]++; return new Pt[] {p3, p4}; } else { + // This branch is currently not covered, given the tests in main bc[10]++; } // Segment #1 is enclosed in segment #2 if (pointOnLine(p3, p4, p1) && pointOnLine(p3, p4, p2)) { + // This branch is currently not covered, given the tests in main bc[11]++; return new Pt[] {p1, p2}; } else { + // This branch is currently not covered, given the tests in main bc[12]++; } @@ -114,16 +127,19 @@ public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4 // There is actually only one middle point! if (midPoint1.equals(midPoint2)) { + // This branch is currently not covered, given the tests in main bc[13]++; return new Pt[] {midPoint1}; } else { + // This branch is currently not covered, given the tests in main bc[14]++; } return new Pt[] {midPoint1, midPoint2}; } else { + // This branch is covered, given the tests in main bc[15]++; } @@ -131,23 +147,27 @@ public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4 // Segment #1 is a vertical line. if (abs(p1.x - p2.x) < EPS) { + // This branch is currently not covered, given the tests in main bc[16]++; double m = (p4.y - p3.y) / (p4.x - p3.x); double b = p3.y - m * p3.x; return new Pt[] {new Pt(p1.x, m * p1.x + b)}; } else { + // This branch is covered, given the tests in main bc[17]++; } // Segment #2 is a vertical line. if (abs(p3.x - p4.x) < EPS) { + // This branch is currently not covered, given the tests in main bc[18]++; double m = (p2.y - p1.y) / (p2.x - p1.x); double b = p1.y - m * p1.x; return new Pt[] {new Pt(p3.x, m * p3.x + b)}; } else { + // This branch is covered, given the tests in main bc[19]++; } From b08cd56a113fcc054633894b3195d90654ac9792 Mon Sep 17 00:00:00 2001 From: Daniel Tsada Yosief Date: Wed, 23 Feb 2022 19:07:51 +0100 Subject: [PATCH 3/3] #5 add changes to coverage output --- .../LineSegmentLineSegmentIntersection.java | 63 ++++++++++--------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java b/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java index ff42c941d..072a65ea2 100644 --- a/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java +++ b/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java @@ -42,23 +42,23 @@ public boolean equals(Pt pt) { public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4, int[] bc) { // No intersection. - if (!segmentsIntersect(p1, p2, p3, p4)) { + if (!segmentsIntersect(p1, p2, p3, p4)) { // branch 1 // This branch is currently not covered, given the tests in main bc[0]++; return new Pt[] {}; } - else { + else { // branch 2 // This branch is covered, given the tests in main bc[1]++; } // Both segments are a single point. - if (p1.equals(p2) && p2.equals(p3) && p3.equals(p4)) { + if (p1.equals(p2) && p2.equals(p3) && p3.equals(p4)) { // branch 3 // This branch is currently not covered, given the tests in main bc[2]++; return new Pt[] {p1}; } - else { + else { // branch 4 // This branch is covered, given the tests in main bc[3]++; } @@ -70,23 +70,23 @@ public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4 // NOTE: checking only n == 1 is insufficient to return early // because the solution might be a sub segment. boolean singleton = p1.equals(p2) || p3.equals(p4); - if (n == 1 && singleton) { + if (n == 1 && singleton) { // branch 5 // This branch is currently not covered, given the tests in main bc[4]++; return new Pt[] {endpoints.get(0)}; } - else { + else { // branch 6 // This branch is covered, given the tests in main bc[5]++; } // Segments are equal. - if (n == 2) { + if (n == 2) { // branch 7 // This branch is currently not covered, given the tests in main bc[6]++; return new Pt[] {endpoints.get(0), endpoints.get(1)}; } - else { + else { // branch 8 // This branch is covered, given the tests in main bc[7]++; } @@ -95,27 +95,27 @@ public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4 // The intersection will be a sub-segment of the two // segments since they overlap each other. - if (collinearSegments) { + if (collinearSegments) { // branch 9 // This branch is covered, given the tests in main bc[8]++; // Segment #2 is enclosed in segment #1 - if (pointOnLine(p1, p2, p3) && pointOnLine(p1, p2, p4)) { + if (pointOnLine(p1, p2, p3) && pointOnLine(p1, p2, p4)) { // branch 10 // This branch is covered, given the tests in main bc[9]++; return new Pt[] {p3, p4}; } - else { + else { // branch 11 // This branch is currently not covered, given the tests in main bc[10]++; } // Segment #1 is enclosed in segment #2 - if (pointOnLine(p3, p4, p1) && pointOnLine(p3, p4, p2)) { + if (pointOnLine(p3, p4, p1) && pointOnLine(p3, p4, p2)) { // branch 12 // This branch is currently not covered, given the tests in main bc[11]++; return new Pt[] {p1, p2}; } - else { + else { // branch 13 // This branch is currently not covered, given the tests in main bc[12]++; } @@ -126,19 +126,19 @@ public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4 Pt midPoint2 = pointOnLine(p3, p4, p1) ? p1 : p2; // There is actually only one middle point! - if (midPoint1.equals(midPoint2)) { + if (midPoint1.equals(midPoint2)) { // branch 14 // This branch is currently not covered, given the tests in main bc[13]++; return new Pt[] {midPoint1}; } - else { + else { // branch 15 // This branch is currently not covered, given the tests in main bc[14]++; } return new Pt[] {midPoint1, midPoint2}; } - else { + else { // branch 16 // This branch is covered, given the tests in main bc[15]++; } @@ -146,27 +146,27 @@ public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4 /* Beyond this point there is a unique intersection point. */ // Segment #1 is a vertical line. - if (abs(p1.x - p2.x) < EPS) { + if (abs(p1.x - p2.x) < EPS) { // branch 17 // This branch is currently not covered, given the tests in main bc[16]++; double m = (p4.y - p3.y) / (p4.x - p3.x); double b = p3.y - m * p3.x; return new Pt[] {new Pt(p1.x, m * p1.x + b)}; } - else { + else { // branch 18 // This branch is covered, given the tests in main bc[17]++; } // Segment #2 is a vertical line. - if (abs(p3.x - p4.x) < EPS) { + if (abs(p3.x - p4.x) < EPS) { // branch 19 // This branch is currently not covered, given the tests in main bc[18]++; double m = (p2.y - p1.y) / (p2.x - p1.x); double b = p1.y - m * p1.x; return new Pt[] {new Pt(p3.x, m * p3.x + b)}; } - else { + else { // branch 20 // This branch is covered, given the tests in main bc[19]++; } @@ -252,6 +252,20 @@ private static List getCommonEndpoints(Pt p1, Pt p2, Pt p3, Pt p4) { return points; } + //Prints the branch coverage of the function lineSegmentLineSegmentIntersection + public static void printCoverage(int[] bc) { + System.out.println("Branch coverage:"); + System.out.println("Function lineSegmentLineSegmentIntersection"); + int count = 0; + for (int i = 0; i < bc.length; i++) { + System.out.printf("%d: %d%n", i+1, bc[i]); + if (bc[i] != 0) { + count++; + } + } + System.out.printf("Branch coverage = %.1f%% (%d/%d)%n",((double)count/bc.length)*100, count, bc.length); + } + public static void main(String[] args) { int[] bc = new int[20]; //Branch coverage array containing number of branch hits for each branch @@ -279,13 +293,6 @@ public static void main(String[] args) { System.out.printf("(%.3f, %.3f) (%.3f, %.3f)\n", point1.x, point1.y, point2.x, point2.y); //Branch coverage - int count = 0; - for (int j : bc) { - if (j != 0) { - count++; - } - } - System.out.printf("Branch coverage = %.1f%% (%d/%d)%n",((double)count/bc.length)*100, count, bc.length); - System.out.println(Arrays.toString(bc)); + printCoverage(bc); } }