예제 #1
0
    /// **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);
    }
예제 #2
0
    /// **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);
    }
예제 #3
0
    /// **Overview** Build the first three special case reflections and add them to the
    /// scene.
    public void BuildFirstReflections()
    {
        GameObject      go;
        TrungleBehavior baseTriangle = trungles[0];

        // TRIANGLE 1
        if (References.CurrentMode == ReflectionMode.Regular || blueReflect)
        {
            go      = Instantiate(trungleStandard, Vector3.zero, Quaternion.identity);
            go.name = "Gen1";

            var child1 = go.GetComponent <TrungleBehavior>();

            Vector3 reflectedPoint = baseTriangle.GammaPoint.Reflect();
            Vector3 cP;

            if (References.CurrentType == TriangleType.Euclidean)
            {
                cP = References.Infinity;

                child1.ABisArc = child1.ACisArc = child1.BCisArc = false;
            }
            else
            {
                cP = baseTriangle.CPrime.Reflect();

                child1.ABisArc = false;
                child1.ACisArc = false;
                child1.BCisArc = true;
            }

            child1.Generation = 1;

            child1.ABwasReflectedAcross = true;
            child1.ACwasReflectedAcross = false;
            child1.BCwasReflectedAcross = false;

            child1.SetAngles(baseTriangle.AlphaAngle, baseTriangle.BetaAngle, baseTriangle.GammaAngle);
            child1.SetPoints(baseTriangle.AlphaPoint, baseTriangle.BetaPoint, reflectedPoint);
            child1.SetPrimePoints(baseTriangle.APrime, baseTriangle.BPrime, cP);
            child1.SetSides((Vector3[])baseTriangle.AB_Points.Clone(), TrungleUtils.Reflect(baseTriangle.AC_Points), TrungleUtils.Reflect(baseTriangle.BC_Points));

            child1.Parent = baseTriangle;

            trungles.Add(child1);

            baseTriangle.ABwasReflectedAcross = true;
        }
        // TRIANGLE 2
        if (References.CurrentMode == ReflectionMode.Regular || purpleReflect)
        {
            go      = Instantiate(trungleStandard, Vector3.zero, Quaternion.identity);
            go.name = "Gen1";
            var child2 = go.GetComponent <TrungleBehavior>();

            Matrix child2Matrix = new Matrix(baseTriangle.BetaPoint, baseTriangle.BPrime, baseTriangle.BetaAngle, RotationDirection.Clockwise);

            Vector3 rotatedAlpha = baseTriangle.AlphaPoint.ApplyMatrix(child2Matrix);
            Vector3 aP;

            if (References.CurrentType == TriangleType.Euclidean)
            {
                aP             = References.Infinity;
                child2.ABisArc = child2.ACisArc = child2.BCisArc = false;
            }
            else
            {
                aP             = baseTriangle.APrime.ApplyMatrix(child2Matrix);
                child2.ABisArc = child2.ACisArc = child2.BCisArc = true;
            }

            child2.Generation = 1;

            child2.ABwasReflectedAcross = false;
            child2.ACwasReflectedAcross = false;
            child2.BCwasReflectedAcross = true;

            child2.SetAngles(baseTriangle.AlphaAngle, baseTriangle.BetaAngle, baseTriangle.GammaAngle);
            child2.SetPoints(rotatedAlpha, baseTriangle.BetaPoint, baseTriangle.GammaPoint);
            child2.SetPrimePoints(aP, baseTriangle.BPrime, baseTriangle.CPrime);

            var newAB = TrungleUtils.Rotate(baseTriangle.AB_Points, child2Matrix);
            var newAC = TrungleUtils.Rotate(TrungleUtils.Reflect(baseTriangle.AC_Points), child2Matrix);
            var newBC = (Vector3[])baseTriangle.BC_Points.Clone();

            child2.SetSides(newAB, newAC, newBC);

            child2.Parent = baseTriangle;

            trungles.Add(child2);

            baseTriangle.BCwasReflectedAcross = true;
        }
        // TRIANGLE 3
        if (References.CurrentMode == ReflectionMode.Regular || orangeReflect)
        {
            go      = Instantiate(trungleStandard, Vector3.zero, Quaternion.identity);
            go.name = "Gen1";
            var child3 = go.GetComponent <TrungleBehavior>();

            Matrix child3Matrix = new Matrix(baseTriangle.AlphaPoint, baseTriangle.APrime, baseTriangle.AlphaAngle, RotationDirection.Counterclockwise);

            Vector3 rotatedBeta = baseTriangle.BetaPoint.ApplyMatrix(child3Matrix);
            Vector3 bP;

            if (References.CurrentType == TriangleType.Euclidean)
            {
                bP = References.Infinity;

                child3.ABisArc = child3.ACisArc = child3.BCisArc = false;
            }
            else
            {
                bP = baseTriangle.BPrime.ApplyMatrix(child3Matrix);

                child3.ABisArc = false;
                child3.ACisArc = false;
                child3.BCisArc = true;
            }

            child3.Generation = 1;

            child3.ABwasReflectedAcross = false;
            child3.ACwasReflectedAcross = true;
            child3.BCwasReflectedAcross = false;

            child3.SetAngles(baseTriangle.AlphaAngle, baseTriangle.BetaAngle, baseTriangle.GammaAngle);
            child3.SetPoints(baseTriangle.AlphaPoint, rotatedBeta, baseTriangle.GammaPoint);
            child3.SetPrimePoints(baseTriangle.APrime, bP, baseTriangle.CPrime);

            var newerAB = TrungleUtils.Rotate(baseTriangle.AB_Points, child3Matrix);
            var newerAC = (Vector3[])baseTriangle.AC_Points.Clone();
            var newerBC = TrungleUtils.Rotate(TrungleUtils.Reflect(baseTriangle.BC_Points), child3Matrix);

            child3.SetSides(newerAB, newerAC, newerBC);

            child3.Parent = baseTriangle;

            trungles.Add(child3);

            baseTriangle.ACwasReflectedAcross = true;
        }
    }
예제 #4
0
    /// **Overview** Called by `IncrementSteps` when the user presses + button.
    /// Makes a call to AngleChanged of this manager with the angles from the
    /// original triangle in the queue.
    public void AddGenerations()
    {
        TrungleBehavior baseTrungle = trungles[0];

        AngleChanged(baseTrungle.AlphaAngle, baseTrungle.BetaAngle, baseTrungle.GammaAngle);
    }