Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Drawing a circle segment  (Read 3872 times)

0 Members and 1 Guest are viewing this topic.

timrh

  • Newbie
  • *
  • Posts: 5
    • View Profile
Drawing a circle segment
« on: November 20, 2017, 07:07:43 pm »
I want to draw circle segment, segment will be drawn dependent on mouse position, in this image you can see what I want to achieve:

https://imgur.com/a/HKiHc

as you can see, circle segment is looking to mouse, I had been trying to do it alone, but I can't.

This was my idea:

my basic circle draw code:

Code: [Select]
gameWindow.clear(sf::Color{ 60, 60, 60 });

float angle = PI;
float radius = 50;
unsigned points = 50;

VertexArray circle(LinesStrip, 0);
Vector2f orgin = gameWindow.getView().getCenter();

do
{
Vector2f pointPos = { cos(angle) * radius, sin(angle) * radius };
pointPos += orgin;

circle.append(pointPos);

angle -= PI * 2 / points;

} while (angle > -PI);

circle.append(circle[0]);

gameWindow.draw(circle);
gameWindow.display();

getting angles:

Code: [Select]
alpha = atan2(mouse.y, mouse.x);
beta = alpha - alpha / 2;
gamma = alpha + alpha / 2;

as you can see I set range from PI to -PI, to have the same angle range as in atan2.
Next I wanted to check points that are in range specified by beta and gamma, and that worked, but partionally...

Because in some cases, my circle was drawed in that way:

https://imgur.com/a/N5e3b

Inverting beta and gamma not worked to me, I created conditions that were checking that beta and gamma are in range <-PI; PI>, if not, then I changed for example angles, but that not worked too.

After hour of thinking, and complicating my code, I removed it, and I think that I need help.
Please show me how can I draw circle segment in that way.
Thanks.





« Last Edit: November 20, 2017, 07:17:07 pm by timrh »

FRex

  • Hero Member
  • *****
  • Posts: 1845
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Drawing a circle segment
« Reply #1 on: November 20, 2017, 11:11:05 pm »
Is this the result you want? I'm not sure why you're 'checking' from PI to -PI actually so I'm unsure if this is exactly what you want..

#include <SFML/Graphics.hpp>
#include <cmath>

inline float angle(sf::Vector2f v)
{
    return std::atan2(v.y, v.x);
}

inline std::vector<sf::Vector2f> getCirclePoints(float angle)
{
    std::vector<sf::Vector2f> ret;
    const int maxpts = 10;
    const float spread = 1.f;
    const float radius = 200.f;
    for(int i = 0; i < maxpts; ++i)
    {
        const float a = (angle - spread / 2.f) + (i * spread) / (maxpts - 1);
        ret.push_back(radius * sf::Vector2f(std::cos(a), std::sin(a)));
    }
    return ret;
}

int main()
{
    sf::RenderWindow app(sf::VideoMode(800u, 600), "cricl");
    app.setFramerateLimit(60);
    const sf::Vector2f mid = sf::Vector2f(app.getSize()) / 2.f;

    while(app.isOpen())
    {
        sf::Event eve;
        while(app.pollEvent(eve))
            if(eve.type == sf::Event::Closed)
                app.close();

        app.clear();
        sf::VertexArray arr(sf::LinesStrip);
        const sf::Vector2f mpos = app.mapPixelToCoords(sf::Mouse::getPosition(app));
        arr.append(sf::Vertex(mid));
        for(sf::Vector2f v : getCirclePoints(angle(mpos - mid)))
            arr.append(sf::Vertex(mid + v));

        arr.append(sf::Vertex(mid));

        app.draw(arr);
        app.display();
    }
}
 
Back to C++ gamedev with SFML in May 2023

timrh

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Drawing a circle segment
« Reply #2 on: November 21, 2017, 02:06:58 pm »
This is exactly what I wanted...

Can you tell me the secret behind getting a? I know that is angle of segment point, but what is spread? And how exactly it works?

Code: [Select]
const float a = (angle - spread / 2.f) + (i * spread) / (maxpts - 1);

timrh

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Drawing a circle segment
« Reply #3 on: November 21, 2017, 05:31:52 pm »
I tried to write it one more time. And it works now.

And this was my idea:
1.In do while loop, from temp angle variable to segment angle,
2.Get mouse to radius center angle by atan2,
3.Set point of segment, as product of rotation around circle center, where angle is equal to temp angle variable + mouse to radius center angle - segment angle / 2, * radius.

                gameWindow.clear();
        sf::VertexArray arr(sf::LinesStrip);

        float segmentAngle{degToRad(60)};
        float radius{100};
        sf::Vector2f radiusPos{ gameWindow.getView().getCenter() };

        unsigned circlePoints{10};
        float angle{ 0 };

        arr.append(radiusPos);
        do
        {      
                sf::Vector2f mRelP //get relative mouse position
                {
                        sf::Mouse::getPosition(gameWindow).x - radiusPos.x,
                        sf::Mouse::getPosition(gameWindow).y - radiusPos.y
                };

                float mouseAngle{ atan2(mRelP.y, mRelP.x) }; //get angle between mouse and circle center

                sf::Vector2f p
                {                      
                        cos(angle + (mouseAngle - segmentAngle / 2)) * radius, //position = cos(angle + lookAngle) * rad
                        sin(angle + (mouseAngle - segmentAngle / 2)) * radius  //position = sin(angle + lookAngle) * rad               
                };

                p += radiusPos;
                arr.append(p);

                angle += segmentAngle / circlePoints;

        } while (angle < segmentAngle);

        arr.append(radiusPos);

        gameWindow.draw(arr);
        gameWindow.display();
 
« Last Edit: November 21, 2017, 05:37:11 pm by timrh »

FRex

  • Hero Member
  • *****
  • Posts: 1845
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Drawing a circle segment
« Reply #4 on: November 22, 2017, 12:11:02 am »
The spread is how wide the cone should be in radians and it's defined in that function few lines above. It works by getting 10 (or whatever you want) evenly spaced points on the cone around the angle and linking them together.



Your new code has the potential to add too many points (90 degrees + 10 points creates 11 points) or to add wrong last points (180 degrees + 8 points doesn't produce a half circle). I think you should divide by circlePoints - 1 instead and check for angle <= segmentAngle (not just <) but I'm not 100% sure because it's a bit confusing and roundabout way of doing it compared to looping on an int and calculating angles directly.
« Last Edit: November 22, 2017, 12:34:15 am by FRex »
Back to C++ gamedev with SFML in May 2023

timrh

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Drawing a circle segment
« Reply #5 on: November 22, 2017, 08:37:15 pm »
Now I see the point of your solution, it's better than mine.
Thanks for the help!