Как я могу получить простой «блочный» контур пути GDI +? - PullRequest
3 голосов
/ 04 января 2011

Предположим, у меня есть относительно сложный GDI + GraphicsPath с "дырами" в нем. Текст является хорошим примером, например, буква «О». Я хочу преобразовать этот путь, чтобы полностью заполнить его, включая «дыры». Как я могу это сделать?

sample image

Ответы [ 2 ]

2 голосов
/ 09 октября 2012

Cody

Я не видел, чтобы вы уже приняли ответ, поэтому я помещаю эту функцию 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 голос
/ 07 января 2011

Вот частичное решение, в 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;

Комментарии и улучшения приветствуются.

...