예제 #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);
    }