# [cairo] Qahirah: A High-Level Cairo API Binding For Python 3

Olaf Schmidt ng at vbRichClient.com
Wed Mar 11 23:37:50 PDT 2015

```Am 12.03.2015 um 00:09 schrieb Lawrence D'Oliveiro:

> So your version ends up full of hard-coded numbers.
> Which you had to get from the formulas in my version!

Now, now - you don't really want to sell me, that the
simplest trigon. math functions were your own invention,
will you?

An equilateral triangle which stands on one side, will
have a certain aspect-ratio to its bounding rectangle.

E.g.:
sin(120 * PI / 360) = 0.866025403784439
or
sqrt(3) / 2 = 0.866025403784439

Ergo, I've choosen my pattern-size appropriately:
26 / 30 = 0,866666666666667
(since meeting certain Pixel-Boundaries is important for patterns,
which are placed with "Extend-Repeat" on image-surfaces)

> Besides, I think my version has fewer statements than yours.
> Remember that
>
>      (qah.Context(tile)
>          .set_matrix(Matrix.scale(pattern_res) * Matrix.translate(- path_bounds.topleft))
>          .set_source_colour(Colour.grey(1))
>          .set_operator(CAIRO.OPERATOR_SOURCE)
>          .paint()
>          .set_source_colour(Colour.grey(0))
>          .new_path()
>          .append_path(shape)
>          # need enough copies to cover neighbouring spots under all possible pattern parameters
>          .append_path(shape.transform(Matrix.translate(tips[2] - tips[1])))
>          .append_path(shape.transform(Matrix.translate(tips[0] - tips[1])))
>          .append_path(shape.transform(Matrix.translate((+ pattern_dimensions.x, 0))))
>          .append_path(shape.transform(Matrix.translate((- pattern_dimensions.x, 0))))
>          .append_path(shape.transform(Matrix.translate(tips[1] - tips[2])))
>          .append_path(shape.transform(Matrix.translate(tips[1] - tips[0])))
>          .fill()
>      )
>
> is technically one Python statement.

And this "single statement" will of course appear "magically" within

>>> Then I see things like
>>>
>>>     For j = 0 To 3: For i = 0 To 3 + j
>>>
>>> So you have to make 22 separate copies of the pattern in order to
>>> ensure there are no gaps. A bit excessive, don’t you think?
>>
>> I've just played it safe there...
>
> In other words, you are taking a brute-force approach, rather than
> trying to understand the maths to get it right.

Well, I freely admit that I came to that amount of coverage
"empirically" in the first place (since early on I've experimented
already with larger curve-factors) - but looking at the results
I'm now certainly able to explain *why* I had to do so...

You claim, to have "understood the math" (which is clearly wrong),
since your low coverage with only 7 appended shape-paths is
certainly still insufficient for certain (larger) factors.

So, here's my explanation for you:

Please take a look at this (correct) image here, which I've produced
with my larger coverage, using: AddTriWingPat "TriWing", 3, 0,-1.6,-0.8

I've marked the (over-reaching, cross-tile) Bezier, which was
involved in the construction with a few green dots.

Now let's see, what your "understanding of the involved math" was worth:

First, let's introduce the proper even-odd fill-rule for this into your
(qah.Context(tile)
...
.set_source_colour(Colour.grey(1))
.set_fill_rule(1)
...

Then, using this param-set: {"curve_factor" : 1.6, "tilt" : 125 * deg}

I've marked your still insufficient coverage with red circles.

So, a certain amount of additionally appended paths is necessary,
to be able to cover (in case of curves which reach across a larger
amount of tiles) also the overlaps, where path-snippets contribute
into "remote, foreign tiles".

This is of course an endless game (in case we want to ensure enough
coverage for really *huge* Bezier-Curve-expansions) - but overly
large factors then tend to produce images, which are quite "cluttered
with smaller snippets" and don't really look good anymore.

So my current coverage of 22 paths is "playing it safe" for larger
(or midsized) curve-factors which "still look good and useful".

Your current coverage of only 7 paths is insufficient for those
midsized factors (as shown in the example-images I linked to above).

> Just adding more curve instances is easier in my code: you don’t have
> to calculate the new layout, since the script will automatically
> adjust to new row and column numbers.

That's pathetic, really.
I guess you're operating under the prejudice, that *any* VB-Developer
has to be some kind of idiot - but well - here I am Lawrence, and nice
to meet you too... <g>

>> Not sure what you're trying to "get away from", when working near the
>> cairo-API causes smaller, easier to understand code (for most of us).
>
> If you don’t accept the goals of Qahirah, why are you bothering with it?

Because you asked me (or "us") to come up with "comparable code"?
And since doing so automatically involves "comparisons" of some kind,
I had to "bother" with your wrapper (along the way) of course.

And no, looking at the results, I'm not sure whether your current
"getting-away"-approach is as attractive as you seem to think...

Olaf

```