Algorithm 给定欧几里德距离范围划分相邻点

Algorithm 给定欧几里德距离范围划分相邻点,algorithm,cluster-analysis,partitioning,spatial,euclidean-distance,Algorithm,Cluster Analysis,Partitioning,Spatial,Euclidean Distance,给定两点p,Q和aδ,我定义了等价关系~=,其中p~=Q,如果欧几里德距离(p,Q)肯定是一个问题 您还可以尝试对每个coordonate进行排序,并使用这两个列表(排序是n*log(n),并且您只能检查满足dx的点。重述问题的一种方法如下:给定一组n2D点,对于每个点p找到以p为中心的直径圆delta所包含的点集 简单的线性搜索给出了您提到的O(n^2)算法 在我看来,在最坏的情况下,这是最好的方法。当集合中的所有点都包含在一个直径的圆内时,对于每个点,计算距离原点的距离D(n),这是一个O(

给定两点p,Q和aδ,我定义了等价关系~=,其中p~=Q,如果
欧几里德距离(p,Q)
肯定是一个问题


您还可以尝试对每个coordonate进行排序,并使用这两个列表(排序是
n*log(n)
,并且您只能检查满足
dx的点。重述问题的一种方法如下:给定一组
n
2D点,对于每个点
p
找到以
p
为中心的直径圆
delta
所包含的点集

简单的线性搜索给出了您提到的
O(n^2)
算法


在我看来,在最坏的情况下,这是最好的方法。当集合中的所有点都包含在一个直径的圆内时,对于每个点,计算距离原点的距离D(n),这是一个O(n)运算

使用O(n^2)算法查找匹配项,其中D(a-b)delta

平均而言,由于跳过的数量(希望很大),结果一定比O(n^2)好。

这是一个C#KdTree实现,应该能够解决“在增量中查找点p的所有邻居”。它大量使用函数编程技术(是的,我喜欢Python)这是测试的,但我在理解
\u TreeFindNearest()
方面仍然有疑问。解决问题的代码(或伪代码)“在平均情况下划分一组n个点的关系比O(n^2)更好”在另一个答案中发布

/*
Stripped C# 2.0 port of ``kdtree'', a library for working with kd-trees.
Copyright (C) 2007-2009 John Tsiombikas <nuclear@siggraph.org>
Copyright (C) 2010 Francesco Pretto <ceztko@gmail.com>

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/

using System;
using System.Collections.Generic;
using System.Text;

namespace ITR.Data.NET
{
    public class KdTree<T>
    {
        #region Fields

        private Node _Root;
        private int _Count;
        private int _Dimension;
        private CoordinateGetter<T>[] _GetCoordinate;

        #endregion // Fields

        #region Constructors

        public KdTree(params CoordinateGetter<T>[] coordinateGetters)
        {
            _Dimension = coordinateGetters.Length;
            _GetCoordinate = coordinateGetters;
        }

        #endregion // Constructors

        #region Public methods

        public void Insert(T location)
        {
            _TreeInsert(ref _Root, 0, location);
            _Count++;
        }

        public void InsertAll(IEnumerable<T> locations)
        {
            foreach (T location in locations)
                Insert(location);
        }

        public IEnumerable<T> FindNeighborsRange(T location, double range)
        {
            return _TreeFindNeighborsRange(_Root, 0, location, range);
        }

        #endregion // Public methods

        #region Tree traversal

        private void _TreeInsert(ref Node current, int currentPlane, T location)
        {
            if (current == null)
            {
                current = new Node(location);
                return;
            }

            int nextPlane = (currentPlane + 1) % _Dimension;

            if (_GetCoordinate[currentPlane](location) <
                    _GetCoordinate[currentPlane](current.Location))
                _TreeInsert(ref current._Left, nextPlane, location);
            else
                _TreeInsert(ref current._Right, nextPlane, location);
        }

        private IEnumerable<T> _TreeFindNeighborsRange(Node current, int currentPlane,
            T referenceLocation, double range)
        {
            if (current == null)
                yield break;

            double squaredDistance = 0;
            for (int it = 0; it < _Dimension; it++)
            {
                double referenceCoordinate = _GetCoordinate[it](referenceLocation);
                double currentCoordinate = _GetCoordinate[it](current.Location);
                squaredDistance +=
                    (referenceCoordinate - currentCoordinate)
                    * (referenceCoordinate - currentCoordinate);
            }

            if (squaredDistance <= range * range)
                yield return current.Location;

            double coordinateRelativeDistance =
                _GetCoordinate[currentPlane](referenceLocation)
                    - _GetCoordinate[currentPlane](current.Location);
            Direction nextDirection = coordinateRelativeDistance <= 0.0
                ? Direction.LEFT : Direction.RIGHT;
            int nextPlane = (currentPlane + 1) % _Dimension;
            IEnumerable<T> subTreeNeighbors =
                _TreeFindNeighborsRange(current[nextDirection], nextPlane,
                    referenceLocation, range);
            foreach (T location in subTreeNeighbors)
                yield return location;

            if (Math.Abs(coordinateRelativeDistance) <= range)
            {
                subTreeNeighbors =
                    _TreeFindNeighborsRange(current.GetOtherChild(nextDirection),
                        nextPlane, referenceLocation, range);
                foreach (T location in subTreeNeighbors)
                    yield return location;
            }
        }

        #endregion // Tree traversal

        #region Node class

        public class Node
        {
            #region Fields

            private T _Location;
            internal Node _Left;
            internal Node _Right;

            #endregion // Fields

            #region Constructors

            internal Node(T nodeValue)
            {
                _Location = nodeValue;
                _Left = null;
                _Right = null;
            }

            #endregion // Contructors

            #region Children Indexers

            public Node this[Direction direction]
            {
                get { return direction == Direction.LEFT ? _Left : Right; }
            }

            public Node GetOtherChild(Direction direction)
            {
                return direction == Direction.LEFT ? _Right : _Left;
            }

            #endregion // Children Indexers

            #region Properties

            public T Location
            {
                get { return _Location; }
            }

            public Node Left
            {
                get { return _Left; }
            }

            public Node Right
            {
                get { return _Right; }
            }

            #endregion // Properties
        }

        #endregion // Node class

        #region Properties

        public int Count
        {
            get { return _Count; }
            set { _Count = value; }
        }

        public Node Root
        {
            get { return _Root; }
            set { _Root = value; }
        }

        #endregion // Properties
    }

    #region Enums, delegates

    public enum Direction
    {
        LEFT = 0,
        RIGHT
    }

    public delegate double CoordinateGetter<T>(T location);

    #endregion // Enums, delegates
}
/*
剥离了“kdtree”的C#2.0端口,这是一个用于处理kd树的库。
版权所有(C)2007-2009 John Tsiombikas
版权所有(C)2010 Francesco Pretto
以源代码和二进制形式重新分发和使用,带或不带
如果满足以下条件,则允许进行修改:
1.源代码的重新分发必须保留上述版权声明,本
条件列表和以下免责声明。
2.以二进制形式重新分发必须复制上述版权声明,
此条件列表和文档中的以下免责声明
和/或分发时提供的其他材料。
3.作者的姓名不得用于产品的宣传或推广
未经事先书面许可,从本软件派生。
本软件由作者“按原样”和任何明示或暗示的方式提供
保证,包括但不限于以下各项的默示保证:
不承认适销性和特定用途的适用性
作者应对任何直接、间接、偶然、特殊、,
惩戒性或间接损害(包括但不限于采购)
替代商品或服务的损失;使用、数据或利润的损失;或业务损失
中断)无论是何种原因造成的,且基于任何责任理论,无论是在
产生的合同、严格责任或侵权行为(包括疏忽或其他)
以任何方式退出本软件的使用,即使被告知的可能性
这样的损失。
*/
使用制度;
使用System.Collections.Generic;
使用系统文本;
命名空间ITR.Data.NET
{
公共类KdTree
{
#区域字段
私有节点_根;
私人国际单位计数;
私有整数维;
私人协调人[]_GetCoordinate;
#endregion//字段
#区域构造函数
公共KdTree(参数CoordinateGeter[]CoordinateGeters)
{
_尺寸=坐标系。长度;
_GetCoordinate=协调器;
}
#endregion//构造函数
#区域公共方法
公共空白插入(T位置)
{
_树插入(参考根,0,位置);
_计数++;
}
public void InsertAll(IEnumberable位置)
{
foreach(位置中的T位置)
插入(位置);
}
公共IEnumerable FindNeighborsRange(T位置,双范围)
{
返回_TreeFindNeighborsRange(_Root,0,location,range);
}
#endregion//公共方法
#区域树遍历
私有void _TreeInsert(ref节点当前、int currentPlane、T位置)
{
如果(当前==null)
{
当前=新节点(位置);
返回;
}
int nextPlane=(当前平面+1)%\u维度;
if(_GetCoordinate[currentPlane](位置)<
_GetCoordinate[currentPlane](当前位置))
_树入口(参考电流,左,下一平面,位置);
其他的
_树入口(参考当前位置,下一个平面,位置);
}
private IEnumerable\u TreeFindNeighborsRange(节点当前、int currentPlane、,
T参考位置,双量程)
{
如果(当前==null)
屈服断裂;
双平方距离=0;
对于(int it=0;it<\u维;it++)
{
double referenceCoordinate=_GetCoordinate[it](referenceLocation);
double currentCoordinate=_GetCoordinate[it](当前位置);
平方距离+=
(参考坐标-当前坐标)
*(参考坐标-当前坐标);
}
如果(squaredInstance以下C#方法与KdTree类、Join()(枚举作为参数传递的所有集合)和Shuffled()(返回传递集合的无序版本)方法解决了我的问题。可能存在一些有缺陷的情况(阅读问题中的编辑)当
referenceVectors
vectorsToRelocate
是相同的向量时,正如我在问题中所做的那样

public static Dictionary<Vector2D, Vector2D> FindRelocationMap(
    IEnumerable<Vector2D> referenceVectors,
    IEnumerable<Vector2D> vectorsToRelocate)
{
    Dictionary<Vector2D, Vector2D> ret = new Dictionary<Vector2D, Vector2D>();

    // Preliminary filling
    IEnumerable<Vector2D> allVectors =
        Utils.Join(referenceVectors, vectorsToRelocate);
    foreach (Vector2D vector in allVectors)
        ret[vector] = vector;

    KdTree<Vector2D> kdTree = new KdTree<Vector2D>(
        delegate(Vector2D vector) { return vector.X; },
        delegate(Vector2D vector) { return vector.Y; });
    kdTree.InsertAll(Utils.Shuffled(ret.Keys));

    HashSet<Vector2D> relocatedVectors = new HashSet<Vector2D>();
    foreach (Vector2D vector in referenceVectors)
    {
        if (relocatedVectors.Contains(vector))
            continue;

        relocatedVectors.Add(vector);

        IEnumerable<Vector2D> neighbors =
            kdTree.FindNeighborsRange(vector, Tolerances.EUCLID_DIST_TOLERANCE);

        foreach (Vector2D neighbor in neighbors)
        {
            ret[neighbor] = vector;
            relocatedVectors.Add(neighbor);
        }
    }

    return ret;
}
公共静态字典FindLocationMap(
IEnumerable referenceVectors,
IEnumerable vectorsToRelocat