← Home
```go
package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
	"sort"
)

const EPS = 1e-12

type Pt struct {
	x, y int64
}

type Rect [4]Pt

type Interval struct {
	l, r float64
}

type Scanner struct {
	data []byte
	idx  int
}

func (s *Scanner) nextInt() int64 {
	n := len(s.data)
	for s.idx < n {
		c := s.data[s.idx]
		if c != ' ' && c != '\n' && c != '\r' && c != '\t' {
			break
		}
		s.idx++
	}
	sign := int64(1)
	if s.idx < n && s.data[s.idx] == '-' {
		sign = -1
		s.idx++
	}
	var v int64
	for s.idx < n {
		c := s.data[s.idx]
		if c < '0' || c > '9' {
			break
		}
		v = v*10 + int64(c-'0')
		s.idx++
	}
	return sign * v
}

func sub(a, b Pt) Pt {
	return Pt{a.x - b.x, a.y - b.y}
}

func cross(a, b Pt) int64 {
	return a.x*b.y - a.y*b.x
}

func dot(a, b Pt) int64 {
	return a.x*b.x + a.y*b.y
}

func abs64(x int64) int64 {
	if x < 0 {
		return -x
	}
	return x
}

func doubleArea(r Rect) int64 {
	var s int64
	for i := 0; i < 4; i++ {
		s += cross(r[i], r[(i+1)%4])
	}
	return s
}

func makeCCW(r Rect) Rect {
	if doubleArea(r) < 0 {
		return Rect{r[0], r[3], r[2], r[1]}
	}
	return r
}

func rightCoverage(a, b Pt, rect Rect) (float64, float64, bool) {
	d := sub(b, a)
	n := Pt{d.y, -d.x}
	l, r := 0.0, 1.0
	for i := 0; i < 4; i++ {
		u := rect[i]
		v := rect[(i+1)%4]
		s := sub(v, u)
		alpha := cross(s, d)
		beta := cross(s, sub(a, u))
		if alpha == 0 {
			if beta < 0 {
				return 0, 0, false
			}
			if beta == 0 && cross(s, n) < 0 {
				return 0, 0, false
			}
			continue
		}
		t := -float64(beta) / float64(alpha)
		if alpha > 0 {
			if t > l {
				l = t
			}
		} else {
			if t < r {
				r = t
			}
		}
	}
	if l < 0 {
		l = 0
	}
	if r > 1 {
		r = 1
	}
	if r-l > EPS {
		return l, r, true
	}
	return 0, 0, false
}

func sameSideOverlap(a, b, c, d Pt) (float64, float64, bool) {
	e := sub(b, a)
	f := sub(d, c)
	if cross(e, f) != 0 {
		return 0, 0, false
	}
	if dot(e, f) <= 0 {
		return 0, 0, false
	}
	if cross(e, sub(c, a)) != 0 {
		return 0, 0, false
	}
	den := float64(dot(e, e))
	t1 := float64(dot(sub(c, a), e)) / den
	t2 := float64(dot(sub(d, a), e)) / den
	if t1 > t2 {
		t1, t2 = t2, t1
	}
	if t1 < 0 {
		t1 = 0
	}
	if t2 > 1 {
		t2 = 1
	}
	if t2-t1 > EPS {
		return t1, t2, true
	}
	return 0, 0, false
}

func main() {
	data, _ := io.ReadAll(os.Stdin)
	sc := Scanner{data: data}

	n := int(sc.nextInt())
	rects := make([]Rect, n)
	var totalDoubleArea int64

	for i := 0; i < n; i++ {
		var r Rect
		for j := 0; j < 4; j++ {
			r[j] = Pt{sc.nextInt(), sc.nextInt()}
		}
		totalDoubleArea += abs64(doubleArea(r))
		rects[i] = makeCCW(r)
	}

	intervals := make([]Interval, 0, 2500)
	unionArea := 0.0

	for i := 0; i < n; i++ {
		for e := 0; e < 4; e++ {
			a := rects[i][e]
			b := rects[i][(e+1)%4]
			intervals = intervals[:0]

			for j := 0; j < n; j++ {
				if j == i {
					continue
				}
				if l, r, ok := rightCoverage(a, b, rects[j]); ok {
					intervals = append(intervals, Interval{l, r})
				}
			}

			for j := 0; j < i; j++ {
				for f := 0; f < 4; f++ {
					c := rects[j][f]
					d := rects[j][(f+1)%4]
					if l, r, ok := sameSideOverlap(a, b, c, d); ok {
						intervals = append(intervals, Interval{l, r})
					}
				}
			}

			covered := 0.0
			if len(intervals) > 0 {
				sort.Slice(intervals, func(x, y int) bool {
					if intervals[x].l == intervals[y].l {
						return intervals[x].r < intervals[y].r
					}
					return intervals[x].l < intervals[y].l
				})

				curL := intervals[0].l
				curR := intervals[0].r
				if curL < 0 {
					curL = 0
				}
				if curR > 1 {
					curR = 1
				}

				for k := 1; k < len(intervals); k++ {
					l := intervals[k].l
					r := intervals[k].r
					if l < 0 {
						l = 0
					}
					if r > 1 {
						r = 1
					}
					if r-l <= EPS {
						continue
					}
					if l <= curR+EPS {
						if r > curR {
							curR = r
						}
					} else {
						covered += curR - curL
						curL, curR = l, r
					}
				}
				covered += curR - curL
				if covered > 1 {
					covered = 1
				}
			}

			visible := 1.0 - covered
			if visible > EPS {
				unionArea += float64(cross(a, b)) * visible * 0.5
			}
		}
	}

	ans := float64(totalDoubleArea) * 0.5 / math.Abs(unionArea)

	out := bufio.NewWriter(os.Stdout)
	fmt.Fprintf(out, "%.10f\n", ans)
	out.Flush()
}
```