示例#1
0
        public void Validate(UnitCell attacker, HexCell target, int damage, Action onCompletionCallback)
        {
            if (this.attacker != attacker)
            {
                Debug.LogError("Invalid attacker!");
                return;
            }

            if (this.target != target)
            {
                Debug.LogError("Invalid target!");
                isActioned = true;
                attacker.AttackComplete();
                return;
            }

            if (this.damage != damage)
            {
                Debug.LogError($"Damage mismatch. Expected {this.damage} got {damage}");
                this.damage = damage;
            }

            this.damage = damage;
            this.onCompletionCallback = onCompletionCallback;

            isValidated = true;

            CompleteAttackIfSynced();
        }
示例#2
0
 public ValidatedAttack(Int16 id, UnitCell attacker, HexCell target, int damage)
 {
     ID            = id;
     this.attacker = attacker;
     this.target   = target;
     this.damage   = damage;
 }
示例#3
0
    /**
     * Spawn cell into world from object pool
     */
    public void spawn(Vector3Int pos, UnitCell parent)
    {
        // If cell exists in this position, kill it
        if (getCell(pos) != null)
        {
            kill(pos);
        }

        // Expand object pool if required
        if (cellPool.Count == 0)
        {
            expandPool(1, cellPrefab);
        }

        // Get inactive cell GameObject
        GameObject cellObj = cellPool.Pop();

        // Set GameObject position
        cellObj.transform.position = getWorldPosition(pos);
        cellObj.transform.rotation = Quaternion.identity;
        cellObj.SetActive(true);

        UnitCell cell = cellObj.GetComponent <UnitCell>();

        cell.pos        = pos;
        cell.state      = SPAWNING;
        cell.generation = parent ? parent.generation + 1 : 0;
        setCell(pos, cellObj);
    }
示例#4
0
    public static ViewBox CreateViewBox(int cellsLong, int cellsHigh, int cellsWide, float boxSize, float rotX, float rotY, float rotZ, string filepath, Vector3 initPos)
    {
        Vector3 middlePoint = initPos;

        //making the object that will be copied
        GameObject boxObject = Instantiate(ViewBoxPreFab.gameObject, middlePoint, Quaternion.Euler(rotX, rotY, rotZ));

        ViewBox viewBox = boxObject.GetComponent <ViewBox>();

        //using square scales for proper display
        float boxLength = boxSize;
        float boxHeight = boxSize;
        float boxWidth  = boxSize;

        viewBox.cells   = new int[] { cellsLong, cellsHigh, cellsWide };
        viewBox.boxSize = new float[] { boxLength, boxHeight, boxWidth };
        Vector3 boxNum = new Vector3(boxLength, boxHeight, boxWidth);

        viewBox.origin    = new float[] { -boxLength / 2f, -boxHeight / 2f, -boxWidth / 2f };
        viewBox.rotations = new float[] { rotX, rotY, rotZ };

        boxObject.transform.localScale = boxNum;

        //could also detect if there are other view boxes and try to line them up

        // this is the unit cell that is copied; it gets disabled later
        UnitCell primeUnitCell = UnitCell.NewUnitCell(filepath, boxObject.GetComponent <ViewBox>());

        for (int i = 0; i < cellsLong; i++)
        {
            for (int j = 0; j < cellsHigh; j++)
            {
                for (int k = 0; k < cellsWide; k++)
                {
                    Vector3 xposVec = primeUnitCell.vecA * (float)i;
                    Vector3 yposVec = primeUnitCell.vecB * (float)j;
                    Vector3 zposVec = primeUnitCell.vecC * (float)k;

                    float xpos = xposVec.x + yposVec.x + zposVec.x;

                    float ypos = xposVec.y + yposVec.y + zposVec.y;

                    float zpos = xposVec.z + yposVec.z + zposVec.z;

                    Vector3 newPos = new Vector3(xpos, ypos, zpos);

                    newPos += new Vector3(viewBox.origin[0], viewBox.origin[1], viewBox.origin[2]);

                    GameObject iterUnitCell = Instantiate(primeUnitCell.gameObject, boxObject.transform);
                    iterUnitCell.transform.localPosition = newPos;
                }
            }
        }

        //disables this instance but keeps all of the other ones that are corectly positioned wrt eachother
        primeUnitCell.gameObject.SetActive(false);

        return(viewBox);
    }
示例#5
0
        public static int GetDamage(UnitCell attacker, HexCell target)
        {
            var attackerStats = attacker.GetStats();

            var damageMultiplier = Mathf.Max(1f - target.GetDamageMitigation(), 0f);

            return(Mathf.RoundToInt(attackerStats.Attack * damageMultiplier));
        }
示例#6
0
    /**
     * Return cell state at given position
     */
    public int getState(Vector3Int pos)
    {
        UnitCell cell = getCell(pos);

        if (!cell)
        {
            return(DEAD);
        }
        return(cell.state);
    }
示例#7
0
    /**
     * Returns True if given cell should die
     */
    protected virtual bool shouldDie(UnitCell cell)
    {
        int adjacentCells = adjacentCellCount(cell.pos);

        return(
            (cellLife != IMMORTAL && cell.age >= cellLife) ||
            adjacentCells >= neighboursCausingDeathMax ||
            adjacentCells <= neighboursCausingDeathMin
            );
    }
示例#8
0
 /**
  * Attempt to spawn child cells
  */
 protected virtual void spawnChildren(UnitCell cell)
 {
     foreach (Vector3Int apos in adjacentPositions(cell.pos))
     {
         if (shouldSpawn(apos))
         {
             spawn(apos, cell);
         }
     }
 }
示例#9
0
 /**
  * Update state of spawning cells and dying cells
  */
 public virtual void advanceState(UnitCell cell)
 {
     if (cell.state == SPAWNING)
     {
         cell.state = ALIVE;
     }
     if (cell.state == DYING)
     {
         kill(cell.pos);
     }
 }
示例#10
0
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    *                                           Cell behaviour
    *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    /**
     * Update cell spawning and cell death
     */
    public virtual void update(UnitCell cell)
    {
        cell.age += 1;
        if (cell.canMultiply)
        {
            spawnChildren(cell);
        }
        if (shouldDie(cell))
        {
            cell.state = DYING;
        }
    }
示例#11
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // 1. Retrieve/validate input
            var curves = new List <Curve>();

            if (!DA.GetDataList(0, curves))
            {
                return;
            }

            // 2. Convert curve input to line input
            var lines = new List <Line>();

            foreach (Curve curve in curves)
            {
                // Make sure the curve is linear, if not, return error and abort.
                if (!curve.IsLinear())
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "All struts must be linear.");
                    return;
                }
                // Convert curve to line
                lines.Add(new Line(curve.PointAtStart, curve.PointAtEnd));
            }

            // 3. Instantiate UnitCell object.
            UnitCell cell = new UnitCell(lines);

            // 4. CheckValidity instance method to check the unit cell. Use the return value to output useful error message.
            switch (cell.CheckValidity())
            {
            case -1:
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid cell - opposing faces must be identical.");
                return;

            case 0:
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid cell - each face needs at least one node lying on it.");
                return;

            case 1:
                AddRuntimeMessage(GH_RuntimeMessageLevel.Blank, "Your cell is valid!");
                break;
            }

            // 5. Set output
            DA.SetData(0, new UnitCellGoo(cell));
        }
    /**
     * Update cell spawning and cell death
     */
    public override void update(UnitCell cell)
    {
        if (cells.Count > 1024)
        {
            return;
        }

        cell.age += 1;
        if (cell.age > 1 && cell.canMultiply)
        {
            spawnChildren(cell);
            cell.canMultiply = false;
        }
        if (shouldDie(cell))
        {
            cell.state = DYING;
        }
    }
示例#13
0
        protected override void OnStart()
        {
            modify = Entity.Instance.UnitList.Clone();

            petCell.DataSource     = new PetCell(petItemPrefab, modify);
            petCell.ActionDelegate = this;
            petCell.PressDelegate  = this;

            var view = new UnitCell(petInfoItemPrefab);

            unitCell.DataSource     = view;
            unitCell.ActionDelegate = this;
            unitCell.PressDelegate  = this;
            view.GetCurrentUnit     = () => { return(modify.items[0]); };

            SetupUnit();
            Observer.Instance.Subscribe(UnitList.UpdateEvent, OnSubscribe);
            base.OnStart();
        }
