I am trying to implement quad tree data structure. When I already done with it and run a project, I have got a break with message:
System.TypeLoadException
HResult=0x80131522
Message= Could not load type: "DataStructures.WorldQuadTree+Node" from "SomeProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null".
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>
Here is my WorldQuadTree
class:
using System;
using System.Collections.Generic;
using MyMath;
namespace DataStructures
{
class WorldQuadTree
{
public struct Configuration
{
public int nodeCapacity;
public float width;
public float length;
}
struct Node
{
private readonly WorldQuadTree tree;
private bool isSubdivided;
public readonly BoundingBox boundary;
public readonly int index;
public Heap<Node>.Block subNodes;
public Heap<WorldObject>.Block content;
public Node(WorldQuadTree tree, int index, BoundingBox boundary, Heap<WorldObject>.Block content)
{
this.tree = tree;
this.index = index;
this.boundary = boundary;
this.content = content;
this.subNodes = default(Heap<Node>.Block);
this.isSubdivided = false;
}
public bool Contains(Vector3 point)
{
return boundary.Contains(point) != ContainmentType.Disjoint;
}
public bool Intersects(BoundingBox box)
{
return boundary.Intersects(box);
}
public bool Insert(WorldObject obj)
{
for (byte call = 0; call < 2; call++)
{
if (isSubdivided)
{
int capacity = subNodes.Capacity;
for (int i = 0; i < capacity; i++)
{
if (subNodes[i].Insert(obj))
return true;
}
return false;
}
else
{
int capacity = content.Capacity;
for (int i = 0; i < capacity; i++)
{
if (content[i] is null)
{
content[i] = obj;
return true;
}
else if (content[i].Equals(obj))
return false;
}
isSubdivided = true;
subNodes = tree.Subdivide(index);
continue;
}
}
throw new NotImplementedException("Insertion operation has failed.");
}
public bool Remove(WorldObject obj)
{
if (isSubdivided)
{
int capacity = subNodes.Capacity;
for (int i = 0; i < capacity; i++)
{
if (subNodes[i].Remove(obj))
return true;
}
return false;
}
else
{
int index = content.Remove(obj);
return index < 0 ? false : true;
}
}
public int GetResponsibleFor(Vector3 point)
{
if (boundary.Contains(point) == ContainmentType.Disjoint)
return -1;
if (isSubdivided)
{
int capacity = subNodes.Capacity;
for (int current, i = 0; i < capacity; i++)
{
current = subNodes[i].GetResponsibleFor(point);
if (current >= 0)
return current;
}
return -1;
}
else return index;
}
public void Query(BoundingBox box, List<WorldObject> results)
{
if (Intersects(box) is false)
return;
if (isSubdivided)
{
int capacity = subNodes.Capacity;
for (int i = 0; i < capacity; i++)
subNodes[i].Query(box, results);
}
else
{
int capacity = content.Capacity;
for (int i = 0; i < capacity; i++)
{
if (content[i].BoundingBox.Intersects(box))
results.Add(content[i]);
}
}
}
}
private readonly int nodeCapacity;
private readonly Heap<Node> nodesHeap;
private readonly Heap<WorldObject> contentHeap;
private Node root;
public int Capacity => contentHeap.Capacity;
public WorldObject this[int index] => contentHeap[index];
public WorldQuadTree(Configuration config, Heap<WorldObject>.Configuration heapConfig)
{
var boundary = new BoundingBox
{
Min = new Vector3(-config.width * 0.5f, 0, -config.length * 0.5f),
Max = new Vector3( config.width * 0.5f, 0, config.length * 0.5f),
};
this.nodeCapacity = config.nodeCapacity;
this.nodesHeap = new Heap<Node>(4, 16);
this.contentHeap = new Heap<WorldObject>(heapConfig.initialCapacity, heapConfig.growRate);
this.root = new Node(this, 0, boundary, contentHeap.GetBlock(config.nodeCapacity, out _));
}
private Heap<Node>.Block Subdivide(int index)
{
Node node = nodesHeap[index];
Vector3 center = node.boundary.Center;
Vector3 thickness = node.boundary.HalfExtents;
var subNodes = nodesHeap.GetBlock(4, out int pointer);
// begin configuring sub nodes in the conter-clokwise order.
// Configure top-right node.
var boundary = new BoundingBox(center, center + thickness);
subNodes[0] = new Node(this, pointer, boundary, contentHeap.GetBlock(nodeCapacity, out _));
// Configure top-left node.
pointer++;
thickness.X = -thickness.X;
boundary = new BoundingBox(center, center + thickness);
subNodes[1] = new Node(this, pointer, boundary, contentHeap.GetBlock(nodeCapacity, out _));
// Configure down-left node.
pointer++;
thickness.Y = -thickness.Y;
boundary = new BoundingBox(center, center + thickness);
subNodes[2] = new Node(this, pointer, boundary, contentHeap.GetBlock(nodeCapacity, out _));
// Configure down-right node.
pointer++;
thickness.X = -thickness.X;
boundary = new BoundingBox(center, center + thickness);
subNodes[3] = new Node(this, pointer, boundary, contentHeap.GetBlock(nodeCapacity, out _));
// delegate parent node content to sub nodes
int length = node.content.Capacity;
for (int i = 0; i < length; i++)
{
for (int j = 0; j < 4; j++)
{
if (subNodes[j].Contains(node.content[i].Position))
{
subNodes[j].Insert(node.content[i]);
continue;
}
}
}
// free parent node content
node.content.Free();
nodesHeap[index] = node;
return subNodes;
}
public bool Insert(WorldObject obj) => root.Insert(obj);
public bool Remove(WorldObject obj) => root.Remove(obj);
public void Query(BoundingBox box, List<WorldObject> results) => root.Query(box, results);
/// <summary>
/// Updates quad tree according to the object movement.
/// </summary>
/// <returns>
/// Returns false when given object is outside of boundary, otherwise true.
/// </returns>
public bool OnObjectMoved(WorldObject obj, Vector3 displacement)
{
int to = root.GetResponsibleFor(obj.Position);
int from = root.GetResponsibleFor(obj.Position - displacement);
if (from < 0)
{
throw new ArgumentException($"Has not contained object: {obj}, at position: {obj.Position - displacement}.");
}
else nodesHeap[from].Remove(obj);
if (to >= 0)
{
nodesHeap[to].Insert(obj);
}
else return false;
return true;
}
public void Clear(bool shouldMinimizeMemory = false)
{
if (shouldMinimizeMemory)
{
contentHeap.SetMinimumCapacity(nodeCapacity);
}
nodesHeap.Clear();
contentHeap.Clear();
}
}
}
I know there is already popular: Assembly name should differ from .exe file name
. But I don't know how to check it. I mean, I have many .dll
files in my bin/x86/Debug
folder, but none of them have the same name as my .exe
file. I also think that VS even didn't build my main(project) .dll
file.
Has no clue what is going wrong...
Btw, I use Visual Studio 2019 with project run on .NET framework 4.
EDIT:
When I remove that file(WorldQuadTree.cs) from my project - everything works fine and aplication is runnable. Now I know that it is somthing wrong with my CODE. However, I don't see any problem in my code which could cause "TypeLoadException". I tryid to rename every class I used in it, but result was the same. Hope it helps you... and me.
I solved problem, even though I could not repeat it in a blank new project.
But.
When I have changed "Block" type from "struct" to "class" System.TypeLoadException has gone; and if I roll previous changes back exception will be thrown again.
Even though I could not repeat it in a blank new project, it defenetly depence on Block type being struct.
User contributions licensed under CC BY-SA 3.0