如何获得GDI +路径的简单“块”轮廓?

时间:2011-01-04 07:14:21

标签: windows graphics gdi+

假设我有一个相对复杂的GDI + GraphicsPath,其中有“漏洞”。文本是一个很好的例子,就像字母“O”。我想改变这条路,以便我可以完全填充它,包括“洞”。我怎么能这样做?

sample image

2 个答案:

答案 0 :(得分:2)

科迪,

我没有看到你已经接受了答案,所以我在这里放置这个C#功能,看看它是否有帮助。它已经过测试。

与上面的版本略有不同:此例程查找具有最大边界区域的路径,因此它比上面的版本更慷慨,因为它不需要“主”路径通过2个测试来证明它值得保留。

我把它变成了扩展方法,所以在.Net中你可以写:

GraphicsPath solid = LetterPath.ToSolidPath();

返回值是一个新的GraphicsPath,其内部已经被剔除(哇,我不经常使用这个词)。

/// <summary>
///  Removes all subpaths (holes) from a graphics path, leaving only the largest whole path behind
/// </summary>
public static GraphicsPath ToSolidPath(this GraphicsPath path)
{
    GraphicsPath BiggestPath = null;
    GraphicsPath SubPath = new GraphicsPath();
    RectangleF BoundsRect = RectangleF.Empty;
    RectangleF BiggestRect = RectangleF.Empty;
    bool bIsClosed = false;

    var pathIterator = new GraphicsPathIterator(path);
    pathIterator.Rewind();

    for (int i = 0; i < pathIterator.SubpathCount; i++)
    {
        SubPath.Reset();
        pathIterator.NextSubpath(SubPath, out bIsClosed);
        BoundsRect = SubPath.GetBounds();
        if (BoundsRect.Width * BoundsRect.Height > BiggestRect.Width * BiggestRect.Height)
        {
            BiggestRect = BoundsRect;
            BiggestPath = (GraphicsPath)SubPath.Clone();
        }
    }

    return BiggestPath;
}

答案 1 :(得分:1)

这是我在Delphi中提出的部分解决方案。它仅适用于整个路径“包含”在单个子路径中的情况。它只是迭代子路径并返回与最大子路径相同的新路径。它不是上述问题的通用解决方案,但它适用于手头的情况,并可能在未来帮助其他人:

function BlockPath(Path: IGPGraphicsPath): IGPGraphicsPath;
var
  PathIterator: IGPGraphicsPathIterator;
  SubPath: IGPGraphicsPath;
  I: Integer;
  IsClosed: Boolean;
  BiggestPath: IGPGraphicsPath;
  BiggestRect, BoundsRect: TGPRectF;
begin
  Result := TGPGraphicsPath.Create;
  SubPath := TGPGraphicsPath.Create;
  PathIterator := TGPGraphicsPathIterator.Create(Path);
  PathIterator.Rewind;
  BiggestPath := nil;
  BiggestRect.Width := 0;
  BiggestRect.Height := 0;
  for I := 0 to PathIterator.SubpathCount - 1 do
  begin
    SubPath.Reset;
    PathIterator.NextSubPath(SubPath, IsClosed);
    SubPath.GetBounds(BoundsRect);
    if (BoundsRect.Width >= BiggestRect.Width) and
     (BoundsRect.Height >= BiggestRect.Height) then
    begin
     BiggestRect := BoundsRect;
     BiggestPath := SubPath.Clone;
    end;
  end;
  if BiggestPath <> nil then
  begin
    Result.AddPath(BiggestPath, True);
  end;
end;

欢迎提出意见和改进。