/*
     Copy constructor
 */
 public UniformGridGeometry(UniformGridGeometry gridToCopy)
 {
     mMinCorner = gridToCopy.mMinCorner;
     mGridExtent = gridToCopy.mGridExtent;
     mCellExtent = gridToCopy.mCellExtent;
     mCellsPerExtent = gridToCopy.mCellsPerExtent;
     mNumPoints = gridToCopy.mNumPoints;
 }
    /*
     *  Add a layer to the top of the nested grid.
     *  layerTemplate - UNiformGridGeometry defining child layer.
     *  iDecimation - amount by which to decimate child layer.
     *
     *  This facilitates building the tree from leaves to root.
     *  This method laso allocates memory for the newly added layer,
     *  and initializes its content with the default constructor.
     */
    public void AddLayer(UniformGridGeometry layerTemplate, int iDecimation)
    {
        mLayers.Add(new UniformGrid <ItemT>());
        int count = mLayers.Count;

        mLayers[count - 1].Decimate(layerTemplate, iDecimation);
        mLayers[count - 1].Init();
    }
 /*
  *  Copy constructor
  */
 public UniformGridGeometry(UniformGridGeometry gridToCopy)
 {
     mMinCorner      = gridToCopy.mMinCorner;
     mGridExtent     = gridToCopy.mGridExtent;
     mCellExtent     = gridToCopy.mCellExtent;
     mCellsPerExtent = gridToCopy.mCellsPerExtent;
     mNumPoints      = gridToCopy.mNumPoints;
 }
    void Awake()
    {
        Vector3 posMin = transform.position - 0.5f * new Vector3(transform.localScale.x, transform.localScale.y, transform.localScale.z);
        Vector3 posMax = transform.position + 0.5f * new Vector3(transform.localScale.x, transform.localScale.y, transform.localScale.z);

        // Define base grid to instantiate one particle per cell
        grid    = new UniformGridGeometry(numberOfTracers, posMin, posMax, false);
        tracers = new List <ParticleSystem.Particle>();

        CreateTracers();
    }
    void Awake()
    {
        Vector3 posMin = transform.position - 0.5f * new Vector3(transform.localScale.x, transform.localScale.y, transform.localScale.z);
        Vector3 posMax = transform.position + 0.5f * new Vector3(transform.localScale.x, transform.localScale.y, transform.localScale.z);

        // Define base grid to instantiate one particle per cell
        grid = new UniformGridGeometry(numberOfTracers, posMin, posMax, false);
        tracers = new List<ParticleSystem.Particle>();

        CreateTracers();
    }
    /*
     *  Create a lower-resolution uniform grid based on another
     *  src - Source uniform grid upon which to base dimensions of this one
     *  iDecimation - amount by which to reduce the number of grid cells in each dimension. Typically this would be 2.
     *
     *  The number of cells is decimated.  The number of points is different.
     */
    public virtual void Decimate(UniformGridGeometry src, int iDecimation)
    {
        mGridExtent   = src.mGridExtent;
        mMinCorner    = src.mMinCorner;
        mNumPoints[0] = (int)(src.GetNumCells(0) / iDecimation + 1);
        mNumPoints[1] = (int)(src.GetNumCells(1) / iDecimation + 1);
        mNumPoints[2] = (int)(src.GetNumCells(2) / iDecimation + 1);

        if (iDecimation > 1)
        {   // Decimation could reduce dimension and integer arithmetic could make value be 0, which is useless if src contained any data.
            mNumPoints[0] = Mathf.Max(2, mNumPoints[0]);
            mNumPoints[1] = Mathf.Max(2, mNumPoints[1]);
            mNumPoints[2] = Mathf.Max(2, mNumPoints[2]);
        }

        PrecomputeSpacing();
    }
    void AssignVorticity(float fMagnitude, uint numVortonsMax, IVorticityDistribution vorticityDistribution)
    {
        Vector3             vDimensions = vorticityDistribution.GetDomainSize(); // length of each side of grid box
        Vector3             vCenter     = (vorticityDistribution).GetCenter();   // Center of vorticity distribution
        Vector3             vMin        = (vCenter - 0.5f * vDimensions);        // Minimum corner of box containing vortons
        Vector3             vMax        = (vMin + vDimensions);                  // Maximum corner of box containing vortons
        UniformGridGeometry skeleton    = new UniformGridGeometry(numVortonsMax, vMin, vMax, true);

        // number of grid cells in each direction of virtual uniform grid
        int[] numCells = { (int)Mathf.Max(1, skeleton.GetNumCells(0))
                           ,                 (int)Mathf.Max(1, skeleton.GetNumCells(1))
                           ,                 (int)Mathf.Max(1, skeleton.GetNumCells(2)) };

        // Total number of cells should be as close to numVortonsMax as possible without going over.
        // Worst case allowable difference would be numVortonsMax=7 and numCells in each direction is 1 which yields a ratio of 1/7.
        // But in typical situations, the user would like expect total number of virtual cells to be closer to numVortonsMax than that.
        // E.g. if numVortonsMax=8^3=512 somehow yielded numCells[0]=numCells[1]=numCells[2]=7 then the ratio would be 343/512~=0.67.
        while (numCells[0] * numCells[1] * numCells[2] > numVortonsMax)
        {   // Number of cells is excessive.
            // This can happen when the trial number of cells in any direction is less than 1 -- then the other two will likely be too large.
            numCells[0] = (int)Mathf.Max(1, numCells[0] / 2);
            numCells[1] = (int)Mathf.Max(1, numCells[1] / 2);
            numCells[2] = (int)Mathf.Max(1, numCells[2] / 2);
        }

        float[] oneOverN     = { 1.0f / (float)(numCells[0]), 1.0f / (float)(numCells[1]), 1.0f / (float)(numCells[2]) };
        Vector3 gridCellSize = new Vector3(vDimensions.x * oneOverN[0], vDimensions.y * oneOverN[1], vDimensions.z * oneOverN[2]);
        float   vortonRadius = Mathf.Pow(gridCellSize.x * gridCellSize.y * gridCellSize.z, 1.0f / 3.0f) * 0.5f;

        if (0.0f == vDimensions.z)
        {   // z size is zero, so domain is 2D.
            vortonRadius = Mathf.Pow(gridCellSize.x * gridCellSize.y, 0.5f) * 0.5f;
        }
        Vector3 vNoise = (0.0f * gridCellSize);

        //-----------------------------------------------------------------------
        // Iterate through each point in a uniform grid.
        // If probe position is inside vortex core, add a vorton there.
        // This loop could be rewritten such that it only visits points inside the core,
        // but this loop structure can readily be reused for a wide variety of configurations.
        Vector3 position = new Vector3(0.0f, 0.0f, 0.0f); // vorton position

        int[] index = new int[3];                         // index of each position visited

        for (index[2] = 0; index[2] < numCells[2]; ++index[2])
        {   // For each z-coordinate...
            position.z = ((float)(index[2]) + 0.25f) * gridCellSize.z + vMin.z;
            for (index[1] = 0; index[1] < numCells[1]; ++index[1])
            {   // For each y-coordinate...
                position.y = ((float)(index[1]) + 0.25f) * gridCellSize.y + vMin.y;
                for (index[0] = 0; index[0] < numCells[0]; ++index[0])
                {   // For each x-coordinate...
                    position.x = ((float)(index[0]) + 0.25f) * gridCellSize.x + vMin.x;
                    position  += Random.Range(-1, 1) * (vNoise);
                    Vector3 vorticity = Vector3.zero;
                    vorticityDistribution.AssignVorticity(ref vorticity, position, vCenter);
                    Vorton vorton = new Vorton(position, vorticity * fMagnitude, vortonRadius);
                    if (vorticity.sqrMagnitude > global.GlobalVar.sTiny)
                    {   // Vorticity is significantly non-zero.
                        mVortonSim.AddVorton(vorton);
                    }
                }
            }
        }
        //-----------------------------------------------------------------------
    }
 public override void Decimate(UniformGridGeometry src, int iDecimation)
 {
     base.Decimate(src, iDecimation);
 }
 /*
  *  Copy shape from given uniform grid
  */
 public UniformGrid(UniformGridGeometry gridToCopy) : base(gridToCopy)
 {
 }
    /*
        Create a lower-resolution uniform grid based on another
        src - Source uniform grid upon which to base dimensions of this one
        iDecimation - amount by which to reduce the number of grid cells in each dimension. Typically this would be 2.

        The number of cells is decimated.  The number of points is different.
    */
    public virtual void Decimate(UniformGridGeometry src, int iDecimation)
    {
        mGridExtent = src.mGridExtent;
        mMinCorner = src.mMinCorner;
        mNumPoints[0] = (int)(src.GetNumCells(0) / iDecimation + 1);
        mNumPoints[1] = (int)(src.GetNumCells(1) / iDecimation + 1);
        mNumPoints[2] = (int)(src.GetNumCells(2) / iDecimation + 1);

        if (iDecimation > 1)
        {   // Decimation could reduce dimension and integer arithmetic could make value be 0, which is useless if src contained any data.
            mNumPoints[0] = Mathf.Max(2, mNumPoints[0]);
            mNumPoints[1] = Mathf.Max(2, mNumPoints[1]);
            mNumPoints[2] = Mathf.Max(2, mNumPoints[2]);
        }

        PrecomputeSpacing();
    }
 /*
     Copy shape information from another UniformGrid into this one
 */
 public void CopyShape(UniformGridGeometry src)
 {
     Decimate(src, 1);
 }
 /*
  *  Copy shape information from another UniformGrid into this one
  */
 public void CopyShape(UniformGridGeometry src)
 {
     Decimate(src, 1);
 }
    void AssignVorticity(float fMagnitude, uint numVortonsMax, IVorticityDistribution vorticityDistribution)
    {
        Vector3 vDimensions = vorticityDistribution.GetDomainSize(); // length of each side of grid box
        Vector3 vCenter = (vorticityDistribution).GetCenter(); // Center of vorticity distribution
        Vector3 vMin = (vCenter - 0.5f * vDimensions) ; // Minimum corner of box containing vortons
        Vector3 vMax = (vMin + vDimensions) ; // Maximum corner of box containing vortons
        UniformGridGeometry skeleton = new UniformGridGeometry(numVortonsMax, vMin, vMax, true ) ;
        // number of grid cells in each direction of virtual uniform grid
        int[] numCells = {   (int)Mathf.Max( 1 , skeleton.GetNumCells(0))
                         ,   (int)Mathf.Max( 1 , skeleton.GetNumCells(1))
                         ,   (int)Mathf.Max( 1 , skeleton.GetNumCells(2)) };

        // Total number of cells should be as close to numVortonsMax as possible without going over.
        // Worst case allowable difference would be numVortonsMax=7 and numCells in each direction is 1 which yields a ratio of 1/7.
        // But in typical situations, the user would like expect total number of virtual cells to be closer to numVortonsMax than that.
        // E.g. if numVortonsMax=8^3=512 somehow yielded numCells[0]=numCells[1]=numCells[2]=7 then the ratio would be 343/512~=0.67.
        while (numCells[0] * numCells[1] * numCells[2] > numVortonsMax)
        {   // Number of cells is excessive.
            // This can happen when the trial number of cells in any direction is less than 1 -- then the other two will likely be too large.
            numCells[0] = (int)Mathf.Max(1, numCells[0] / 2);
            numCells[1] = (int)Mathf.Max(1, numCells[1] / 2);
            numCells[2] = (int)Mathf.Max(1, numCells[2] / 2);
        }

        float[] oneOverN = { 1.0f / (float)(numCells[0]), 1.0f / (float)(numCells[1]), 1.0f / (float)(numCells[2]) };
        Vector3 gridCellSize = new Vector3(vDimensions.x * oneOverN[0] , vDimensions.y * oneOverN[1], vDimensions.z * oneOverN[2] ) ;
        float vortonRadius = Mathf.Pow(gridCellSize.x * gridCellSize.y * gridCellSize.z, 1.0f / 3.0f) * 0.5f;
        if (0.0f == vDimensions.z)
        {   // z size is zero, so domain is 2D.
            vortonRadius = Mathf.Pow(gridCellSize.x * gridCellSize.y, 0.5f) * 0.5f;
        }
        Vector3 vNoise = (0.0f * gridCellSize) ;

        //-----------------------------------------------------------------------
        // Iterate through each point in a uniform grid.
        // If probe position is inside vortex core, add a vorton there.
        // This loop could be rewritten such that it only visits points inside the core,
        // but this loop structure can readily be reused for a wide variety of configurations.
        Vector3 position = new Vector3(0.0f, 0.0f, 0.0f); // vorton position
        int[] index = new int[3]; // index of each position visited

        for (index[2] = 0; index[2] < numCells[2]; ++index[2])
        {   // For each z-coordinate...
            position.z = ((float)(index[2]) + 0.25f) * gridCellSize.z + vMin.z;
            for (index[1] = 0; index[1] < numCells[1]; ++index[1])
            {   // For each y-coordinate...
                position.y = ((float)(index[1]) + 0.25f) * gridCellSize.y + vMin.y;
                for (index[0] = 0; index[0] < numCells[0]; ++index[0])
                {   // For each x-coordinate...
                    position.x = ((float)(index[0]) + 0.25f) * gridCellSize.x + vMin.x;
                    position += Random.Range(-1, 1) * (vNoise);
                    Vector3 vorticity = Vector3.zero;
                    vorticityDistribution.AssignVorticity(ref vorticity, position, vCenter);
                    Vorton vorton = new Vorton(position, vorticity * fMagnitude, vortonRadius);
                    if (vorticity.sqrMagnitude > global.GlobalVar.sTiny)
                    {   // Vorticity is significantly non-zero.
                        mVortonSim.AddVorton(vorton);
                    }
                }
            }
        }
        //-----------------------------------------------------------------------
    }