Language: C++

#include <bits/stdc++.h>

using namespace std;

#define EPS (1e-6)
#define equal(a,b) (fabs(a-b) < EPS)
#define lt(a,b) (a-b < -EPS)
#define MAX 252
#define INF (1e9)
#define PI acos(-1)

struct Point{
    double x,y;

    Point(){}
    Point(double x,double y) : x(x),y(y) {}

    Point operator + (const Point &p)const{ return Point(x+p.x,y+p.y); }
    Point operator - (const Point &p)const{ return Point(x-p.x,y-p.y); }
    Point operator * (const double &k)const{ return Point(x*k,y*k); }
    Point operator / (const double &k)const{ return Point(x/k,y/k); }
    bool operator < (const Point &p)const{ return x != p.x ? x < p.x : y < p.y; }
    bool operator == (const Point &p)const{ return (x == p.x && y == p.y); }
};

double dot(const Point &a,const Point &b){ return a.x*b.x+a.y*b.y; }
double cross(const Point &a,const Point &b){ return a.x*b.y - b.x*a.y; }
double norm(const Point &p){ return dot(p,p); }
double abs(const Point &p){ return sqrt(norm(p)); }
double dist(const Point &a,const Point &b){
    return sqrt(pow(a.x-b.x,2) + pow(a.y-b.y,2));
}

double toRad(double ang){ return ang*PI/180; }
double toAng(double rad){ return rad*180/PI; }

#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
typedef Point Vector;

int ccw(Point p0,Point p1,Point p2){
    Vector a = p1 - p0;
    Vector b = p2 - p0;
    if(cross(a,b) > EPS) return COUNTER_CLOCKWISE;
    if(cross(a,b) < -EPS) return CLOCKWISE;
    if(dot(a,b) < -EPS) return ONLINE_BACK;
    if(norm(a) < norm(b)) return ONLINE_FRONT;
    return ON_SEGMENT;
}

map<Point,int> mp;
double mem[MAX][MAX];

double getAngle(const Point &a,const Point &b,const Point &c){
    Vector v1 = b-a, v2 = c-b;
    double aa = mem[mp[b]][mp[a]];
    double ba = mem[mp[c]][mp[b]];
    if(aa == -1){
        aa = atan2(v1.y,v1.x);
        mem[mp[b]][mp[a]] = aa;
    }
    if(ba == -1){
        ba = atan2(v2.y,v2.x);
        mem[mp[c]][mp[b]] = ba;
    }
    if(aa > ba) swap(aa,ba);
    double rad = ba - aa;
    double ang = toAng(rad);
    return min(ang,180-ang);
}

struct Segment{
    Point s,t;
    Segment(){}
    Segment(Point &s,Point &t) : s(s),t(t) {}
};

bool isIntersectSP(const Segment &s,const Point &p){
    return (ccw(s.s,s.t,p) == 0);
}

bool isIntersectSS(const Segment &a,const Segment &b){
    Point s[2] = {a.s,a.t}, t[2] = {b.s,b.t};
    return (ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
            ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0);
}

Point crosspointSS(const Segment &a,const Segment &b){
    Vector va = a.t-a.s, vb = b.t-b.s;
    double d = cross(vb,va);
    if(abs(d) < EPS) return b.s;
    return a.s+va*cross(vb,b.t-a.s)*(1.0/d);
}

typedef vector<int> Edges;
typedef vector<Edges> Graph;

Graph segmentArrangement(vector<Segment> &segs,vector<Point> &ps){
    Graph G;
    int N = segs.size();
    ps.clear();

    for(int i = 0 ; i < N ; i++){
        ps.push_back(segs[i].s);
        ps.push_back(segs[i].t);
        for(int j = i+1 ; j < N ; j++){
            Vector a = segs[i].t - segs[i].s;
            Vector b = segs[j].t - segs[j].s;
            if(equal(cross(a,b),0)) continue;
            if(isIntersectSS(segs[i],segs[j])){
                ps.push_back(crosspointSS(segs[i],segs[j]));
            }
        }
    }
    sort(ps.begin(),ps.end());
    ps.erase(unique(ps.begin(),ps.end()),ps.end());

    int N2 = ps.size();
    G.resize(N2);
    for(int i = 0 ; i < N ; i++){
        vector<int> vec;
        for(int j = 0 ; j < N2 ; j++){
            if(isIntersectSP(segs[i],ps[j])){
                vec.push_back(j);
            }
        }
        sort(vec.begin(),vec.end());
        for(int j = 0 ; j < (int)vec.size()-1 ; j++){
            int u = vec[j], v = vec[j+1];
            G[u].push_back(v);
            G[v].push_back(u);
        }
    }
    return G;
}

