3

我正在尝试找出将 .net 中的 GraphicsPath 变形为特定形状的最佳方法。我想要达到的结果是扭曲文本以向上、向下、向左、向右扇形以及像波浪一样的东西。所有这些都可以在 Adob​​e Illustrator 中使用包络扭曲功能来实现。

我考虑过使用一些预定义的网格和点映射系统来转换点来使用我自己的方法。但是,似乎有一些关于如何做到这一点的算法或样本已经可用?

4

2 回答 2

4

我想跟进我前段时间发表的这篇文章。我已经制定了其他一些方法来完成我在这篇文章中最初想做的事情。首先,GraphicsPath 有一个很好的 warp() 方法,它执行此操作,将任何路径变形为矩形的 4 个点。使用这个想法,您可以在下面完成此操作。

向右翘曲

这是应用于文本拱起的路径的相同扭曲

文本拱起翘曲

这是经典的星球大战文本扭曲,只需在 warp() 方法中设置矩形的 4 个点 星球大战文字变形

相同的扭曲应用于拱起的路径。

用星球大战曲折拱起

我得出的结论是,可以通过首先在诸如拱形或波浪之类的路径上键入,然后在 GraphicsPath 中应用 warp() 方法来完成许多扭曲。

更新

将近 2 年后,我终于开始真正想出一个真正的解决方案。我在我的博客上发布了带有代码的深入解释。 在这里阅读

于 2012-09-25T14:07:50.200 回答
3

以下是我们使用的验证码生成器中的几种方法,它们可能会引导您朝着正确的方向前进:

    internal static void DrawPhrase(
        this Graphics graphics, 
        int width, 
        int height, 
        string phrase)
    {
        graphics.FillRectangle(
            Brushes.White,
            0,
            0,
            width,
            height);

        using (var gp = new GraphicsPath())
        {
            gp.AddString(phrase,
                         FontFamily.GenericMonospace,
                         (int)FontStyle.Bold,
                         33f,
                         new Point(0,
                                   0),
                         StringFormat.GenericTypographic);

            using (var gpp = gp.Deform(width, height))
            {
                var bounds = gpp.GetBounds();
                var matrix = new Matrix();
                var x = (width - bounds.Width) / 2 - bounds.Left;
                var y = (height - bounds.Height) / 2 - bounds.Top;
                matrix.Translate(x,
                                 y);
                gpp.Transform(matrix);
                graphics.FillPath(Brushes.Black,
                                  gpp);
            }
        }

        graphics.Flush();
    }
    internal static GraphicsPath Deform(
        this GraphicsPath path, 
        int width, 
        int height)
    {
        var WarpFactor = 4;
        var xAmp = WarpFactor * width / 300d;
        var yAmp = WarpFactor * height / 50d;
        var xFreq = 2d * Math.PI / width;
        var yFreq = 2d * Math.PI / height;
        var deformed = new PointF[path.PathPoints.Length];
        var xSeed = rng.NextDouble() * 2 * Math.PI;
        var ySeed = rng.NextDouble() * 2 * Math.PI;
        var i = 0;
        foreach (var original in path.PathPoints)
        {
            var val = xFreq * original.X + yFreq * original.Y;
            var xOffset = (int)(xAmp * Math.Sin(val + xSeed));
            var yOffset = (int)(yAmp * Math.Sin(val + ySeed));
            deformed[i++] = new PointF(original.X + xOffset,
                                     original.Y + yOffset);
        }

        return new GraphicsPath(deformed,
                                path.PathTypes);
    }
于 2012-01-26T14:18:37.053 回答