diff --git a/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java b/src/main/java/com/williamfiset/algorithms/geometry/LineSegmentLineSegmentIntersection.java index d8b6768e8..072a65ea2 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,29 @@ 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)) { // branch 1 + // This branch is currently not covered, given the tests in main + bc[0]++; + return new Pt[] {}; + } + 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)) return new Pt[] {p1}; + 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 { // branch 4 + // This branch is covered, given the tests in main + bc[3]++; + } List endpoints = getCommonEndpoints(p1, p2, p3, p4); int n = endpoints.size(); @@ -53,22 +70,55 @@ 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) { // branch 5 + // This branch is currently not covered, given the tests in main + bc[4]++; + return new Pt[] {endpoints.get(0)}; + } + else { // branch 6 + // This branch is covered, given the tests in main + bc[5]++; + } // Segments are equal. - if (n == 2) return new Pt[] {endpoints.get(0), endpoints.get(1)}; + 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 { // branch 8 + // This branch is covered, given the tests in main + 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) { - + 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)) return new Pt[] {p3, 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 { // 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)) return new Pt[] {p1, 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 { // branch 13 + // This branch is currently not covered, given the tests in main + 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 +126,50 @@ 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)) { // branch 14 + // This branch is currently not covered, given the tests in main + bc[13]++; + return new Pt[] {midPoint1}; + } + else { // branch 15 + // This branch is currently not covered, given the tests in main + bc[14]++; + } return new Pt[] {midPoint1, midPoint2}; } + else { // branch 16 + // This branch is covered, given the tests in main + bc[15]++; + } /* 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 { // 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 { // branch 20 + // This branch is covered, given the tests in main + bc[19]++; + } double m1 = (p2.y - p1.y) / (p2.x - p1.x); double m2 = (p4.y - p3.y) / (p4.x - p3.x); @@ -178,7 +252,22 @@ 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 // Segment #1 is (p1, p2), segment #2 is (p3, p4) Pt p1, p2, p3, p4; @@ -187,7 +276,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 +286,13 @@ 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 + printCoverage(bc); } }