package area import ( "fmt" "math" ) const epsilon = 1e-9 func ValidateGeometry(kind, direction string, points []Point) error { for _, point := range points { if point.X < 0 || point.X > 1 || point.Y < 0 || point.Y > 1 { return fmt.Errorf("坐标必须位于画面范围内") } } switch kind { case KindPolygon: if len(points) < 3 { return fmt.Errorf("多边形至少需要 3 个点") } if math.Abs(polygonArea(points)) < epsilon { return fmt.Errorf("多边形不能退化为直线") } if selfIntersects(points, true) { return fmt.Errorf("多边形不能自交") } case KindLine: if len(points) != 2 { return fmt.Errorf("警戒线必须恰好包含 2 个点") } if distance(points[0], points[1]) < epsilon { return fmt.Errorf("警戒线两点不能重合") } if direction != DirectionAToB && direction != DirectionBToA && direction != DirectionBoth { return fmt.Errorf("警戒线方向不正确") } default: return fmt.Errorf("区域类型不正确") } return nil } func polygonArea(points []Point) float64 { sum := 0.0 for i := range points { next := (i + 1) % len(points) sum += points[i].X*points[next].Y - points[next].X*points[i].Y } return sum / 2 } func distance(a, b Point) float64 { dx, dy := a.X-b.X, a.Y-b.Y; return dx*dx + dy*dy } func selfIntersects(points []Point, closed bool) bool { segments := len(points) - 1 if closed { segments = len(points) } for i := 0; i < segments; i++ { a1, a2 := points[i], points[(i+1)%len(points)] if distance(a1, a2) < epsilon { return true } for j := i + 1; j < segments; j++ { if j == i+1 || closed && i == 0 && j == segments-1 { continue } b1, b2 := points[j], points[(j+1)%len(points)] if segmentsIntersect(a1, a2, b1, b2) { return true } } } return false } func segmentsIntersect(a, b, c, d Point) bool { o1, o2, o3, o4 := orientation(a, b, c), orientation(a, b, d), orientation(c, d, a), orientation(c, d, b) return o1*o2 < 0 && o3*o4 < 0 } func orientation(a, b, c Point) float64 { return (b.X-a.X)*(c.Y-a.Y) - (b.Y-a.Y)*(c.X-a.X) }