c# - 围绕给定路径绘制路径

标签 c# graphics pdfsharp

* 更新 *

找到了使用 Clipper 库的解决方案。解决方案添加为答案。不过,我们仍然欢迎新的/更好的/更简单的想法!


给定一个这样的路径:

original black path

我想创建一条以给定距离围绕这条路径的路径,例如1 厘米。下面的草图展示了——红色路径围绕黑色路径,距离为 1 厘米。

black path surrounded by a red path with a distance of 1 cm

如何使用 PDFSharp 以通用方式完成此操作? (意思是我最终想用 PDFSharp 绘制它,我不在乎计算在哪里完成) 这是黑色路径的代码:

// helper for easily getting an XPoint in centimeters
private XPoint cmPoint(double x, double y)
{
    return new XPoint(
        XUnit.FromCentimeter(x),
        XUnit.FromCentimeter(y)
        );
}


// the path to be drawn
private XGraphicsPath getMyPath()
{
    XGraphicsPath path = new XGraphicsPath();

    XPoint[] points = new XPoint[3];
    points[0] = cmPoint(0, 0);
    points[1] = cmPoint(5, 2);
    points[2] = cmPoint(10,0);

    path.AddCurve(points);
    path.AddLine(cmPoint(10, 0), cmPoint(10, 10));
    path.AddLine(cmPoint(10, 10), cmPoint(0, 10));
    path.CloseFigure(); 

    return path;
}


// generate the PDF file
private void button3_Click(object sender, RoutedEventArgs e)
{
    // Create a temporary file
    string filename = String.Format("{0}_tempfile.pdf", Guid.NewGuid().ToString("D").ToUpper());

    XPen penBlack = new XPen(XColors.Black, 1);
    XPen penRed = new XPen(XColors.Red, 1);

    PdfDocument pdfDocument = new PdfDocument();

    PdfPage page = pdfDocument.AddPage();
    page.Size = PdfSharp.PageSize.A1;

    XGraphics gfx = XGraphics.FromPdfPage(page);

    //give us some space to the left and top
    gfx.TranslateTransform(XUnit.FromCentimeter(3), XUnit.FromCentimeter(3));

    // draw the desired path
    gfx.DrawPath(penBlack, getMyPath());


    // Save the pdfDocument...
    pdfDocument.Save(filename);
    // ...and start a viewer
    Process.Start(filename);
}

感谢您对此主题的任何帮助!

最佳答案

您可以使用 Widen() 函数,用指定笔绘制路径时包围填充区域的曲线替换路径,为路径添加额外的轮廓。

此函数接收参数 a XPen , 所以你可以创建这个 XPen使用所需的偏移量作为宽度,将以恒定距离(笔的宽度)添加外部路径。

XGraphicsPath类实际上是 System.Drawing.Drawing2D.GraphicsPath 的包装器, 所以你可以使用 Widen()XGraphicsPath 中发挥作用,获取内部对象并使用 GraphicsPathIterator 对其进行迭代类来获取添加的路径。

此方法将完成这项工作:

public XGraphicsPath GetSurroundPath(XGraphicsPath path, double width)
{
    XGraphicsPath container = new XGraphicsPath();

    container.StartFigure();
    container.AddPath(path, false);
    container.CloseFigure();

    var penOffset = new XPen(XColors.Black, width);

    container.StartFigure();
    container.Widen(penOffset);
    container.CloseFigure();

    var iterator = new GraphicsPathIterator(container.Internals.GdiPath);

    bool isClosed;
    var outline = new XGraphicsPath();
    iterator.NextSubpath(outline.Internals.GdiPath, out isClosed);

    return outline;
}

您可以使用重载 Widen(XPen pen, XMatrix matrix, double flatness) 处理曲线中的平坦度级别.打这个电话 container.Widen(penOffset, XMatrix.Identity, 0.05);导致更圆润的边缘。

然后使用这个函数绘制一条外部路径:

string filename = String.Format("{0}_tempfile.pdf", Guid.NewGuid().ToString("D").ToUpper());

XPen penBlack = new XPen(XColors.Black, 1);
XPen penRed = new XPen(XColors.Red, 1);

PdfDocument pdfDocument = new PdfDocument();

PdfPage page = pdfDocument.AddPage();
page.Size = PdfSharp.PageSize.A1;

XGraphics gfx = XGraphics.FromPdfPage(page);

//give us some space to the left and top
gfx.TranslateTransform(XUnit.FromCentimeter(3), XUnit.FromCentimeter(3));

var path = getMyPath();

// draw the desired path
gfx.DrawPath(penBlack, path);
gfx.DrawPath(penRed, GetSurroundPath(path, XUnit.FromCentimeter(1).Point));

// Save the pdfDocument...
pdfDocument.Save(filename);
// ...and start a viewer
Process.Start(filename);

这是你得到的:

enter image description here

另一种方法可能是使用反射来检索内部 PenXPen和设置 CompoundArray 属性(property)。这允许您绘制平行线和空间。使用此属性,您可以执行以下操作:

enter image description here

但问题是你只能使用一种颜色,反正这只是一个想法,我没有在PDFsharp中尝试过。

此外,您应该搜索offset polyline curvesoffsetting polygon 算法。

关于c# - 围绕给定路径绘制路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35162657/

相关文章:

c# - 使用 PDFsharp 制作表格和图表

c# - 左缩进的 MigraDoc 表边框问题

c# - Unity 5 以圆形或椭圆形路径(轨道)移动行星

c# - 在 MonoTouch 中显示 3D 模型

c# - 如何在 web api 上发布 SOAP 消息(asp.net core -> web api)

Java:重写paint()和paintComponent()

javascript - "saturation"globalCompositeOperation 不改变透明度?

c++ - 玩家移动时,GameBoy Advance对象未显示在正确的位置

c# - 如何将 Windows 窗体保存为 pdf

c# - 获取索引为 int[] indices 的 string[] 元素