我目前正在尝试构建一种饼图/voronoi 图混合(在画布/javascript 中)。我不知道它是否可能。我对此很陌生,我还没有尝试任何方法。
假设我有一个圆圈和一组数字 2、3、5、7、11。
我想将圆圈细分为与数字相当的部分(很像饼图),但形成格子/蜂窝状的形状。
这甚至可能吗?这是否非常困难,尤其是对于只做了一些基本饼图渲染的人来说?
我目前正在尝试构建一种饼图/voronoi 图混合(在画布/javascript 中)。我不知道它是否可能。我对此很陌生,我还没有尝试任何方法。
假设我有一个圆圈和一组数字 2、3、5、7、11。
我想将圆圈细分为与数字相当的部分(很像饼图),但形成格子/蜂窝状的形状。
这甚至可能吗?这是否非常困难,尤其是对于只做了一些基本饼图渲染的人来说?
给定一组 voronio 中心(即每个中心的坐标列表),我们可以计算最接近每个中心的区域:
area[i] = areaClosestTo(i,positions)
假设这些有点错误,因为我们没有将中心放在正确的位置。因此,我们可以通过将区域与理想区域进行比较来计算当前集合中的误差:
var areaIndexSq = 0;
var desiredAreasMagSq = 0;
for(var i = 0; i < areas.length; ++i) {
var contrib = (areas[i] - desiredAreas[i]);
areaIndexSq += contrib*contrib;
desiredAreasMagSq += desiredAreas[i]*desiredAreas[i];
}
var areaIndex = Math.sqrt(areaIndexSq/desiredAreasMagSq);
这是区域和期望区域之间的差向量的向量范数。可以把它想象成衡量最小二乘拟合线的好坏。
我们还想要某种蜂窝状图案,所以我们可以称之为honeycombness(positions)
,并获得事物质量的整体度量(这只是一个开始,它的权重或形式可以是任何漂浮的东西):
var overallMeasure = areaIndex + honeycombnessIndex;
然后我们有一个知道猜测有多糟糕的机制,我们可以将它与修改位置的机制结合起来;最简单的就是在每个中心的 x 和 y 坐标上添加一个随机量。或者,您可以尝试将每个点移向面积过高的相邻区域,并远离面积过低的相邻区域。
这不是一个直接的解决方案,但除了计算最接近每个点的区域之外,它需要最少的数学运算,而且它是平易近人的。困难的部分可能是识别局部最小值并处理它们。
顺便说一句,获得该过程的起点应该相当容易;饼片的质心不应该离真相太远。
一个明确的优点是您可以使用中间计算来动画从饼图到 voronoi 的过渡。
这是我快速浏览后对此的看法。
假设存在n
具有顶点/边的多边形,一般解决方案k
将取决于n
方程的解,其中每个方程的变量不超过2nk
, (但恰好2k
非零)。每个多边形方程中的变量都是相同的x_1, x_2, x_3... x_nk
和y_1, y_2, y_3... y_nk
变量。对于每个多边形的方程,恰好四个x_1, x_2, x_3... x_nk
具有非零系数,并且恰好四个y_1, y_2, y_3... y_nk
具有非零系数。x_i
并且y_i
根据父形状有不同的界限。为了简单起见,我们假设形状是圆形。边界条件为:(x_i)^2 + (y_i)^2 <= r^2
注意:我说不超过2nk
,因为我不确定下限,但知道它不能超过2nk
。这是多边形作为要求共享顶点的结果。
这些方程是确定的但有界的积分的集合,表示每个多边形的面积,多边形的面积相等ith
:
A_i = pi*r^2/S_i
其中r
是父圆的半径,S_i
是分配给多边形的数字,如您的图表中所示。
四对独立的(x_j,y_j)
,在多边形方程中都具有非零系数,将产生多边形的顶点。
这可能被证明是相当困难的。
边界是从一开始就固定的,还是可以稍微变形一下?
如果我必须解决这个问题,我会将这些区域从大到小排序。然后,从最大的区域开始,我将首先生成一个具有所需大小的随机凸多边形(沿圆的顶点)。下一个区域将与第一个区域共享一条边,但在其他方面也是随机和凸的。之后的每个多边形将从已经存在的多边形中选择一条现有的边,并且还将共享从那里开始的任何“凸”边(其中“凸边”是一个,如果用于新多边形,将导致新的多边形仍然是凸的)。
通过评估“总边界接近所需边界”的不同预期多边形位置,您可能会为您的初始目标生成一个廉价的近似值。这与词云的作用非常相似:将事物从最大到最小递增地放置,同时试图填充或多或少的封闭空间。