Option Explicit On
Option Strict On
Option Compare Binary
Option Infer On
Imports System.Collections.Generic
Imports System.Numerics
Imports Tp = System.Tuple(Of Integer, Integer)
Public Class CheckPolygon
Private Class Point
Public ReadOnly x, y As BigInteger
Sub New (x As Integer, y As Integer)
Me.x = x: Me.y = y
End Sub
Function Gaiseki(p1 As Point, p2 As Point) As BigInteger
Dim a As BigInteger = (p1.x - Me.x) * (p2.y - Me.y)
Dim b As BigInteger = (p1.y - Me.y) * (p2.x - Me.x)
Gaiseki = a - b
End Function
End Class
Private Class Line
Public ReadOnly p1, p2 As Point
Public ReadOnly dx, dy As BigInteger
Sub New (p1 As Point, p2 As Point)
Me.p1 = p1: Me.p2 = p2
Me.dx = p2.x - p1.x
Me.dy = p2.y - p1.y
End Sub
Function IsPara(other As Line) As Boolean
If Me.dx = 0 Then
IsPara = other.dx = 0
ElseIf other.dx = 0 Then
IsPara = Me.dx = 0
ElseIf Me.dy = 0 Then
IsPara = other.dy = 0
ElseIf other.dy = 0 Then
IsPara = Me.dy = 0
Else
Dim a As BigInteger = Me.dx * other.dy
Dim b As BigInteger = Me.dy * other.dx
IsPara = a - b = 0
End If
End Function
Function IsIntersect(other As Line) As Boolean
IsIntersect = False
If IsPara(other) Then Exit Function
Dim a As BigInteger = Me.p1.Gaiseki(Me.p2, other.p1)
Dim b As BigInteger = Me.p1.Gaiseki(Me.p2, other.p2)
Dim c As BigInteger = other.p1.Gaiseki(other.p2, Me.p1)
Dim d As BigInteger = other.p1.Gaiseki(other.p2, Me.p2)
IsIntersect = a * b <= 0 AndAlso c * d <= 0
End Function
End Class
Public Function check(X As Integer(), Y As Integer()) As String
check = "Not simple"
Dim N As Integer = X.Length
Dim lines(N) As Line
Dim hs As New HashSet(Of Tp)()
For i As Integer = 0 To N - 1
Dim t As New Tp(X(i), Y(i))
If Not hs.Add(t) Then Exit Function
Next i
For i As Integer = 0 To N - 2
Dim p1 As New Point(X(i), Y(i))
Dim p2 As New Point(X(i+1), Y(i+1))
lines(i) = New Line(p1, p2)
If lines(i).dx = 0 AndAlso lines(i).dy = 0 Then Exit Function
Next i
lines(N - 1) = New Line(New Point(X(N-1),Y(N-1)), New Point(X(0),Y(0)))
lines(N) = lines(0)
For i As Integer = 0 To N - 1
If lines(i).IsPara(lines(i+1)) Then Exit Function
Next i
For i As Integer = 0 To N
For j As Integer = 0 To N
If Math.Abs(j - i) <= 1 Then Continue For
If Math.Abs(j - i) >= N - 1 Then Continue For
If lines(i).IsIntersect(lines(j)) Then
Console.WriteLine("intersect {0} {1}", i, j)
Console.WriteLine("({0}, {1}) - ({2}, {3})", lines(i).p1.x, lines(i).p1.y, lines(i).p2.x, lines(i).p2.y)
Console.WriteLine("({0}, {1}) - ({2}, {3})", lines(j).p1.x, lines(j).p1.y, lines(j).p2.x, lines(j).p2.y)
Exit Function
End If
Next j
Next i
Dim ret As BigInteger = 0
For i As Integer = 0 To N - 1
Dim ln As Line = lines(i)
ret += ln.p1.x * ln.p2.y - ln.p1.y * ln.p2.x
Next i
If ret < 0 Then ret = -ret
check = String.Format("{0:F01}", CDbl(ret) / 2.0)
End Function
End Class