Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@ChrisThrasher
Copy link
Member

@ChrisThrasher ChrisThrasher commented Apr 8, 2022

Description

sf::LineShape models a line segment defined by two points. The first point specifies the position of the line segment and the segment is drawn to the second point. The goal is to give users the simplest possible API for something they're already doing, drawing lines.

Here is an example of me using sf::LineShape to replace sf::RectangleShape in a project of mine.

Tasks

  • Tested on Linux
  • Tested on Windows
  • Tested on macOS
  • Tested on iOS
  • Tested on Android

@codecov
Copy link

codecov bot commented Apr 8, 2022

Codecov Report

Merging #2063 (e2f0fea) into master (45986c6) will decrease coverage by 0.04%.
The diff coverage is n/a.

❗ Current head e2f0fea differs from pull request most recent head 5da8c5e. Consider uploading reports for the commit 5da8c5e to get more accurate results

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2063      +/-   ##
==========================================
- Coverage   13.94%   13.90%   -0.05%     
==========================================
  Files         189      189              
  Lines       15821    15817       -4     
  Branches     4179     4169      -10     
==========================================
- Hits         2207     2199       -8     
- Misses      13460    13464       +4     
  Partials      154      154              
Impacted Files Coverage Δ
src/SFML/Audio/Music.cpp 0.00% <0.00%> (ø)
src/SFML/Audio/Sound.cpp 0.00% <0.00%> (ø)
src/SFML/Audio/ALCheck.cpp 0.00% <0.00%> (ø)
include/SFML/System/Time.inl 100.00% <0.00%> (ø)
src/SFML/Audio/AudioDevice.cpp 0.00% <0.00%> (ø)
src/SFML/Audio/SoundBuffer.cpp 0.00% <0.00%> (ø)
src/SFML/Audio/SoundSource.cpp 0.00% <0.00%> (ø)
src/SFML/Audio/SoundStream.cpp 0.00% <0.00%> (ø)
src/SFML/Audio/SoundRecorder.cpp 0.00% <0.00%> (ø)
src/SFML/Window/OSX/SFContext.mm 0.00% <0.00%> (ø)
... and 9 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 45986c6...5da8c5e. Read the comment docs.

@JonnyPtn
Copy link
Contributor

JonnyPtn commented Apr 8, 2022

I personally don’t see much value in adding this, there are already great libraries built on top of SFML which offer this (or it’s relatively simple to roll your own) and although it seems simple on the surface, a line shape like this can actually get quite complex use cases.

@ChrisThrasher ChrisThrasher force-pushed the sf_lineshape branch 3 times, most recently from ace9ab6 to 895699f Compare April 8, 2022 17:37
@Bromeon
Copy link
Member

Bromeon commented Apr 8, 2022

although it seems simple on the surface, a line shape like this can actually get quite complex use cases.

Isn't that rather a reason for adding a line shape to SFML?

In the past, it was often recommended that sf::RectangleShape can be used for lines. And while technically true (at least for non-rounded ends), it adds a lot of overhead for someone who simply wants to draw a few debug graphics.

It's well possible that there may be further feature requests though, e.g. end style (rectangular, pointy, rounded, arrow), line style (constant, dotted, dashed), etc.


Regarding implementation, I like the current one, as it is fairly simple. One possible change would be to cache the offset vector perpendicular to the direction (see comment).

@ChrisThrasher ChrisThrasher force-pushed the sf_lineshape branch 6 times, most recently from e7a1ac5 to 25a6919 Compare April 9, 2022 19:17
@JonnyPtn
Copy link
Contributor

Isn't that rather a reason for adding a line shape to SFML?

Sorry I don't quite understand how? It would mean we have to implement or at least consider the more complex use-cases as well as dealing with further feature requests (as you say). It would also like make the implementation/API much less simple than it currently is

someone who simply wants to draw a few debug graphics.

Yeah this use-case has been mentioned a few times in this discussion but I struggle to get on board with it. Debug lines are easily done with existing primitives, with this new class only offering the benefit of thickness, which is not something I've ever desired with my debug tools.