示例#14
0
    // functions within UnitCell
    public static UnitCell NewUnitCell(string filepath, ViewBox parentViewBox)
    { //this is the order these functions should be run in, otherwise there won't be the correct things in place
        GameObject unitCellObject = Instantiate(UnitCellPreFab.gameObject, parentViewBox.transform);
        UnitCell   unitCell       = unitCellObject.GetComponent <UnitCell>();

        string[] atomsCIF = unitCell.ReadCif(filepath);

        unitCell.parentViewBox = parentViewBox;

        unitCell.unitCellScale = unitCell.SetScaleSize();

        unitCell.SetCorners();

        unitCell.atomList = unitCell.MakeAtoms(atomsCIF);

        unitCell.SetAtomColors();

        unitCell.DrawAllBoundaries();

        return((unitCell));;
    }
示例#15
0
        public void OnAttackReceived(Int16 id, UnitCell attacker, HexCell target, int damage, bool isDestroyed)
        {
            var attackIndex = attackActions.FindIndex(a => a.ID == id);

            if (attackIndex < 0)
            {
                Debug.LogError($"Received invalid attack action with id {id}");
                return;
            }

            var attack = attackActions[attackIndex];

            attackActions.RemoveAt(attackIndex);

            attack.Validate(attacker, target, damage, () =>
            {
                if (isDestroyed)
                {
                    game.Cells.RemoveCell(target);
                }
            });
        }
示例#16
0
    /**
     * Kill cell at given position and return cell to object pool
     */
    public void kill(Vector3Int pos)
    {
        GameObject cellObj = getCellObject(pos);

        if (!cellObj)
        {
            return;
        }

        // Deactivate object and add to stack
        cellObj.SetActive(false);
        cellPool.Push(cellObj);

        // Reset cell attributes
        UnitCell cell = cellObj.GetComponent <UnitCell>();

        cell.state      = DEAD;
        cell.age        = 0;
        cell.generation = 0;

        // Remove reference to GameObject
        setCell(pos, null);
    }
示例#17
0
    // Will be called by Unitcell while it is making all of the atoms originally
    public static Atom NewAtom(Element atomElement, Vector3 atomPosition, Vector3 latticePosition, string atomLabel, UnitCell parentUnitCell)
    {
        GameObject atomObject = Instantiate(Atom.AtomPreFab.gameObject, parentUnitCell.transform);

        Atom atom = atomObject.GetComponent <Atom>();

        atomObject.transform.localPosition = atomPosition;

        atom.atomElement     = atomElement;
        atom.atomPosition    = atomPosition;
        atom.latticePosition = latticePosition;
        //atomPosition is set relative to the unit cell and the unit cell will be scaled based off a, b, c
        atom.atomLabel      = atomLabel;
        atom.parentUnitCell = parentUnitCell;

        float atomSize = (float)atomElement.GetAtomicRadius() * parentUnitCell.unitCellScale;

        atom.transform.localScale = new Vector3(atomSize, atomSize, atomSize);


        return(atom);
    }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and
        /// to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // 1. Retrieve and validate data
            var    cell    = new UnitCell();
            double radius  = 0;
            double height  = 0;
            int    nU      = 0;
            int    nV      = 0;
            int    nW      = 0;
            bool   morphed = false;

            if (!DA.GetData(0, ref cell))
            {
                return;
            }
            if (!DA.GetData(1, ref radius))
            {
                return;
            }
            if (!DA.GetData(2, ref height))
            {
                return;
            }
            if (!DA.GetData(3, ref nU))
            {
                return;
            }
            if (!DA.GetData(4, ref nV))
            {
                return;
            }
            if (!DA.GetData(5, ref nW))
            {
                return;
            }
            if (!DA.GetData(6, ref morphed))
            {
                return;
            }

            if (!cell.isValid)
            {
                return;
            }
            if (radius == 0)
            {
                return;
            }
            if (height == 0)
            {
                return;
            }
            if (nU == 0)
            {
                return;
            }
            if (nV == 0)
            {
                return;
            }
            if (nW == 0)
            {
                return;
            }

            // 2. Initialize the lattice
            var lattice = new Lattice();
            // Will contain the morphed uv spaces (as surface-surface, surface-axis or surface-point)
            var spaceTree = new DataTree <GeometryBase>();

            // 3. Define cylinder
            Plane   basePlane = Plane.WorldXY;
            Surface cylinder  = (new Cylinder(new Circle(basePlane, radius), height)).ToNurbsSurface();

            cylinder = cylinder.Transpose();
            LineCurve axis = new LineCurve(basePlane.Origin, basePlane.Origin + height * basePlane.ZAxis);

            // 4. Package the number of cells in each direction into an array
            float[] N = new float[3] {
                nU, nV, nW
            };

            // 5. Normalize the UV-domain
            Interval unitDomain = new Interval(0, 1);

            cylinder.SetDomain(0, unitDomain); // surface u-direction
            cylinder.SetDomain(1, unitDomain); // surface v-direction
            axis.Domain = unitDomain;

            // 6. Prepare cell (this is a UnitCell object)
            cell = cell.Duplicate();
            cell.FormatTopology();

            // 7. Map nodes to design space
            //    Loop through the uvw cell grid
            for (int u = 0; u <= N[0]; u++)
            {
                for (int v = 0; v <= N[1]; v++)
                {
                    for (int w = 0; w <= N[2]; w++)
                    {
                        // Construct cell path in tree
                        GH_Path treePath = new GH_Path(u, v, w);
                        // Fetch the list of nodes to append to, or initialise it
                        var nodeList = lattice.Nodes.EnsurePath(treePath);

                        // This loop maps each node index in the cell onto the UV-surface maps
                        for (int i = 0; i < cell.Nodes.Count; i++)
                        {
                            double   usub = cell.Nodes[i].X;                  // u-position within unit cell (local)
                            double   vsub = cell.Nodes[i].Y;                  // v-position within unit cell (local)
                            double   wsub = cell.Nodes[i].Z;                  // w-position within unit cell (local)
                            double[] uvw  = { u + usub, v + vsub, w + wsub }; // uvw-position (global)

                            // Check if the node belongs to another cell (i.e. it's relative path points outside the current cell)
                            bool isOutsideCell = (cell.NodePaths[i][0] > 0 || cell.NodePaths[i][1] > 0 || cell.NodePaths[i][2] > 0);
                            // Check if current uvw-position is beyond the upper boundary
                            bool isOutsideSpace = (uvw[0] > N[0] || uvw[1] > N[1] || uvw[2] > N[2]);

                            if (isOutsideCell || isOutsideSpace)
                            {
                                nodeList.Add(null);
                            }
                            else
                            {
                                Point3d    pt1, pt2;
                                Vector3d[] derivatives;

                                // Construct z-position vector
                                Vector3d vectorZ = height * basePlane.ZAxis * uvw[0] / N[0];
                                // Compute pt1 (on axis)
                                pt1 = basePlane.Origin + vectorZ;
                                // Compute pt2 (on surface)
                                cylinder.Evaluate(uvw[0] / N[0], uvw[1] / N[1], 2, out pt2, out derivatives);

                                // Create vector joining these two points
                                Vector3d wVect = pt2 - pt1;
                                // Instantiate new node
                                var newNode = new LatticeNode(pt1 + wVect * uvw[2] / N[2]);
                                // Add new node to tree
                                nodeList.Add(newNode);
                            }
                        }
                    }

                    // Define the uv space map tree (used for morphing)
                    if (morphed && u < N[0] && v < N[1])
                    {
                        GH_Path spacePath = new GH_Path(u, v);
                        // Set trimming interval
                        var uInterval = new Interval((u) / N[0], (u + 1) / N[0]);
                        var vInterval = new Interval((v) / N[1], (v + 1) / N[1]);
                        // Create sub-surface and sub axis
                        Surface ss1 = cylinder.Trim(uInterval, vInterval);
                        Curve   ss2 = axis.Trim(uInterval);
                        // Unitize domains
                        ss1.SetDomain(0, unitDomain); ss1.SetDomain(1, unitDomain);
                        ss2.Domain = unitDomain;
                        // Save to the space tree
                        spaceTree.Add(ss1, spacePath);
                        spaceTree.Add(ss2, spacePath);
                    }
                }
            }

            // 8. Map struts to the node tree
            if (morphed)
            {
                lattice.MorphMapping(cell, spaceTree, N);
            }
            else
            {
                lattice.ConformMapping(cell, N);
            }

            // 9. Set output
            DA.SetDataList(0, lattice.Struts);
        }
