SFML community forums

General => Feature requests => Topic started by: Hyden on April 17, 2016, 05:18:59 pm

Title: sf::Line(int x1, int y1, int x2, int y2)
Post by: Hyden on April 17, 2016, 05:18:59 pm
I'd like to see a sf::Line function. The common reply is usually something along the lines: "You can easily create a line with sf::VertexArray, so what's the point?". However you could just as easily say: "What's the point in having sf::RectangleShape when you can easily create a rectangle with sf::VertexArray". Implementing you own line function is annoying and just wastes time and I see no reason at all as to why SFML doesn't have its own line function.
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: korczurekk on April 17, 2016, 05:54:02 pm
sf::Line (btw it should be sf::LineShape) would be just sf::RectangleShape with changed names of variables and one or two additional methods, there is no need to implement it in sfml if that can be easly written within 30-40 lines of code. I would rather add something like this:
void rotateTo(sf::Vector2f & factors) { /*some cool code*/ }
to some abstract class inherited by most default drawables, that one would be much more useful and universal.
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Nexus on April 17, 2016, 06:04:12 pm
This has been discussed many times already, so please address the original arguments if you want to bring in something new.

In case you have the Thor library, you can use the class thor::Arrow (http://www.bromeon.ch/libraries/thor/documentation/v2.1/classthor_1_1_arrow.html), which also supports arrow tips (and in the future maybe different line styles). Thor also comes with rotation functions for vectors, in case you need them.
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Hapax on April 17, 2016, 11:18:56 pm
There is a Line class and even a Spline class included in Selba Ward (https://github.com/Hapaxia/SelbaWard/wiki) (a collection of SFML drawables). The Line class can draw with or without thickness.

There are also a few line classes listed on SFML's wiki in the Sources section - under Drawables (https://github.com/SFML/SFML/wiki/Sources#drawables).
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Hyden on April 23, 2016, 12:04:46 pm
Alright... So you're saying that if I want to create a line (the most basic shape) in SFML (a library centered around GRAPHICS) I have to use another library or create the sf::LineShape class myself?
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Kojay on April 24, 2016, 12:31:46 am
In case you have the Thor library, you can use the class thor::Arrow (http://www.bromeon.ch/libraries/thor/documentation/v2.1/classthor_1_1_arrow.html), which also supports arrow tips (and in the future maybe different line styles). Thor also comes with rotation functions for vectors, in case you need them.

Uh, you have a line function (http://www.bromeon.ch/libraries/thor/documentation/v2.1/namespacethor_1_1_shapes.html#aaf7a2812214d46e49746d9b07e79762a) returning a ConvexShape - why not recommending that one?

I'm in agreement with the OP. No this isn't the first time this pops up and yes, we all know it can be coded easily or found somewhere. It still is a glaring hole in the API. A line between two points is a very basic thing to do, particularly when prototyping; it is quite jarring to have to write boilerplate/hunt some dependency/dig up a pre-written snippet.
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Hyden on April 24, 2016, 02:19:30 pm
@Kojay That is what I'm trying to get across. There is a reason this keeps popping up. I'm utterly mind blown as to why people are arguing a GRAPHICS library shouldn't have support for drawing a LINE. Is it really that hard to believe that people using a graphics library might want to draw a line?

Have you tried creating a line with a rectangle? You can't specify a start position and an end position, you have to rotate it and it's so hard to get it perfect.
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Laurent on April 24, 2016, 02:34:51 pm
So, to make it clear, the proposal is to add this:
sf::Line line(x1, y1, x2, y2);
line.setFillColor(color);
window.draw(line);

... to avoid writing this:
sf::Vertex line[] = {{{x1, y1}, color}, {{x2, y2}, color}};
window.draw(line, sf::Lines);

Is it really worth it? (real question, I personally don't know)
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Hyden on April 24, 2016, 02:39:18 pm
sf::RectangleShape could be created using sf::Vertex yet we still have it. The reason that sf::Line is better than using sf::Vertex is because it is easier to read and you can quickly glance at it and understand it. It's completely worth it, if you believe that it isn't then surely it's not worth having sf::RectangleShape either?
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Kojay on April 24, 2016, 03:36:16 pm
So, to make it clear, the proposal is to add this:
sf::Line line(x1, y1, x2, y2);
line.setFillColor(color);
window.draw(line);

... to avoid writing this:
sf::Vertex line[] = {{{x1, y1}, color}, {{x2, y2}, color}};
window.draw(line, sf::Lines);

Is it really worth it? (real question, I personally don't know)

That does not have thickness.

To add a line with thickness between two points requires a bit more boilerplate, like here (https://github.com/SFML/SFML/wiki/Source:-Line-segment-with-thickness). If I have been missing an obvious way to do that, by all means point it out.
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Laurent on April 24, 2016, 05:26:07 pm
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?
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Kojay on April 24, 2016, 05:32:10 pm
There is one more difference I believe: increasing the outline thickness of a rectangle pads the two edges beyond where the original points are located. A dedicated LineShape can add thickness to the sides only.

It is unlikely one wants a hugely thick line so the difference should not be great visually. But it is there.
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Laurent on April 24, 2016, 07:24:21 pm
Quote
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.
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Hyden on April 24, 2016, 10:51:11 pm
The main issue with creating a line using sf::RectangleShape is that you can't define the start position and the end position. It's very arkward to rotate a sf::RectangleShape to do that. This is what I see a sf::LineShape looking like:

sf::LineShape arrow;

arrow.setThickness(2);
arrow.setPosition(sf::Vector2f(23, 74), sf::Vector2f(163, 293));
arrow.setFillColor(sf::Color::Red);
arrow.setOutlineColor(sf::Color::Black);
arrow.setOutlineThickness(4);
arrow.setSmoothEnds(true);
arrow.setFeatures(sf::Arrow::Front);
 

This abstracts away the whole having to create a rectangle, get the right angle and length so it starts at 23, 74 and ends at 163, 293, then creating two other rectangles and rotating them at the right angle so they make an arrow. And then having to create two circles or something at the end of the rectangle so that it has smooth ends. This gets tedious and sf::LineShape is much quicker and easier. Otherwise using a sf::RectangleShape to create this would be bordering on impossible.
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Nexus on April 25, 2016, 12:09:00 am
Alright... So you're saying that if I want to create a line (the most basic shape) in SFML (a library centered around GRAPHICS) I have to use another library or create the sf::LineShape class myself?
I'm not saying anything, just showing you alternatives to achieve what you want given SFML's status quo. I haven't implied that the lack of line shapes in SFML is a good thing. So, no need for that cynical tone :)


Uh, you have a line function (http://www.bromeon.ch/libraries/thor/documentation/v2.1/namespacethor_1_1_shapes.html#aaf7a2812214d46e49746d9b07e79762a) returning a ConvexShape - why not recommending that one?
As stated in the documentation:
Quote
If you want a more flexible line implementation that can also be changed after creation, look at the thor::Arrow class and its Line style.
thor::Shapes::line() is for simple one-liners. It may be enough in many cases though.


then creating two other rectangles and rotating them at the right angle so they make an arrow. And then having to create two circles or something at the end of the rectangle so that it has smooth ends.  Otherwise using a sf::RectangleShape to create this would be bordering on impossible.

[...]

This gets tedious and sf::LineShape is much quicker and easier.
Yes, but what you're talking about is no longer a line. Strictly mathematically speaking, lines don't even have a thickness, it's just a common feature for convenience. Above you're talking about "the most basic shape"; I don't think arrow tips are part of that.

The problem is that the features you're proposing are too broad to fit into the concept of sf::Shape. Your class is not even a shape, it's multiple shapes (rectangle + 2 circles or triangles for arrow tips). In addition, it's not convex, a requirement for SFML shapes. What should getPoint() and getPointCount() return? Is it not totally unintuitive if a line has more than 2 points? Have you tried to implement texturing on those shapes? Furthermore, do lines have fill and outlines like shapes with actual area?

As you see, writing a line class is one thing, but integrating it well into the library is another. We have to solve the above-mentioned problems before sf::LineShape can be considered. And if it ends up 99% like sf::RectangleShape, we should rather think about adapting that class. Laurent mentioned this point before, by the way.
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Hapax on April 28, 2016, 01:05:32 am
Alright... So you're saying that if I want to create a line (the most basic shape) in SFML (a library centered around GRAPHICS) I have to use another library or create the sf::LineShape class myself?
No.
Firstly, the "library" that I mentioned contains pretty much self-contained classes that can be used without the rest of the library; you can just copy and paste and use individual classes.
Secondly, I also mentioned that there are line classes in the SFML wiki that can just be copied directly.

[T]hey are just rotated rectangles.
[...]
[M]aybe a better option would be to provide alternative ways to build a rectangle?
This makes a lot of sense.
Why is a thick line called a line? It is because of the controls to manipulate it are different.
Creation of a line rectangle would require the positions of the centres of opposition sides and the width (or height) of the rectangle. However, just creation is not enough; it must be able to be moved in this way too (imagine moving one point of a line, for example).

The main issue with creating a line using sf::RectangleShape is that you can't define the start position and the end position. It's very arkward to rotate a sf::RectangleShape to do that.
...
This abstracts away the whole having to create a rectangle, get the right angle and length so it starts at 23, 74 and ends at 163, 293, then creating two other rectangles and rotating them at the right angle so they make an arrow. And then having to create two circles or something at the end of the rectangle so that it has smooth ends. This gets tedious and sf::LineShape is much quicker and easier. Otherwise using a sf::RectangleShape to create this would be bordering on impossible.
I don't think that using a rectangle shape to create a line is a lot of work.
See here (https://github.com/Hapaxia/SelbaWard/blob/master/src/SelbaWard/Line.cpp#L149-L159).

One thing you mentioned here is that you think that lines should have rounded edges which is a completely new thing entirely (technically, a rounded rectangle, which, by the way, is also available in the SFML wiki).
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: R23MJ on May 03, 2016, 03:36:34 pm
I don't have much to add here; however a line class could be useful for something like raycasting, for arrows or the such, or as a tool to measure distance, (someLine.getLength()). This is a completely different topic though, implementing it like that would make it more of a utility then a shape, and I don't think that is what the OP really wanted. Anyways, just my two cents.
Title: Re: sf::Line(int x1, int y1, int x2, int y2)
Post by: Zamadatix on May 24, 2016, 10:20:29 pm
So, to make it clear, the proposal is to add this:
sf::Line line(x1, y1, x2, y2);
line.setFillColor(color);
window.draw(line);

... to avoid writing this:
sf::Vertex line[] = {{{x1, y1}, color}, {{x2, y2}, color}};
window.draw(line, sf::Lines);

Is it really worth it? (real question, I personally don't know)

Just chiming in to say I think it has value. It shouldn't be about code golf or the difficultly to manually implement, the point is to provide consistency in SFML for the base set of shapes and if a line isn't included in the base set of shapes it's all quite arbitrary that anything is in my opinion.

If  I don't care much one way or the other on the line thickness debate, I think it leads into a "how many style options should we add to the base shapes" argument more than it leads to any added value on the "should there be a line shape" argument.