C# 用同一路径的较小版本填充路径

C# 用同一路径的较小版本填充路径,c#,.net,graphics,C#,.net,Graphics,这个问题对我来说很难解释,所以我将用一些图片和文字来说明 对于钢制雕刻机,我需要使用.NET的普通图形框架来创建发送到雕刻机的文档-它就像普通打印机一样处理。有问题的机器是这台: 我可以用C语言在上面打印文本大纲: // ALL UNITS ARE SET IN MILIMETERS (MM) Graphics g = <instantiated from my printers-printpage-event>; // The following values are set

这个问题对我来说很难解释,所以我将用一些图片和文字来说明

对于钢制雕刻机,我需要使用.NET的普通图形框架来创建发送到雕刻机的文档-它就像普通打印机一样处理。有问题的机器是这台:

我可以用C语言在上面打印文本大纲:

// ALL UNITS ARE SET IN MILIMETERS (MM)

Graphics g = <instantiated from my printers-printpage-event>;

// The following values are set as "constants" here for the purpose of my question
// they normally are passed as parameters
string s = "ABC";
float fontSize = 4.0F;
RectangleF r = new RectangleF(0, 30.0F, 100.0F, 40.0F);

StringFormat sfDraw = new StringFormat();
sfDraw.Alignment = StringAlignment.Center;
FontStyle fStyle = FontStyle.Regular;

using (var gpDraw = new GraphicsPath())
{
  gpDraw.AddString(text, fFamily, (int)fStyle, fSize, r, sfDraw);

  SolidBrush brushFG = new SolidBrush(Color.Black);
  Pen pen = new Pen(brushFG, 0.01F);

  g.DrawPath(pen, gpDraw);
}
它的输出与此类似:

我现在要做的是填写这个大纲。不像g.FillPathbrushFG、gpDraw那样简单地使用笔刷填充

相反,它应该用越来越小的轮廓填充,如下图所示:

不同的线条颜色仅用于使示例更清晰

当我在Photoshop中制作这个例子时,我意识到我实际上要做的是模拟Photoshop的Select/Modify/Contract中的功能

但我对如何做到这一点束手无策

有什么帮助吗?我不是在寻找一个完整的解决方案,但我现在完全陷入了困境。我尝试过简单的缩放,这可能是错误的方式,因为它不会产生正确的结果

更新2012-07-16:我现在正在使用Clipper库,它有一个很棒的函数叫做OffsetPolygons

我的测试代码如下所示:

它适用于单个多边形-例如a C,因为它只包含单个多边形。O由两个多边形组成——一个内部多边形和一个外部多边形。A也是这样,这些给我带来了一些麻烦。请参见以下图片:

C: O: A: B:

你明白了,嘿嘿-

我认为问题在于,我将GraphicsPath中的所有内容提取为一个多边形,而a和O的情况下实际上有2个,B的情况下有3个

Clipper的OffsetPolygons实际上需要一组多边形,所以我想它能够正确地实现这一点。但我不知道如何从GraphicsPath中提取路径作为单独的多边形

当天晚些时候更新2012-07-16:

好吧,我现在已经成功了,我会在回答中解释,希望它能帮助其他有类似问题的人

向所有在这一过程中给予帮助的人表示衷心的感谢!我接受我自己的答案的唯一原因是,这样其他人可能会从这个问题中受益,并有一个完整的解决方案。

看看——提问者实际上是在询问反向操作,但那里的答案也适用于您的案例。其中一个级别最高的有一个指向具有C版本的开源库的指针


顺便说一句,您描述的操作的通常名称是多边形偏移。

使用Clipper库仅仅是战斗的一半

我在一个数组中从GraphicsPath中提取了所有点,因此无意中创建了一个基于两个独立多边形的变形多边形(在a的情况下)

相反,我需要检查GraphicsPath上的PointTypes数组属性。每次点的PointType==0时,表示新多边形的开始。因此,提取方法应使用此选项,而不是返回多边形数组,而不仅仅是单个多边形:

private ClipperPolygons graphicsPathToPolygons(GraphicsPath gp)
{
    ClipperPolygons polyList = new ClipperPolygons();
    ClipperPolygon poly = null;

    for (int i = 0; i < gp.PointCount; i++)
    {
        PointF p = gp.PathPoints[i];
        byte pType = gp.PathTypes[i];

        if (pType == 0)
        {
            if (poly != null)
                polyList.Add(poly);
            poly = new ClipperPolygon();
        }

        IntPoint ip = new IntPoint();
        ip.X = (int)(p.X * pointScale);
        ip.Y = (int)(p.Y * pointScale);
        poly.Add(ip);
    }
    if (poly != null)
        polyList.Add(poly);

    return polyList;
}
Clipper的OffsetPolygons实际上需要一个多边形列表,所以这对我之前来说应该是显而易见的

整个代码可以在这里看到:

如果您好奇的话,我已经将整个测试项目压缩到这里,在VisualStudio中打开并编译

它没有以任何方式优化速度


/卡斯滕

你当然需要编写你自己版本的压缩算法,但要针对矢量而不是像素。你试过使用负数加宽方法吗?@leppie:没有,但现在我找到了另一种解决方案。无论如何谢谢你