struct State{
    double w;
    int p,n;
    State(){}
    State(double w,int p,int n) :
        w(w),p(p),n(n) {}
    
    bool operator > (const State &s)const{
        return lt(w,s.w);
    }
};

double add(double a,double b){
    if(abs(a+b) < EPS * (abs(a) + abs(b))){
        return 0;
    }
    return a + b;
}

double dijkstra(Graph &G,Point &s,Point &t,vector<Point> &ps){
    mp.clear();
    memset(mem,-1,sizeof(mem));
    for(int i = 0 ; i < (int)ps.size() ; i++){
        mp[ps[i]] = i;
    }
    double d[MAX][MAX];
    for(int i = 0 ; i < MAX ; i++){
        for(int j = 0 ; j < MAX ; j++){
            d[i][j] = INF;
        }
    }
    priority_queue<State> Q;
    for(int i = 0 ; i < (int)G[mp[s]].size() ; i++){
        int to = G[mp[s]][i];
        Q.push(State(0,mp[s],to));
        d[mp[s]][to] = 0;
    }
    while(!Q.empty()){
        State st = Q.top(); Q.pop();
        int p = st.p,n = st.n;
        if(lt(d[p][n],st.w)) continue;
        Point p1 = ps[p],p2 = ps[n];
        if(p2 == t) return d[p][n];
        for(int i = 0 ; i < (int)G[n].size() ; i++){
            int to = G[n][i];
            Point p3 = ps[to];
            if(p1 == p3) continue;
            double ncost = add(st.w,getAngle(p1,p2,p3));
            if(lt(ncost,d[n][to])){
                d[n][to] = ncost;
                Q.push(State(d[n][to],n,to));
            }
        }
    }
    return INF;
}

int main(){
    int N;
    while(cin >> N, N){
        Point s,t;
        vector<Segment> segs(N);
        for(int i = 0 ; i < N ; i++){
            cin >> segs[i].s.x >> segs[i].s.y;
            cin >> segs[i].t.x >> segs[i].t.y;
        }
        cin >> s.x >> s.y >> t.x >> t.y;
        vector<Point> ps;
        Graph G = segmentArrangement(segs,ps);
        double res = dijkstra(G,s,t,ps);
        if(res == INF){
            cout << -1 << endl;
        }else{
            printf("%.12f\n",res);
        }
    }
    return 0;
}

Compiler output:
In file included from /usr/include/c++/14/string:49,
                 from /usr/include/c++/14/bitset:52,
                 from /usr/include/x86_64-linux-gnu/c++/14/bits/stdc++.h:52,
                 from a.cc:1:
/usr/include/c++/14/bits/stl_function.h: In instantiation of 'constexpr bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = State]':
/usr/include/c++/14/bits/predefined_ops.h:196:23:   required from 'bool __gnu_cxx::__ops::_Iter_comp_val<_Compare>::operator()(_Iterator, _Value&) [with _Iterator = __gnu_cxx::__normal_iterator<State*, std::vector<State, std::allocator<State> > >; _Value = State; _Compare = std::less<State>]'
  196 |         { return bool(_M_comp(*__it, __val)); }
      |                       ~~~~~~~^~~~~~~~~~~~~~