示例#19
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and
        /// to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // 1. Declare placeholder variables and assign initial invalid data.
            //    This way, if the input parameters fail to supply valid data, we know when to abort
            var    cell      = new UnitCell();
            double xCellSize = 0;
            double yCellSize = 0;
            double zCellSize = 0;
            int    nX        = 0;
            int    nY        = 0;
            int    nZ        = 0;

            // 2. Retrieve input data.
            if (!DA.GetData(0, ref cell))
            {
                return;
            }
            if (!DA.GetData(1, ref xCellSize))
            {
                return;
            }
            if (!DA.GetData(2, ref yCellSize))
            {
                return;
            }
            if (!DA.GetData(3, ref zCellSize))
            {
                return;
            }
            if (!DA.GetData(4, ref nX))
            {
                return;
            }
            if (!DA.GetData(5, ref nY))
            {
                return;
            }
            if (!DA.GetData(6, ref nZ))
            {
                return;
            }

            // 3. If data is invalid, we need to abort.
            if (!cell.isValid)
            {
                return;
            }
            if (xCellSize == 0)
            {
                return;
            }
            if (yCellSize == 0)
            {
                return;
            }
            if (zCellSize == 0)
            {
                return;
            }
            if (nX == 0)
            {
                return;
            }
            if (nY == 0)
            {
                return;
            }
            if (nZ == 0)
            {
                return;
            }

            // 4. Initialise the lattice object
            var lattice = new Lattice();

            // 5. Prepare cell (this is a UnitCell object)
            cell = cell.Duplicate();
            cell.FormatTopology();

            // 6. Define BasePlane and directional iteration vectors
            Plane    basePlane = Plane.WorldXY;
            Vector3d vectorX   = xCellSize * basePlane.XAxis;
            Vector3d vectorY   = yCellSize * basePlane.YAxis;
            Vector3d vectorZ   = zCellSize * basePlane.ZAxis;

            float[] N = new float[3] {
                nX, nY, nZ
            };

            // 7. Map nodes to design space
            //    Loop through the uvw cell grid
            for (int u = 0; u <= N[0]; u++)
            {
                for (int v = 0; v <= N[1]; v++)
                {
                    for (int w = 0; w <= N[2]; w++)
                    {
                        // Construct cell path in tree
                        GH_Path treePath = new GH_Path(u, v, w);
                        // Fetch the list of nodes to append to, or initialise it
                        var nodeList = lattice.Nodes.EnsurePath(treePath);

                        // This loop maps each node in the cell
                        for (int i = 0; i < cell.Nodes.Count; i++)
                        {
                            double   usub = cell.Nodes[i].X;                  // u-position within unit cell (local)
                            double   vsub = cell.Nodes[i].Y;                  // v-position within unit cell (local)
                            double   wsub = cell.Nodes[i].Z;                  // w-position within unit cell (local)
                            double[] uvw  = { u + usub, v + vsub, w + wsub }; // uvw-position (global)

                            // Check if the node belongs to another cell (i.e. it's relative path points outside the current cell)
                            bool isOutsideCell = (cell.NodePaths[i][0] > 0 || cell.NodePaths[i][1] > 0 || cell.NodePaths[i][2] > 0);
                            // Check if current uvw-position is beyond the upper boundary
                            bool isOutsideSpace = (uvw[0] > N[0] || uvw[1] > N[1] || uvw[2] > N[2]);

                            if (isOutsideCell || isOutsideSpace)
                            {
                                nodeList.Add(null);
                            }
                            else
                            {
                                // Compute position vector
                                Vector3d V = uvw[0] * vectorX + uvw[1] * vectorY + uvw[2] * vectorZ;
                                // Instantiate new node
                                var newNode = new LatticeNode(basePlane.Origin + V);
                                // Add new node to tree
                                nodeList.Add(newNode);
                            }
                        }
                    }
                }
            }

            // 8. Map struts to the node tree
            lattice.ConformMapping(cell, N);

            // 9. Set output
            DA.SetDataList(0, lattice.Struts);
        }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // 0. Generate input menu list
            Component           = this;
            GrasshopperDocument = this.OnPingDocument();
            // Only generate it if the input has no source
            if (Component.Params.Input[0].SourceCount == 0)
            {
                InputTools.TopoSelect(ref Component, ref GrasshopperDocument, 0, 11);
            }

            // 1. Retrieve input
            int cellType = 0;

            if (!DA.GetData(0, ref cellType))
            {
                return;
            }

            // 2. Instantiate line list
            var lines = new List <Line>();

            // 3. Set cell size
            double d = 5;

            // 4. Switch statement for the different cell types
            switch (cellType)
            {
            // "GRID"
            case 0:
                lines = GridLines(d);
                break;

            // "X"
            case 1:
                lines = XLines(d);
                break;

            // "STAR"
            case 2:
                lines = StarLines(d);
                break;

            // "CROSS"
            case 3:
                lines = CrossLines(d);
                break;

            // "TESSERACT"
            case 4:
                lines = TesseractLines(d);
                break;

            // "VINTILES"
            case 5:
                lines = VintileLines(d);
                break;

            // "OCTET"
            case 6:
                lines = OctetLines(d);
                break;

            // "DIAMOND"
            case 7:
                lines = DiamondLines(d);
                break;

            // "HONEYCOMB"
            case 8:
                lines = Honeycomb(d);
                break;

            // "AUXETIC HONEYCOMB"
            case 9:
                lines = AuxeticHoneycomb(d);
                break;
            }

            // 5. Instantiate UnitCell object and check validity.
            var cell = new UnitCell(lines);

            if (!cell.isValid)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid cell - this is embarassing.");
            }

            // 6. Construct normalized cell lines (for optional output)
            var lines2 = new List <Line>();

            foreach (IndexPair nodePair in cell.NodePairs)
            {
                lines2.Add(new Line(cell.Nodes[nodePair.I], cell.Nodes[nodePair.J]));
            }

            // 7. Set output (as LatticeCellGoo)
            DA.SetData(0, new UnitCellGoo(cell));
            DA.SetDataList(1, lines2);
        }
 protected override bool shouldDie(UnitCell cell)
 {
     return(cell.age > 2);
 }