Based on my experience using lines with thickness (for end products, not debugging) there are a couple of things I've needed in my own implementations that I would question for this one:

  • How should textures be applied? With the current implementation I believe the texture would not rotate with the line, which is often what I would want/expect
  • Will we offer any control over the orientation of the ends of the line? A common use-case given for this is line graphs, but with any thickness larger than a couple of pixels the joins between the lines won't look good. In my own implementations i've made the ends of the line vertical for cases like this, but this is quite case-specific

@ChrisThrasher
Copy link
Member Author

ChrisThrasher commented Apr 11, 2022

with this new class only offering the benefit of thickness

It's more than just setThickness. We can't dismiss how this class provides much improved semantics as well. It lets you reason about lines as lines as opposed to stretched and rotated rectangles. Being able to set the end point is a much more friendly API.

How should textures be applied? With the current implementation I believe the texture would not rotate with the line, which is often what I would want/expect

Currently line segments can use any two start and end points while the rotation remains zero. An alternative solution is to dynamically update the rotation to match the direction to the end point. Then we just store a length and thickness internally. This approach might be friendlier to applying textures.

Will we offer any control over the orientation of the ends of the line? A common use-case given for this is line graphs, but with any thickness larger than a couple of pixels the joins between the lines won't look good.

This is why we also ought to consider sf::CurveShape for drawing curves comprised of many line segments.

@ChrisThrasher ChrisThrasher force-pushed the sf_lineshape branch 2 times, most recently from 82b6782 to 4a6f676 Compare April 19, 2022 15:12
@ChrisThrasher ChrisThrasher marked this pull request as ready for review April 20, 2022 23:14
@ChrisThrasher ChrisThrasher force-pushed the sf_lineshape branch 3 times, most recently from c53a94c to 3e84346 Compare April 25, 2022 02:51
@eXpl0it3r
Copy link
Member

eXpl0it3r commented Apr 30, 2022

While I can understand most arguments against a sf::LineShape, I still think that it should be implemented.

The fact that just about every SFML extension library has added such a line shape in one way or another and we have a multiple implementations in the community wiki is a strong indication that this is something SFML should provide out of the box.

Additionally, it's an often requested feature, which is also a good measure to show what people want - interestingly enough, each of these requests, is immediately followed by a link to one of the implementations above.

With that, I believe it's quite undeniable that there is demand for such a functionality.


Now for some of the arguments...

It's well possible that there may be further feature requests though, e.g. end style (rectangular, pointy, rounded, arrow), line style (constant, dotted, dashed), etc.
~ Bromeon

It would mean we have to implement or at least consider the more complex use-cases as well as dealing with further feature requests (as you say). It would also like make the implementation/API much less simple than it currently is
~ Jonny

There are many potential more complex use cases for other shapes as well (dotted outlines, rounded rectangles, different colored for each side outline, etc.). Just because there's a potential for additional feature requests, doesn't mean that we have to follow through with these requests, nor that they will actually happen. It's good to discuss some of those points for the initial implementation and define what problem the sf::LineShape solves, but it's not a good argument against the feature overall.

On the other hand, why are things like an arrow class or a rounded line or a spline not something SFML should have from the get go?

What worries me about lines with thickness, is that they are just rotated rectangles. Thus, the overlap between this class and sf::RectangleShape is close to 100%. The only thing that differs is how to define the shape, but the shape itself is still a rectangle. So maybe a better option would be to provide alternative ways to build a rectangle?
~ Laurent

I believe this highly depends on the API we build for sf::LineShape. Yes, it might be very similar to a rectangle shape underneath, but if the access APIs work with start/end points, then the usage becomes quite different and does justify a dedicated class for me.

A dedicated LineShape can add thickness to the sides only.

That's not obvious. It would feel strange / inconsistent to have outline only on two sides. That's in my opinion a good example of what kind of problems we'd get with a line-with-thickness class
~ Laurent

This is certainly something we need to make a decision on. Should a line only have an outline on the "long" side or all around it? Or should it be configurable?

Are there any additional arguments?


My personal design goals for a sf::LineShape class are:

  • Needs to fully implement the sf::Shape interface
  • "Simple" API to handling the two end points / constructing a line
  • Needs to clearly define the scope of the class:
    • No arrows
    • No rounded ends
    • No joints
    • Just a line between two points with an optional thickness

