Ejemplo n.º 1
0
    protected static Vector3 MaxGradient(ArcOfSphere arc, Vector3 desired)
    {
        Vector3 max_gradient = Vector3.zero;
        float   max_product  = Mathf.NegativeInfinity;

        /** if we don't calculate per quadrant, calculations for an arc with angle 2*PI become ambiguous because left == right
         */
        float quadrants = Mathf.Ceil(arc.End() / (Mathf.PI / 2f)); //maximum of 4, always integral, float for casting "left" and "right"

        for (float quadrant = 0; quadrant < quadrants; ++quadrant)
        {
            float left  = arc.End() * (quadrant / quadrants);               //get beginning of quadrant i.e. 0.00,0.25,0.50,0.75
            float right = arc.End() * ((quadrant + 1) / quadrants);         //get    end    of quadrant i.e. 0.25,0.50,0.75,1.00

            float left_product  = Vector3.Dot(arc.Evaluate(left), desired); //find the correlation factor between left and the desired direction
            float right_product = Vector3.Dot(arc.Evaluate(right), desired);

            /** this is basically a binary search
             *
             *  1) take the left and right vectors and compute their dot products with the desired direction.
             *  2) take the lesser dot product and ignore that half of the remaining arc
             */
            for (int iteration = 0; iteration < 8 * sizeof(float); ++iteration) //because we are dealing with floats, more precision could help (or hurt?)
            {
                float midpoint = (left + right) / 2;
                if (left_product < right_product) //is the right vector closer to the desired direction?
                {
                    left         = midpoint;      //throw out the left half if the right vector is closer
                    left_product = Vector3.Dot(arc.Evaluate(left), desired);
                }
                else
                {
                    right         = midpoint; //throw out the right half if the left vector is closer
                    right_product = Vector3.Dot(arc.Evaluate(right), desired);
                }
            }

            /** figure out if this quadrant contains a larger gradient
             */
            if (max_product < right_product)
            {
                max_gradient = arc.Evaluate(right);
                max_product  = right_product;
            }
            if (max_product < left_product)
            {
                max_gradient = arc.Evaluate(left);
                max_product  = left_product;
            }
        }
        return(max_gradient);
    }
Ejemplo n.º 2
0
    public bool Traverse(ArcOfSphere path, Vector3 desiredPos)     //I don't like these parameters, they can be fixed //I don't like that this is public, it should be private and exposed via a generic move option if possible
    {
        optional <float> interpolation_factor = path.CartesianToRadial(desiredPos);

        if (interpolation_factor.exists)
        {
            ground = new GroundInfo();

            ground.data.angle = interpolation_factor.data;

            ground.data.arc    = path;
            ground.data.block  = path.GetComponentInParent <Block>();
            ground.data.height = path.LengthRadius(radius);
            ground.data.begin  = path.Begin(radius);
            ground.data.end    = path.End(radius);

            current_position = ArcOfSphere.Evaluate(ground.data, radius);
        }
        else
        {
            Debug.Log("Critical Failure: Traverse's interpolation factor doesn't exist!");
        }

        return(interpolation_factor.exists);
    }
Ejemplo n.º 3
0
    public static Edge LinkRight(ArcOfSphere left, Vector3 position)
    {
        Vector3 right = left.Evaluate(left.End());

        Edge obj = Edge.StartEdge(left.transform.parent.transform, right, position);

        obj.Relink(left, left.next);

        return(obj);
    }
Ejemplo n.º 4
0
    public override void Initialize(ArcOfSphere left, ArcOfSphere right)
    {
        #if UNITY_EDITOR
        this.Save();
        #endif

        Vector3 path_center = right.Evaluate(right.Begin());

        //Debug.DrawRay(path_center, Vector3.up, Color.yellow);

        path_normal = right.Evaluate(right.Begin());

        arc_left  = left.EvaluateNormal(left.End());
        arc_right = right.EvaluateNormal(right.Begin());

        Initialize(path_center);

        this.Relink(left, right);
    }
Ejemplo n.º 5
0
    public static void Append(GameObject shape)
    {
        lines = new List <QuadraticBezier>();

        ArcOfSphere first_edge = shape.GetComponentInChildren <Edge>();
        ArcOfSphere arc        = first_edge;

        do
        {
            float begin       = arc.Begin();
            float end         = arc.End();
            float range_begin = arc.Begin();
            float range_end   = arc.End();
            float range_mid   = arc.End() / 2;

            int[,] xyz_signs_begin       = new int[2, 3]; //positional, derivative; x, y, z
            int[,] xyz_signs_end         = new int[2, 3];
            int[,] xyz_signs_range_begin = new int[2, 3]; //immediately before the first detected change in sign
            int[,] xyz_signs_range_end   = new int[2, 3]; //the first detected change in any sign
            int[,] xyz_signs_range_mid   = new int[2, 3]; //middle of begin and range_end

            // get signs for beginning and end
            UpdateSigns(arc, ref xyz_signs_begin, arc.Begin(), delta);
            UpdateSigns(arc, ref xyz_signs_end, arc.End(), -delta);

            // process new lines until the signs match
            while (!SameSigns(ref xyz_signs_begin, ref xyz_signs_end))
            {
                xyz_signs_range_begin = xyz_signs_begin;
                xyz_signs_range_end   = xyz_signs_end;

                // binary search and discard ranges with matching slope signs and position signs at ends; and then update the slope signs.
                while (range_end - range_begin > delta)
                {
                    range_mid = (range_begin + range_end) / 2; //guaranteed not to overflow since numbers are in range [0, 2pi]
                    UpdateSigns(arc, ref xyz_signs_range_mid, range_mid, delta);
                    if (SameSigns(ref xyz_signs_range_begin, ref xyz_signs_range_mid))
                    {
                        range_begin = range_mid;
                        //xyz_signs_begin = xyz_signs_range_mid; //not necessary, the signs are the same
                    }
                    else
                    {
                        range_end           = range_mid;
                        xyz_signs_range_end = xyz_signs_range_mid;
                    }
                }
                // when you find a sign that switches, log the exact position of the switch with as much precision as possible

                Subdivide(arc, begin, range_begin);
                // when you find that position, you must then switch the x, y, z signs at the new beginning of the arc and the slope signs xyz at the beginning of the arc
                begin           = range_end;
                xyz_signs_begin = xyz_signs_range_end;
            }
            // draw the last line
            Subdivide(arc, begin, end);

            arc = arc.next;                                    // move to next arc
            while (arc.GetType().IsSubclassOf(typeof(Corner))) // skip corners //XXX: Corner is abstract... for now
            {
                arc = arc.next;
            }
        } while (arc != first_edge);
        ClampToEdges();
        OverlapSharedEdges();
        BuildShape();
    }