示例#22
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // 1. Retrieve and validate inputs
            var     cell    = new UnitCell();
            Surface surface = null;
            Point3d pt      = Point3d.Unset;
            int     nU      = 0;
            int     nV      = 0;
            int     nW      = 0;
            bool    morphed = false;

            if (!DA.GetData(0, ref cell))
            {
                return;
            }
            if (!DA.GetData(1, ref surface))
            {
                return;
            }
            if (!DA.GetData(2, ref pt))
            {
                return;
            }
            if (!DA.GetData(3, ref nU))
            {
                return;
            }
            if (!DA.GetData(4, ref nV))
            {
                return;
            }
            if (!DA.GetData(5, ref nW))
            {
                return;
            }
            if (!DA.GetData(6, ref morphed))
            {
                return;
            }

            if (!cell.isValid)
            {
                return;
            }
            if (!surface.IsValid)
            {
                return;
            }
            if (!pt.IsValid)
            {
                return;
            }
            if (nU == 0)
            {
                return;
            }
            if (nV == 0)
            {
                return;
            }
            if (nW == 0)
            {
                return;
            }

            // 2. Initialize the node tree, derivative tree and morphed space tree
            var lattice   = new Lattice();
            var spaceTree = new DataTree <GeometryBase>(); // will contain the morphed uv spaces (as surface-surface, surface-axis or surface-point)

            // 3. Package the number of cells in each direction into an array
            float[] N = new float[3] {
                nU, nV, nW
            };

            // 4. Normalize the UV-domain
            Interval unitDomain = new Interval(0, 1);

            surface.SetDomain(0, unitDomain); // surface u-direction
            surface.SetDomain(1, unitDomain); // surface v-direction

            // 5. Prepare cell (this is a UnitCell object)
            cell = cell.Duplicate();
            cell.FormatTopology();

            // 6. Map nodes to design space
            //    Loop through the uvw cell grid
            for (int u = 0; u <= N[0]; u++)
            {
                for (int v = 0; v <= N[1]; v++)
                {
                    for (int w = 0; w <= N[2]; w++)
                    {
                        // Construct cell path in tree
                        GH_Path treePath = new GH_Path(u, v, w);
                        // Fetch the list of nodes to append to, or initialise it
                        var nodeList = lattice.Nodes.EnsurePath(treePath);

                        // This loop maps each node in the cell onto the UV-surface map
                        for (int i = 0; i < cell.Nodes.Count; i++)
                        {
                            double   usub = cell.Nodes[i].X;                  // u-position within unit cell (local)
                            double   vsub = cell.Nodes[i].Y;                  // v-position within unit cell (local)
                            double   wsub = cell.Nodes[i].Z;                  // w-position within unit cell (local)
                            double[] uvw  = { u + usub, v + vsub, w + wsub }; // uvw-position (global)

                            // Check if the node belongs to another cell (i.e. it's relative path points outside the current cell)
                            bool isOutsideCell = (cell.NodePaths[i][0] > 0 || cell.NodePaths[i][1] > 0 || cell.NodePaths[i][2] > 0);
                            // Check if current uvw-position is beyond the upper boundary
                            bool isOutsideSpace = (uvw[0] > N[0] || uvw[1] > N[1] || uvw[2] > N[2]);

                            if (isOutsideCell || isOutsideSpace)
                            {
                                nodeList.Add(null);
                            }
                            else
                            {
                                Point3d pt1;
                                // Initialize for surface 2
                                Point3d pt2; Vector3d[] derivatives;

                                // Set pt1 (on point)
                                pt1 = pt;
                                // Compute pt2 (on surface)
                                surface.Evaluate(uvw[0] / N[0], uvw[1] / N[1], 2, out pt2, out derivatives);

                                // Create vector joining the two points (this is our w-range)
                                Vector3d wVect = pt2 - pt1;

                                // Create the node, accounting for the position along the w-direction
                                var newNode = new LatticeNode(pt1 + wVect * uvw[2] / N[2]);
                                // Add node to tree
                                nodeList.Add(newNode);
                            }
                        }
                    }

                    // Define the uv space tree (used for morphing)
                    if (morphed && u < N[0] && v < N[1])
                    {
                        GH_Path spacePath = new GH_Path(u, v);
                        // Set trimming interval
                        var uInterval = new Interval((u) / N[0], (u + 1) / N[0]);
                        var vInterval = new Interval((v) / N[1], (v + 1) / N[1]);
                        // Create sub-surface and point (never changes)
                        Surface ss1 = surface.Trim(uInterval, vInterval);
                        Point   ss2 = new Point(pt);
                        // Unitize domain
                        ss1.SetDomain(0, unitDomain); ss1.SetDomain(1, unitDomain);
                        // Save to the space tree
                        spaceTree.Add(ss1, spacePath);
                        spaceTree.Add(ss2, spacePath);
                    }
                }
            }

            // 7. Map struts to the node tree
            if (morphed)
            {
                lattice.MorphMapping(cell, spaceTree, N);
            }
            else
            {
                lattice.ConformMapping(cell, N);
            }

            // 8. Set output
            DA.SetDataList(0, lattice.Struts);
        }
示例#23
0
 protected override void spawnChildren(UnitCell cell)
 {
     spawn(cell.pos + Vector3Int.left, cell);
     cell.canMultiply = false;
 }
示例#24
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // 1. Retrieve and validate data
            var          cell             = new UnitCell();
            GeometryBase designSpace      = null;
            Plane        orientationPlane = Plane.Unset;
            double       xCellSize        = 0;
            double       yCellSize        = 0;
            double       zCellSize        = 0;
            double       minLength        = 0; // the trim tolerance (i.e. minimum strut length)
            double       maxLength        = 0;
            bool         strictlyIn       = false;

            if (!DA.GetData(0, ref cell))
            {
                return;
            }
            if (!DA.GetData(1, ref designSpace))
            {
                return;
            }
            if (!DA.GetData(2, ref orientationPlane))
            {
                return;
            }
            if (!DA.GetData(3, ref xCellSize))
            {
                return;
            }
            if (!DA.GetData(4, ref yCellSize))
            {
                return;
            }
            if (!DA.GetData(5, ref zCellSize))
            {
                return;
            }
            if (!DA.GetData(6, ref minLength))
            {
                return;
            }
            if (!DA.GetData(7, ref maxLength))
            {
                return;
            }
            if (!DA.GetData(8, ref strictlyIn))
            {
                return;
            }

            if (!cell.isValid)
            {
                return;
            }
            if (!designSpace.IsValid)
            {
                return;
            }
            if (!orientationPlane.IsValid)
            {
                return;
            }
            if (xCellSize == 0)
            {
                return;
            }
            if (yCellSize == 0)
            {
                return;
            }
            if (zCellSize == 0)
            {
                return;
            }
            if (minLength >= xCellSize || minLength >= yCellSize || minLength >= zCellSize)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Tolerance parameter cannot be larger than the unit cell dimensions.");
                return;
            }
            // 2. Validate the design space
            int spaceType = FrameTools.ValidateSpace(ref designSpace);

            if (spaceType == 0)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Design space must be a closed Brep, Mesh or Surface");
                return;
            }

            double tol = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance;

            // 3. Compute oriented bounding box and its corner points
            Box bBox = new Box();

            designSpace.GetBoundingBox(orientationPlane, out bBox);
            Point3d[] bBoxCorners = bBox.GetCorners();
            //    Set basePlane based on the bounding box
            Plane basePlane = new Plane(bBoxCorners[0], bBoxCorners[1], bBoxCorners[3]);

            // 4. Determine number of iterations required to fill the box, and package into array
            double xLength = bBoxCorners[0].DistanceTo(bBoxCorners[1]);
            double yLength = bBoxCorners[0].DistanceTo(bBoxCorners[3]);
            double zLength = bBoxCorners[0].DistanceTo(bBoxCorners[4]);
            int    nX      = (int)Math.Ceiling(xLength / xCellSize); // Roundup to next integer if non-integer
            int    nY      = (int)Math.Ceiling(yLength / yCellSize);
            int    nZ      = (int)Math.Ceiling(zLength / zCellSize);

            float[] N = new float[3] {
                nX, nY, nZ
            };

            // 5. Initialize nodeTree
            var lattice = new Lattice();

            // 6. Prepare cell (this is a UnitCell object)
            cell = cell.Duplicate();
            cell.FormatTopology();

            // 7. Define iteration vectors in each direction (accounting for Cell Size)
            Vector3d vectorU = xCellSize * basePlane.XAxis;
            Vector3d vectorV = yCellSize * basePlane.YAxis;
            Vector3d vectorW = zCellSize * basePlane.ZAxis;

            // 8. Map nodes to design space
            //    Loop through the uvw cell grid
            for (int u = 0; u <= N[0]; u++)
            {
                for (int v = 0; v <= N[1]; v++)
                {
                    for (int w = 0; w <= N[2]; w++)
                    {
                        // Construct cell path in tree
                        GH_Path treePath = new GH_Path(u, v, w);
                        // Fetch the list of nodes to append to, or initialise it
                        var nodeList = lattice.Nodes.EnsurePath(treePath);

                        // This loop maps each node in the cell
                        for (int i = 0; i < cell.Nodes.Count; i++)
                        {
                            double   usub = cell.Nodes[i].X;                  // u-position within unit cell (local)
                            double   vsub = cell.Nodes[i].Y;                  // v-position within unit cell (local)
                            double   wsub = cell.Nodes[i].Z;                  // w-position within unit cell (local)
                            double[] uvw  = { u + usub, v + vsub, w + wsub }; // uvw-position (global)

                            // Check if the node belongs to another cell (i.e. it's relative path points outside the current cell)
                            bool isOutsideCell = (cell.NodePaths[i][0] > 0 || cell.NodePaths[i][1] > 0 || cell.NodePaths[i][2] > 0);

                            // Check if current uvw-position is beyond the upper boundary
                            bool isOutsideSpace = (uvw[0] > N[0] || uvw[1] > N[1] || uvw[2] > N[2]);

                            if (isOutsideCell || isOutsideSpace)
                            {
                                nodeList.Add(null);
                            }
                            else
                            {
                                // Compute position vector
                                Vector3d V       = uvw[0] * vectorU + uvw[1] * vectorV + uvw[2] * vectorW;
                                var      newNode = new LatticeNode(basePlane.Origin + V);

                                // Check if point is inside - use unstrict tolerance, meaning it can be outside the surface by the specified tolerance
                                bool isInside = FrameTools.IsPointInside(designSpace, newNode.Point3d, spaceType, tol, strictlyIn);

                                // Set the node state (it's location wrt the design space)
                                if (isInside)
                                {
                                    newNode.State = LatticeNodeState.Inside;
                                }
                                else
                                {
                                    newNode.State = LatticeNodeState.Outside;
                                }

                                // Add node to tree
                                nodeList.Add(newNode);
                            }
                        }
                    }
                }
            }

            // 9. Map struts to the node tree
            lattice.UniformMapping(cell, designSpace, spaceType, N, minLength, maxLength);

            // 10. Set output
            DA.SetDataList(0, lattice.Struts);
        }