/// **Overview** Calculates the correct rotation matrix and applies it to all the sides and vertices of /// the given trungle. Builds a new trungle object, adds it to the scene, and returns a reference to that /// new child to be added to the list. /// /// **Params** /// - current - triangle to be rotated /// - angle - angle to rotate through /// - CoR1 - first center of rotation /// - CoR2 - second center of rotation /// - side - string representation of what side we are reflecting across, e.g. `"AB"` /// - direction - direction to rotate about /// /// **Returns** a new `TrungleBehavior` which is a rotated version of the given triangle private TrungleBehavior RotateTriangle(TrungleBehavior current, float angle, Vector3 CoR1, Vector3 CoR2, string side, RotationDirection direction) { Matrix m = new Matrix(CoR1, CoR2, angle, direction); Vector3 newAlpha, newBeta, newGamma; Vector3 newAP, newBP, newCP; if (side == "AB" || side == "AC") { newAlpha = current.AlphaPoint; newAP = current.APrime; } else { newAlpha = current.AlphaPoint.ApplyMatrix(m); if (References.CurrentType == TriangleType.Euclidean) { newAP = References.Infinity; } else { newAP = current.APrime.ApplyMatrix(m); } } if (side == "AB" || side == "BC") { newBeta = current.BetaPoint; newBP = current.BPrime; } else { newBeta = current.BetaPoint.ApplyMatrix(m); if (References.CurrentType == TriangleType.Euclidean) { newBP = References.Infinity; } else { newBP = current.BPrime.ApplyMatrix(m); } } if (side == "AC" || side == "BC") { newGamma = current.GammaPoint; newCP = current.CPrime; } else { newGamma = current.GammaPoint.ApplyMatrix(m); if (References.CurrentType == TriangleType.Euclidean) { newCP = References.Infinity; } else { newCP = current.CPrime.ApplyMatrix(m); } } Vector3[] newAB, newAC, newBC; bool newABwasReflectedAcross = false, newACwasReflectedAcross = false, newBCwasReflectedAcross = false; bool newABisArc, newACisArc, newBCisArc; // if not doing a Euclidean rotation, everything becomes an arc // we check the Matrix that we used for rotations to see if that is Mobius if (m.IsMobius) { newABisArc = newACisArc = newBCisArc = true; } // otherwise, take the previous values else { newABisArc = current.Parent.ABisArc; newACisArc = current.Parent.ACisArc; newBCisArc = current.Parent.BCisArc; } if (side == "AB") { newAB = (Vector3[])current.AB_Points.Clone(); current.ABwasReflectedAcross = true; newABwasReflectedAcross = true; } else { newAB = TrungleUtils.Rotate(current.Parent.AB_Points, m); } if (side == "AC") { newAC = (Vector3[])current.AC_Points.Clone(); current.ACwasReflectedAcross = true; newACwasReflectedAcross = true; } else { newAC = TrungleUtils.Rotate(current.Parent.AC_Points, m); } if (side == "BC") { newBC = (Vector3[])current.BC_Points.Clone(); current.BCwasReflectedAcross = true; newBCwasReflectedAcross = true; } else { newBC = TrungleUtils.Rotate(current.Parent.BC_Points, m); } GameObject go = Instantiate(trungleStandard, Vector3.zero, Quaternion.identity); go.name = "Gen" + (current.Generation + 1).ToString(); TrungleBehavior child = go.GetComponent <TrungleBehavior>(); child.Generation = current.Generation + 1; child.ABwasReflectedAcross = newABwasReflectedAcross; child.ACwasReflectedAcross = newACwasReflectedAcross; child.BCwasReflectedAcross = newBCwasReflectedAcross; child.ABisArc = newABisArc; child.ACisArc = newACisArc; child.BCisArc = newBCisArc; child.SetPoints(newAlpha, newBeta, newGamma); child.SetPrimePoints(newAP, newBP, newCP); child.SetAngles(current.AlphaAngle, current.BetaAngle, current.GammaAngle); child.SetSides(newAB, newAC, newBC); child.Parent = current; return(child); }
/// **Overview** Calculate all necessary values and build the first trungle, adding /// it to the scene. /// /// **Params** /// - newAlpha: new alpha angle /// - newBeta: new beta angle /// - newGamma: new gamma angle public void BuildFirstTriangle(float newAlpha, float newBeta, float newGamma) { GameObject go = Instantiate(trungleStandard, Vector3.zero, Quaternion.identity); go.name = "Gen0 a.k.a. GOD TRUNGLE"; TrungleBehavior triangle = go.GetComponent <TrungleBehavior>(); // required for calculations but are the same for each trungle Vector3 a = new Vector3(0, 0, 0); Vector3 b = new Vector3(1, 0, 0); // these are different per triangle and are set in each if branch Vector3 c; Vector3 aP, bP, cP; // prime points List <Vector3> bc; if (References.CurrentType == TriangleType.Euclidean) { var gammaX = (Mathf.Sin(newBeta) * Mathf.Cos(newAlpha)) / Mathf.Sin(newGamma); var gammaY = (Mathf.Sin(newBeta) * Mathf.Sin(newAlpha)) / Mathf.Sin(newGamma); c = new Vector3(gammaX, gammaY, 0); aP = bP = cP = References.Infinity; bc = TrungleUtils.LineBetween(b, c); triangle.BCisArc = false; } else { var A = (Mathf.Tan(newGamma + newAlpha) * Mathf.Tan(newAlpha)) + 1; var E = (Mathf.Tan(newGamma + newAlpha) + Mathf.Tan(newBeta)) - (A * Mathf.Tan(newBeta)); var F = (Mathf.Tan(newAlpha) * Mathf.Tan(newGamma + newAlpha)) + (Mathf.Tan(newAlpha) * Mathf.Tan(newBeta)) - A; var G = 1 - A; var H = Mathf.Tan(newAlpha); var a_ = (E * E) + (F * F) - ((A * A) * Mathf.Pow(Mathf.Tan(newBeta), 2)) - (A * A); var b_ = (2 * E * G) + (2 * F * H); var c_ = (G * G) + (H * H); float centerY; // we commence the Weird Hyperbolic checks const float piOverTwo = 90 * Mathf.Deg2Rad; if ((newBeta > piOverTwo && newGamma < piOverTwo) || (newBeta < piOverTwo && newGamma > piOverTwo)) { centerY = (-b_ + (Mathf.Sqrt((b_ * b_) - (4 * a_ * c_)))) / (2 * a_); } else { centerY = (-b_ - (Mathf.Sqrt((b_ * b_) - (4 * a_ * c_)))) / (2 * a_); } float centerX = 1 + (centerY * Mathf.Tan(newBeta)); var radius = Mathf.Sqrt(((1 - centerX) * (1 - centerX)) + (centerY * centerY)); var center = new Vector3(centerX, centerY, 0); var gammaX = (Mathf.Tan(newAlpha + newGamma) * centerY + centerX) / A; var gammaY = ((Mathf.Tan(newAlpha + newGamma) * centerY + centerX) / A) * Mathf.Tan(newAlpha); c = new Vector3(gammaX, gammaY, 0); aP = References.Infinity; bP = TrungleUtils.CalculateBPrime(center, radius, b); cP = TrungleUtils.CalculateCPrime(c, center, radius); bc = TrungleUtils.ArcBetween(b, c, center, radius, newAlpha); triangle.BCisArc = true; } // these are in common too but couldn't be set until after the ifs List <Vector3> ab = TrungleUtils.LineBetween(a, b); List <Vector3> ac = TrungleUtils.LineBetween(a, c); // everything left is in common and should be set by now: triangle.Generation = 0; triangle.ABwasReflectedAcross = false; triangle.ACwasReflectedAcross = false; triangle.BCwasReflectedAcross = false; triangle.ABisArc = false; triangle.ACisArc = false; triangle.SetAngles(newAlpha, newBeta, newGamma); triangle.SetPoints(a, b, c); triangle.SetPrimePoints(aP, bP, cP); triangle.SetSides(ab, ac, bc); trungles.Add(triangle); }