Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Barycentric coordinates #10

Merged
merged 29 commits into from
Jun 4, 2023
Merged

Barycentric coordinates #10

merged 29 commits into from
Jun 4, 2023

Conversation

asinghvi17
Copy link
Member

@asinghvi17 asinghvi17 commented May 20, 2023

I want this PR so that we can actually render polygons with color-per-vertex correctly, rather than triangulating and rendering that way which introduces a lot of discontinuities.

Here's how this PR can render them:

Mean value barycentric coordinate rendering

Here's how Makie renders them now:
Mesh based polygon rendering CairoMakie
Mesh based polygon rendering GLMakie

Barycentric coordinates

Generalized barycentric coordinates are a generalization of barycentric coordinates, which are typically used in triangles, to arbitrary polygons.

They provide a way to express a point within a polygon as a weighted average of the polygon's vertices.

In the case of a triangle, barycentric coordinates are a set of three numbers $(λ_1, λ_2, λ_3)$, each associated with a vertex of the triangle. Any point within the triangle can be expressed as a weighted average of the vertices, where the weights are the barycentric coordinates. The weights sum to 1, and each is non-negative.

For a polygon with n vertices, generalized barycentric coordinates are a set of $n$ numbers $(λ_1, λ_2, ..., λ_n)$, each associated with a vertex of the polygon. Any point within the polygon can be expressed as a weighted average of the vertices, where the weights are the generalized barycentric coordinates.

As with the triangle case, the weights sum to 1, and each is non-negative.

Methods to find barycentric coordinates

Mean value coordinates

This method is what I've implemented here for now. This basically sweeps around the vertices of the polygon, and computes a weight for each point based on the angles formed by the vertices with respect to the point.

@asinghvi17
Copy link
Member Author

I have changed the default method to the one described by Hormann in About barycentric coordinates.pdf, which is significantly faster (tenths of a second for polygons without holes, ~1s for a 400 point polygon with hole). These were both on 1000x1000 grids, so all in all these seem to be reasonable methods to render.

Now the next task (and boy howdy it's a task 😓 ) is to make this compatible with color interpolation. It's not as easy as it sounds unfortunately - right now, we're just interpolating from a texture. I've tested that the interpolator currently works with e.g. UV coordinates (Vec2f), so we're on track there. But direct color interpolation would mean using Colors.weighted_color_mean, which means we have to do streaming averages which can be a hair less accurate. They are also a pain to keep track of, and we may have to make an API specifically for this kind of thing.

@rafaqz
Copy link
Member

rafaqz commented May 25, 2023

If you have multiple formulations, you can always keep a few and define a Hormann() singleton so users can choose them, but pick a default. I've done that for simplifiy now to have the three main algorithms (I'll push it later on).

@asinghvi17
Copy link
Member Author

asinghvi17 commented May 26, 2023

Ah nice! I have a prototype common API but it's got a lot of code replication that I can't figure out how to get rid of. Will push that when I get to the hotel though.

I also made a more efficient implementation which takes 0.15 seconds for multivalue polygon rasterization. So that helps :D - its also generic so accepts rgb, uv vectors, number types, etc.

@asinghvi17
Copy link
Member Author

I added a quick and dirty readme as well as some tests. The provisional logo is the barycentric rendering but with inverted color - but that can be changed :D

@asinghvi17
Copy link
Member Author

Looks like libcurl is still messing with nightly. See below:

└─PROJ_jll [58948b4f] log:
 │   ├─possible versions are: 6.2.1-900.100.0 or uninstalled
 │   ├─restricted by julia compatibility requirements to versions: [6.2.1-7.2.1, 700.202.100-900.100.0] or uninstalled
 │   ├─restricted by compatibility requirements with Proj [c94c279d] to versions: 900.0.0-900.100.0
 │   │ └─Proj [c94c279d] log:
 │   │   ├─possible versions are: 1.0.0-1.4.0 or uninstalled
 │   │   └─restricted to versions 1 by GeometryOps [3251bfac], leaving only versions: 1.0.0-1.4.0
 │   │     └─GeometryOps [3251bfac] log: see above
 │   └─restricted by compatibility requirements with LibCURL_jll [deac9b47] to versions: 6.2.1-900.0.0 or uninstalled, leaving only versions: 900.0.0

@asinghvi17
Copy link
Member Author

asinghvi17 commented May 31, 2023

So this PR is pretty much ready to go, but it seems like some of the syntax we used ((; x, y, z) = struct1) is incompatible with v1.6. I might change that here, then merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants