最适合具有固定大小但具有规范化位置的实体



>想象一下,我有一个由规范化位置(t)和宽度组成的实体数组。

struct Entity 
{ 
float t;       // left position as a percentage of the parent's size
float width;   // width of the entity in absolute values
}

一旦我决定了父级的大小,我可以轻松地像这样渲染所有实体:

void Draw(Entity[] entities, float size) 
{
foreach(var entity in entities) 
{
var x = entity.t * size;
Draw(x, entity.width);       // x corresponds to left side, not center
}
}

我很难弄清楚如何计算最小size对于任何给定的实体集,允许它们在不相交边界的情况下渲染。


如果您对此操作的用例感到好奇,它是一个辅助函数,我需要解决乐谱渲染系统上的一些边缘情况。和弦标签放置在乐谱顶部的布局周期结束时,它们的位置需要与相应的音乐内容正确对齐。但在某些情况下,满足此约束意味着度量值上没有足够的空间来适应标签。我需要这个函数来提前确定是否没有足够的空间,如果没有,请要求度量值按缺失的数量增长。

如果您不想移动标签,即t应该始终位于标签的左端位置,我认为这个简单的代码可以满足您的需求

static float CalcMinWidth(IList<Entity> entities)
{
var count = entities.Count;
List<Entity> local = new List<Entity>(count + 1);
local.AddRange(entities);
local.Add(new Entity(1, 0)); // add one that marks "end"
local.Sort((e1, e2) => Comparer<float>.Default.Compare(e1.t, e2.t));
float minReqW = 0;
for (int i = 0; i < count; i++)
{
var e1 = local[i];
var e2 = local[i + 1];
var reqW = e1.width / (e2.t - e1.t);
if (reqW > minReqW)
minReqW = reqW;
}
return minReqW;
}

这个想法是,最小宽度由某个特定的实体e1指定,该实体不应与下一个实体e2重叠(或在代码中由假实体(1.0, 0.0)标记的末端)。所以我们得到的是以下等式:

e1.t * required_width + e1.width < e2.t * required_width

或者如果你解决了它required_width你会得到

e1.width / (e2.t - e1.t) < required_width

最新更新