class SquareInCube {
// A, B, C, and D are coordinates of the square's corners
static double[] A = {0,0,0};
static double[] B = {0,0,0};
static double[] C = {0,0,0};
static double[] D = {0,0,0};
// CrossProd values will be used to place point C
static double[] CrossProd1 = {0,0,0};
static double[] CrossProd2 = {0,0,0};
static double stepsize = 0.02;
static double largesthit = 1;
// calculates the distance between two points
static double Dist(double[] Point1, double[] Point2) {
return Math.pow(
Math.pow(Point1[0]-Point2[0], 2) +
Math.pow(Point1[1]-Point2[1], 2) +
Math.pow(Point1[2]-Point2[2], 2) , 0.5);
}
// calculates the cross product of two vectors
// the first two parameters are the vectors to be cross-producted
// the third parameter is the array that will hold the answer
static void CrossProduct(double[] Vec1, double[] Vec2, double[] Answer) {
Answer[0] = Vec1[1] * Vec2[2] - Vec1[2] * Vec2[1];
Answer[1] = Vec1[2] * Vec2[0] - Vec1[0] * Vec2[2];
Answer[2] = Vec1[0] * Vec2[1] - Vec1[1] * Vec2[0];
}
// places a point in the unit cube
// systematically places it at each point, increasing by stepsize
// when it's moving point A, it will keep it restricted to the area
// from (0,0,0) to (0.5,0.5,0.5) to minimize the search area and
// increase efficiency
// when it's moving point B, it will put it anywhere in the unit cube
// returns true if it places it at a new point
// returns false if it has already placed it at every point
static boolean MovePoint(double[] Point, double maxval) {
for(int i=0; i<3; i++) {
Point[i] += stepsize;
if(Point[i]<maxval) return true;
Point[i] = 0;
}
return false;
}
// moves point B to a point in the unit cube where the distance is
// at least largesthit from point A
// returns true if it was able to place point B
// returns false if it was not
static boolean MoveB() {
boolean succeeded = true;
do {
succeeded = MovePoint(B,1);
} while(succeeded && Dist(A,B)<largesthit);
return succeeded;
}
// figures out where to place point C
//
// this first function just does calculations to find
// cross products needed to place point C, but doesn't
// actually place point C yet
// it calculates CrossProd1 as the cross product of a vector
// from A to B and a vector from the origin to B
// to produce a vector perpendicular to the line A-B
// if that cross product is small in magnitude, it uses the
// vector from (1,0,0) to B instead of the origin to B
// then it calculates CrossProd2 as the cross product of
// the vector from A to B and CrossProd1
// then normalizes both of them to Dist(A,B)
static void CrossProdsC() {
double[] AtoB = {B[0]-A[0], B[1]-A[1], B[2]-A[2]};
double[] OZZtoB = {-B[0], B[1], B[2]};
double[] Zero = {0,0,0};
double magCP1 = 0, magCP2 = 0;
CrossProduct(AtoB, B, CrossProd1);
if(Dist(Zero,CrossProd1)<0.1)
CrossProduct(AtoB, OZZtoB, CrossProd1);
CrossProduct(AtoB, CrossProd1, CrossProd2);
magCP1 = Dist(Zero, CrossProd1);
magCP2 = Dist(Zero, CrossProd2);
for(int i=0; i<3; i++) {
CrossProd1[i] *= Dist(A,B) / magCP1;
CrossProd2[i] *= Dist(A,B) / magCP2;
}
}
static boolean PlaceC(double rotate) {
boolean succeeded = true;
for(int i=0; i<3; i++) {
C[i] = B[i] +
CrossProd1[i] * Math.sin(rotate) +
CrossProd2[i] * Math.cos(rotate);
if(C[i]<0 || C[i]>1) succeeded=false;
}
return succeeded;
}
static void PlaceD() {
D[0] = A[0] + (C[0]-B[0]);
D[1] = A[1] + (C[1]-B[1]);
D[2] = A[2] + (C[2]-B[2]);
if(D[0]>0 && D[0]<1 &&
D[1]>0 && D[1]<1 &&
D[2]>0 && D[2]<1) {
PrintResult();
largesthit = Dist(A,B);
}
}
// prints the coordinates and edge length
static void PrintResult(){
System.out.println("A: "+A[0]+" "+A[1]+" "+A[2]);
System.out.println("B: "+B[0]+" "+B[1]+" "+B[2]);
System.out.println("C: "+C[0]+" "+C[1]+" "+C[2]);
System.out.println("D: "+D[0]+" "+D[1]+" "+D[2]);
System.out.println("Edge length AB: "+Dist(A,B));
System.out.println("Edge length AC: "+Dist(A,C));
System.out.println("Edge length AD: "+Dist(A,D));
System.out.println("Edge length BC: "+Dist(B,C));
System.out.println("Edge length BD: "+Dist(B,D));
System.out.println("Edge length CD: "+Dist(C,D));
System.out.println(" ");
}
// this will place the point A with the MovePoint function
// point A will be moved systematically throughout a "quadrant" of the
// unit cube from the origin to point (0.5,0.5,0.5)
// then it places point B with the MoveB function
// so it will be placed at a distance of at least largesthit from point A
// then it places point C using CrossProdsC once to calculate values of
// CrossProd1 and CrossProd2 that will be used to make an orthogonal circle
// for the given coordinates of A and B, then PlaceC to place point C somewhere
// on that circle
// then it places point D
// the function PlaceD handles printing the output and updating largesthit
// if point D lies within the unit cube
public static void main(String[] args){
while(MovePoint(A,0.5)) {
while(MoveB()) {
CrossProdsC();
for(double rotate=0; rotate<2*Math.PI; rotate+=stepsize) {
if(PlaceC(rotate)) {
PlaceD();
}
}
}
}
}
}