diff --git a/README.md b/README.md index f7aae71..23ba81d 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,11 @@ -Geometric Separators and the Parabolic Lift +geometric_separators ==================== -About: ------- - -This Processing application is based off the paper [**Geometric Separators and the Parabolic Lift** by Don Sheehy](http://donsheehy.net/research/sheehy13geometric.pdf) and demonstrates basic usage of an algorithm (in the above paper) for finding a geometric separator for 2-D points. +Geometric separators project for CSE 4095 (Computational Geometry). -Usage: +About: ------ -The application consists of a canvas and two buttons. It will allow you input a number of 2-D Euclidean points using a mouse and calculate the geometric separator. Tentatively, you will also be able to provide a file of predefined points (e.g. .csv format). - -Click the mouse anywhere on the canvas to create a new input point. When you have completed your input, either press 'Reset.' to clear it or 'Calculate.' to find the separator. - -Features: ---------- +This Java program will allow you to input 2D -The program will visualize several components of the algorithm: -* Highlights the estimated centerpoint for your input. -* Shows the separator in relation to your input. -* Outputs the numerical information associated with the above. -* Perhaps more... \ No newline at end of file diff --git a/geometric_separators.pde b/geometric_separators.pde index bb9e558..5dae63c 100644 --- a/geometric_separators.pde +++ b/geometric_separators.pde @@ -1,6 +1,8 @@ import java.util.*; import java.util.Map.*; import java.lang.Boolean; +import java.util.Random; +import org.jblas.*; int reset_x = 140; int reset_y = 460; @@ -12,13 +14,33 @@ int calc_y = 460; int calc_w = 100; int calc_h = 25; +int exam_x = 360; +int exam_y = 460; +int exam_w = 100; +int exam_h = 25; + PShape reset; PShape calculate; PShape sphere; +PShape example; PVector centerPoint; ArrayList rawInput = new ArrayList(); Comparator compareX, compareXRev, compareY, compareYRev; +PShape exampleSphere; +PVector exampleCenterPoint; + +ArrayList exampleList = new ArrayList(); +PVector ex1; +PVector ex2; +PVector ex3; +PVector ex4; +PVector ex5; +PVector ex6; +PVector ex7; +PVector ex8; +PVector ex9; + // Triple used for returning three items private class ReturnTriple { public float sum; @@ -48,6 +70,8 @@ void setup() { // Create buttons reset = createShape(RECT, reset_x, reset_y, reset_w, reset_h); calculate = createShape(RECT, calc_x, calc_y, calc_w, calc_h); + example = createShape(RECT, exam_x, exam_y, exam_w, exam_h); + // sphere = null; noLoop(); compareX = new Comparator() { @@ -102,6 +126,16 @@ void setup() { } } }; + ex1 = new PVector(253, 102); + ex2 = new PVector(248, 99); + ex3 = new PVector(256, 106); + ex4 = new PVector(88, 347); + ex5 = new PVector(89, 345); + ex6 = new PVector(92, 356); + ex7 = new PVector(411, 347); + ex8 = new PVector(407, 354); + ex9 = new PVector(410, 346); + exampleList = new ArrayList(); } // On mouse press @@ -111,16 +145,38 @@ void mousePressed() { (mouseY >= reset_y && mouseY <= (reset_y + reset_h))) { // Reset input and background rawInput.clear(); + exampleList.clear(); centerPoint = null; sphere = null; + exampleCenterPoint = null; + exampleSphere = null; } // If mouse presses calculate button else if ((mouseX >= calc_x && mouseX <= (calc_x + calc_w)) && (mouseY >= calc_y && mouseY <= (calc_y + calc_h))) { // Run algorithm - CenterAndSphere returnVals = getSeparator(rawInput); - sphere = returnVals.sphere; - centerPoint = returnVals.center; + // CenterAndSphere returnVals = getSeparator(rawInput); + // sphere = returnVals.sphere; + // centerPoint = returnVals.center; + getSolution(rawInput); + } + // If example + else if ((mouseX >= exam_x && mouseX <= (exam_x + exam_w)) && + (mouseY >= exam_y && mouseY <= (exam_y + exam_h))) { + rawInput.clear(); + exampleList.add(ex1); + exampleList.add(ex2); + exampleList.add(ex3); + exampleList.add(ex4); + exampleList.add(ex5); + exampleList.add(ex6); + exampleList.add(ex7); + exampleList.add(ex8); + exampleList.add(ex9); + exampleCenterPoint = new PVector(250, 250, 20000); + CenterAndSphere example = getExample(exampleCenterPoint); + exampleSphere = example.sphere; + System.out.println(exampleSphere); } else { // Create new 2D point from mouse coordinates @@ -128,12 +184,95 @@ void mousePressed() { // Lift to 3D with the squared magnitude of the original point PVector final_point = new PVector(prelim_point.x, prelim_point.y, (float)Math.pow(prelim_point.mag(), 2)); - System.out.println(final_point); rawInput.add(final_point); } redraw(); } +// Set solution of set of equations +void getSolution(ArrayList input) { + System.out.println("Solver..."); + // Set a to equal our points + // DenseMatrix64F a = new DenseMatrix64F(input.size(), 4); + // DenseMatrix64F b = new DenseMatrix64F(5, 1); + // DenseMatrix64F x = new DenseMatrix64F(4, 1); + float[][] aData = new float[3][input.size()]; + for (int i = 0; i < input.size(); i++) { + for (int j = 0; j < 3; j++) { + switch(j) { + case 0: aData[j][i] = input.get(i).x; + break; + case 1: aData[j][i] = input.get(i).y; + break; + case 2: aData[j][i] = input.get(i).z; + break; + } + } + } + FloatMatrix coefficients = new FloatMatrix(aData); + System.out.println("Coeff"); + for (int i = 0; i < 3; i++) { + System.out.println("Row"); + for (int j = 0; j < 5; j++) { + System.out.println(coefficients.get(i,j)); + } + } + FloatMatrix constants = FloatMatrix.zeros(5, 2); + FloatMatrix solution = Solve.solveLeastSquares(coefficients, constants); + System.out.println("Sol"); + for (int i = 0; i < 5; i++) { + System.out.println("Row"); + for (int j = 0; j < 2; j++) { + System.out.println(solution.get(i,j)); + } + } + // RealMatrix coefficients = new Array2DRowRealMatrix(aData, false); + // RealVector constants = new ArrayRealVector(new double[] {1, 1, 1, 1, 1}, false); + // DecompositionSolver solver = new org.apache.commons.math3.linear.SingularValueDecomposition(coefficients).getSolver(); + // RealVector solution = solver.solve(constants); + // for (int i = 0; i < input.size(); i++) { + // for (int j = 0; j < 5; j++) { + // switch(j) { + // case 0: a.set(j, i, input.get(i).x); + // break; + // case 1: a.set(j, i, input.get(i).y); + // break; + // case 2: a.set(j, i, input.get(i).z); + // break; + // case 3: a.set(j, i, 1); + // break; + // } + // System.out.println(a.get(j, i)); + // } + // } + // System.out.println("Finished A."); + // // Set b to equal 0 + // for (int i = 0; i < 4; i++) { + // b.set(i, 0, 0); + // } + // LinearSolver solver = LinearSolverFactory.leastSquares(4, input.size()); + // solver = new LinearSolverSafe(solver); + // solver.solve(b, x); + // for (int i = 0; i < x.getNumElements(); i++) { + // System.out.println(x.get(i, 0)); + // } +} + +// Show example +CenterAndSphere getExample(PVector exampleCenterPoint) { + PVector unitVector = PVector.random3D(); + //unitVector.mult(500); + unitVector.x = Math.abs(unitVector.x); + unitVector.y = Math.abs(unitVector.y); + unitVector.z = Math.abs(unitVector.z); + float radius = getRadius(exampleCenterPoint, unitVector); + System.out.println(radius); + float[] sphereAttributes = getSphereAttr(exampleCenterPoint, unitVector, radius); + PShape separator = createShape(ELLIPSE, sphereAttributes); + CenterAndSphere returnVals = new CenterAndSphere(exampleCenterPoint, separator); + return returnVals; +} + // Get geometric separator CenterAndSphere getSeparator(ArrayList input) { // Algorithm @@ -141,6 +280,12 @@ CenterAndSphere getSeparator(ArrayList input) { PVector centerPoint = approxCenterpoint(input); // 2. Get random unit vector in 3D PVector unitVector = PVector.random3D(); + unitVector.mult(500); + unitVector.x = Math.abs(unitVector.x); + unitVector.y = Math.abs(unitVector.y); + unitVector.z = Math.abs(unitVector.z); + System.out.println("Unit Vector..."); + System.out.println(unitVector); // 3. Get radius float radius = getRadius(centerPoint, unitVector); // 4. Output sphere separator @@ -153,8 +298,11 @@ CenterAndSphere getSeparator(ArrayList input) { // Get radius for our separator float getRadius(PVector centerPoint, PVector unitVector) { PVector centerPoint2D = new PVector(centerPoint.x, centerPoint.y); + System.out.println(centerPoint); + System.out.println(centerPoint2D); float num = (float)Math.sqrt(Math.abs(centerPoint.z - Math.pow(centerPoint2D.mag(), 2))); System.out.println(num); + System.out.println(unitVector.z); return num / Math.abs(unitVector.z); } @@ -164,10 +312,7 @@ float[] getSphereAttr(PVector centerPoint, PVector unitVector, float radius) { PVector centerPointCopy = new PVector(centerPoint.x, centerPoint.y); unitVectorCopy.mult(radius); centerPointCopy.sub(unitVectorCopy); - float x = centerPointCopy.x - radius; - float y = centerPointCopy.y - radius; - float z = centerPointCopy.z - radius; - float[] attributes = {x, y, 2 * radius, 2 * radius}; + float[] attributes = {centerPointCopy.x, centerPointCopy.y, 2 * radius, 2 * radius}; return attributes; } @@ -180,12 +325,12 @@ PVector getGeometricMedian(ArrayList input) { else if (input.size() == 1) { return input.get(0); } - else if (input.size() == 2) { - // Nothing yet - } - else if (input.size() == 4) { - // Nothing yet - } + // else if (input.size() == 2) { + // // Nothing yet + // } + // else if (input.size() == 4) { + // // Nothing yet + // } else { // Get the point HashMap total = new HashMap(); @@ -343,29 +488,49 @@ HashMap getAxisMin(ArrayList input, boolean isY) { // Draw void draw() { background(255); + // Draw center point + if (centerPoint != null) { + strokeWeight(6); + point(centerPoint.x, centerPoint.y); + System.out.println("x-coordinate: " + Float.toString(centerPoint.x)); + System.out.println("y-coordinate: " + Float.toString(centerPoint.y)); + } + // Draw separator sphere projected to 2D + if (sphere != null) { + strokeWeight(6); + shape(sphere); + } + if (exampleSphere != null) { + strokeWeight(6); + fill(255); + ellipseMode(CENTER); + shape(exampleSphere); + } + if (exampleCenterPoint != null) { + stroke(255, 0, 0); + strokeWeight(6); + point(exampleCenterPoint.x, exampleCenterPoint.y); + System.out.println("x-coordinate: " + Float.toString(exampleCenterPoint.x)); + System.out.println("y-coordinate: " + Float.toString(exampleCenterPoint.y)); + stroke(0); + } shape(reset); shape(calculate); + shape(example); fill(50); textSize(20); text("Geometric Separators", 140, 20); textSize(12); text("Reset.", reset_x + 30, reset_y + 15); text("Calculate.", calc_x + 25, calc_y + 15); + text("Example.", exam_x + 25, exam_y + 15); // Draw input for (PVector point : rawInput) { - strokeWeight(4); + strokeWeight(8); point(point.x, point.y); } - // Draw center point - if (centerPoint != null) { - strokeWeight(6); - point(centerPoint.x, centerPoint.y); - System.out.println("x-coordinate: " + Float.toString(centerPoint.x)); - System.out.println("y-coordinate: " + Float.toString(centerPoint.y)); - } - // Draw separator sphere projected to 2D - if (sphere != null) { - strokeWeight(6); - shape(sphere); + for (PVector point : exampleList) { + strokeWeight(8); + point(point.x, point.y); } }