VB.NET实现甘特图条形重叠时PosIndex排序调整问题求解
甘特视图预约条形位置重排实现问题
核心需求
正在开发预约类应用,采用甘特视图可视化预约数据,根据预约起止时间范围绘制对应矩形条形,条形通过PosIndex属性定位(第1行对应PosIndex为0)。
条形位置分配规则:
- 同一
PosIndex下若两个条形存在时间范围重叠,需将重叠条形的PosIndex加1下移1位,同时该位置下方所有条形的PosIndex同步加1下移 - 代码迭代过程中若检测到同
PosIndex的其他重叠(非上方条形挤压导致),重复上述下移操作 - 同索引下无时间重叠的条形
PosIndex保持不变,仅受上方重叠条形挤压时才向下偏移 - 后续会调整网格与床位行线宽度,适配同一行容纳多个条形的场景
此前尝试使用Rectangle.IntersectsWith方法做相交检测,编写多版排序逻辑,但始终无法正确完成所有条形的位置分配,仍有部分重叠条形未被正确分离。
简化版测试模块代码
Module ttest Public Class barAllocations Dim lstBars As List(Of barAllocations) Public Property barText As String Public Property FromTime() As DateTime Public Property ToTime() As DateTime Public Property PosIndex() As Integer Public Sub addAlloBar(ByVal setBarText As String, ByVal FromTime As DateTime, ToTime As DateTime, PosIndex As Integer) Dim alloBar As New barAllocations alloBar.barText = setBarText alloBar.FromTime = FromTime alloBar.ToTime = ToTime alloBar.PosIndex = PosIndex lstBars.Add(alloBar) End Sub Public Sub sortList() Dim prevIndex As Integer Dim prevFromDT As DateTime Dim prevToDT As DateTime For Each bar As barAllocations In lstBars If bar.ToTime > prevFromDT And bar.FromTime < prevToDT And bar.PosIndex = prevIndex Then bar.PosIndex += 1 For Each bars As barAllocations In lstBars If bar.PosIndex > prevIndex Then bars.PosIndex += 1 Next End If prevFromDT = bar.FromTime prevToDT = bar.ToTime prevIndex = bar.PosIndex Next End Sub End Class Private Sub barAdd() Dim startDT As DateTime = Now().AddHours(-48) Dim endDT As DateTime = startDT.AddHours(12) Dim allogrid As New barAllocations allogrid.addAlloBar("test1", startDT, endDT, 0) allogrid.addAlloBar("test2", startDT, endDT, 0) allogrid.addAlloBar("test3", startDT.AddHours(12), endDT.AddHours(12), 0) allogrid.addAlloBar("test4", startDT.AddHours(24), endDT.AddHours(24), 0) allogrid.addAlloBar("test5", startDT.AddHours(5), endDT.AddHours(5), 5) allogrid.addAlloBar("test6", startDT.AddHours(2), endDT.AddHours(2), 5) allogrid.addAlloBar("test7", startDT.AddHours(1), endDT.AddHours(1), 6) allogrid.addAlloBar("test8", startDT.AddHours(5), endDT.AddHours(5), 6) allogrid.addAlloBar("test9", startDT.AddHours(7), endDT.AddHours(7), 7) allogrid.addAlloBar("test10", startDT.AddHours(8), endDT.AddHours(8), 7) allogrid.addAlloBar("test11", startDT.AddHours(10), endDT.AddHours(10), 8) allogrid.addAlloBar("test12", startDT.AddHours(1), endDT.AddHours(1), 8) allogrid.addAlloBar("test13", startDT.AddHours(22), endDT.AddHours(34), 8) allogrid.addAlloBar("test14", startDT.AddHours(20), endDT.AddHours(32), 8) allogrid.addAlloBar("test15", startDT.AddHours(6), endDT.AddHours(6), 9) allogrid.addAlloBar("test16", startDT.AddHours(11), endDT.AddHours(11), 9) allogrid.sortList() End Sub End Module
旧版问题描述与实现代码
同一床位同一时间可存在两个预约,最初实现逻辑为:若存在时间重叠,将对应条形向下移动1位,同时所有下方条形也同步移动1位,后续调整网格与床位行线宽度适配同一行同时容纳多个条形的场景。最初尝试使用矩形相交检测方法,检测效果符合预期,但排序逻辑始终存在问题,部分重叠条形未被分离,留存有对应应用效果示例截图。
旧版实现代码如下:
Dim lst As List(Of barAllocation) = lstBars Dim prevIndex As Integer Dim prevRec As Rectangle Dim msg As String = "" lst = lst.OrderBy(Function(x) x.PosIndex).ThenBy(Function(y) y.FromTime).ToList For Each bar In lst Dim tsDate As TimeSpan = bar.ToTime - bar.FromTime Dim recstart As Integer = bar.ToTime.Month & bar.ToTime.Day & bar.ToTime.Hour & bar.ToTime.Minute Dim barRec As New Rectangle(recstart, bar.PosIndex * 10, tsDate.TotalMinutes, 10) If prevRec.IntersectsWith(barRec) Then If prevIndex = bar.PosIndex Then If bar.PosIndex = 0 Then bar.PosIndex += 1 barChanged = bar.PosIndex Else barChanged = bar.PosIndex bar.PosIndex += 1 End If End If End If If bar.PosIndex > barChanged Then bar.PosIndex += 1 prevRec = barRec prevIndex = bar.PosIndex
内容的提问来源于stack exchange,提问作者cyberblitz
相关产品推荐
相关产品推荐