@Bromeon
Copy link
Member

Bromeon commented Apr 30, 2022

@eXpl0it3r Thanks a lot for the detailed research, this greatly summarizes the discussion!

This is certainly something we need to make a decision on. Should a line only have an outline on the "long" side or all around it? Or should it be configurable?

I think the most straightforward approach would be if line didn't have an outline at all -- or, the line itself is the outline.

This is how user software like Microsoft Word does it. There, shapes have the following properties:

  • Fill
    • Color
    • Gradient
    • Texture
  • Outline
    • Color
    • Weight (= thickness)
    • Dashes (dotted, dashed, straight)
    • Arrows

For line-like shapes (lines, arrows, curves), the Fill property is simply disabled, because it's meaningless. So everything is determined through the outline.


Back to SFML, this shows a LSP issue with sf::Shape. We have both fill and outline properties, although not all shapes support them. I see multiple options:

  1. Add a new intermediate interface sf::AreaShape or sf::FilledShape which provides methods regarding texture, texture rect, fill color. These methods would be moved down from sf::Shape. All existing shapes would inherit the new interface, while sf::Line would inherit the (now reduced) sf::Shape.
  2. Define a meaning for texturing/filling lines. Is that a feature that's really useful? Can it be provided in an intuitive way?
  3. Make some methods do nothing for sf::Line. This is quite ugly and like Java's UnsupportedOperationException shows bad OOP design.

@ChrisThrasher ChrisThrasher force-pushed the sf_lineshape branch 2 times, most recently from 6b76cf7 to 79f64d3 Compare May 9, 2022 14:16
@ChrisThrasher
Copy link
Member Author

Fixed minor merge conflict.

@ChrisThrasher
Copy link
Member Author

Rebasing to keep up with master. No changes.

@ChrisThrasher
Copy link
Member Author

Fixed trivial merge conflict.

@ChrisThrasher
Copy link
Member Author

Rebased and reformatted because of #2159

@ChrisThrasher
Copy link
Member Author

Rebased and fixed compiler error.

@ChrisThrasher
Copy link
Member Author

Rebased because it's been a while and because I needed to convert some size_ts to std::size_ts.

@vittorioromeo
Copy link
Member

Consider calling this sf::LineSegmentShape so that we can use sf::LineShape for a more full-fledged line class.

@vittorioromeo
Copy link
Member

@eXpl0it3r @Bromeon: would you be in favour of this PR if we rename it as sf::LineSegmentShape and make it clear that this is just a basic primitive over a line with some thickness, and then we can build on top of it (e.g. sf::LineShape could be a bunch of sf::LineSegmentShape, or we could have a sf::FancyLineSegmentShape where we can add rounded edges/arrows and stuff like that).

What do you think?

Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

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

I'm happy with this PR. While the outline issue is still there, it could be addressed in a later refactoring.

I don't think it's necessary to rename LineShape to LineSegmentShape. In 2D graphics, the term "line" is often used to refer to the concept as embodied by this PR. I encountered "line segment" more in mathematical contexts where lines are infinite, or when the graphics library needs to explicitly distinguish the two.

If you want to keep the term "line" for more fancy shapes like bezier, poly-lines etc, I'd probably rather use "curve" for those. "Line" seems very connected to "straight" to me 🙂

@ChrisThrasher
Copy link
Member Author

Rebased to catch up with master. No changes required.

@ChrisThrasher
Copy link
Member Author

Rebased to get new CI jobs.

@ChrisThrasher ChrisThrasher force-pushed the sf_lineshape branch 2 times, most recently from d73bbf3 to 0361288 Compare October 14, 2022 15:16
@ChrisThrasher
Copy link
Member Author

Fixed small merge conflict with master.

sf::LineShape models a line segment defined by two points. The
first point specifies the position of the line segment and the
segment is drawn to the second point.
@ChrisThrasher
Copy link
Member Author

I'm not interested in maintaining or discussing this anymore so I'm closing it (again). If motivation returns we can resurrect this but it's not worth keeping this open in the meantime.

@SFML SFML deleted a comment from eXpl0it3r Dec 26, 2022
@SFML SFML deleted a comment from vittorioromeo Dec 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants