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

One-sided offset with EndType::ButtLeft #905

Closed
wants to merge 1 commit into from

Conversation

LarsSkiba
Copy link
Contributor

Implement a one-sided offset by extending the EndType with ButtLeft.

@LarsSkiba
Copy link
Contributor Author

LarsSkiba commented Oct 18, 2024

Hi @AngusJohnson,

  • This implementation is not fully finalized yet but i created a PR so you can comment on the code early during my development and maybe give helpful feedback, if you recognize undesired changes.

  • Please leave it open unless you plan not to accept such a contribution at all, which would also be helpful feedback ;)

  • This only implements a left-sided offset

  • My testcases work fine so far, i'd also contribute them to your tests when i'm done.

  • Does the API extension makes sense to you? It's not really an EndType but so is polygon and this extension seems like the least "invasive" API extension.

  • I'd also add a right-sided offset, one really trivial approach would be reverse the EndType from ButtRight to ButtLeft, call OffsetOpenPath and reverse the last path in the solution. Do you have an opinion on this approach?

  • I can also try extending other languages once i have a finalized, accepted C++ PR.

The additional logic in OffsetPoint solves this problem:
image

To my knowledge this is not solvable by a FillRule so i went with calculation the intersection point.

const bool intersect =
end_type_ == EndType::ButtLeft // one-sided offset
&& cos_a < 0 // < 90 degre
&& !path_out.empty() // safety check, can this never happen?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think path_out can never by empty at this point, but i'm not 100% sure.

end_type_ == EndType::ButtLeft // one-sided offset
&& cos_a < 0 // < 90 degre
&& !path_out.empty() // safety check, can this never happen?
&& l < path.size(); // safety check, can this never happen?
Copy link
Contributor Author

@LarsSkiba LarsSkiba Oct 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basicely j must never be the last or first point, depending on direction given by the relation between k and j.
It seems given to me, but again i'm not 100% sure.

@@ -398,16 +429,23 @@ void ClipperOffset::OffsetOpenPath(Group& group, const Path64& path)
case EndType::Round:
DoRound(path, 0, 0, PI);
break;
case EndType::ButtLeft:
left_end = Point64(GetPerpendicD(path[0], norms[0], -abs_group_delta));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this can be done more elegant later.

@LarsSkiba
Copy link
Contributor Author

I discovered further major challenges, closing for now.

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