遇到的问题
在一个多边形上放置文本标签或工具提示的最佳位置通常位于其“视觉中心”的某个位置,即多边形内部的一个点,周围有尽可能多的空间。
计算这样一个中心首先想到的是多边形质心。你可以用一个简单快速的公式计算多边形中心,但如果形状是凹的或有一个洞,点可以落在形状外面。
现有的解决方案
这项在线任务的唯一近似算法是由加西亚-卡斯特利亚诺斯和伦巴多在2007年的论文中描述的。算法是这样的:
- 将点置于任意大小的网格上(本文中为24x24,或576个点),在其边界框内探测多边形,丢弃多边形外的所有点。
- 计算每个点到多边形的距离,选择距离最长的点。
- 重复上面的步骤,但是在这一点上有一个更小的网格(比任意系数1.414小)。
- 该算法运行多次,直到搜索区域足够小,达到我们想要的精度。

- 它不能保证找到一个好的解决方案,这取决于机会和外形相对良好的多边形。
- 在较大的多边形上运行速度较慢,因为有很多点检查的过程。对于上图中的每个蓝点,你必须循环遍历所有多边形点。
新的解决方案
我们需要设计一种不依赖于任意常数的算法,并且能够以可靠的增加精度对整个多边形进行彻底搜索。那么就有一个熟悉的概念可以与这个问题直接相关——四叉树。
四叉树的主要概念是递归地将二维空间细分为四个象限。这在许多应用程序中都有应用——不仅是空间索引,而且有图像压缩,甚至是物理模拟,在这些应用程序中,提高特定领域的自适应精度是有益的。
- 从覆盖多边形的几个大单元开始。
- 递归地将它们细分为4个较小的单元,探索单元中心作为候选,丢弃那些不可能包含比我们已经找到的更好的解决方案的单元。

寻找更快的解决方案
越早发现一个远离多边形边缘的“好的”单元格,我们在运行中丢弃的单元格就越多,搜索速度也就越快。那么我们如何更快地找到好的单元格呢?
我们决定试试另一种方法。我们开始管理优先队列中的单元格,按照单元格的“潜力(potential)”:dist + radius进行排序。通过这种方式,单元格按照其潜力的顺序进行处理。差不多使算法的性能提高了一倍。我们可以做到的另一个加速方法是把多边形质心作为第一个“最佳猜测”,这样我们就可以丢弃所有更坏的单元格。这提高了形状相对规则的多边形的性能。总结
最终得出来的算法就是Polylabel,这是一个快速而精确的JavaScript模块,用于查找合适的点,以便在多边形上放置标签。它比我们开始时的算法快40倍,同时保证在所有情况下都能得到正确的结果。

