使用相同路径的较小版本填充路径

时间:2012-07-13 08:02:19

标签: c# .net graphics

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

对于钢雕刻机,我需要使用.NET的普通图形框架来创建一个发送到雕刻机的“文档” - 它被视为普通打印机。有问题的机器就是这个:

http://www.rolanddga.com/products/impactprinters/mpx90/features.asp

我可以用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);
}

它提供类似于此的输出:http://i47.tinypic.com/mruu4j.jpg

我现在想要的是填写这个大纲。不仅仅是使用画笔填充(可以使用g.FillPath(brushFG,gpDraw)轻松完成。

它应该被“填充”越来越小的轮廓,如此图所示:http://i46.tinypic.com/b3kb29.png

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

正如我在Photoshop中做的那样,我意识到我实际上要做的是模仿你在Photoshop的选择/修改/合同中找到的功能。

但是,就我如何做到这一点而言,我完全知道了。

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

更新2012-07-16:我现在正在使用Clipper Library http://www.angusj.com/delphi/clipper.php,它有一个名为 OffsetPolygons 的精彩功能。

我的测试代码显示在此处:http://pastie.org/4264890

它与“单个”多边形一起工作正常 - 例如一个“C”,因为它只包含一个多边形。 “O”由两个多边形组成 - 内部和外部。与“A”相同。这些给我带来了一些麻烦。见这些图片:

C:http://i46.tinypic.com/ap304.png O:http://i45.tinypic.com/35k60xg.jpg 答:http://i50.tinypic.com/1zyaibm.png B:http://i49.tinypic.com/5lbb40.png

你得到了照片(嘿嘿......; - )

我认为问题在于,当实际有2个(在A和O的情

Clipper的OffsetPolygons实际上是一个多边形数组,所以我想它能够做到这一点。但我不知道如何从GraphicsPath中提取我的路径作为单独的多边形。

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

好吧,我实际上已经设法将它拉下来,并将在答案中解释它,希望它可以帮助其他类似问题的人。

非常感谢所有在此过程中提供帮助的人!我接受自己答案的唯一理由是,其他人可以通过一个完整的解决方案从这个问题中受益。

2 个答案:

答案 0 :(得分:2)

看看An algorithm for inflating/deflating (offsetting, buffering) polygons - 提问者实际上询问的是反向操作,但那里的答案也适用于你的情况。其中一个(评分最高)有一个指向具有C#版本的开源库的指针。

顺便说一下,你所描述的操作的通常名称是“多边形偏移”。

答案 1 :(得分:1)

使用Clipper库只是战斗的一半。

我在一个数组中从GraphicsPath中提取了所有点,因此无意中基于2个单独的多边形创建了一个畸形多边形(在“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实际上是一个多边形列表,所以这对我来说应该是显而易见的。

整个代码可以在这里看到:http://pastie.org/4265265

如果你很好奇,我已将整个测试项目压缩到此处,在Visual Studio中打开并编译。

http://gehling.dk/wp-content/uploads/2012/07/TestClipper.zip

它没有以任何方式针对速度进行优化。

/ Carsten

相关问题