This commit is contained in:
niko
2026-06-04 11:42:34 +02:00
parent f39ba70a9f
commit e720b98cd1
7488 changed files with 2493818 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
using System;
namespace KDTree
{
// Token: 0x02000002 RID: 2
public interface DistanceFunctions
{
// Token: 0x06000001 RID: 1
double Distance(double[] p1, double[] p2);
// Token: 0x06000002 RID: 2
double DistanceToRectangle(double[] point, double[] min, double[] max);
}
}
+362
View File
@@ -0,0 +1,362 @@
using System;
namespace KDTree
{
// Token: 0x02000004 RID: 4
public class IntervalHeap<T>
{
// Token: 0x06000006 RID: 6 RVA: 0x0000211D File Offset: 0x0000031D
public IntervalHeap()
: this(64)
{
}
// Token: 0x06000007 RID: 7 RVA: 0x0000212A File Offset: 0x0000032A
public IntervalHeap(int capacity)
{
this.tData = new T[capacity];
this.tKeys = new double[capacity];
this.Capacity = capacity;
this.Size = 0;
}
// Token: 0x17000001 RID: 1
// (get) Token: 0x06000008 RID: 8 RVA: 0x00002160 File Offset: 0x00000360
// (set) Token: 0x06000009 RID: 9 RVA: 0x00002177 File Offset: 0x00000377
public int Size { get; private set; }
// Token: 0x17000002 RID: 2
// (get) Token: 0x0600000A RID: 10 RVA: 0x00002180 File Offset: 0x00000380
// (set) Token: 0x0600000B RID: 11 RVA: 0x00002197 File Offset: 0x00000397
public int Capacity { get; private set; }
// Token: 0x17000003 RID: 3
// (get) Token: 0x0600000C RID: 12 RVA: 0x000021A0 File Offset: 0x000003A0
public T Min
{
get
{
if (this.Size == 0)
{
throw new Exception();
}
return this.tData[0];
}
}
// Token: 0x17000004 RID: 4
// (get) Token: 0x0600000D RID: 13 RVA: 0x000021D4 File Offset: 0x000003D4
public T Max
{
get
{
if (this.Size == 0)
{
throw new Exception();
}
T t;
if (this.Size == 1)
{
t = this.tData[0];
}
else
{
t = this.tData[1];
}
return t;
}
}
// Token: 0x17000005 RID: 5
// (get) Token: 0x0600000E RID: 14 RVA: 0x0000222C File Offset: 0x0000042C
public double MinKey
{
get
{
if (this.Size == 0)
{
throw new Exception();
}
return this.tKeys[0];
}
}
// Token: 0x17000006 RID: 6
// (get) Token: 0x0600000F RID: 15 RVA: 0x0000225C File Offset: 0x0000045C
public double MaxKey
{
get
{
if (this.Size == 0)
{
throw new Exception();
}
double num;
if (this.Size == 1)
{
num = this.tKeys[0];
}
else
{
num = this.tKeys[1];
}
return num;
}
}
// Token: 0x06000010 RID: 16 RVA: 0x000022AC File Offset: 0x000004AC
public void Insert(double key, T value)
{
if (this.Size >= this.Capacity)
{
this.Capacity *= 2;
T[] array = new T[this.Capacity];
Array.Copy(this.tData, array, this.tData.Length);
this.tData = array;
double[] array2 = new double[this.Capacity];
Array.Copy(this.tKeys, array2, this.tKeys.Length);
this.tKeys = array2;
}
this.Size++;
this.tData[this.Size - 1] = value;
this.tKeys[this.Size - 1] = key;
this.SiftInsertedValueUp();
}
// Token: 0x06000011 RID: 17 RVA: 0x00002368 File Offset: 0x00000568
public void RemoveMin()
{
if (this.Size == 0)
{
throw new Exception();
}
this.Size--;
this.tData[0] = this.tData[this.Size];
this.tKeys[0] = this.tKeys[this.Size];
this.tData[this.Size] = default(T);
this.SiftDownMin(0);
}
// Token: 0x06000012 RID: 18 RVA: 0x000023F0 File Offset: 0x000005F0
public void ReplaceMin(double key, T value)
{
if (this.Size == 0)
{
throw new Exception();
}
this.tData[0] = value;
this.tKeys[0] = key;
if (this.Size > 1)
{
if (this.tKeys[1] < key)
{
this.Swap(0, 1);
}
this.SiftDownMin(0);
}
}
// Token: 0x06000013 RID: 19 RVA: 0x00002460 File Offset: 0x00000660
public void RemoveMax()
{
if (this.Size == 0)
{
throw new Exception();
}
if (this.Size == 1)
{
this.RemoveMin();
}
else
{
this.Size--;
this.tData[1] = this.tData[this.Size];
this.tKeys[1] = this.tKeys[this.Size];
this.tData[this.Size] = default(T);
this.SiftDownMax(1);
}
}
// Token: 0x06000014 RID: 20 RVA: 0x00002504 File Offset: 0x00000704
public void ReplaceMax(double key, T value)
{
if (this.Size == 0)
{
throw new Exception();
}
if (this.Size == 1)
{
this.ReplaceMin(key, value);
}
else
{
this.tData[1] = value;
this.tKeys[1] = key;
if (key < this.tKeys[0])
{
this.Swap(0, 1);
}
this.SiftDownMax(1);
}
}
// Token: 0x06000015 RID: 21 RVA: 0x00002580 File Offset: 0x00000780
private int Swap(int x, int y)
{
T t = this.tData[y];
double num = this.tKeys[y];
this.tData[y] = this.tData[x];
this.tKeys[y] = this.tKeys[x];
this.tData[x] = t;
this.tKeys[x] = num;
return y;
}
// Token: 0x06000016 RID: 22 RVA: 0x000025E8 File Offset: 0x000007E8
private void SiftInsertedValueUp()
{
int num = this.Size - 1;
if (num != 0)
{
if (num == 1)
{
if (this.tKeys[num] < this.tKeys[num - 1])
{
this.Swap(num, num - 1);
}
}
else if (num % 2 == 1)
{
int num2 = (num / 2 - 1) | 1;
if (this.tKeys[num] < this.tKeys[num - 1])
{
num = this.Swap(num, num - 1);
if (this.tKeys[num] < this.tKeys[num2 - 1])
{
num = this.Swap(num, num2 - 1);
this.SiftUpMin(num);
}
}
else if (this.tKeys[num] > this.tKeys[num2])
{
num = this.Swap(num, num2);
this.SiftUpMax(num);
}
}
else
{
int num2 = (num / 2 - 1) | 1;
if (this.tKeys[num] > this.tKeys[num2])
{
num = this.Swap(num, num2);
this.SiftUpMax(num);
}
else if (this.tKeys[num] < this.tKeys[num2 - 1])
{
num = this.Swap(num, num2 - 1);
this.SiftUpMin(num);
}
}
}
}
// Token: 0x06000017 RID: 23 RVA: 0x00002758 File Offset: 0x00000958
private void SiftUpMin(int iChild)
{
int num = (iChild / 2 - 1) & -2;
while (num >= 0 && this.tKeys[iChild] < this.tKeys[num])
{
this.Swap(iChild, num);
iChild = num;
num = (iChild / 2 - 1) & -2;
}
}
// Token: 0x06000018 RID: 24 RVA: 0x000027A8 File Offset: 0x000009A8
private void SiftUpMax(int iChild)
{
int num = (iChild / 2 - 1) | 1;
while (num >= 0 && this.tKeys[iChild] > this.tKeys[num])
{
this.Swap(iChild, num);
iChild = num;
num = (iChild / 2 - 1) | 1;
}
}
// Token: 0x06000019 RID: 25 RVA: 0x000027F4 File Offset: 0x000009F4
private void SiftDownMin(int iParent)
{
for (int i = iParent * 2 + 2; i < this.Size; i = iParent * 2 + 2)
{
if (i + 2 < this.Size && this.tKeys[i + 2] < this.tKeys[i])
{
i += 2;
}
if (this.tKeys[i] >= this.tKeys[iParent])
{
break;
}
this.Swap(iParent, i);
if (i + 1 < this.Size && this.tKeys[i + 1] < this.tKeys[i])
{
this.Swap(i, i + 1);
}
iParent = i;
}
}
// Token: 0x0600001A RID: 26 RVA: 0x000028B8 File Offset: 0x00000AB8
private void SiftDownMax(int iParent)
{
for (int i = iParent * 2 + 1; i <= this.Size; i = iParent * 2 + 1)
{
if (i == this.Size)
{
if (this.tKeys[i - 1] > this.tKeys[iParent])
{
this.Swap(iParent, i - 1);
}
break;
}
if (i + 2 == this.Size)
{
if (this.tKeys[i + 1] > this.tKeys[i])
{
if (this.tKeys[i + 1] > this.tKeys[iParent])
{
this.Swap(iParent, i + 1);
}
break;
}
}
else if (i + 2 < this.Size)
{
if (this.tKeys[i + 2] > this.tKeys[i])
{
i += 2;
}
}
if (this.tKeys[i] <= this.tKeys[iParent])
{
break;
}
this.Swap(iParent, i);
if (this.tKeys[i - 1] > this.tKeys[i])
{
this.Swap(i, i - 1);
}
iParent = i;
}
}
// Token: 0x04000001 RID: 1
private const int DEFAULT_SIZE = 64;
// Token: 0x04000002 RID: 2
private T[] tData;
// Token: 0x04000003 RID: 3
private double[] tKeys;
}
}
+247
View File
@@ -0,0 +1,247 @@
using System;
namespace KDTree
{
// Token: 0x02000005 RID: 5
public class KDNode<T>
{
// Token: 0x0600001B RID: 27 RVA: 0x00002A10 File Offset: 0x00000C10
protected KDNode(int iDimensions, int iBucketCapacity)
{
this.iDimensions = iDimensions;
this.iBucketCapacity = iBucketCapacity;
this.Size = 0;
this.bSinglePoint = true;
this.tPoints = new double[iBucketCapacity + 1][];
this.tData = new T[iBucketCapacity + 1];
}
// Token: 0x17000007 RID: 7
// (get) Token: 0x0600001C RID: 28 RVA: 0x00002A60 File Offset: 0x00000C60
// (set) Token: 0x0600001D RID: 29 RVA: 0x00002A77 File Offset: 0x00000C77
public int Size { get; private set; }
// Token: 0x17000008 RID: 8
// (get) Token: 0x0600001E RID: 30 RVA: 0x00002A80 File Offset: 0x00000C80
public bool IsLeaf
{
get
{
return this.tPoints != null;
}
}
// Token: 0x0600001F RID: 31 RVA: 0x00002AA0 File Offset: 0x00000CA0
public void AddPoint(double[] tPoint, T kValue)
{
KDNode<T> kdnode = this;
while (!kdnode.IsLeaf)
{
kdnode.ExtendBounds(tPoint);
kdnode.Size++;
if (tPoint[kdnode.iSplitDimension] > kdnode.fSplitValue)
{
kdnode = kdnode.pRight;
}
else
{
kdnode = kdnode.pLeft;
}
}
kdnode.AddLeafPoint(tPoint, kValue);
}
// Token: 0x06000020 RID: 32 RVA: 0x00002B0C File Offset: 0x00000D0C
private void AddLeafPoint(double[] tPoint, T kValue)
{
this.tPoints[this.Size] = tPoint;
this.tData[this.Size] = kValue;
this.ExtendBounds(tPoint);
this.Size++;
if (this.Size == this.tPoints.Length - 1)
{
if (this.CalculateSplit())
{
this.SplitLeafNode();
}
else
{
this.IncreaseLeafCapacity();
}
}
}
// Token: 0x06000021 RID: 33 RVA: 0x00002B90 File Offset: 0x00000D90
private bool CheckBounds(double[] tPoint)
{
int i = 0;
while (i < this.iDimensions)
{
bool flag;
if (tPoint[i] > this.tMaxBound[i])
{
flag = false;
}
else
{
if (tPoint[i] >= this.tMinBound[i])
{
i++;
continue;
}
flag = false;
}
return flag;
}
return true;
}
// Token: 0x06000022 RID: 34 RVA: 0x00002BEC File Offset: 0x00000DEC
private void ExtendBounds(double[] tPoint)
{
if (this.tMinBound == null)
{
this.tMinBound = new double[this.iDimensions];
this.tMaxBound = new double[this.iDimensions];
Array.Copy(tPoint, this.tMinBound, this.iDimensions);
Array.Copy(tPoint, this.tMaxBound, this.iDimensions);
}
else
{
for (int i = 0; i < this.iDimensions; i++)
{
if (double.IsNaN(tPoint[i]))
{
if (!double.IsNaN(this.tMinBound[i]) || !double.IsNaN(this.tMaxBound[i]))
{
this.bSinglePoint = false;
}
this.tMinBound[i] = double.NaN;
this.tMaxBound[i] = double.NaN;
}
else if (this.tMinBound[i] > tPoint[i])
{
this.tMinBound[i] = tPoint[i];
this.bSinglePoint = false;
}
else if (this.tMaxBound[i] < tPoint[i])
{
this.tMaxBound[i] = tPoint[i];
this.bSinglePoint = false;
}
}
}
}
// Token: 0x06000023 RID: 35 RVA: 0x00002D27 File Offset: 0x00000F27
private void IncreaseLeafCapacity()
{
Array.Resize<double[]>(ref this.tPoints, this.tPoints.Length * 2);
Array.Resize<T>(ref this.tData, this.tData.Length * 2);
}
// Token: 0x06000024 RID: 36 RVA: 0x00002D58 File Offset: 0x00000F58
private bool CalculateSplit()
{
bool flag;
if (this.bSinglePoint)
{
flag = false;
}
else
{
double num = 0.0;
for (int i = 0; i < this.iDimensions; i++)
{
double num2 = this.tMaxBound[i] - this.tMinBound[i];
if (double.IsNaN(num2))
{
num2 = 0.0;
}
if (num2 > num)
{
this.iSplitDimension = i;
num = num2;
}
}
if (num == 0.0)
{
flag = false;
}
else
{
this.fSplitValue = (this.tMinBound[this.iSplitDimension] + this.tMaxBound[this.iSplitDimension]) * 0.5;
if (this.fSplitValue == double.PositiveInfinity)
{
this.fSplitValue = double.MaxValue;
}
else if (this.fSplitValue == double.NegativeInfinity)
{
this.fSplitValue = double.MinValue;
}
if (this.fSplitValue == this.tMaxBound[this.iSplitDimension])
{
this.fSplitValue = this.tMinBound[this.iSplitDimension];
}
flag = true;
}
}
return flag;
}
// Token: 0x06000025 RID: 37 RVA: 0x00002EB4 File Offset: 0x000010B4
private void SplitLeafNode()
{
this.pRight = new KDNode<T>(this.iDimensions, this.iBucketCapacity);
this.pLeft = new KDNode<T>(this.iDimensions, this.iBucketCapacity);
for (int i = 0; i < this.Size; i++)
{
double[] array = this.tPoints[i];
T t = this.tData[i];
if (array[this.iSplitDimension] > this.fSplitValue)
{
this.pRight.AddLeafPoint(array, t);
}
else
{
this.pLeft.AddLeafPoint(array, t);
}
}
this.tPoints = null;
this.tData = null;
}
// Token: 0x04000006 RID: 6
protected internal int iDimensions;
// Token: 0x04000007 RID: 7
protected internal int iBucketCapacity;
// Token: 0x04000008 RID: 8
protected internal double[][] tPoints;
// Token: 0x04000009 RID: 9
protected internal T[] tData;
// Token: 0x0400000A RID: 10
protected internal KDNode<T> pLeft;
// Token: 0x0400000B RID: 11
protected internal KDNode<T> pRight;
// Token: 0x0400000C RID: 12
protected internal int iSplitDimension;
// Token: 0x0400000D RID: 13
protected internal double fSplitValue;
// Token: 0x0400000E RID: 14
protected internal double[] tMinBound;
// Token: 0x0400000F RID: 15
protected internal double[] tMaxBound;
// Token: 0x04000010 RID: 16
protected internal bool bSinglePoint;
}
}
+33
View File
@@ -0,0 +1,33 @@
using System;
namespace KDTree
{
// Token: 0x02000006 RID: 6
public class KDTree<T> : KDNode<T>
{
// Token: 0x06000026 RID: 38 RVA: 0x00002F60 File Offset: 0x00001160
public KDTree(int iDimensions)
: base(iDimensions, 24)
{
}
// Token: 0x06000027 RID: 39 RVA: 0x00002F6E File Offset: 0x0000116E
public KDTree(int iDimensions, int iBucketCapacity)
: base(iDimensions, iBucketCapacity)
{
}
// Token: 0x06000028 RID: 40 RVA: 0x00002F7C File Offset: 0x0000117C
public NearestNeighbour<T> NearestNeighbors(double[] tSearchPoint, int iMaxReturned, double fDistance = -1.0)
{
DistanceFunctions distanceFunctions = new SquareEuclideanDistanceFunction();
return this.NearestNeighbors(tSearchPoint, distanceFunctions, iMaxReturned, fDistance);
}
// Token: 0x06000029 RID: 41 RVA: 0x00002FA0 File Offset: 0x000011A0
public NearestNeighbour<T> NearestNeighbors(double[] tSearchPoint, DistanceFunctions kDistanceFunction, int iMaxReturned, double fDistance)
{
return new NearestNeighbour<T>(this, tSearchPoint, kDistanceFunction, iMaxReturned, fDistance);
}
}
}
+55
View File
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{99604A24-13D0-4C83-A3AA-9A315339FA49}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>KDTree</RootNamespace>
<AssemblyName>KDTree</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
</PropertyGroup>
<ItemGroup>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Compile Include="DistanceFunctions.cs" />
<Compile Include="IntervalHeap.cs" />
<Compile Include="KDNode.cs" />
<Compile Include="KDTree.cs" />
<Compile Include="MinHeap.cs" />
<Compile Include="NearestNeighbour.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SquareEuclideanDistanceFunction.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\mscorlib\mscorlib.csproj">
<Project>{99604a24-13d0-4c83-a3aa-9a315339fa4c}</Project>
<Name>mscorlib</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+143
View File
@@ -0,0 +1,143 @@
using System;
namespace KDTree
{
// Token: 0x02000007 RID: 7
public class MinHeap<T>
{
// Token: 0x0600002A RID: 42 RVA: 0x00002FBD File Offset: 0x000011BD
public MinHeap()
: this(MinHeap<T>.DEFAULT_SIZE)
{
}
// Token: 0x0600002B RID: 43 RVA: 0x00002FCD File Offset: 0x000011CD
public MinHeap(int iCapacity)
{
this.tData = new T[iCapacity];
this.tKeys = new double[iCapacity];
this.Capacity = iCapacity;
this.Size = 0;
}
// Token: 0x17000009 RID: 9
// (get) Token: 0x0600002C RID: 44 RVA: 0x00003000 File Offset: 0x00001200
// (set) Token: 0x0600002D RID: 45 RVA: 0x00003017 File Offset: 0x00001217
public int Size { get; private set; }
// Token: 0x1700000A RID: 10
// (get) Token: 0x0600002E RID: 46 RVA: 0x00003020 File Offset: 0x00001220
// (set) Token: 0x0600002F RID: 47 RVA: 0x00003037 File Offset: 0x00001237
public int Capacity { get; private set; }
// Token: 0x06000030 RID: 48 RVA: 0x00003040 File Offset: 0x00001240
public void Insert(double key, T value)
{
if (this.Size >= this.Capacity)
{
this.Capacity *= 2;
T[] array = new T[this.Capacity];
Array.Copy(this.tData, array, this.tData.Length);
this.tData = array;
double[] array2 = new double[this.Capacity];
Array.Copy(this.tKeys, array2, this.tKeys.Length);
this.tKeys = array2;
}
this.tData[this.Size] = value;
this.tKeys[this.Size] = key;
this.SiftUp(this.Size);
this.Size++;
}
// Token: 0x06000031 RID: 49 RVA: 0x00003100 File Offset: 0x00001300
public void RemoveMin()
{
if (this.Size == 0)
{
throw new Exception();
}
this.Size--;
this.tData[0] = this.tData[this.Size];
this.tKeys[0] = this.tKeys[this.Size];
this.tData[this.Size] = default(T);
this.SiftDown(0);
}
// Token: 0x1700000B RID: 11
// (get) Token: 0x06000032 RID: 50 RVA: 0x00003188 File Offset: 0x00001388
public T Min
{
get
{
if (this.Size == 0)
{
throw new Exception();
}
return this.tData[0];
}
}
// Token: 0x1700000C RID: 12
// (get) Token: 0x06000033 RID: 51 RVA: 0x000031BC File Offset: 0x000013BC
public double MinKey
{
get
{
if (this.Size == 0)
{
throw new Exception();
}
return this.tKeys[0];
}
}
// Token: 0x06000034 RID: 52 RVA: 0x000031EC File Offset: 0x000013EC
private void SiftUp(int iChild)
{
int num = (iChild - 1) / 2;
while (iChild != 0 && this.tKeys[iChild] < this.tKeys[num])
{
T t = this.tData[num];
double num2 = this.tKeys[num];
this.tData[num] = this.tData[iChild];
this.tKeys[num] = this.tKeys[iChild];
this.tData[iChild] = t;
this.tKeys[iChild] = num2;
iChild = num;
num = (iChild - 1) / 2;
}
}
// Token: 0x06000035 RID: 53 RVA: 0x00003280 File Offset: 0x00001480
private void SiftDown(int iParent)
{
for (int i = iParent * 2 + 1; i < this.Size; i = iParent * 2 + 1)
{
if (i + 1 < this.Size && this.tKeys[i] > this.tKeys[i + 1])
{
i++;
}
if (this.tKeys[iParent] <= this.tKeys[i])
{
break;
}
T t = this.tData[iParent];
double num = this.tKeys[iParent];
this.tData[iParent] = this.tData[i];
this.tKeys[iParent] = this.tKeys[i];
this.tData[i] = t;
this.tKeys[i] = num;
iParent = i;
}
}
// Token: 0x04000012 RID: 18
private static int DEFAULT_SIZE = 64;
// Token: 0x04000013 RID: 19
private T[] tData;
// Token: 0x04000014 RID: 20
private double[] tKeys;
}
}
+192
View File
@@ -0,0 +1,192 @@
using System;
using System.Collections;
namespace KDTree
{
// Token: 0x02000008 RID: 8
public class NearestNeighbour<T> : IEnumerator
{
// Token: 0x06000037 RID: 55 RVA: 0x00003360 File Offset: 0x00001560
public NearestNeighbour(KDNode<T> pRoot, double[] tSearchPoint, DistanceFunctions kDistance, int iMaxPoints, double fThreshold)
{
if (tSearchPoint.Length != pRoot.iDimensions)
{
throw new Exception("Dimensionality of search point and kd-tree are not the same.");
}
this.tSearchPoint = new double[tSearchPoint.Length];
Array.Copy(tSearchPoint, this.tSearchPoint, tSearchPoint.Length);
this.iPointsRemaining = Math.Min(iMaxPoints, pRoot.Size);
this.fThreshold = fThreshold;
this.kDistanceFunction = kDistance;
this.pRoot = pRoot;
this.iMaxPointsReturned = iMaxPoints;
this._CurrentDistance = -1.0;
this.pEvaluated = new IntervalHeap<T>();
this.pPending = new MinHeap<KDNode<T>>();
this.pPending.Insert(0.0, pRoot);
}
// Token: 0x06000038 RID: 56 RVA: 0x00003444 File Offset: 0x00001644
public bool MoveNext()
{
bool flag;
if (this.iPointsRemaining == 0)
{
this._Current = default(T);
flag = false;
}
else
{
while (this.pPending.Size > 0 && (this.pEvaluated.Size == 0 || this.pPending.MinKey < this.pEvaluated.MinKey))
{
KDNode<T> kdnode = this.pPending.Min;
this.pPending.RemoveMin();
while (!kdnode.IsLeaf)
{
KDNode<T> kdnode2;
if (this.tSearchPoint[kdnode.iSplitDimension] > kdnode.fSplitValue)
{
kdnode2 = kdnode.pLeft;
kdnode = kdnode.pRight;
}
else
{
kdnode2 = kdnode.pRight;
kdnode = kdnode.pLeft;
}
double num = this.kDistanceFunction.DistanceToRectangle(this.tSearchPoint, kdnode2.tMinBound, kdnode2.tMaxBound);
if (this.fThreshold < 0.0 || num <= this.fThreshold)
{
if (this.pEvaluated.Size < this.iPointsRemaining || num <= this.pEvaluated.MaxKey)
{
this.pPending.Insert(num, kdnode2);
}
}
}
if (kdnode.bSinglePoint)
{
double num = this.kDistanceFunction.Distance(kdnode.tPoints[0], this.tSearchPoint);
if (this.fThreshold < 0.0 || num < this.fThreshold)
{
if (this.pEvaluated.Size < this.iPointsRemaining || num <= this.pEvaluated.MaxKey)
{
for (int i = 0; i < kdnode.Size; i++)
{
if (this.pEvaluated.Size == this.iPointsRemaining)
{
this.pEvaluated.ReplaceMax(num, kdnode.tData[i]);
}
else
{
this.pEvaluated.Insert(num, kdnode.tData[i]);
}
}
}
}
}
else
{
for (int i = 0; i < kdnode.Size; i++)
{
double num = this.kDistanceFunction.Distance(kdnode.tPoints[i], this.tSearchPoint);
if (this.fThreshold < 0.0 || num < this.fThreshold)
{
if (this.pEvaluated.Size < this.iPointsRemaining)
{
this.pEvaluated.Insert(num, kdnode.tData[i]);
}
else if (num < this.pEvaluated.MaxKey)
{
this.pEvaluated.ReplaceMax(num, kdnode.tData[i]);
}
}
}
}
}
if (this.pEvaluated.Size == 0)
{
flag = false;
}
else
{
this.iPointsRemaining--;
this._CurrentDistance = this.pEvaluated.MinKey;
this._Current = this.pEvaluated.Min;
this.pEvaluated.RemoveMin();
flag = true;
}
}
return flag;
}
// Token: 0x06000039 RID: 57 RVA: 0x000037D4 File Offset: 0x000019D4
public void Reset()
{
this.iPointsRemaining = Math.Min(this.iMaxPointsReturned, this.pRoot.Size);
this._CurrentDistance = -1.0;
this.pEvaluated = new IntervalHeap<T>();
this.pPending = new MinHeap<KDNode<T>>();
this.pPending.Insert(0.0, this.pRoot);
}
// Token: 0x1700000D RID: 13
// (get) Token: 0x0600003A RID: 58 RVA: 0x00003840 File Offset: 0x00001A40
object IEnumerator.Current
{
get
{
return this._Current;
}
}
// Token: 0x1700000E RID: 14
// (get) Token: 0x0600003B RID: 59 RVA: 0x00003860 File Offset: 0x00001A60
public double CurrentDistance
{
get
{
return this._CurrentDistance;
}
}
// Token: 0x1700000F RID: 15
// (get) Token: 0x0600003C RID: 60 RVA: 0x00003878 File Offset: 0x00001A78
public T Current
{
get
{
return this._Current;
}
}
// Token: 0x04000017 RID: 23
private double[] tSearchPoint;
// Token: 0x04000018 RID: 24
private DistanceFunctions kDistanceFunction;
// Token: 0x04000019 RID: 25
private MinHeap<KDNode<T>> pPending;
// Token: 0x0400001A RID: 26
private IntervalHeap<T> pEvaluated;
// Token: 0x0400001B RID: 27
private KDNode<T> pRoot = null;
// Token: 0x0400001C RID: 28
private int iMaxPointsReturned = 0;
// Token: 0x0400001D RID: 29
private int iPointsRemaining;
// Token: 0x0400001E RID: 30
private double fThreshold;
// Token: 0x0400001F RID: 31
private double _CurrentDistance = -1.0;
// Token: 0x04000020 RID: 32
private T _Current = default(T);
}
}
+17
View File
@@ -0,0 +1,17 @@
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("KDTree")]
[assembly: AssemblyTitle("KDTree")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b1f6e08e-691d-42c0-9eea-7e9de37deb76")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+40
View File
@@ -0,0 +1,40 @@
using System;
namespace KDTree
{
// Token: 0x02000003 RID: 3
public class SquareEuclideanDistanceFunction : DistanceFunctions
{
// Token: 0x06000003 RID: 3 RVA: 0x00002050 File Offset: 0x00000250
public double Distance(double[] p1, double[] p2)
{
double num = 0.0;
for (int i = 0; i < p1.Length; i++)
{
double num2 = p1[i] - p2[i];
num += num2 * num2;
}
return num;
}
// Token: 0x06000004 RID: 4 RVA: 0x00002094 File Offset: 0x00000294
public double DistanceToRectangle(double[] point, double[] min, double[] max)
{
double num = 0.0;
for (int i = 0; i < point.Length; i++)
{
double num2 = 0.0;
if (point[i] > max[i])
{
num2 = point[i] - max[i];
}
else if (point[i] < min[i])
{
num2 = point[i] - min[i];
}
num += num2 * num2;
}
return num;
}
}
}