我在尝试绘制饼图时遇到问题.
当然,绘制图表没有问题,问题是图标放置.
理想情况下,图标应放在圆圈上(让我们忘记现在的百分比标签).
但是,当存在具有较小值的邻居项时,设计显然会中断.
你能推荐一个解决这个问题的算法吗?为了简化,作为输入,我们有:
PIE_RADIUS – 馅饼的外半径.
ICON_RADIUS – 图标圆的半径.
ICON_PLACEMENT_RADIUS – 理想放置图标中心时的圆的半径.
NUM_ICONS – 要放置的图标数.
iconAngles每个图标的角度,位于其截面的中心
所需输出:
当图标移出理想圆圈时,可以在饼图或iconPositions周围放置项目的iconAngles.
我知道如何检查两个图标是否重叠.
我们可以认为饼图的中心位于(0,0).
(该实现是iOS应用程序的一部分,但我对一般的algorihm感兴趣).
最佳答案 第一个天真的算法,我们“推”与其他图标重叠的图标:
FOR iconToPlace in icons do:
isPlaced = false
WHILE(not isPlaced) DO:
isPlaced = true
FOR icon in icons DO:
IF overlap(iconToPlace, icon) AND iconToPlace != icon THEN:
isPlaced = false
push(iconToPlace) // same angle but the icon is now further
BREAK
ENDIF
ENDFOR
ENDWHILE
ENDFOR
使用这个第一算法,一些图标将比其他图标更中心.但它没有通过改变角度来利用可能的地方.通过将其应用于您的第二个设计(具有较小的值),很明显该解决方案将远离理想的解决方案.
第二个不太天真的算法,首先我们为每个图标分配一个新的角度(差值小于DeltaAngleMax),然后我们应用第一个算法:
icons = SORT(icons)
iconsRef = icons
isFinished = false
WHILE(not isFinished) DO:
isFinished = true
FOR i = 0 TO i = NUM_ICONS-1 DO:
IF overlap(icons(i), icons(i+1 % NUM_ICONS))
AND not overlap(icons(i), icons(i-1 % NUM_ICONS)) //seems useless
AND not overlap(icons(i)-DeltaAngle % 360, icons(i-1 % NUM_ICONS))
AND ABS(icons(i)-iconsRef(i)) <= DeltaAngleMax THEN:
//overlap with next icon but not with previous,
//if we decrease angle we still not overlap with previous icon and
//the futur delta angle is less than DeltaAngleMax
//then we can move the icon :
icons(i) = icons(i)-DeltaAngle
isFinished = false
ELSE IF overlap(icons(i), icons(i-1 % NUM_ICONS))
AND not overlap(icons(i), icons(i+1 % NUM_ICONS)) //seems useless
AND not overlap(icons(i)+DeltaAngle % 360, icons(i+1 % NUM_ICONS))
AND ABS(icons(i)-iconsRef(i)) <= DeltaAngleMax THEN:
//vice et versa:
icons(i) = icons(i)+DeltaAngle
isFinished = false
ENDFOR
ENDWHILE
APPLY_FIRST_ALGO
明智地选择deltaAngle和DeltaAngleMax. deltaAngle太少会导致大的运行时间.
为了更进一步,你应该看看the force-directed graph drawing算法,这是实现你的目标更加健壮的方法,其中一个难点是找到正确的节点力(你的图标,你没有边缘).