instance of parent Class not accessible from subclass? "does not exist in current context"

50 Views Asked by At

So I'm fairly new to all this. I've got the beginnings of a simple Octree implementation for a Unity project. This consists of an Octree parent class, an instance of it, and a OctreeNode subclass

I'm currently trying to access some cached public variables in an instance of Octree from the OctreeNode subclass but it's throwing "The name 'oTree' does not exist in current context".

Previously, I had tried to access these variables directly from the parent class, without having created an instance of it - this resulting in a different error of "An object reference is required for the non-static field, method, or property 'Octree.property'" so I tried remedying it by instantiating the class.

Now that I check, it seems that the oTree instance isn't available anywhere except the constructor... My foundation in C# is fairly patchy so it's probably something rlly basic

Here the errors are in the last 3 methods - I've commented the lines that present the error.

public class Octree
{
    public OctreeNode rootNode;
    public List<OctreeNode> LeafNodes { get; private set; }
    public float MinimumWidth { get; private set; }
    public int MaxDepth { get; private set; }

    public Octree(Vector3 center, Bounds bounds, int capacity = 5, float minimumWidth = .5f, int maxDepth = 5)
    {
        Octree oTree = this;
        oTree.rootNode = new OctreeNode(center, bounds, capacity);
        oTree.MinimumWidth = minimumWidth;
        oTree.MaxDepth = maxDepth;
        oTree.LeafNodes = new List<OctreeNode>();
    }

    public class OctreeNode
    {
        public Vector3 Center { get; private set; }
        public Bounds Bounds { get; private set; }
        public List<Vector3> Members { get; private set; }
        public OctreeNode[] Children { get; private set; }
        public List<OctreeNode> CurrentNeighbours { get; private set; }
        public int Capacity { get; private set; }


        public OctreeNode(Vector3 center, Bounds bounds, int capacity = 5)
        {
            Center = center;
            Bounds = bounds;
            Members = new List<Vector3>(capacity);
            Children = null;
            CurrentNeighbours = null;
            Capacity = capacity;
        }

        public bool IsLeaf()
        {
            return Children == null;
        }

        private bool IsPotentialNeighbour(OctreeNode other, float searchRadius)
        {
            // Bounds Checks
        }

        private void BuildNeighbourList(OctreeNode node, float searchRadius = 1f)
        {
            foreach (OctreeNode otherLeaf in oTree.LeafNodes)   // Error: oTree non-existent?
            {
                if (node != otherLeaf) 
                {
                    if (IsPotentialNeighbour(otherLeaf, searchRadius))
                    {
                        node.CurrentNeighbours.Add(otherLeaf);
                    }
                }
            }
        }

        // Initial Call
        private void BuildLeafNodeList()
        {
            List<OctreeNode> LeafNodes = oTree.LeafNodes;      // Error: oTree non-existent?
            OctreeNode root = oTree.rootNode;                  // Error: oTree non-existent?

            if (root.IsLeaf()) { LeafNodes.Add(root); return; }
            foreach (OctreeNode child in root.Children)
            {
                BuildLeafNodeList(child, LeafNodes);
            }
        }

        // Recursive Call
        private void BuildLeafNodeList(OctreeNode node, List<OctreeNode> LeafNodes)
        {
            if (node.IsLeaf()) { LeafNodes.Add(node); return; }

            foreach (OctreeNode child in node.Children)
            {
                BuildLeafNodeList(child, LeafNodes);
            }
        }
    }
}

Any help/suggestions would be much obliged :)

1

There are 1 best solutions below

5
Enigmativity On

I've created a cut-down version of your code so that you can see how to traverse the nodes to build a set of leaf nodes.

public class Octree
{
    public OctreeNode RootNode { get; private set; }

    public Octree()
    {
        this.RootNode = new OctreeNode();
    }

    public Octree(OctreeNode rootNode)
    {
        this.RootNode = rootNode;
    }

    public class OctreeNode
    {
        private List<OctreeNode> Children = new List<OctreeNode>();

        public OctreeNode()
        { }
        
        public OctreeNode(IEnumerable<OctreeNode> children)
        {
            this.Children.AddRange(children);
        }

        public bool IsLeaf => this.Children.IsEmpty();

        public IEnumerable<OctreeNode> GetDescendantLeafNodes()
        {
            if (this.IsLeaf)
            {
                yield return this;
            }
            else
            {
                foreach (var child in this.Children)
                {
                    foreach (var leaf in child.GetDescendantLeafNodes())
                    {
                        yield return leaf;
                    }
                }
            }
        }
    }
}

I have purposefully made the children a private List<OctreeNode> rather than an array. You can instantiate an empty list to represent leaf nodes rather than using null which has a habit of throwing NullReferenceExceptions, and you don't want external code changing the members of your tree.

Here's a sample tree:

var octree =
    new Octree(
        new Octree.OctreeNode(
            new Octree.OctreeNode[]
            {
                new Octree.OctreeNode(
                    new Octree.OctreeNode[]
                    {
                        new Octree.OctreeNode(),
                        new Octree.OctreeNode(),
                    }),
                new Octree.OctreeNode(),
                new Octree.OctreeNode(),
                new Octree.OctreeNode(),
            }));

When I call octree.RootNode.GetDescendantLeafNodes() I get the expected 5 empty nodes:

emptynodes