【问题标题】:drawing bezier paths with cairo用 cairo 绘制贝塞尔路径
【发布时间】:2020-10-12 14:44:35
【问题描述】:

我需要在 C++ 中借助 Cairo 绘制一组 Bezier 路径。 到目前为止,我可以绘制一条路径。

但我需要绘制许多由多条贝塞尔曲线和直线组成的路径。

我从 python 生成的外部字典加载路径集合。 在这里,对于这个最小的示例,我通过变量 path0 引入路径。

它是一个向量,由 2 个子向量组成。第一个代表贝塞尔样条,而第二个是简单的直线。

第一个子向量自然有 4 个分量,而第二个子向量只有 2 个。

这是我的代码示例。

#include <iostream>
#include <vector>
#include "cairo.h"
#include <string> 

int main(int argc, char* argv[])
{
    cairo_surface_t* surface;
    cairo_t* cr;

    surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1000, 1000);
    cr = cairo_create(surface);
    cairo_scale(cr, 1, 1);
    cairo_set_line_width(cr, 1);
    cairo_set_source_rgb(cr, 0, 0, 0);  

    // Here goes the svg-path. It is a bezier curve and unconnected line. 
    
    std::vector<std::vector<std::vector<double>>> path0 = { {{82.801,-204.48},{66.241,-204.48},{52.561,-214.56},{52.561,-235.44}},{{277.921,-192.24},{277.921,-173.5}} };
        
        // Here I put the initial point in the middle of the canvas. 

        double x0 = 300+path0[0][0][0];
        double y0 = 700+ path0[0][0][1];

        cairo_move_to(cr, x0, y0);

        // Parsing path
        for (int i = 0; i < path0.size(); i++) {
            if (path0[i].size() == 4) {
                cairo_rel_curve_to(cr, path0[i][1][0], path0[i][1][1], path0[i][2][0], path0[i][2][1], path0[i][3][0], path0[i][3][1]);
                cairo_stroke(cr);
            }
            if (path0[i].size() == 2) {
                cairo_rel_line_to(cr, symbol[0][i][1][0], symbol[0][i][1][1]);
                cairo_stroke(cr);
            }
        }
        cairo_surface_write_to_png(surface, "stroke.png");
        cairo_destroy(cr);
        cairo_surface_destroy(surface);

        return 0;

}

关键是我在画布上只看到一条曲线。大概,第二个在外面。 你能帮我理解我做错了什么吗?

雅罗斯拉夫。

【问题讨论】:

  • 你的例子没有编译:t.cpp:35:39: error: ‘symbol’ was not declared in this scope

标签: c++ drawing bezier cairo


【解决方案1】:

您能否说明您希望看到的内容?通过以下更改,我得到类似两行的内容,但我不确定这是您想要看到的。

--- t.cpp.orig  2020-10-13 17:00:12.404871474 +0200
+++ t.cpp   2020-10-13 17:04:20.573101739 +0200
@@ -29,13 +29,12 @@ int main(int argc, char* argv[])
         for (int i = 0; i < path0.size(); i++) {
             if (path0[i].size() == 4) {
                 cairo_rel_curve_to(cr, path0[i][1][0], path0[i][1][1], path0[i][2][0], path0[i][2][1], path0[i][3][0], path0[i][3][1]);
-                cairo_stroke(cr);
             }
             if (path0[i].size() == 2) {
-                cairo_rel_line_to(cr, symbol[0][i][1][0], symbol[0][i][1][1]);
-                cairo_stroke(cr);
+                cairo_rel_line_to(cr, path0[i][1][0], path0[i][1][1]);
             }
         }
+   cairo_stroke(cr);
         cairo_surface_write_to_png(surface, "stroke.png");
         cairo_destroy(cr);
         cairo_surface_destroy(surface);

结果是:

上述程序中发生的事情是:

  • 首先你打电话给cairo_move_to(cr, 382.8, 495.5)。这决定了下一条曲线的起点。
  • 然后调用cairo_rel_curve_to()。这会添加一条从当前点到类似382.8+52.5, 495.5-235.4 的曲线。另外两点描述曲线是如何弯曲的。
  • 接下来会调用cairo_rel_line_to(cr, 277.9, -173.5);
    • 在我的版本中,这会添加从曲线末端开始的线段。
    • 在您的版本中,对cairo_stroke() 的调用删除了路径。由于没有当前点,所以 line_to 不做任何事情(嗯,它为以下绘图命令设置当前点)。

【讨论】: