OGRECave / ogre-procedural

procedural geometry for Ogre3D
https://ogrecave.github.io/ogre-procedural/
MIT License
40 stars 15 forks source link

Bug in bool Segment2D::findIntersect() in ProceduralGeometryHelpers #156

Open geotyper opened 4 years ago

geotyper commented 4 years ago

when use boolean operations on shape, found that on simple examples all work well, but sometime take false on function l Segment2D::findIntersect when it need to be true. Cannot understand why function is so heavy, change to more simple variant and all works well. old code

bool Segment2D::findIntersect(const Segment2D& other, Vector2& intersection) const
{

    const Vector2& p1 = mA;
    const Vector2& p2 = mB;
    const Vector2& p3 = other.mA;
    const Vector2& p4 = other.mB;

    Vector2 d1 = p2-p1;
    float a1 = d1.y;
    float b1 = -d1.x;
    float g1 = d1.x*p1.y-d1.y*p1.x;

    Vector2 d3 = p4-p3;
    float a2 = d3.y;
    float b2 = -d3.x;
    float g2 = d3.x*p3.y-d3.y*p3.x;

    float det=d1.crossProduct(d3);
    // if both segments are parallel, early out
    if (det == 0.)
        return false;

    Vector2 intersect;
    float intersectx = (b2*g1-b1*g2)/(b1*a2-b2*a1);
    float intersecty = (a2*g1-a1*g2)/(a1*b2-a2*b1);

    intersect = Vector2(intersectx, intersecty);

    if ((intersect-p1).dotProduct(intersect-p2)<0 && (intersect-p3).dotProduct(intersect-p4)<0)
    {
        intersection = intersect;
        return true;
    }
    return false;
}

new code

bool Segment2D::findIntersect(const Segment2D& other, Vector2& intersection) const
{
    const Vector2& p0 = mA;
    const Vector2& p1 = mB;
    const Vector2& p2 = other.mA;
    const Vector2& p3 = other.mB;

    float s1_x, s1_y, s2_x, s2_y;
        s1_x = p1.x - p0.x;     s1_y = p1.y - p0.y;
        s2_x = p3.x - p2.x;     s2_y = p3.y - p2.y;

        float s, t;
        s = (-s1_y * (p0.x - p2.x) + s1_x * (p0.y - p2.y)) / (-s2_x * s1_y + s1_x * s2_y);
        t = ( s2_x * (p0.y - p2.y) - s2_y * (p0.x - p2.x)) / (-s2_x * s1_y + s1_x * s2_y);

        if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
        {
            // Collision detected
                intersection.x = p0.x + (t * s1_x);
                intersection.y = p0.y + (t * s1_y);
            return true;
        }
        return false; // No collision
}

Screenshot at 2020-06-04 19-49-29

paroj commented 4 years ago

can you make a pull request for this?

geotyper commented 4 years ago

sorry, but have not big experience in github in part of pull request, and new function code is not test well. So let it be issue.