coding for sweep line to determine if two figures are intercepted.

#include<bits/stdc++.h>

struct Point {
    double x, y;
};

struct Segment {
    Point p, q;
    int group; // A for figure 1 and B for 2

    Segment(Point a, Point b, int g) : group(g) {
        if (a.x < b.x || a.x == b.x && a.y <= b.y) {
            p = a;
            q = b;
        }
        else {
            p = b;
            q = a;
        }
    }
};

// initial position for x 
double currentX = 0.0;

// determine y for given x
double getY(const Segment &seg, double x) {
    if (seg.p.x == seg.q.x) 
        return seg.p.y;
    double slope = (seg.q.y - seg.p.y) / (seg.q.x - seg.p.x);
    return seg.p.y + slope*(x-seg.p.x);
}

// comparator: c
struct SegmentComparator {
    bool operator() (const Segment *s1, const Segment *s2) const {
        double y1 = getY(*s1, currentX);
        double y2 = getY(*s2, currentX);
        if (y1 == y2) 
            return s1 < s2;
        return y1 < y2;
    }
};

// determine cross product
double cross(const Point &A, const Point &B, const Point &C) {
    return (B.x - A.x) * (C.y - A.y) - (B.y - A.y) * (C.x - A.x);
}
// hier I still use formular cross product to see if two sedments is intersected, because I think this is more comprehensive
bool isIntersected(const Segment &s1, const Segment &s2) {
    if (s1.group == s2.group) 
        return false;
    
    const Point &A = s1.p, &B = s1.q, &C = s2.p, &D = s2.q;
    double d1 = cross(A, B, C);
    double d2 = cross(A, B, C);
    double d3 = cross(C, D, A);
    double d4 = cross(C, D, B);

    if (d1*d2 < 0 && d3*d4 < 0) {
        return true;
    }
    return false;
}

struct Event {
    double x;
    int type; // 1: left point, -1: right point
    Segment *seg;
};

bool eventComparator(const Event &e1, const Event &e2) {
    if (e1.x == e2.x) 
        return e1.type > e2.type;
    
    return e1.x < e2.x;
}

bool sweeplineIntersection(std::vector<Segment> &segments) {
    std::vector<Event> events;

    for (auto &seg : segments) {
        events.push_back(Event{seg.p.x, 1, &seg});
        events.push_back(Event{seg.q.x, -1, &seg});
    }

    std::sort(events.begin(), events.end(), eventComparator);

    std::set<Segment *, SegmentComparator> active;

    for (auto &event : events) {
        currentX = event.x;
        if (event.type == 1) {
            // insert segment
            auto iter = active.insert(event.seg).first;

            //check if current one intercept with last one
            if (iter != active.begin()) {
                auto prev = std::prev(iter);
                if (isIntersected(**prev, *event.seg)) 
                    return true;
            }
            //check if current one intercept with next one
            auto next = std::next(iter);
            if (next != active.end()) {
                if (isIntersected(**next, *event.seg))
                    return true;
            }
        }
        else {
            auto iter = active.find(event.seg);
            if (iter != active.end()) {
                auto prev = (iter == active.begin()) ? active.end() : std::prev(iter);
                auto next = std::next(iter);
                active.erase(iter);
                if (prev != active.end() && next != active.end()) {
                    if (isIntersected(**prev, **next))
                        return true;
                }
            }
        }
    }

    return false;
}

int main() {
    std::vector<Segment> segments;
    segments.push_back(Segment({0, 0}, {4, 4}, 0));
    segments.push_back(Segment({0, 4}, {4, 0}, 1));

    bool intersect = sweeplineIntersection(segments);
    if (intersect)
        std::cout << "two figures is intercepted." << std::endl; 
    else {
        std::cout << "two figures has no cross point. " << std::endl; 
    }

    return 0;
}


posted @ 2025-03-27 23:25  七块蛋糕  阅读(21)  评论(0)    收藏  举报