[osg-users] Finding the edge of a frustum, or intersection with the edge of a frustum

Brad Colbert bcolbert at rscusa.com
Fri Nov 15 09:50:37 PST 2019


Hi,

I thought I would post my solution for finding the intersection of circles with a rectangle.  Used to test were circles are intersecting the edge of my Ortho projection.


Code:
bool isPointOnSegment(const osg::Vec3d& p1, const osg::Vec3d& p2, const osg::Vec3d& point)
{
    // First test that the point is co-linear
    osg::Vec3d v1 = p2 - p1;
    osg::Vec3d v2 = point - p1;

    // Cross product
    double z = v1.x() * v2.y() - v1.y() * v2.x();

    if(z)
        return false;

    // Dot product will tell us if it's between the points
    double dp1 = v1 * v1;
    double dp2 = v1 * v2;

    // On end
    if((dp1 == 0) || (dp1 == dp2))
        return true;

    // On Segment
    else if((dp1 > 0.0) && (dp2 < dp1))
        return true;

    return false;
}

//
template <typename T> int sgn(T val) {
    return (T(0) < val) - (val < T(0));
}
std::list<osg::Vec3d> findLineCircleIntersections(const osg::Vec3d& p1, const osg::Vec3d& p2, const osg::Vec3d& center, const double r)
{
    std::list<osg::Vec3d> points;
    double dx, dy, A, B, C, dis, t;

    dx = p2.x() - p1.x();
    dy = p2.y() - p1.y();

    A = dx * dx + dy * dy;
    B = 2 * (dx * (p1.x() - center.x()) + dy * (p1.y() - center.y()));
    C = (p1.x() - center.x()) * (p1.x() - center.x()) +
        (p1.y() - center.y()) * (p1.y() - center.y()) -
        r * r;

    dis = B * B - 4 * A * C;

    if(dis < 0.0)
    {
        // No intersection
    }
    else
    {
        // Two solutions.
        double t1 = (float)((-B - sqrt(dis)) / (2 * A));
        double t2 = (float)((-B + sqrt(dis)) / (2 * A));

        double x1 = p1.x() + t2 * dx;
        double y1 = p1.y() + t2 * dy;
        osg::Vec3d point1(x1, y1, p1.z());

        if (dis == 0.0) // Tangent
        {
            // Validate
            if(isPointOnSegment(p1, p2, point1))
                points.push_back(point1);
        }
        else if (dis > 0.0)
        {
            double x2 = p1.x() + t1 * dx;
            double y2 = p1.y() + t1 * dy;
            osg::Vec3d point2(x2, y2, p1.z());

            // Two intersections
            if(isPointOnSegment(p1, p2, point1))
                points.push_back(osg::Vec3d(x1,y1,p1.z()));
            if(isPointOnSegment(p1, p2, point2))
                points.push_back(osg::Vec3d(x2,y2,p1.z()));
        }
    }

    return points;
}

std::list<osg::Vec3d> findRectangleCircleIntersections(const osg::Vec3d& s1p1, const osg::Vec3d& s1p2,
                                                       const osg::Vec3d& s2p1, const osg::Vec3d& s2p2,
                                                       const osg::Vec3d& s3p1, const osg::Vec3d& s3p2,
                                                       const osg::Vec3d& s4p1, const osg::Vec3d& s4p2,
                                                       const osg::Vec3d& center, const double r)
{
    std::list<osg::Vec3d> points;

    std::list<osg::Vec3d> s1points = findLineCircleIntersections(s1p1, s1p2, center, r);
    points.insert(points.end(), s1points.begin(), s1points.end());

    std::list<osg::Vec3d> s2points = findLineCircleIntersections(s2p1, s2p2, center, r);
    points.insert(points.end(), s2points.begin(), s2points.end());

    std::list<osg::Vec3d> s3points = findLineCircleIntersections(s3p1, s3p2, center, r);
    points.insert(points.end(), s3points.begin(), s3points.end());

    std::list<osg::Vec3d> s4points = findLineCircleIntersections(s4p1, s4p2, center, r);
    points.insert(points.end(), s4points.begin(), s4points.end());

    return points;
}




Cheers,
Brad

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=76910#76910







More information about the osg-users mailing list