2

我需要将任意形状的 GraphicsPath“适配”到定义的空间中(几乎总是矩形或圆形)。

我目前使用 Matrix 对象缩放 GraphicsPath 并且缩放工作正常,但问题是获取比例因子。

我能想到的最好的技术是将 GraphicsPath 转换为区域,将 Rectangle 或 Circle 转换为区域,然后执行:

rgnShape.Intersect(rgnCircle);

然后检查是否:

rgnShape.IsEmpty()

但是,这只是告诉我形状是否太大而无法容纳,并且有必要将形状缩放得更小,然后再试一次(可能很多次)。

有没有一种简单的方法可以立即计算缩放因子以适合多边形 GraphicsPath,使其完全适合圆形。结果应该是仍然完全适合圆的最大多边形。

4

5 回答 5

2

我不明白你为什么需要二进制搜索。

一旦你得到你的形状的边界矩形,并且你有你想要适应形状的目标矩形,你可以比较两个比率targetHeight / shapeHeighttargetWidth / shapeWidth

取较小的比率,并将其用作缩放形状的比例因子。

如果目标是圆形而不是矩形,您可以使用类似的解决方案,将其targetCircleDiameter / boundingRectangleDiagonal作为比例因子。

于 2010-12-30T06:45:42.130 回答
2

请参阅http://en.wikipedia.org/wiki/Smallest_circle_problem以根据点而不是路径来讨论此问题,由 Simon 发现。

  1. 所以,这样做,用rgnShape.Intersect(rgnCircle);它来检查它是否有效。如果它失败了,取每条曲线并抓住离你找到的圆心最远的点(对于任何给定的区域可能有不止一个这样的点)。

  2. 将它们添加到您的积分列表中重新应用算法。您无需从头开始;您不需要考虑不在边界上的点(即,忽略最初调用算法发现的不在“Set Q”中的点)。

请注意,这不再是线性的,因为对于第 i 个点,生成递归调用的概率不再是 1/i。

这有一个您必须明确处理的边缘条件。如果在步骤 1 的第一次迭代中发现的区域之外发现的一条曲线是完美的圆形并与外圆相接触,则“Set Q”内将有无限个点,该算法将惨遭失败。因此,在rgnShape.Intersect(rgnCircle);第一次申请后,您应该针对这种情况明确检查任何完美的圆形曲线。例如,如果你的形状是(}你应该明确检查()(为了讨论的目的,假装()是一个圆圈)是否(位于第一次迭代期间发现的区域之外。

这仍然很糟糕,但比将每条曲线都变成点要好。

于 2011-01-04T15:21:24.287 回答
0

您可以在 GraphicsPath 和区域上使用 GetBounds,然后比较矩形的大小以至少让您接近。

如果定义的空间是一个正方形,那应该是准确的。

如果定义的空间是别的东西,那至少会让你接近。然后,您可以使用二进制搜索来查找实际的缩放量。

于 2010-12-30T00:33:39.313 回答
0

你不能计算图形路径的中心和半径吗?

您可以计算重心(坐标的平均值)并添加 2 倍标准偏差 - 这应该可以让您获得大约 92% 的图表 - 大多数情况下它会很好,但如果您的图表具有最大的“权重”,则会失败一方面。

您还可以计算点的中心 - 遍历所有点,在计算边界框时获得所有方向的最大/最小点,取其中心并测量到您的(最大/最小)点的最长距离作为半径。

如果您寻找边界球算法,您可能会找到更复杂的算法 - 但如果它只是为了显示某些东西,您可以做一些权衡。如果您正在进行碰撞检测,那么也存在一些快速算法:)

于 2011-01-03T09:42:15.520 回答
0

用简单的数学反其道而行之如何?即,获取路径的边界框/圆,计算预定义的高/宽矩形比,将其与BB的相同值进行比较,相应地拉伸BB(例如,如果预定义的比例小于1,则BB水平拉伸和垂直,否则以匹配相同的比例),最后将整个东西缩放到预定义的矩形大小。比例因子现在只是预定义高度除以 BB 高度和预定义宽度除以 BB 宽度之间的最小值。(对于边界圆,无需调整其大小。)

于 2011-01-04T07:16:23.190 回答