-
Notifications
You must be signed in to change notification settings - Fork 28
Spline
A class to draw a composite line, which is made up of multiple smaller lines. The lines can be interpolated either linearly or using Bezier in conjunction with vertex handles to display a (composite) Bezier curve.
The Spline can be closed, which automatically connects the final vertex to the first vertex.
Each interpolated vertex can be offset by a random amount - within a specified range.
Each vertex can be coloured individually and also specify its own thickness and range for random offset. Vertex colours, thicknesses and ranges are multiplied by the global colour, thickness and range; for that reason, the vertex's default thickness, range and colour are 1, 1 and white respectively.
The Spline can be infinitely thin - and always drawn as single pixel wide - or have any thickness, including 1.
The Spline's corners and caps can be customised.
Splines can be connected to other Splines and/or combined.
An empty spline (no vertices):
sw::Spline spline;
A spline with an initial number of vertices:
sw::Spline spline(std::size_t numberOfVertices);
A spline with an initial number of vertices that all default to the specified position:
sw::Spline spline(std::size_t numberOfVertices, sf::Vector2f position);
A spline with a set of vertices' positions (sf::Vector2f) passed via the initializer list:
sw::Spline spline(std::initializer_list<sf::Vector2f>);
This class inherits from sf::Drawable so it is drawn in the same way as all SFML drawables:
window.draw(spline);
where window is an sf::RenderWindow.
Note: actually, window could be any sf::RenderTarget.
Spline has its own vertex type which stores its position and two offsets: front handle and back handle. The spline is made up of multiple of these vertices, which can be used to display a polyline (when handles are both zero) or a polybezier.
Each vertex also stores its own thickness, colour and range (for random normal offsets). These are multiplied by the global values for each of these. When vertices are interpolated, these values are also interpolated at that point.
-
setThickness(thickness)
changes the global thickness of the Spline. If thickness is zero, the Spline is drawn using sf::LineStrip (or whichever primitive type is chosen - see below) otherwise it is drawn using sf::TriangleStrip. This method is templated so the thickness parameter can be any type (it's casted to a float). This global thickness value is multiplied with the vertex thickness. -
setRandomNormalOffsetRange(float randomNormalOffsetRange)
changes the range of the random normal offset of the Spline. This method is templated so the thickness parameter can be any type (it's casted to a float). This global randomNormalOffsetRange value is multiplied with the vertex randomNormalOffsetRange. -
setRandomNormalOffsetsActivated(bool)
sets whether the random normal offsets are activated or not. If they are, the random normal offsets (see setRandomNormalOffsetRange above) are applied to each vertex (including interpolated vertices), if they are not activated, the random normal offsets are not calculated at all, reducing the random number calculations when not needed. Note that from v1.6, this is deactivated by default so needs to be activated before they can be used. -
setClosed(bool)
changes the state of the spline to closed, if bool is true, and open, if it is false. A closed spline automatically connects the final vertex to the first vertex as if the first vertex was also included after the final vertex. -
setColor(sf::Color)
changes the global colour of the spline to the specified sf::Color. This colour is multiplied with the vertex colour. -
setPrimitiveType(sf::PrimitiveType)
changes the sf::PrimitiveType used to display the (standard thin) spline -
reserveVertices(std::size_t)
reserves the memory for a specific (or expected maximum) sized spline. If reservations are required, reserveVertices() should be called after setting interpolation steps -
reverseVertices()
reverses the order of the vertices. The handles are also swapped so that the spline looks the same after reversing -
update()
updates the visual representation of the spline from the current state of the Spline object. This includes recalculating the interpolations. It is most likely not necessary to call this more than once per draw call although it's only required if the object has altered. This also updates output vertices. If nothing has changed to affected interpolated vertices, this can be skipped and updateOutputVertices() can be called directly. -
updateOutputVertices()
updates the actual visual representation of the spline from the current stored calculations of the interpolated Spline. It is most likely not necessary to call this more than once per draw call although it's only required if the object has altered. Although update() calls this automatically, this can be called directly instead if nothing has changed the interpolated vertices. This is useful if something else has changed e.g. corners or caps type changed or the range for random normal offsets -
setThickCornerType(cornerType)
changes the corner type for thick Splines. The type for cornerType is selbaward::Spline::ThickCornerType (an enum class) and can be any of the three types: Point, PointLimit, PointClip, Bevel or Round. Point extends the corners of the rectangles - that make up the thick line between two points - to the point where they meet. Bevel joins the corners of the rectangles with a straight edge. Round joins the corners with a circle sector with a diameter equal to the line's thickness. PointClip creates a Point-type corner but if its length (from the point to the Spline vertex position) is greater than the maximum corner point length (see setMaxCornerPointLength below), the corner is converted to a Bevel-style corner. PointLimit also creates a Point-type corner and modifies it if its length is greater than the maximum. However, PointLimit moves the point inwards so that its length is equal to that maximum. Note that if the maximum length is less than half of the line's thickness, the corner is 'pulled inwards' and when the maximum length is zero, the appearance is equivalent to two overlapping rectangles with no corner join. -
setRoundedThickCornerInterpolationLevel(interpolationLevel)
changes the interpolation level of the corners for thick Splines. This is the number of points along the arc on each corner. Note that this does not include the start and end point of the arc so zero interpolation level is visually equivalent to a bevelled corner. -
setThickStartCapType(capType)
changes the cap type of the start point for thick Splines. The type for capType is selbaward::Spline::ThickCapType (an enum class) and can be any of the three types: None, Extended or Round. These types may be known by other names elsewhere: None (AKA flat/butt), Extended (AKA projected/square), Round (AKA circle) -
setRoundedThickStartCapInterpolationLevel(interpolationLevel)
changes the interpolation level of the start cap for thick Splines. This is the number of points along the arc (semi-circle) on the cap. Note that this does not include the start and end point of the arc so zero interpolation level is visually equivalent to a cap with type None. -
setThickEndCapType(capType)
changes the cap type of the end point for thick Splines. The type for capType is selbaward::Spline::ThickCapType (an enum class) and can be any of the three types: None, Extended or Round. These types may be known by other names elsewhere: None (AKA flat/butt), Extended (AKA projected/square), Round (AKA circle) -
setRoundedThickEndCapInterpolationLevel(interpolationLevel)
changes the interpolation level of the end cap for thick Splines. This is the number of points along the arc (semi-circle) on the cap. Note that this does not include the start and end point of the arc so zero interpolation level is visually equivalent to a cap with type None. -
setInterpolationSteps(std::size_t)
informs the Spline how many times each line segment (between two vertices) should be interpolated. Starting with start and end points for a segment, if interpolation steps is set to 5, there will be 7 points for that segment. Interpolation is unnoticable when the spline is a continous, solid line and linearly interpolated -
setMaxCornerPointLength(float)
changes the maximum allowed length for a pointed corner when using the PointLimit or PointClip thick corner types. See setThickCornerType above. -
setBezierInterpolation(bool)
enables or disables bezier interpolation of line segments. If enabled, the vertices' handles are used create a Bezier curve, otherwise the vertices are interpolated linearly, creating straight lines -
setHandleMirrorLock(bool)
enables or disables a lock that constrains a handle to the mirror of its opposite - whenever a handle is changed. Mirror Lock and Angle Lock are not exclusive - they can be enabled or disabled separately -
setHandleAngleLock(bool)
enables or disables a lock that constrains a handle so that its angle is the mirror of its opposite handle - whenever a handle is changed. The angle is mirrored but the constrained handle keeps its length. Mirror Lock and Angle Lock are not exclusive - they can be enabled or disabled separately -
rotate(angle, origin)
rotates the entire Spline around origin by angle degrees. note that this permanently modifies the actual vertices. -
scale(scaleFactor, origin, scaleThickness, scaleHandles)
scales the entire Spline from/to origin by scaleFactor. If scaleThickness is true, the global thickness is also scaled by the same factor. If scaleHandles is true, the handle lengths are scaled by the same factor. scaleThickness and scaleHandles are true by default (if omitted). note that this permanently modifies the actual vertices. -
move(offset)
moves the entire Spline by offset (sf::Vector2f). note that this permanently modifies the actual vertices.
-
addVertex(std::size_t index, sf::Vector2f position)
inserts a vertex with the specified position before the vertex at the specified index. If index is omitted, the vertex is added to the end. If position is omitted, the position is (0, 0) -
addVertices(std::size_t index, sf::vector<sf::Vector2f>& positions)
inserts vertices with specified positions before the vertex at the specified index. If index is omitted, the vertices are added to the end -
addVertices(std::size_t numberOfVertices, std::size_t index, sf::Vector2f position)
inserts numberOfVertices vertices with the specified position before the vertex at the specified index. If index is omitted, the vertices are added to the end. If position is omitted, the position is (0, 0) -
removeVertex(std::size_t index)
removes the vertex with the specified index -
removeVertices(std::size_t index, std::size_t numberOfVertices)
removes multiple vertices starting from the specified index. If numberOfVertices is omitted, all vertices from the specified index until the end are removed -
[index]
Direct access to a Spline's vertex is possible using the [] operator.
Note: no checks are performed and using an invalid index results in undefined behaviour
-
setPosition(std::size_t index, sf::Vector2f position)
sets the position of the vertex at the specified index to the specified position. If position is omitted, position is (0, 0) -
setPositions(std::size_t index, std::size_t numberOfVertices, sf::Vector2f position)
sets the positions of the vertices starting at the specified index to the specified position. If numberOfVertices is zero, all vertices from the specified index until the end will have their positions changed. If position is omitted, position is (0, 0) -
setPositions(std::vector<sf::Vector2f>& positions, unsigned int index)
sets the positions of the vertices starting at the specified index to the specified positions. If index is omitted, it begins from the first vertex
-
setFrontHandle(std::size_t index, sf::Vector2f offset)
sets the front handle of the vertex at the specified index to the specified offset. If a handle lock is enabled, the back handle of the same vertex may also be affected -
setBackHandle(std::size_t index, sf::Vector2f offset)
sets the back handle of the vertex at the specified index to the specified offset. If a handle lock is enabled, the front handle of the same vertex may also be affected -
smoothHandles()
adjusts handles so that the spline becomes a smooth curve that passes through the vertices' positions -
resetHandles(std::size_t index, std::size_t numberOfVertices)
resets both handles of the vertices starting from the specified index. If numberOfVertices is omitted, all vertices from the index to the end are affected. If index is also omitted, all handles are reset -
setHandlesVisible(bool)
enables or disables the visual representation of the handles
-
setThickness(std::size_t index, thickness)
sets the thickness of the vertex at the specified index to the specified thickness. This thickness is multiplied with the global thickness. This method is templated so the thickness parameter can be any type (it's casted to a float).
-
setColor(std::size_t index, color)
sets the colour of the vertex at the specified index to the specified color (sf::Color). This colour is multiplied with the global colour.
-
setRandomNormalOffsetRange(std::size_t index, randomNormalOffsetRange)
sets the range for the random normal offset of the vertex at the specified index to the specified range. This range is multiplied with the global range. This method is templated so the range parameter can be any type (it's casted to a float).
-
addSplineToFront(spline)
adds the vertices of spline to the beginning (before all vertices). -
addSplineToBack(spline)
adds the vertices of spline to the end (after all vertices).
Note that the connection is from the current Spline to the external Spline. e.g. connecting back-to-front moves the back to the external Spline's front.
-
connectFrontToFrontOf(spline, bool rotate, bool move)
connects the front vertex to the front vertex of spline. If move is true, all vertices are moved the same distance (the Spline's shape is maintained). If rotate is true, the spline is rotated (around the front vertex) so that the front vertex's tangent is in the opposite direction to the front vertex's tangent of spline. Note that rotate and move have defaults of true. Also note that they can be used together or independently. -
connectFrontToBackOf(spline, bool rotate, bool move)
connects the front vertex to the back vertex of spline. If move is true, all vertices are moved the same distance (the Spline's shape is maintained). If rotate is true, the spline is rotated (around the front vertex) so that the front vertex's tangent is in the same direction as the back vertex's tangent of spline. Note that rotate and move have defaults of true. Also note that they can be used together or independently. -
connectBackToFrontOf(spline, bool rotate, bool move)
connects the back vertex to the front vertex of spline. If move is true, all vertices are moved the same distance (the Spline's shape is maintained). If rotate is true, the spline is rotated (around the back vertex) so that the back vertex's tangent is in the same direction to the front vertex's tangent of spline. Note that rotate and move have defaults of true. Also note that they can be used together or independently. -
connectBackToBackOf(spline, bool rotate, bool move)
connects the back vertex to the back vertex of spline. If move is true, all vertices are moved the same distance (the Spline's shape is maintained). If rotate is true, the spline is rotated (around the back vertex) so that the back vertex's tangent is in the opposite direction to the back vertex's tangent of spline. Note that rotate and move have defaults of true. Also note that they can be used together or independently.
Note that connection is from the external Spline to the current Spline. e.g. connecting front-to-back moves the front of the external Spline to the back.
-
addSplineConnectFrontToFront(spline, bool rotate, bool move)
adds spline by connecting its front to the front. All of the vertices of spline are inserted at the beginning except one; this one is the one that is matched and is combined with the one already there. Its handles are also combined. -
addSplineConnectFrontToBack(spline, bool rotate, bool move)
adds spline by connecting its front to the back. All of the vertices of spline are added at the end except one; this one is the one that is matched and is combined with the one already there. Its handles are also combined. -
addSplineConnectBackToFront(spline, bool rotate, bool move)
adds spline by connecting its back to the front. All of the vertices of spline are inserted at the beginning except one; this one is the one that is matched and is combined with the one already there. Its handles are also combined. -
addSplineConnectBackToBack(spline, bool rotate, bool move)
adds spline by connecting its back to the back. All of the vertices of spline are added at the end except one; this one is the one that is matched and is combined with the one already there. Its handles are also combined.
-
getLength()
returns the length of the spline "cage" - the lines through the control vertices. This length does not take into account interpolation and is not affected by the number of interpolation steps -
getInterpolatedLength()
returns the actual length of the drawn spline. This length takes into account interpolation and is affected by the number of interpolation steps -
getVertexCount()
returns the number of vertices in the Spline
Note: this is not the number of visual vertices -
getLastVertexIndex()
returns the index of the last vertex -
getHandlesVisible()
returns bool of the current state of handle visibility -
getThickness()
returns a float representing the global thickness setting of the spline. A zero value is returned for "infinitely thin" splines (does not generate thick spline using a triangle strip). -
getThickness(std::size_t index)
returns a float representing the thickness value of the vertex specified by index. -
getColor()
returns an sf::Color representing the global colour of the spline. -
getColor(std::size_t index)
returns an sf::Color representing the colour value of the vertex specified by index. -
getThickCornerType()
returns a value of type sw::Spline::ThickCornerType that represents the type of corners used for the visual representation of the spline. See setThickCornerType above for more information. -
getRoundedThickCornerInterpolationLevel()
returns an std::size_t representing the level of interpolation applied to corner of a thick spline. See setRoundedThickCornerInterpolationLevel above. -
getThickStartCapType()
returns a value of type sw::Spline::ThickCapType that represents the type of cap used at the start vertex in the visual representation of the spline. See setThickStartCapType above. -
getRoundedThickStartCapInterpolationLevel()
returns an std::size_t representing the level of interpolation applied to the cap used at the start vertex in a thick spline. See setRoundedThickStartCapInterpolationLevel() above. -
getThickEndCapType()
returns a value of type sw::Spline::ThickCapType that represents the type of cap used at the end vertex in the visual representation of the spline. See setThickEndCapType above. -
getRoundedThickEndCapInterpolationLevel()
returns an std::size_t representing the level of interpolation applied to the cap used at the end vertex in a thick spline. See setRoundedThickEndCapInterpolationLevel() above. -
getMaxCornerPointLength()
returns a float representing the maximum allowed length of a point corner of a thick spline when the thick corner type is PointLimit or PointClip. See setThickCornerType and setMaxCornerPointLength above. -
getRandomNormalOffsetRange()
returns a float representing the global range (for random normal offsets) setting of the spline. -
getRandomNormalOffsetRange(std::size_t index)
returns a float representing the range (for random normal offsets) value of the vertex specified by index. -
getRandomNormalOffsetsActivated()
returns a boolean representing if the random normal offsets are activated. See setRandomNormalOffsetsActivated above for more details. -
getInterpolationSteps()
returns the current number of interpolation steps. Zero is no interpolation. -
getBezierInterpolation()
returns true if Bezier interpolation is enabled. -
getPrimitiveType()
returns an sf::PrimitiveType that is used to display the Spline. -
getInterpolatedPosition(interpolationOffset, index)
returns an sf::Vector2f of the position of the specified interpolated position. The index represents the Spline's vertex and the interpolationOffset represents the number of interpolated positions from that vertex. The interpolationOffset can, however, extend beyond the range into the following vertex/ices so index can be omitted (it defaults to zero). This method includes an assert to check the validity of the parameters. -
getInterpolatedPositionTangent(interpolationOffset, index)
returns an sf::Vector2f representing a unit vector of the tangent/direction at the specified interpolated position. The interpolationOffset and index are used as above (see getInterpolatedPosition). -
getInterpolatedPositionNormal(interpolationOffset, index)
returns an sf::Vector2f representing a unit vector of the normal at the specified interpolated position. The interpolationOffset and index are used as above (see getInterpolatedPosition). This vector is the tangent rotated 90 degrees anti-clockwise. -
getInterpolatedPositionThickness(interpolationOffset, index)
returns a float representing the thickness at the specified interpolated position. The interpolationOffset and index are used as above (see getInterpolatedPosition). This value is the linear interpolation of the two surrounding vertices' thicknesses. -
getInterpolatedPositionThicknessCorrectionScale(interpolationOffset, index)
returns a float representing the thickness correction scale at the specified interpolated position. The interpolationOffset and index are used as above (see getInterpolatedPosition). The correction scale is the amount that the thickness is scaled so that the thickness is constant regardless of curvature. This scale is highest at sharp corners and is one at straight sections. -
getInterpolatedPositionCount()
returns an unsigned int representing the number of interpolated positions in the entire Spline (includes actual vertex positions). Note that this does not include the final vertex in a closed Spline; it does include it in an open Spline. -
getClosed()
returns a bool representing if the Spline is closed or open (i.e. not closed).
-
getPosition(std::size_t index)
returns an sf::Vector2f representing the position of the vertex at the specified index -
getFrontHandle(std::size_t index)
returns an sf::Vector2f representing the front handle offset of the vertex at the specified index -
getBackHandle(std::size_t index)
returns an sf::Vector2f representing the back handle offset of the vertex at the specified index
-
exportAllPositions()
returns an std::vector of sf::Vector2fs containing all of the vertex positions. -
exportAllInterpolatedPositions()
returns an std::vector of sf::Vector2fs containing all of the interpolated positions.
#include <SFML/Graphics.hpp>
#include <SelbaWard/Spline.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode({ 800u, 600u }), "Spline simple example");
sw::Spline spline{ { 100.f, 50.f }, { 150.f, 45.f }, { 200.f, 60.f }, { 30.f, 70.f }, { 40.f, 300.f }, { 600.f, 400.f }, { 700.f, 10.f } };
spline.update();
while (window.isOpen())
{
while (const auto event{ window.pollEvent() }) if (event->is<sf::Event::Closed>()) window.close();
window.clear();
window.draw(spline);
window.display();
}
}
The code above displays:
#include <SFML/Graphics.hpp>
#include <SelbaWard/Spline.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode({ 800u, 600u }), "Spline (lightning) simple example");
sw::Spline spline{ { 100.f, 50.f }, { 150.f, 45.f }, { 200.f, 60.f }, { 30.f, 70.f }, { 40.f, 300.f }, { 600.f, 400.f }, { 700.f, 10.f } };
spline.setRandomNormalOffsetsActivated(true); // required as of v1.6 if random normal offsets are used.
spline.setRandomNormalOffsetRange(20.f);
spline.setInterpolationSteps(30u);
spline.update();
while (window.isOpen())
{
while (const auto event{ window.pollEvent() }) if (event->is<sf::Event::Closed>()) window.close();
window.clear();
window.draw(spline);
window.display();
}
}
The code above displays:
(smoothed Spline)
#include <SFML/Graphics.hpp>
#include <SelbaWard/Spline.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode({ 800u, 600u }), "Spline (smoothed) simple example");
sw::Spline spline{ { 100.f, 50.f }, { 150.f, 45.f }, { 200.f, 60.f }, { 30.f, 70.f }, { 40.f, 300.f }, { 600.f, 400.f }, { 700.f, 10.f } };
spline.setBezierInterpolation(); // enable Bezier spline
spline.setInterpolationSteps(20); // curvature resolution
spline.smoothHandles(); // automatically position handles to create a smooth curve that passes through the points
spline.update();
while (window.isOpen())
{
while (const auto event{ window.pollEvent() }) if (event->is<sf::Event::Closed>()) window.close();
window.clear();
window.draw(spline);
window.display();
}
}
The code above displays:
(thick Spline)
#include <SFML/Graphics.hpp>
#include <SelbaWard/Spline.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode({ 400u, 400u }), "Spline (thick) simple example", sf::Style::Default);
sw::Spline spline{ { 150.f, 300.f }, { 150.f, 100.f }, { 300.f, 200.f } }; // 3 vertices
spline.setThickness(40); // very thick spline
spline.update();
while (window.isOpen())
{
while (const auto event{ window.pollEvent() }) if (event->is<sf::Event::Closed>()) window.close();
window.clear();
window.draw(spline);
window.display();
}
}
The code above displays:
(thick Spline with rounded corners and caps)
#include <SFML/Graphics.hpp>
#include <SelbaWard/Spline.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode({ 400u, 400u }), "Spline (thick and rounded) simple example", sf::Style::Default);
sw::Spline spline{ { 150.f, 300.f },{ 150.f, 100.f },{ 300.f, 200.f } }; // 3 vertices
spline.setThickness(40); // very thick spline
spline.setThickCornerType(sw::Spline::ThickCornerType::Round); // rounded corners
spline.setThickStartCapType(sw::Spline::ThickCapType::Round); // rounded start cap
spline.setThickEndCapType(sw::Spline::ThickCapType::Round); // rounded end cap
spline.update();
while (window.isOpen())
{
while (const auto event{ window.pollEvent() }) if (event->is<sf::Event::Closed>()) window.close();
window.clear();
window.draw(spline);
window.display();
}
}
The code above displays:
(thick Bezier Spline)
#include <SFML/Graphics.hpp>
#include <SelbaWard/Spline.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode({ 400u, 400u }), "Spline (thick and smoothed) simple example", sf::Style::Default);
sw::Spline spline{ { 150.f, 300.f },{ 150.f, 100.f },{ 300.f, 200.f } }; // 3 vertices
spline.setFrontHandle(0u, { -100.f, -50.f }); // forward handle of first vertex (toward middle vertex)
spline.setBackHandle(2u, { -50.f, 100.f }); // backward handle of last vertex (towards middle vertex)
spline.setBezierInterpolation(); // enable curvature
spline.setInterpolationSteps(30u);
spline.setThickness(40); // very thick spline
spline.update();
while (window.isOpen())
{
while (const auto event{ window.pollEvent() }) if (event->is<sf::Event::Closed>()) window.close();
window.clear();
window.draw(spline);
window.display();
}
}
The code above displays:
(thick Bezier Spline with rounded corners and caps)
#include <SFML/Graphics.hpp>
#include <SelbaWard/Spline.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode({ 400u, 400u }), "Spline (thick, smoothed and rounded) simple example", sf::Style::Default);
sw::Spline spline{ { 150.f, 300.f },{ 150.f, 100.f },{ 300.f, 200.f } }; // 3 vertices
spline.setFrontHandle(0u, { -100.f, -50.f }); // forward handle of first vertex (toward middle vertex)
spline.setBackHandle(2u, { -50.f, 100.f }); // backward handle of last vertex (towards middle vertex)
spline.setBezierInterpolation(); // enable curvature
spline.setInterpolationSteps(30u);
spline.setThickness(40); // very thick spline
spline.setThickCornerType(sw::Spline::ThickCornerType::Round); // rounded corners
spline.setThickStartCapType(sw::Spline::ThickCapType::Round); // rounded start cap
spline.setThickEndCapType(sw::Spline::ThickCapType::Round); // rounded end cap
spline.update();
while (window.isOpen())
{
while (const auto event{ window.pollEvent() }) if (event->is<sf::Event::Closed>()) window.close();
window.clear();
window.draw(spline);
window.display();
}
}
The code above displays:
(thick Bezier closed and duplicated)
#include <SFML/Graphics.hpp>
#include <SelbaWard/Spline.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode({ 320u, 300u }), "Spline (closed) simple example", sf::Style::Default);
sw::Spline spline{ { 100.f, 250.f }, { 100.f, 50.f }, { 250.f, 150.f } }; // 3 vertices via initializer list
spline.setFrontHandle(0u, { -100.f, -50.f }); // forward handle of first vertex (toward middle vertex)
spline.setBackHandle(2u, { -100.f, 25.f }); // backward handle of last vertex (towards middle vertex)
spline.setBezierInterpolation(); // enable curvature
spline.setInterpolationSteps(30u); // smooth
spline.setThickness(40); // very thick spline
spline.setClosed(true); // automatically close spline
spline.update();
sw::Spline splineInner{ spline };
splineInner.setThickness(spline.getThickness() / 3.f);
splineInner.setColor(sf::Color::Magenta);
splineInner.update();
while (window.isOpen())
{
while (const auto event{ window.pollEvent() }) if (event->is<sf::Event::Closed>()) window.close();
window.clear();
window.draw(spline);
window.draw(splineInner);
window.display();
}
}
The code above displays:
Adding anti-alias to the window in the code above displays:
(per vertex colours and thickness)
#include <SFML/Graphics.hpp>
#include <SelbaWard/Spline.hpp>
int main()
{
sf::ContextSettings contextSettings;
contextSettings.antiAliasingLevel = 16u;
sf::RenderWindow window(sf::VideoMode({ 320u, 300u }), "Spline (per vertex) simple example", sf::Style::Default, sf::State::Windowed, contextSettings);
sw::Spline spline{ { 100.f, 250.f }, { 100.f, 50.f }, { 250.f, 100.f }, { 200.f, 175.f } }; // 4 vertices via initializer list
spline.setFrontHandle(0u, { -100.f, -50.f });
spline.setFrontHandle(1u, { 50.f, 0.f });
spline.setFrontHandle(2u, { 75.f, 50.f });
spline.setFrontHandle(3u, { -25.f, 25.f });
spline.setColor(0u, sf::Color::Red); // first vertex red
spline.setColor(1u, sf::Color::Green); // first vertex green
spline.setColor(2u, sf::Color::Blue); // first vertex blue
spline.setThickness(1u, 0.5); // second vertex half thickness
spline.setThickness(2u, 0.75); // third vertex three quarters thickness
spline.setThickness(3, 0.25); // fourth vertex quarter thickness
spline.setBezierInterpolation();
spline.setInterpolationSteps(30u);
spline.setThickness(40); // global thickness
spline.setClosed(true);
spline.update();
sw::Spline splineInner{ spline };
splineInner.setThickness(spline.getThickness() / 3.f);
splineInner.setColor(sf::Color::Magenta); // multiply all vertex colours with magenta
splineInner.update();
while (window.isOpen())
{
while (const auto event{ window.pollEvent() }) if (event->is<sf::Event::Closed>()) window.close();
window.clear();
window.draw(spline);
window.draw(splineInner);
window.display();
}
}
The code above displays:
(anti-aliasing included in code)
Note: more Selba Ward examples are available in the examples folder. This includes examples that uses some of the features unused in these simple example such as change caps and corners as well as using random normal offsets.
(Spline v1.7)