# 浮点数的符号函数
ESP = 10 ** (-8)
def sign(val: float):
if abs(val) < ESP:
return 0
return 1 if val > 0 else -1
# 向量的外乘积,表示两个向量围成的平行四边形面积,b在a逆时针方向,面积为正,否则面积为负
# 输入是两个向量的坐标(x1, y1), (x2, y2)
def cross(a, b):
return a[0]*b[1] - b[0]*a[1]
# 判断两线段是否相交, a1, a2是线段1两个端点,b1, b2是线段2两个端点
def has_segment_intersection(a1, a2, b1, b2)->bool:
c1 = cross( (a2[0]-a1[0], a2[1]-a1[1]), (b1[0]-a1[0], b1[1]-a1[1]) )
c2 = cross( (a2[0]-a1[0], a2[1]-a1[1]), (b2[0]-a1[0], b2[1]-a1[1]) )
c3 = cross( (b2[0]-b1[0], b2[1]-b1[1]), (a2[0]-b1[0], a2[1]-b1[1]) )
c4 = cross( (b2[0]-b1[0], b2[1]-b1[1]), (a1[0]-b1[0], a1[1]-b1[1]) )
return sign(c1) * sign(c2) <= 0 and sign(c3) * sign(c4) <= 0
# 求解两条直线的交点(注意前提是两条直线不平行)
# p1, v1 是第一条直线的点向式表示,p2, v2 是第二条直线的点向式表示
def intersection_point(p1, v1, p2, v2):
u = (p1[0]-p2[0], p1[1]-p2[1])
if sign(cross(v1, v2)) == 0:
return None
t = cross(v2, u) / cross(v1, v2)
return (p1[0] + v1[0]*t, p1[1] + v1[1]*t)
# 求解点到线段的交点, a1, b1 是第一条线段的两个端点,a2, b2是第二条线段两个端点
def intersection_point_on_segment(a1, b1, a2, b2):
if not has_segment_intersection(a1, b1, a2, b2):
return None
v1 = (b1[0]-a1[0], b1[1]-a1[1])
v2 = (b2[0]-a2[0], b2[1]-a2[1])
return intersection_point(a1, v1, a2, v2)
n = int(input())
seg = []
triangle = []
x_set = set()
for _ in range(n):
x1, y1, x2, y2, x3, y3 = map(float, input().split())
triangle.append((x1, y1, x2, y2, x3, y3))
a, b, c = (x1, y1), (x2, y2), (x3, y3)
seg.append((a, b))
seg.append((a, c))
seg.append((b, c))
x_set.add(x1)
x_set.add(x2)
x_set.add(x3)
# 求所有线段的交点
for i in range(len(seg)):
for j in range(i+1, len(seg)):
pp = intersection_point_on_segment(seg[i][0], seg[i][1], seg[j][0], seg[j][1])
if pp is None:
continue
x_set.add(pp[0])
x_pos = list(x_set)
x_pos.sort()
# x坐标是pos位置的扫描线做区间合并
from functools import lru_cache
@lru_cache(typed=False, maxsize=128000000)
def merge_range(pos):
rr = []
for x1, y1, x2, y2, x3, y3 in triangle:
if pos < min(x1, x2, x3) or pos > max(x1, x2, x3):
continue
pp1 = intersection_point_on_segment((x1, y1), (x2, y2), (pos, -10000000), (pos, 10000000))
pp2 = intersection_point_on_segment((x1, y1), (x3, y3), (pos, -10000000), (pos, 10000000))
pp3 = intersection_point_on_segment((x3, y3), (x2, y2), (pos, -10000000), (pos, 10000000))
y_arr = []
for pp in [pp1, pp2, pp3]:
if pp is not None:
y_arr.append(pp[1])
if len(y_arr) < 2:
continue
y_arr.sort()
if len(y_arr) == 2:
rr.append((y_arr[0], y_arr[1]))
else:
rr.append((y_arr[0], y_arr[1]))
rr.append((y_arr[1], y_arr[2]))
# 区间合并
rr.sort()
tot = 0
max_end = -0x7fffffff # 当前已经枚举过的区间的结尾的最大值
for a, b in rr:
if a <= max_end:
if b > max_end:
tot += b - max_end
max_end = b
else:
tot += b - a
max_end = b
return tot
# 枚举区间
ans = 0
for ii in range(len(x_pos)-1):
left, right = x_pos[ii], x_pos[ii+1]
sum1, sum2 = merge_range(left), merge_range(right)
# print(left, right, sum1, sum2)
ans += (sum1 + sum2) * (right - left) / 2
print("%.2f" % ans)