Attribute VB_Name = "Geometry_HoleFiller"

Option Explicit

'Hole filler
Private Type Cut
    PositionIndex As Long
    ProjectedPosition As Vector2
    SortUtility As Double
End Type
Public Type HoleFillerData
    Cuts(0 To Geometry_MaxIndices - 1) As Cut
    NumberOfCuts As Long
End Type

Public Sub HoleFiller_AddCut(ByRef Hole As HoleFillerData, NewIndex As Long)
    Dim CutIndex As Long
    For CutIndex = 0 To Hole.NumberOfCuts - 1
        If Hole.Cuts(CutIndex).PositionIndex = NewIndex Then
            Exit Sub 'A cut with the position index already exists
        End If
    Next CutIndex
    Hole.Cuts(Hole.NumberOfCuts).PositionIndex = NewIndex
    Hole.Cuts(Hole.NumberOfCuts).ProjectedPosition = MakeVector2(0, 0)
    Hole.NumberOfCuts = Hole.NumberOfCuts + 1
End Sub

Private Sub HoleFiller_Swap(ByRef Hole As HoleFillerData, A As Long, B As Long)
    Dim Swap As Cut
    Swap = Hole.Cuts(A)
    Hole.Cuts(A) = Hole.Cuts(B)
    Hole.Cuts(B) = Swap
End Sub

Private Sub HoleFiller_Sort(ByRef Hole As HoleFillerData)
    'Bubble sort may only be used for small element counts because of quadratic complexity!
    Dim I As Long
    Dim N As Long
    Dim NewN As Long
    N = Hole.NumberOfCuts
    Do
        NewN = 0
        For I = 1 To N - 1
            If Hole.Cuts(I - 1).SortUtility > Hole.Cuts(I).SortUtility Then
                HoleFiller_Swap Hole, I - 1, I
                NewN = I
            End If
        Next I
        N = NewN
    Loop Until N = 0
    For I = 0 To Hole.NumberOfCuts - 2
        Debug.Assert Hole.Cuts(I).SortUtility <= Hole.Cuts(I + 1).SortUtility
    Next I
End Sub

Public Sub HoleFiller_Finalize(ByRef Hole As HoleFillerData, TargetCell As Cell, CuttingPlane As FractionPlane)
    If Hole.NumberOfCuts >= 3 Then
        Dim ACuttingPlane As Plane
        Dim CutIndex As Long
        Dim SurfaceIndex As Long
        Dim PlaneSystem As Matrix3
        ACuttingPlane = ApproximateFractionPlane(CuttingPlane)
        PlaneSystem = GetPlaneAxisSystem(ACuttingPlane)
        SurfaceIndex = TargetCell.NumberOfSurfaces
        TargetCell.Surfaces(SurfaceIndex).SurfacePlane = FlipFractionPlane(CuttingPlane)
        TargetCell.NumberOfSurfaces = TargetCell.NumberOfSurfaces + 1
        For CutIndex = Hole.NumberOfCuts - 1 To 0 Step -1
            Dim Pos As Vector3
            Dim Projection As Vector3
            Pos = TargetCell.Positions(Hole.Cuts(CutIndex).PositionIndex)
            Projection = ProjectPointToPlaneSystem(Pos, ACuttingPlane.Point, PlaneSystem)
            Hole.Cuts(CutIndex).ProjectedPosition = Vector3ToVector2(Projection)
        Next CutIndex
        Dim Inside As Vector2
        Inside = DivVector2(AddVector2(AddVector2(Hole.Cuts(0).ProjectedPosition, Hole.Cuts(1).ProjectedPosition), Hole.Cuts(2).ProjectedPosition), 3)
        For CutIndex = 0 To Hole.NumberOfCuts - 1
            Hole.Cuts(CutIndex).SortUtility = Angle(Hole.Cuts(CutIndex).ProjectedPosition.X - Inside.X, Hole.Cuts(CutIndex).ProjectedPosition.Y - Inside.Y)
        Next CutIndex
        HoleFiller_Sort Hole
        For CutIndex = 0 To Hole.NumberOfCuts - 1
            AddPointToSurfaceByIndex TargetCell.Surfaces(SurfaceIndex), Hole.Cuts(CutIndex).PositionIndex
        Next CutIndex
    End If
End Sub
