Skip to content

ear clipping using pnpoly algorithm - #156

Merged
syoyo merged 3 commits into
tinyobjloader:masterfrom
raspofabs:master
Jan 15, 2018
Merged

ear clipping using pnpoly algorithm#156
syoyo merged 3 commits into
tinyobjloader:masterfrom
raspofabs:master

Conversation

@raspofabs

Copy link
Copy Markdown
Contributor

I noticed a bug with badly selecting the axis. pnpoly required selecting an axis for running against its 2D algorithm. Doing what it suggested turned out to be a bad idea on some geometry, so I fixed it, and now here's a new PR.

@syoyo
syoyo merged commit 5383e34 into tinyobjloader:master Jan 15, 2018
@syoyo

syoyo commented Jan 15, 2018

Copy link
Copy Markdown
Collaborator

Super cool! Merged!

@syoyo

syoyo commented Feb 28, 2021

Copy link
Copy Markdown
Collaborator

@raspofabs We found a bug that internal angle test in trinangulation fails in some case: https://github.com/tinyobjloader/tinyobjloader/issues/295

The situation is

  • (signed) area is calculated over the polygon
  • the signedness of area become wrong depending on the value of vertex coordinate
  • each angle is falsely detected as internal angle(even for the square polygon)
  • remainingFace.vertex_indices.size() become 4 or more, resulting some faces become disappear.
    if (remainingFace.vertex_indices.size() == 3) {

Computing signed area per triangle seems correctly handle internal angle test. Code is somewhat like this:

            real_t e0x = vx[1] - vx[0];
            real_t e0y = vy[1] - vy[0];
            real_t e1x = vx[2] - vx[1];
            real_t e1y = vy[2] - vy[1];
            real_t cross = e0x * e1y - e0y * e1x;

            real_t area = (vx[0] * vy[1] - vy[0] * vx[1]) * static_cast<real_t>(0.5);

            // if an internal angle
            if (cross * area < static_cast<real_t>(0.0)) {
              guess_vert += 1;
              continue;
            }

@raspofabs Do you think this is the correct solution?

@raspofabs

Copy link
Copy Markdown
Contributor Author

@raspofabs We found a bug that internal angle test in trinangulation fails in some case: #295

The situation is

* (signed) `area` is calculated over the polygon

* the signedness of `area` become wrong depending on the value of vertex coordinate

* each angle is falsely detected as internal angle(even for the square polygon)

* `remainingFace.vertex_indices.size()` become 4 or more, resulting some faces become disappear. https://github.com/tinyobjloader/tinyobjloader/blob/9173980d1de273b17eba5e10eb189e8b4be89425/tiny_obj_loader.h#L1575

Computing signed area per triangle seems correctly handle internal angle test. Code is somewhat like this:

            real_t e0x = vx[1] - vx[0];
            real_t e0y = vy[1] - vy[0];
            real_t e1x = vx[2] - vx[1];
            real_t e1y = vy[2] - vy[1];
            real_t cross = e0x * e1y - e0y * e1x;

            real_t area = (vx[0] * vy[1] - vy[0] * vx[1]) * static_cast<real_t>(0.5);

            // if an internal angle
            if (cross * area < static_cast<real_t>(0.0)) {
              guess_vert += 1;
              continue;
            }

@raspofabs Do you think this is the correct solution?

Sorry, my mistake. Yes, it looks like the problem is precision during the area calculation.
A simple fix (imo) would be to subtract the first coordinate from every vertex position before committing to doing the calculations. Then there will always be a vertex at 0,0,0 and the likelihood of precision issues occuring should be vastly reduced.

so, take a vertex at random (first is fine), then subtract that vertex's values from all others before doing analysis of the vertices. I can't work on this at the moment as I don't have a machine set up for development right now.

@syoyo

syoyo commented Feb 28, 2021

Copy link
Copy Markdown
Collaborator

@raspofabs Thanks!

A simple fix (imo) would be to subtract the first coordinate from every vertex position before committing to doing the calculations. Then there will always be a vertex at 0,0,0 and the likelihood of precision issues occuring should be vastly reduced.

I see. So compute area over polygon(not per trinagle) based on relative vertex coordinate(e.g. move the first vertex to the origin) would solve the issue. I will try it to implement.

BTW I have integrated mapbox's earcut into tinyobjloader. We can verify the correctness with it: #298

@syoyo

syoyo commented Jul 29, 2021

Copy link
Copy Markdown
Collaborator

@raspofabs After reading algorithm description of earcut, area is calculated per face, not over the polygon. Precision wasn't a problem.

syoyo added a commit that referenced this pull request Nov 10, 2025
ear clipping using pnpoly algorithm
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