有 F#(或 C#)中的 R 树实现吗? [复制]

2024-04-04

可能的重复:
是否有任何记录在案的.NET 的免费 R-Tree 实现? https://stackoverflow.com/questions/2041834/is-there-any-documented-free-r-tree-implementation-for-net

F# 中有 R-Tree 实现吗?

假设是:不需要插入或删除,固定的地理围栏(区域)集。 需求是:非常快的搜索时间。

谢谢


这是一个快速翻译OCaml 中的这个 https://github.com/mariusaeriksen/ocaml-rtree/tree/master/src to F#.

namespace RTree

open System

module Envelope =

  type t = float * float * float * float

  let ranges_intersect a b a' b' = a' <= b && a <= b'

  let intersects (x0, x1, y0, y1) (x0', x1', y0', y1') =
    (* For two envelopes to intersect, both of their ranges do. *)
    ranges_intersect x0 x1 x0' x1' && ranges_intersect y0 y1 y0' y1'

  let add (x0, x1, y0, y1) (x0', x1', y0', y1') =
    min x0 x0', max x1 x1', min y0 y0', max y1 y1'

  let rec add_many = function
    | e :: [] -> e
    | e :: es -> add e (add_many es)
    | [] -> raise (ArgumentException "can't zero envelopes")

  let area (x0, x1, y0, y1) =
    (x1 - x0) * (y1 - y0)

  let within (x0, x1, y0, y1) (x0', x1', y0', y1') =
    x0 <= x0' && x1 >= x1' && y0 <= y0' && y1 >= y1'

  let empty = 0., 0., 0., 0.

module rtree =

  type 'a t =
      Node of (Envelope.t * 'a t) list
    | Leaf of (Envelope.t * 'a) list
    | Empty

  let max_node_load = 8

  let empty = Empty
  let empty_node = (Envelope.empty, Empty)

  let enlargement_needed e e' =
    Envelope.area (Envelope.add e e') - Envelope.area e

  let rec partition_by_min_enlargement e = function
    | (e', _) as n :: [] ->
        n, [], enlargement_needed e e'
    | (e', _) as n :: ns ->
        let enlargement = enlargement_needed e e' 
        let min, maxs, enlargement' = partition_by_min_enlargement e ns 
        if enlargement < enlargement' then
          n, min :: maxs, enlargement
        else
          min, n :: maxs, enlargement'
    | [] ->
        raise (ArgumentException "cannot partition an empty node")

  let pairs_of_list xs =  (* (cross product) *)
    List.concat (List.map (fun x -> List.map (fun y -> (x, y)) xs) xs)

  (* This is Guttman's quadradic splitting algorithm. *)
  let split_pick_seeds ns =
    let pairs = pairs_of_list ns 
    let cost (e0, _) (e1, _) =
      (Envelope.area (Envelope.add e0 e1)) -
      (Envelope.area e0) - (Envelope.area e1) 
    let rec max_cost = function
      | (n, n') :: [] -> cost n n', (n, n')
      | (n, n') as pair :: ns ->
          let max_cost', pair' = max_cost ns 
          let cost = cost n n' 
          if cost > max_cost' then
            cost, pair
          else
            max_cost', pair'
      | [] -> raise (ArgumentException "can't compute split on empty list") 
    let (_, groups) = max_cost pairs in groups

  let split_pick_next e0 e1 ns =
    let diff (e, _) =
      abs ((enlargement_needed e0 e) - (enlargement_needed e1 e)) 
    let rec max_difference = function
      | n :: [] -> diff n, n
      | n :: ns ->
          let diff', n' = max_difference ns 
          let diff = diff n 
          if diff > diff' then
            diff, n
          else
            diff', n'
      | [] -> raise (ArgumentException "can't compute max diff on empty list") 
    let (_, n) = max_difference ns in n

  let split_nodes ns =
    let rec partition xs xs_envelope ys ys_envelope = function
      | [] -> (xs, xs_envelope), (ys, ys_envelope)
      | rest -> 
          let (e, _) as n = split_pick_next xs_envelope ys_envelope rest 
          let rest' = List.filter ((<>) n) rest 
          let enlargement_x = enlargement_needed e xs_envelope 
          let enlargement_y = enlargement_needed e ys_envelope 
          if enlargement_x < enlargement_y then
            partition (n :: xs) (Envelope.add xs_envelope e) ys ys_envelope rest'
          else
            partition xs xs_envelope (n :: ys) (Envelope.add ys_envelope e) rest'
    let (((e0, _) as n0), ((e1, _) as n1)) = split_pick_seeds ns 
    partition [n0] e0 [n1] e1 (List.filter (fun n -> n <> n0 && n <> n1) ns)

  let envelope_of_nodes ns = Envelope.add_many (List.map (fun (e, _) -> e) ns)

  let rec insert' elem e = function
    | Node ns -> 
        let (_, min), maxs, _ = partition_by_min_enlargement e ns 
        match insert' elem e min with
          | min', (_, Empty) ->
              let ns' = min' :: maxs 
              let e' = envelope_of_nodes ns' 
              (e', Node ns'), empty_node
          | min', min'' when (List.length maxs + 2) < max_node_load ->
              let ns' = min' :: min'' :: maxs 
              let e' = envelope_of_nodes ns' 
              (e', Node ns'), empty_node
          | min', min'' ->
              let (a, envelope_a), (b, envelope_b) =
                split_nodes (min' :: min'' :: maxs) 
              (envelope_a, Node a), (envelope_b, Node b)
    | Leaf es ->
        let es' = (e, elem) :: es 
        if List.length es' > max_node_load then
          let (a, envelope_a), (b, envelope_b) = split_nodes es' 
          (envelope_a, Leaf a), (envelope_b, Leaf b)
        else
          (envelope_of_nodes es', Leaf es'), empty_node
    | Empty ->
        (e, Leaf [e, elem]), empty_node

  let insert t elem e =
    match insert' elem e t with
      | (_, a), (_, Empty) -> a
      | a, b -> Node [a; b]  (* root split *)

  let filter_intersecting e =
    List.filter (fun (e', _) -> Envelope.intersects e e')

  let rec find t e =
    match t with
      | Node ns ->
          let intersecting = filter_intersecting e ns 
          let found = List.map (fun (_, n) -> find n e) intersecting 
          List.concat found
      | Leaf es -> List.map snd (filter_intersecting e es)
      | Empty -> []

  let rec size = function
    | Node ns ->
        let sub_sizes = List.map (fun (_, n) -> size n) ns 
        List.fold (+) 0 sub_sizes
    | Leaf es ->
        List.length es
    | Empty ->
        0
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有 F#(或 C#)中的 R 树实现吗? [复制] 的相关文章

随机推荐

  • ng-grid 中的默认 headerCell 模板

    考虑以下 angularJs 代码片段 var myHeaderCellTemplate div class div class ngHeaderText col displayName img src PLUS ICON png div
  • 设置自定义 Git 安装

    我希望将 Git 安装在不同于默认位置的自定义位置usr local git bin git软件包安装程序所在的目录http git scm com http git scm com 网站安装到 例如 我只是尝试复制内容usr local
  • 如何将 TLD 和 Tag Lib 文件添加到 Maven 的 jar 项目中

    我有一个 Maven 项目 打包为jar 我还有一个 Maven 项目 打包为war 这个 war 项目有一个 tld 文件和一些 xhtml 文件 标签库 战争项目的结构 基本上 是 pom xml src main java webap
  • Angular7 中的来源“http://localhost:4200”已被 CORS 策略阻止

    我想使用http 5 160 2 148 8091 api trainTicketing city findAll http 5 160 2 148 8091 api trainTicketing city findAll在我的角度项目中休
  • 如何检测首选项是否发生更改?

    我有一个类扩展 PreferenceActivity 并显示我的应用程序的首选项屏幕 是否可以检查首选项是否有任何更改 这有助于 http developer android com reference android content Sh
  • 连接到 localhost:6379 时出现错误 99。无法分配请求的地址

    设置 我有一个虚拟机 并在虚拟机中运行三个容器 一个 nginx 代理 一个非常简约的 Flask 应用程序和 redis Flask 应在端口 5000 上提供服务 而 redis 应在 6379 上提供服务 这些容器中的每一个都可以作为
  • JQuery 中类似 C# 的 String.Format() 函数? [复制]

    这个问题在这里已经有答案了 是否可以在 JQuery 中调用类似 C 的 String Format 函数 相当于 JQuery 中的 String format https stackoverflow com questions 1038
  • 如何在tmux中获取send-keys的结果?

    我正在使用 tmux 来运行服务器控制台 要检查控制台是否正在应答 我想使用send keys在控制台上运行命令 tmux send keys t mysess mywin show info Enter 实际上 我目前正在将完整的控制台输
  • Django 开发服务器 CPU 密集型 - 如何分析?

    我注意到本地 windows7 机器上的 django 开发服务器 版本 1 1 1 正在使用大量 CPU 根据任务管理器的 python exe 条目 约为 30 即使处于空闲状态 即没有请求到来进 出 是否有一种既定的方法来分析可能造成
  • Magento 图片上传表单字段

    我跟着这个链接 http www magentocommerce com wiki 5 modules and development admin how to create pdf upload in backend for own mo
  • SQL Server 更新触发器,仅获取修改的字段

    我知道COLUMNS UPDATED 好吧 我需要一些快速的捷径 如果有人做了 我已经在做了 但如果有人可以节省我的时间 我会感激的 我基本上需要一个仅包含更新的列值的 XML 我需要它用于复制目的 SELECT FROM Insert 为
  • Jenkins 未识别 Maven

    我在Windows 8上安装了Tomcat 7 上面部署了Jenkins 我在 Jenkin 设置中配置了 JDK Ant 和 Maven 在 Maven 部分 我将名称命名为 LocalMaven 将 MAVEN HOME 命名为C Te
  • Postgres 正则表达式 负向前瞻

    场景 匹配除字符串 J01FA09 之外的任何以 J01 开头的字符串 我很困惑为什么以下代码不返回任何内容 SELECT 1 WHERE J01 FA09 J01FA10 当我能看到regexr com https regex101 co
  • fft 和小波

    我可以使用 fft 获取加载的 1 秒音频文件的频率 相位和幅度 并重新创建它 我现在想做的是找出每个频率在 1 秒音频文件中的开始位置和结束位置 并将数据放入数组中 示例 100hz 从 0 23 秒到 0 34 秒开始 104 34hz
  • 如何修复双编码 UTF8 字符(在 utf-8 表中)

    以前的一个LOAD DATA INFILE运行时假设 CSV 文件是latin1 编码 在此导入过程中 多字节字符被解释为两个单字符 然后 再次 使用 utf 8 进行编码 这种双重编码产生了异常 例如 代替 如何纠正这些字符串 以下 My
  • 在电子中创建多个预加载文件(每页一个)

    我正在创建我的第一个 Electron 应用程序 并且完成了表单的第一页 现在这个应用程序不是 SPA 所以我有大约 3 4 个不同的页面 并且页面通向另一个页面 为了允许正确的代码组织 我想为每个面向客户端的页面保留一个单独的预加载文件
  • 如何设置 NHibernate 事务的超时

    我需要在单个事务中完成大量数据库处理 包括使用 NHibernate 的一些处理 为了使所有内容在同一个事务中工作 我使用 NHibernate 的 Session 来启动它 并在其中登记其他工作的命令 一切都很顺利 直到我承诺为止 那时我
  • 停止无限循环中的delphi程序

    当 Delphi 中发生无限循环时 当我按下停止按钮时 调试器甚至不会给我堆栈跟踪 如果我怀疑程序在哪里停止 我可以放置一个断点 如果这是正确的无限循环 它将停止 下面是一个故意造成无限循环的示例程序 procedure TForm1 bt
  • Android 中的最大 BackStack 大小

    我是android开发的新手 我需要知道最大内存大小 of 后台堆栈 in android我想知道有多少活动 of 安卓应用 can be 存储在 BackStack 中 Thanks 后台堆栈的最大内存大小与设备上的可用内存量相同 您可以
  • 有 F#(或 C#)中的 R 树实现吗? [复制]

    这个问题在这里已经有答案了 可能的重复 是否有任何记录在案的 NET 的免费 R Tree 实现 https stackoverflow com questions 2041834 is there any documented free