如何获得最近的网格交叉点

How do I get nearest grid intersection?

本文关键字:网格 交叉点 最近 何获得      更新时间:2023-10-16

我正试图在相对于鼠标的网格上最近的线交点处画一个圆。我用不同的x和y间距从中心向外绘制网格。我试图得到正确的坐标,但它失败了。我该如何得到正确的座标?

这是我的代码:

class Grid : public sf::Drawable, public sf::Transformable
{
public:
    Grid(unsigned int Xsep, unsigned int Ysep, unsigned int CanvasW, unsigned int CanvasH);
    virtual ~Grid() {};
    void setFillColor(const sf::Color &color);
    void setSize(unsigned int Xsep, unsigned int Ysep, unsigned int CanvasW, unsigned int CanvasH);
    unsigned int xSep = 0;
    unsigned int ySep = 0;
private:
 virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
    {
        // apply the entity's transform -- combine it with the one that was passed by the caller
        states.transform *= getTransform(); // getTransform() is defined by sf::Transformable
        // apply the texture
        states.texture = &m_texture;
        // you may also override states.shader or states.blendMode if you want
        states.blendMode = sf::BlendMode(sf::BlendMode::SrcAlpha, sf::BlendMode::OneMinusDstColor,sf::BlendMode::Add);
        // draw the vertex array
        target.draw(m_vertices, states);
    }
    sf::VertexArray m_vertices;
    sf::Texture m_texture;
};
Grid::Grid(unsigned int Xsep, unsigned int Ysep, unsigned int CanvasW, unsigned int CanvasH)
{
    xSep = Xsep;
    ySep = Ysep;
    m_vertices.setPrimitiveType(sf::Lines);
    m_vertices.clear();
    for (int i=((CanvasW/2)-Xsep); i > 0; i-=Xsep)
    {
        m_vertices.append(sf::Vector2f(i,0));
        m_vertices.append(sf::Vector2f(i,CanvasH));
        m_vertices.append(sf::Vector2f(CanvasW-i,0));
        m_vertices.append(sf::Vector2f(CanvasW-i,CanvasH));
    }
    for (int i=((CanvasH/2)-Ysep); i > 0; i-=Ysep)
    {
        m_vertices.append(sf::Vector2f(0,i));
        m_vertices.append(sf::Vector2f(CanvasW,i));
        m_vertices.append(sf::Vector2f(0,CanvasH-i));
        m_vertices.append(sf::Vector2f(CanvasW,CanvasH-i));
    }
    m_vertices.append(sf::Vector2f(0,CanvasH / 2));
    m_vertices.append(sf::Vector2f(CanvasW,CanvasH / 2));
    m_vertices.append(sf::Vector2f(CanvasW / 2, 0));
    m_vertices.append(sf::Vector2f(CanvasW / 2,CanvasH)); 
}
int RoundNum(int num, int difference)
{
     int rem = num % difference;
     return rem >= 5 ? (num - rem + difference) : (num - rem);
}
sf::CircleShape point(5);
point.setOrigin(point.getRadius()/2,point.getRadius()/2);
sf::Vector2f mousepos = mapPixelToCoords(sf::Mouse::getPosition(*this));
point.setPosition(RoundNum(mousepos.x,grid.xSep),RoundNum(mousepos.y,grid.ySep));
draw(point);

我至少看到了两件需要研究的事情。

首先,将轴线设置为从中心向外均匀间隔。但是RoundNum(mousepos.x,grid.xSep)会将您的位置捕捉到间隔的网格线上从CCD_ 2为零的任何地方均匀地。大概这一点不在长方形它在长方形的一角吗?由于矩形的宽度不是2 * grid.xSep的倍数,与角对齐的网格将偏移从与角对齐的网格。y坐标也是如此。

编辑以回应评论:解决此类问题的一种方法是从x坐标中减去width/2,然后四舍五入,再加上width/2。或者,查找grid.xSep - ((width/2)%grid.xSep);把这个值加到x坐标上,四舍五入,然后减去这个值。第二种方法更复杂,但避免了考虑如果x%n中的x为负会发生什么。当然,你也可以对y坐标做一些类似的事情。

其次,只有当difference为9或10:时,这才有效

    return rem >= 5 ? (num - rem + difference) : (num - rem);

如果将5替换为difference/2,它将适用于difference的偶数值。要使其对difference的所有值(偶数或奇数)正确工作,请替换5具有CCD_ 13。

同样值得确认的是,这符合您的要求:

point.setOrigin(point.getRadius()/2,point.getRadius()/2);

它看起来是正确的,但很容易检查(只需在已知的网格点(如中心)绘制一个CircleShape),因此您还可以确保。