UE4 四叉树 QuadTree

UE4 四叉树 QuadTree

Engine\Source\Runtime\Engine\Public\GenericQuadTree.h

TQuadTree

template <typename ElementType, int32 NodeCapacity = 4>
class TQuadTree
{
	typedef TQuadTree<ElementType, NodeCapacity> TreeType;
public:

	/** DO NOT USE. This constructor is for internal usage only for hot-reload purposes. */
	TQuadTree();

	TQuadTree(const FBox2D& InBox, float InMinimumQuadSize = 100.f);

	/** Gets the TreeBox so systems can test insertions before trying to do so with invalid regions */
	const FBox2D& GetTreeBox() const { return TreeBox; }

	/** Inserts an object of type ElementType with an associated 2D box of size Box (log n). Pass in a DebugContext so when an issue occurs the log can report what requested this insert. */
	void Insert(const ElementType& Element, const FBox2D& Box, const TCHAR* DebugContext = nullptr);

	/** Given a 2D box, returns an array of elements within the box. There will not be any duplicates in the list. */
	template<typename ElementAllocatorType>
	void GetElements(const FBox2D& Box, TArray<ElementType, ElementAllocatorType>& ElementsOut) const;

	/** Removes an object of type ElementType with an associated 2D box of size Box (log n). Does not cleanup tree*/
	bool Remove(const ElementType& Instance, const FBox2D& Box);

	/** Does a deep copy of the tree by going through and re-creating the internal data. Cheaper than re-insertion as it should be linear instead of nlogn */
	void Duplicate(TreeType& OutDuplicate) const;

	/** Removes all elements of the tree */
	void Empty();

	void Serialize(FArchive& Ar);

	TreeType& operator=(const TreeType& Other);

	~TQuadTree();

private:
	enum QuadNames
	{
		TopLeft = 0,
		TopRight = 1,
		BottomLeft = 2,
		BottomRight = 3
	};

	/** Node used to hold the element and its corresponding 2D box*/
	struct FNode
	{
		FBox2D Box;
		ElementType Element;

		FNode() {};

		FNode(const ElementType& InElement, const FBox2D& InBox)
			: Box(InBox)
			, Element(InElement)
		{}

		friend FArchive& operator<<(FArchive& Ar, typename TQuadTree<ElementType, NodeCapacity>::FNode& Node)
		{
			return Ar << Node.Box << Node.Element;
		}
	};

	/** Given a 2D box, return the subtrees that are touched. Returns 0 for leaves. */
	int32 GetQuads(const FBox2D& Box, TreeType* Quads[4]) const;

	/** Split the tree into 4 sub-trees */
	void Split();

	/** Given a list of nodes, return which ones actually intersect the box */
	template<typename ElementAllocatorType>
	void GetIntersectingElements(const FBox2D& Box, TArray<ElementType, ElementAllocatorType>& ElementsOut) const;

	/** Given a list of nodes, remove the node that contains the given element */
	bool RemoveNodeForElement(const ElementType& Element);

	/** Internal recursive implementation of @see Insert */
	void InsertElementRecursive(const ElementType& Element, const FBox2D& Box, const TCHAR* DebugContext);

private:

	/**
	 * Contains the actual elements this tree is responsible for. Nodes are used to keep track of each element's AABB as well.
	 * For a non-internal leaf, this is the list of nodes that are fully contained within this tree.
	 * For an internal tree, this contains the nodes that overlap multiple subtrees.
	 */
	TArray<FNode> Nodes;

	/** The sub-trees of this tree */
	TreeType* SubTrees[4];

	/** AABB of the tree */
	FBox2D TreeBox;

	/** Center position of the tree */
	FVector2D Position;

	/** The smallest size of a quad allowed in the tree */
	float MinimumQuadSize;

	/** Whether this is a leaf or an internal sub-tree */
	bool bInternal;
};

Usage

#include "GenericQuadTree.h"

//Setup the Quad tree
float UVsQuadTreeMinSize = 0.001f;
TQuadTree<uint32, 100> QuadTree(BaseMeshUVBound,UVsQuadTreeMinSize);
//Insert data
for (FTriangleElement& TriangleElement : Triangles)
{
	QuadTree.Insert(TriangleElement.TriangleIndex, TriangleElement.UVsBound, DebugContext);
}
//Find a match triangle for every target vertices
TArray<uint32> QuadTreeTriangleResults;
//Reserve 10% to speed up the query
QuadTreeTriangleResults.Reserve(Triangles.Num() / 10); 

for (uint32 TargetVertexIndex = 0; TargetVertexIndex < (uint32)TargetVertices.Num(); ++TargetVertexIndex)
{
	//Reset the last data without flushing the memmery allocation
	QuadTreeTriangleResults.Reset();
	FVector2D Extent(DistanceThreshold, DistanceThreshold);
	FBox2D CurBox(TargetUV - Extent, TargetUV + Extent);
	while (QuadTreeTriangleResults.Num() <= 0)
	{
		QuadTree.GetElements(CurBox, QuadTreeTriangleResults);
		Extent *= 2;
		CurBox = FBox2D(TargetUV - Extent, TargetUV + Extent);
	}
}

应用

UE4聚合图测试

参考

  1. UE4 LOD Screen Size
在MATLAB中,你可以使用四叉树法(Quadtree)来进行建模。四叉树是一种将二维空间划分为四个象限的树结构,常用于空间索引和区域分割。 以下是一个简单的示例,展示如何使用四叉树法对二维数据进行建模: ```matlab % 创建一个包含二维数据的矩阵 data = rand(100, 2); % 定义四叉树的初始区域边界 x_min = min(data(:, 1)); x_max = max(data(:, 1)); y_min = min(data(:, 2)); y_max = max(data(:, 2)); boundary = [x_min, x_max, y_min, y_max]; % 创建四叉树对象 quadtree = Quadtree(boundary); % 将数据插入四叉树 for i = 1:size(data, 1) point = data(i, :); quadtree.insert(point); end % 可视化四叉树 figure; hold on; quadtree.plot(); % 绘制原始数据点 plot(data(:, 1), data(:, 2), 'ro'); axis equal; ``` 在这个示例中,我们首先创建了一个包含随机二维数据的矩阵。然后,定义了四叉树的初始区域边界,即数据的最小和最大边界。接下来,我们创建了一个四叉树对象,并使用`insert`方法将数据点插入到四叉树中。最后,使用`plot`方法可视化四叉树,并绘制原始数据点。 需要注意的是,上述示例中的`Quadtree`是一个自定义的类,你需要自行实现或者使用第三方库来创建该类。四叉树的实现可以根据具体需求进行调整和优化,可以包括查找、遍历、剪枝等操作。 希望这个示例能对你理解如何在MATLAB中使用四叉树进行建模提供帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值