From bac00e475bab7863a4cbb02fbc1b4cb8d28b0b03 Mon Sep 17 00:00:00 2001 From: BobLd <38405645+BobLd@users.noreply.github.com> Date: Wed, 26 Jun 2024 16:27:12 +0100 Subject: [PATCH] Improve KdTree creation performance --- .../KdTree.cs | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/UglyToad.PdfPig.DocumentLayoutAnalysis/KdTree.cs b/src/UglyToad.PdfPig.DocumentLayoutAnalysis/KdTree.cs index 8d5a10b8a..b6fbf07c2 100644 --- a/src/UglyToad.PdfPig.DocumentLayoutAnalysis/KdTree.cs +++ b/src/UglyToad.PdfPig.DocumentLayoutAnalysis/KdTree.cs @@ -89,16 +89,56 @@ public KdTree(IReadOnlyList elements, Func elementsPointFunc) array[i] = new KdTreeElement(i, elementsPointFunc(el), el); } +#if NET6_0_OR_GREATER + Root = BuildTree(new Span>(array)); +#else Root = BuildTree(new ArraySegment>(array)); +#endif } +#if NET6_0_OR_GREATER + private KdTreeNode BuildTree(Span> P, int depth = 0) + { + if (P.Length == 0) + { + return null; + } + + if (P.Length == 1) + { + return new KdTreeLeaf(P[0], depth); + } + + if (depth % 2 == 0) + { + P.Sort(kdTreeComparerX); + } + else + { + P.Sort(kdTreeComparerY); + } + + if (P.Length == 2) + { + return new KdTreeNode(new KdTreeLeaf(P[0], depth + 1), null, P[1], depth); + } + + int median = P.Length / 2; + + KdTreeNode vLeft = BuildTree(P.Slice(0, median), depth + 1); + KdTreeNode vRight = BuildTree(P.Slice(median + 1), depth + 1); + + return new KdTreeNode(vLeft, vRight, P[median], depth); + } +#else private KdTreeNode BuildTree(ArraySegment> P, int depth = 0) { if (P.Count == 0) { return null; } - else if (P.Count == 1) + + if (P.Count == 1) { return new KdTreeLeaf(P.GetAt(0), depth); } @@ -124,6 +164,7 @@ private KdTreeNode BuildTree(ArraySegment> P, int depth = 0) return new KdTreeNode(vLeft, vRight, P.GetAt(median), depth); } +#endif #region NN ///