pytroll / aggdraw

Python package wrapping AGG2 drawing functionality
https://aggdraw.readthedocs.io/en/latest/
Other
98 stars 48 forks source link

Misleading information in the document #89

Closed setanarut closed 9 months ago

setanarut commented 9 months ago

https://aggdraw.readthedocs.io/en/latest/

This will install the older version that is not published in Pypi.

Ekran Resmi 2023-09-19 23 44 39

Why hasn't this latest repo been released for years? I use aggdraw for the drawing library I wrote, I wish the new version was active. For example, the Draw.polygon() method always closes the entered coordinates. It would be better in terms of performance if there was a method that drew the entered coordinate sequence as an open-ended path.

Ekran Resmi 2023-09-19 23 56 16

djhoese commented 9 months ago

This will install the older version that is not published in Pypi.

Unless I'm misunderstanding you, I disagree. This installs the latest stable release of the software. That version's code is in maint/1.3 branch of this repository and has been released as recently as February of this year to fix or update various build changes needed in the project.

As for "old" install or not, are you saying that the "latest" version of the documentation should not provide installation instructions that install the last stable release? For the record there is a "stable" version of the documentation here:

https://aggdraw.readthedocs.io/en/stable/

And it is the default version chosen when you go to https://aggdraw.readthedocs.io or you can choose the version in the lower right dropdown of the docs page. Perhaps what you're looking/hoping for are instructions for installing from source? I can provide those to you if you'd like or a pull request adding them would be appreciated too.

Why hasn't this latest repo been released for years?

This project is a volunteer effort. It is "maintained" (if I can call it that) by one person, me. This project was not created by me and is not even heavily used by me, but it is a dependency of a dependency of a dependency of a dependency for one of my projects so I need it to stay alive. If you want new features to be released on a certain schedule then you'll either need add them yourself or find a way to fund the development.

In my limited time I was excited when someone submitted such a large pull request (#50) to update the low-level C++ AGG library. Without thoroughly reviewing it I merged it into master and didn't discover until after that that the PR produces drastically different results for most use cases. THIS is why there hasn't been a release of master for many years. It requires debugging not only the changes to aggdraw from #50 but understanding and debugging the C++ library (are these differences expected? are they a bug? who's to say?). That said, I commented on another issue, there has been someone outside of github emailing me with some partial solutions and a path to debugging that may prove successful...but I haven't had time to continue debugging and I haven't received an email from this person in a while so my guess is their time dried up too.

For example, the Draw.polygon() method always closes the entered coordinates. It would be better in terms of performance if there was a method that drew the entered coordinate sequence as an open-ended path.

Does the version in master do that? How would you achieve it? Are there other features that you need that are only in the master branch? What kind of performance differences are you seeing in the closed/opened coordinate handling? Why can't you provide closed coordinates?

setanarut commented 9 months ago

Thanks for your long answer and your effort. You are right about the documentation, my mistake. aggdraw is the simplest, most beautiful I've found. Less dependency drawing library. I hope it gets more attention.

For example, the Draw.polygon() method always closes the entered coordinates. It would be better in terms of performance if there was a method that drew the entered coordinate sequence as an open-ended path.

Does the version in master do that? How would you achieve it? Are there other features that you need that are only in the master branch? What kind of performance differences are you seeing in the closed/opened coordinate handling? Why can't you provide closed coordinates?

One way to do this is to convert the coordinates to an SVG string and send it to the symbol() function. I thought this was a costly operation compared to entering a list of coordinates directly.

    @property
    def d(self):
        """Returns SVG d string"""
        dstr = "M " + str(self.coords[0]) + " " + str(self.coords[1])
        for i in range(2, len(self.coords), 2):
            x, y = self.coords[i], self.coords[i+1]
            dstr += " L " + str(x) + " " + str(y)
        return dstr
        # if self.closed:
        #     dstr += " Z"

The solution I found uses the polygon() if the path is closed. If the path is open, I use the symbol() with SVG d string I produced.

https://github.com/setanarut/pd/blob/d17fd9a2880d92da89cf4e133b12977ff5fc3cb3/src/pd/singleton.py#L32

    def draw(self, fill="#181818", stroke="grey", thickness=1.5):
        """Draws the path on the canvas."""
        if self.is_closed():
            singleton.draw_polygon(self.coords, fill, stroke, thickness)
        else:
            singleton._draw_d(self.d, fill, stroke, thickness)
        return self

The second way is to loop the functions moveto() lineto() ... and create an aggdraw.Path object and draw it with path() function (I haven't tried this, It's more complicated than creating a string.).

In conclusion. I think there should be a function that draws the entered coordinates without closing them.

setanarut commented 9 months ago

full references : https://setanarut.github.io/pd_docs/aggdraw_doc.html

djhoese commented 9 months ago

Sorry I need us to take a step back. What is the end result you want when your path is open? My assumption is that you want to build a polygon over time so you will keep adding coordinates (for example in an animation). In this case you still want it to look like a filled closed polygon (ex. like a lasso selection tool in drawing tools)? Or do you want it to be a line/path? I guess I'm confused why you can't repeat the first coordinate on the end of the list of coordinates to close the polygon and allow it to be drawn.

Side note:

Your _draw_d method could be simplified in a couple ways. First, you should always do x is None (or x is not None) instead of x == None. Second, you could do:

if fill is None and stroke is None:
    print("warning")

pen = aggdraw.Pen(stroke, thickness) if stroke is not None else None
brush = aggdraw.Brush(fill) if fill is not None else None

draw.symbol((0, 0), aggdraw.Symbol(d), pen, brush)
draw.flush()

Then there is no repeated code.

djhoese commented 9 months ago

I think you can just pass a list of coordinates to Path to create one and it will do the move_to and line_to for you:

https://github.com/pytroll/aggdraw/blob/21742bef1581ed5457a428f699efa975266929a3/aggdraw.cxx#L2071-L2082

setanarut commented 9 months ago

I think you can just pass a list of coordinates to Path to create one and it will do the move_to and line_to for you:

Thank you very much, this is exactly what I wanted. I didn't know I could do this because it wasn't written in the documentation. I will also implement your other repeated code fix.

import aggdraw
from PIL import Image

img = Image.new("RGBA", (300, 300), "black")
d = aggdraw.Draw(img)
pen = aggdraw.Pen("white", 2)
brush = aggdraw.Brush("brown")
path = aggdraw.Path([30, 30, 200, 200, 150, 100])
print(path.coords()) # [30.0, 30.0, 200.0, 200.0, 150.0, 100.0]
d.path(path, pen, brush)
d.flush()
img.save("canvas.png")

canvas