/usr/include/c++/14/bits/stl_heap.h:140:48:   required from 'void std::__push_heap(_RandomAccessIterator, _Distance, _Distance, _Tp, _Compare&) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<State*, vector<State, allocator<State> > >; _Distance = long int; _Tp = State; _Compare = __gnu_cxx::__ops::_Iter_comp_val<less<State> >]'
  140 |       while (__holeIndex > __topIndex && __comp(__first + __parent, __value))
      |                                          ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/bits/stl_heap.h:216:23:   required from 'void std::push_heap(_RAIter, _RAIter, _Compare) [with _RAIter = __gnu_cxx::__normal_iterator<State*, vector<State, allocator<State> > >; _Compare = less<State>]'
  216 |       std::__push_heap(__first, _DistanceType((__last - __first) - 1),
      |       ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  217 |                        _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp);
      |                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/bits/stl_queue.h:747:16:   required from 'void std::priority_queue<_Tp, _Sequence, _Compare>::push(value_type&&) [with _Tp = State; _Sequence = std::vector<State, std::allocator<State> >; _Compare = std::less<State>; value_type = State]'
  747 |         std::push_heap(c.begin(), c.end(), comp);
      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
a.cc:174:15:   required from here
  174 |         Q.push(State(0,mp[s],to));
      |         ~~~~~~^~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/bits/stl_function.h:405:20: error: no match for 'operator<' (operand types are 'const State' and 'const State')
  405 |       { return __x < __y; }
      |                ~~~~^~~~~
In file included from /usr/include/c++/14/bits/stl_algobase.h:64,
                 from /usr/include/c++/14/algorithm:60,
                 from /usr/include/x86_64-linux-gnu/c++/14/bits/stdc++.h:51:
/usr/include/c++/14/bits/stl_pair.h:1045:5: note: candidate: 'template<class _T1, class _T2> constexpr bool std::operator<(const pair<_T1, _T2>&, const pair<_T1, _T2>&)'
 1045 |     operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_pair.h:1045:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/stl_function.h:405:20: note:   'const State' is not derived from 'const std::pair<_T1, _T2>'
  405 |       { return __x < __y; }
      |                ~~~~^~~~~
In file included from /usr/include/c++/14/bits/stl_algobase.h:67:
/usr/include/c++/14/bits/stl_iterator.h:448:5: note: candidate: 'template<class _Iterator> constexpr bool std::operator<(const reverse_iterator<_Iterator>&, const reverse_iterator<_Iterator>&)'
  448 |     operator<(const reverse_iterator<_Iterator>& __x,
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:448:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/stl_function.h:405:20: note:   'const State' is not derived from 'const std::reverse_iterator<_Iterator>'
  405 |       { return __x < __y; }
      |                ~~~~^~~~~
/usr/include/c++/14/bits/stl_iterator.h:493:5: note: candidate: 'template<class _IteratorL, class _IteratorR> constexpr bool std::operator<(const reverse_iterator<_Iterator>&, const reverse_iterator<_IteratorR>&)'
  493 |     operator<(const reverse_iterator<_IteratorL>& __x,
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:493:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/stl_function.h:405:20: note:   'const State' is not derived from 'const std::reverse_iterator<_Iterator>'
  405 |       { return __x < __y; }
      |                ~~~~^~~~~
/usr/include/c++/14/bits/stl_iterator.h:1694:5: note: candidate: 'template<class _IteratorL, class _IteratorR> constexpr bool std::operator<(const move_iterator<_IteratorL>&, const move_iterator<_IteratorR>&)'
 1694 |     operator<(const move_iterator<_IteratorL>& __x,
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:1694:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/stl_function.h:405:20: note:   'const State' is not derived from 'const std::move_iterator<_IteratorL>'
  405 |       { return __x < __y; }
      |                ~~~~^~~~~
/usr/include/c++/14/bits/stl_iterator.h:1760:5: note: candidate: 'template<class _Iterator> constexpr bool std::operator<(const move_iterator<_IteratorL>&, const move_iterator<_IteratorL>&)'
 1760 |     operator<(const move_iterator<_Iterator>& __x,
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:1760:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/stl_function.h:405:20: note:   'const State' is not derived from 'const std::move_iterator<_IteratorL>'
  405 |       { return __x < __y; }
      |                ~~~~^~~~~