rts-sim-testing-service/ts/simulation/wayside/memory/wayside_memory_generate.go

786 lines
28 KiB
Go
Raw Normal View History

2023-08-07 15:05:37 +08:00
package memory
import (
"container/list"
2023-09-14 13:58:03 +08:00
"fmt"
"log/slog"
2023-08-08 10:40:24 +08:00
"math"
2023-08-07 15:05:37 +08:00
"reflect"
"sort"
"strings"
2023-08-08 10:40:24 +08:00
"joylink.club/bj-rtsts-server/dto"
2023-10-26 17:16:07 +08:00
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
2023-08-07 15:05:37 +08:00
)
// 参与计算的坡度与曲度均为正线公里标,如果有其他坐标系需要转换
2023-09-14 13:58:03 +08:00
var mainLineType = "MAIN_LINE"
2023-08-07 15:05:37 +08:00
// 参与计算结构体信息
type buildCalcStruct struct {
2023-09-14 13:58:03 +08:00
AxlePointMap map[string]*graphicData.AxleCounting
TurnoutMap map[string]*buildCalcTurnoutStruct
SectionMap map[string]*buildCalcSectionStruct
CoordinateConvertorMap map[string]*coordinateConvertor
2023-08-07 15:05:37 +08:00
}
// 参与计算link时的区段结构体
type buildCalcSectionStruct struct {
2023-08-08 18:09:13 +08:00
Data *graphicData.Section
axlePoints map[graphicData.RelatedRef_DevicePort]*graphicData.AxleCounting // 关联计轴map
stopPositions []*graphicData.StopPosition // 停车位
transponders []*graphicData.Transponder // 应答器
signals []*graphicData.Signal // 信号机
slopes map[string]*graphicData.KilometerSystem // 坡度公里标
curvatures map[string]*graphicData.KilometerSystem // 曲度公里标
2023-08-07 15:05:37 +08:00
}
// 参与计算的
type buildCalcTurnoutStruct struct {
Data *graphicData.Turnout
axlePoints map[graphicData.RelatedRef_DevicePort]*graphicData.AxleCounting // 关联计轴map
CrossKilometerSystem *graphicData.KilometerSystem // 道岔岔心位置
transponders map[graphicData.RelatedRef_DevicePort][]*graphicData.Transponder // 应答器
signals map[graphicData.RelatedRef_DevicePort]*graphicData.Signal // 对应位置信号机
slopes map[graphicData.RelatedRef_DevicePort]map[string]*graphicData.KilometerSystem // 坡度公里标
curvatures map[graphicData.RelatedRef_DevicePort]map[string]*graphicData.KilometerSystem // 曲度公里标
2023-08-07 15:05:37 +08:00
}
2023-09-14 13:58:03 +08:00
// 坐标转换结构体
type coordinateConvertor struct {
ConfigType string
ConfigCoordinate int64
ConvertorType string
ConvertorCoordinate int64
}
func (c *coordinateConvertor) ConvertorKilometer(basisKilometer *graphicData.KilometerSystem, targetType string) int64 {
basisType := basisKilometer.CoordinateSystem
isMatch := (basisType == c.ConfigType && targetType == c.ConvertorType) || (targetType == c.ConfigType && basisType == c.ConvertorType)
if !isMatch {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: fmt.Sprintf("非【%s<>%s】转换方法", basisType, targetType)})
}
if targetType == c.ConfigType {
return c.ConfigCoordinate + basisKilometer.Kilometer - c.ConvertorCoordinate
} else {
return c.ConvertorCoordinate + basisKilometer.Kilometer - c.ConfigCoordinate
}
}
func generateConvertorKey(k1, k2 string) string {
if strings.Compare(k1, k2) > 0 {
return k1 + "_" + k2
} else {
return k2 + "_" + k1
}
}
2023-08-07 15:05:37 +08:00
// 根据地图信息生成calcLink数据
func BuildCalculateLinkData(gd *graphicData.RtssGraphicStorage) []*graphicData.CalculateLink {
gm, startPointQueue := getGraphicDataDeviceMap(gd)
// 这里linkPath是排过序的公里标大小
linkPathMap := getGraphicLinkPath(gm, startPointQueue)
// 根据路径开始包装结果数据
2023-08-31 16:16:18 +08:00
var resultArr []*graphicData.CalculateLink
2023-08-07 15:05:37 +08:00
for id, pathArr := range linkPathMap {
item := &graphicData.CalculateLink{
Common: &graphicData.CommonInfo{},
2023-08-08 10:40:24 +08:00
Index: int32(id),
2023-08-07 15:05:37 +08:00
Points: []*graphicData.Point{},
Length: 0,
2023-08-07 15:05:37 +08:00
DevicePositions: []*graphicData.CalculateLink_DevicePosition{},
}
allTurnout := true
2023-08-08 10:40:24 +08:00
prevKm, offset := getStartKilometer(gm, pathArr[0])
devicePosistionMap := make(map[string]*graphicData.CalculateLink_DevicePosition)
2023-08-07 15:05:37 +08:00
for index, refVal := range pathArr {
if refVal.DeviceType == graphicData.RelatedRef_Section {
allTurnout = false
section := gm.SectionMap[refVal.Id]
// 计算长度
2023-08-08 10:40:24 +08:00
item.Length = item.Length + calcGraphicLenBySection(section)
2023-08-07 15:05:37 +08:00
// 放入设备偏移
offset, prevKm = getGraphicSectionRefDevices(refVal, devicePosistionMap, section, offset, prevKm)
2023-08-07 15:05:37 +08:00
} else {
allTurnout = allTurnout && true
turnout := gm.TurnoutMap[refVal.Id]
// 计算长度
2023-08-08 10:40:24 +08:00
item.Length = item.Length + calcGraphicLenByTurnout(turnout, refVal.DevicePort)
2023-08-07 15:05:37 +08:00
// 放入设备偏移
2023-08-08 18:09:13 +08:00
offset, prevKm = getGraphicTurnoutRefDevices(refVal, devicePosistionMap, turnout, offset, prevKm)
2023-08-07 15:05:37 +08:00
// 道岔时左右端直接赋值
if index == 0 {
item.ARelatedRef = refVal
} else {
item.BRelatedRef = refVal
}
}
2023-08-08 10:40:24 +08:00
}
for _, v := range devicePosistionMap {
item.DevicePositions = append(item.DevicePositions, v)
2023-08-07 15:05:37 +08:00
}
2023-08-08 18:09:13 +08:00
sort.SliceStable(item.DevicePositions, func(i, j int) bool {
return item.DevicePositions[i].Offset < item.DevicePositions[j].Offset
})
2023-08-07 15:05:37 +08:00
// 如果全部为道岔,则长度使用岔心减岔心
if allTurnout {
tk1 := gm.TurnoutMap[pathArr[0].Id].CrossKilometerSystem.Kilometer
tk2 := gm.TurnoutMap[pathArr[len(pathArr)-1].Id].CrossKilometerSystem.Kilometer
item.Length = int32(math.Abs(float64(tk2 - tk1)))
2023-08-07 15:05:37 +08:00
}
resultArr = append(resultArr, item)
}
return resultArr
}
// 计算区段长度
func calcGraphicLenBySection(section *buildCalcSectionStruct) int32 {
2023-08-08 18:09:13 +08:00
if len(section.axlePoints) != 2 {
slog.Warn("区段端点位置缺失", "id", section.Data.Common.Id)
2023-08-07 15:05:37 +08:00
return 0
}
2023-08-08 18:09:13 +08:00
var length int64 // 两端公里标相减即可
for _, a := range section.axlePoints {
2023-09-14 13:58:03 +08:00
if !judgeKilometerVaild(a.KilometerSystem) {
2023-08-08 18:09:13 +08:00
return 0
}
length = a.KilometerSystem.Kilometer - length
2023-08-07 15:05:37 +08:00
}
2023-08-08 18:09:13 +08:00
return int32(math.Abs(float64(length)))
2023-08-07 15:05:37 +08:00
}
// 计算道岔端长度
func calcGraphicLenByTurnout(turnout *buildCalcTurnoutStruct, p graphicData.RelatedRef_DevicePort) int32 {
2023-08-08 18:09:13 +08:00
endPoint := turnout.axlePoints[p]
2023-09-14 13:58:03 +08:00
if endPoint == nil || !judgeKilometerVaild(endPoint.KilometerSystem) {
slog.Warn("道岔对应端口【%s】数据无计轴", "turnoutId", turnout.Data.Common.Id, "port", p.String())
2023-08-07 15:05:37 +08:00
return 0
}
2023-09-14 13:58:03 +08:00
if !judgeKilometerVaild(turnout.CrossKilometerSystem) {
slog.Warn("道岔数据错误,岔心公里标为空", "turnoutId", turnout.Data.Common.Id)
2023-08-07 15:05:37 +08:00
return 0
}
start := turnout.CrossKilometerSystem.Kilometer
end := endPoint.KilometerSystem.Kilometer
return int32(math.Abs(float64(end - start)))
2023-08-07 15:05:37 +08:00
}
// 获取关于区段的设备信息
func getGraphicSectionRefDevices(refVal *graphicData.RelatedRef, deviceMap map[string]*graphicData.CalculateLink_DevicePosition,
section *buildCalcSectionStruct, offset int32, prevKm int64) (int32, int64) {
2023-08-08 18:09:13 +08:00
dealFunc := func(p *graphicData.AxleCounting, d map[string]*graphicData.CalculateLink_DevicePosition, o int32, pk int64) (int32, int64) {
if p != nil && d[p.Common.Id] == nil {
2023-08-08 18:09:13 +08:00
resultOff := o + int32(math.Abs(float64(p.KilometerSystem.Kilometer-pk)))
resultPK := p.KilometerSystem.Kilometer
d[p.Common.Id] = &graphicData.CalculateLink_DevicePosition{
2023-08-08 18:09:13 +08:00
DeviceId: p.Common.Id,
Offset: resultOff,
DeviceType: graphicData.RelatedRef_AxleCounting.String(),
}
return resultOff, resultPK
2023-08-08 10:40:24 +08:00
}
2023-08-08 18:09:13 +08:00
return o, pk
2023-08-08 10:40:24 +08:00
}
2023-08-08 18:09:13 +08:00
// 查看连接点
point := section.axlePoints[refVal.DevicePort]
2023-08-08 18:09:13 +08:00
offsetCalc, prevKmCalc := offset, prevKm
offsetCalc, prevKmCalc = dealFunc(point, deviceMap, offsetCalc, prevKmCalc)
// 获取另一个连接点
nextPoint := graphicData.RelatedRef_B
if refVal.DevicePort == nextPoint {
nextPoint = graphicData.RelatedRef_A
}
point = section.axlePoints[nextPoint]
2023-08-08 18:09:13 +08:00
offsetCalc, prevKmCalc = dealFunc(point, deviceMap, offsetCalc, prevKmCalc)
// 处理区段上的设备
startPoint := section.axlePoints[refVal.DevicePort]
2023-08-08 18:09:13 +08:00
if startPoint != nil {
sppk := startPoint.KilometerSystem.Kilometer // 相对起点的公里标
spof := deviceMap[startPoint.Common.Id].Offset // 相对的起点offset
// 信号机信息
for _, s := range section.signals {
2023-09-14 13:58:03 +08:00
if judgeKilometerVaild(s.KilometerSystem) && deviceMap[s.Common.Id] == nil {
2023-08-08 18:09:13 +08:00
deviceMap[s.Common.Id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: s.Common.Id,
Offset: spof + int32(math.Abs(float64(s.KilometerSystem.Kilometer-sppk))),
DeviceType: "Signal",
}
}
}
// 停车标信息
for _, s := range section.stopPositions {
2023-09-14 13:58:03 +08:00
if judgeKilometerVaild(s.KilometerSystem) && deviceMap[s.Common.Id] == nil {
2023-08-08 18:09:13 +08:00
deviceMap[s.Common.Id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: s.Common.Id,
Offset: spof + int32(math.Abs(float64(s.KilometerSystem.Kilometer-sppk))),
DeviceType: "StopPosition",
}
}
}
// 应答器信息
for _, t := range section.transponders {
2023-09-14 13:58:03 +08:00
if judgeKilometerVaild(t.KilometerSystem) && deviceMap[t.Common.Id] == nil {
2023-08-08 18:09:13 +08:00
deviceMap[t.Common.Id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: t.Common.Id,
Offset: spof + int32(math.Abs(float64(t.KilometerSystem.Kilometer-sppk))),
DeviceType: "Transponder",
}
}
2023-08-08 10:40:24 +08:00
}
// 坡度
for id, s := range section.slopes {
2023-09-14 13:58:03 +08:00
if judgeKilometerVaild(s) && deviceMap[id] == nil {
deviceMap[id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: id,
Offset: spof + int32(math.Abs(float64(s.Kilometer-sppk))),
DeviceType: "slopes",
}
}
}
// 曲度
for id, c := range section.curvatures {
2023-09-14 13:58:03 +08:00
if judgeKilometerVaild(c) && deviceMap[id] == nil {
deviceMap[id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: id,
Offset: spof + int32(math.Abs(float64(c.Kilometer-sppk))),
DeviceType: "curvatures",
}
}
}
2023-08-07 15:05:37 +08:00
}
2023-08-08 18:09:13 +08:00
return offsetCalc, prevKmCalc
2023-08-07 15:05:37 +08:00
}
// 获取关于道岔的设备信息
2023-08-08 18:09:13 +08:00
func getGraphicTurnoutRefDevices(refVal *graphicData.RelatedRef, deviceMap map[string]*graphicData.CalculateLink_DevicePosition, turnout *buildCalcTurnoutStruct, offset int32, prevKm int64) (int32, int64) {
2023-08-08 10:40:24 +08:00
// 目前只放入岔心位置
if turnout.CrossKilometerSystem != nil && deviceMap[turnout.Data.Common.Id] == nil {
2023-08-08 18:09:13 +08:00
offsetCalc := offset + int32(math.Abs(float64(turnout.CrossKilometerSystem.Kilometer-prevKm)))
prevKmCalc := turnout.CrossKilometerSystem.Kilometer
2023-08-08 10:40:24 +08:00
deviceMap[turnout.Data.Common.Id] = &graphicData.CalculateLink_DevicePosition{
2023-08-08 18:09:13 +08:00
DeviceId: turnout.Data.Common.Id,
Offset: offsetCalc,
DeviceType: graphicData.RelatedRef_Turnout.String(),
}
// 查看是否存在连接计轴
point := turnout.axlePoints[refVal.DevicePort]
2023-09-14 13:58:03 +08:00
if point != nil && judgeKilometerVaild(point.KilometerSystem) && deviceMap[point.Common.Id] == nil {
2023-08-08 18:09:13 +08:00
deviceMap[point.Common.Id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: point.Common.Id,
Offset: offset + int32(math.Abs(float64(point.KilometerSystem.Kilometer-prevKm))),
DeviceType: graphicData.RelatedRef_AxleCounting.String(),
}
}
// 处理道岔上的信号机
signal := turnout.signals[refVal.DevicePort]
2023-09-14 13:58:03 +08:00
if signal != nil && judgeKilometerVaild(signal.KilometerSystem) && deviceMap[signal.Common.Id] == nil {
deviceMap[signal.Common.Id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: signal.Common.Id,
Offset: offset + int32(math.Abs(float64(signal.KilometerSystem.Kilometer-prevKm))),
DeviceType: "Signal",
2023-08-08 18:09:13 +08:00
}
}
// 处理道岔上的应答器
transponders := turnout.transponders[refVal.DevicePort]
2023-08-22 16:44:34 +08:00
for _, t := range transponders {
2023-09-14 13:58:03 +08:00
if judgeKilometerVaild(t.KilometerSystem) && deviceMap[t.Common.Id] == nil {
2023-08-22 16:44:34 +08:00
deviceMap[t.Common.Id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: t.Common.Id,
Offset: offset + int32(math.Abs(float64(t.KilometerSystem.Kilometer-prevKm))),
DeviceType: "Transponder",
2023-08-08 18:09:13 +08:00
}
}
2023-08-08 10:40:24 +08:00
}
// 坡度
sm := turnout.slopes[refVal.DevicePort]
2023-08-22 16:44:34 +08:00
for id, s := range sm {
2023-09-14 13:58:03 +08:00
if judgeKilometerVaild(s) && deviceMap[id] == nil {
2023-08-22 16:44:34 +08:00
deviceMap[id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: id,
Offset: offset + int32(math.Abs(float64(s.Kilometer-prevKm))),
DeviceType: "slopes",
}
}
}
// 曲度
cm := turnout.curvatures[refVal.DevicePort]
2023-08-22 16:44:34 +08:00
for id, c := range cm {
2023-09-14 13:58:03 +08:00
if judgeKilometerVaild(c) && deviceMap[id] == nil {
2023-08-22 16:44:34 +08:00
deviceMap[id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: id,
Offset: offset + int32(math.Abs(float64(c.Kilometer-prevKm))),
DeviceType: "curvatures",
}
}
}
2023-08-08 18:09:13 +08:00
return offsetCalc, prevKmCalc
2023-08-07 15:05:37 +08:00
}
2023-08-08 10:40:24 +08:00
return offset, prevKm
2023-08-07 15:05:37 +08:00
}
// 获取link的起始点和包装数据结构方便查找以道岔的各分支的连接点为起点
func getGraphicDataDeviceMap(gd *graphicData.RtssGraphicStorage) (*buildCalcStruct, *list.List) {
gm := &buildCalcStruct{
2023-09-14 13:58:03 +08:00
AxlePointMap: make(map[string]*graphicData.AxleCounting),
TurnoutMap: make(map[string]*buildCalcTurnoutStruct),
SectionMap: make(map[string]*buildCalcSectionStruct),
CoordinateConvertorMap: make(map[string]*coordinateConvertor),
}
// 区段列表
for _, s := range gd.Section {
gm.SectionMap[s.Common.Id] = &buildCalcSectionStruct{
Data: s,
axlePoints: make(map[graphicData.RelatedRef_DevicePort]*graphicData.AxleCounting, 2),
slopes: make(map[string]*graphicData.KilometerSystem),
curvatures: make(map[string]*graphicData.KilometerSystem),
}
2023-08-07 15:05:37 +08:00
}
// 起始点列表
startPoints := list.New()
for _, t := range gd.Turnouts {
2023-09-14 13:58:03 +08:00
// 根据道岔公里标列表,获取道岔公里标并且生成公里标转换对象
op := queryTurnoutKmAndGenerateConvertor(gm, t.KilometerSystem)
2023-08-07 15:05:37 +08:00
if t.PaRef != nil {
startPoints.PushBack(t.PaRef)
}
if t.PbRef != nil {
startPoints.PushBack(t.PbRef)
}
if t.PcRef != nil {
startPoints.PushBack(t.PcRef)
}
2023-08-08 18:09:13 +08:00
gm.TurnoutMap[t.Common.Id] = &buildCalcTurnoutStruct{
Data: t,
CrossKilometerSystem: op,
2023-08-31 16:16:18 +08:00
axlePoints: make(map[graphicData.RelatedRef_DevicePort]*graphicData.AxleCounting, 3),
2023-08-08 18:09:13 +08:00
transponders: make(map[graphicData.RelatedRef_DevicePort][]*graphicData.Transponder),
2023-08-31 16:16:18 +08:00
signals: make(map[graphicData.RelatedRef_DevicePort]*graphicData.Signal, 3),
slopes: make(map[graphicData.RelatedRef_DevicePort]map[string]*graphicData.KilometerSystem),
curvatures: make(map[graphicData.RelatedRef_DevicePort]map[string]*graphicData.KilometerSystem),
2023-08-08 18:09:13 +08:00
}
2023-08-07 15:05:37 +08:00
}
2023-09-14 13:58:03 +08:00
// 处理坐标转换对象
convertorCoordinateByAxleCounting(gm, gd.AxleCountings)
for tid, turnoutInfo := range gm.TurnoutMap {
mainLineKm, v, b := convertorMainLineKM(gm.CoordinateConvertorMap, turnoutInfo.CrossKilometerSystem)
if !v {
slog.Warn("道岔公里标缺失", "turnoutId", tid)
2023-09-14 13:58:03 +08:00
continue
2023-08-08 18:09:13 +08:00
}
2023-09-14 13:58:03 +08:00
if !b {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: fmt.Sprintf("道岔[%s]公里标不能转换正线公里标", tid)})
}
turnoutInfo.CrossKilometerSystem = mainLineKm
2023-08-07 15:05:37 +08:00
}
2023-09-14 13:58:03 +08:00
2023-08-07 15:05:37 +08:00
// 计轴点关联到对应的区段,道岔上
for _, a := range gd.AxleCountings {
2023-09-14 13:58:03 +08:00
mainLineKm, v, b := convertorMainLineKM(gm.CoordinateConvertorMap, a.KilometerSystem)
if !v {
slog.Warn("计轴点公里标缺失", "axleId", a.Common.Id)
2023-09-14 13:58:03 +08:00
continue
}
if !b {
slog.Warn("计轴点[%s]公里标不能转换正线公里标", "axleId", a.Common.Id)
2023-09-14 13:58:03 +08:00
continue
}
a.KilometerSystem = mainLineKm
2023-08-07 15:05:37 +08:00
gm.AxlePointMap[a.Common.Id] = a
for _, r := range a.AxleCountingRef {
if r.DeviceType == graphicData.RelatedRef_Section {
2023-08-08 18:09:13 +08:00
gm.SectionMap[r.Id].axlePoints[r.DevicePort] = a
2023-08-07 15:05:37 +08:00
} else if r.DeviceType == graphicData.RelatedRef_Turnout {
2023-08-08 18:09:13 +08:00
gm.TurnoutMap[r.Id].axlePoints[r.DevicePort] = a
2023-08-07 15:05:37 +08:00
}
}
}
2023-08-08 18:09:13 +08:00
// 信号机关联到对应区段或道岔上
for _, s := range gd.Signals {
2023-09-14 13:58:03 +08:00
mainLineKm, v, b := convertorMainLineKM(gm.CoordinateConvertorMap, s.KilometerSystem)
if !v {
continue
}
if !b {
slog.Warn("信号机公里标不能转换正线公里标", "signalId", s.Common.Id)
continue
}
2023-09-14 13:58:03 +08:00
s.KilometerSystem = mainLineKm
2023-08-08 18:09:13 +08:00
switch s.RefDev.DeviceType {
case graphicData.RelatedRef_Section:
gm.SectionMap[s.RefDev.Id].signals = append(gm.SectionMap[s.RefDev.Id].signals, s)
case graphicData.RelatedRef_Turnout:
gm.TurnoutMap[s.RefDev.Id].signals[s.RefDev.DevicePort] = s
}
}
// 应答器关联到对应区段或道岔
for _, t := range gd.Transponders {
2023-09-14 13:58:03 +08:00
mainLineKm, v, b := convertorMainLineKM(gm.CoordinateConvertorMap, t.KilometerSystem)
if !v {
continue
}
if !b {
slog.Warn("应答器公里标不能转换正线公里标", "id", t.Common.Id)
continue
}
2023-09-14 13:58:03 +08:00
t.KilometerSystem = mainLineKm
2023-08-08 18:09:13 +08:00
switch t.TransponderRef.DeviceType {
case graphicData.RelatedRef_Section:
gm.SectionMap[t.TransponderRef.Id].transponders = append(gm.SectionMap[t.TransponderRef.Id].transponders, t)
case graphicData.RelatedRef_Turnout:
gm.TurnoutMap[t.TransponderRef.Id].transponders[t.TransponderRef.DevicePort] = append(gm.TurnoutMap[t.TransponderRef.Id].transponders[t.TransponderRef.DevicePort], t)
}
}
// 停车标关联到对应区段或道岔
for _, s := range gd.StopPositions {
2023-09-14 13:58:03 +08:00
mainLineKm, v, b := convertorMainLineKM(gm.CoordinateConvertorMap, s.KilometerSystem)
if !v {
continue
}
2023-09-14 13:58:03 +08:00
if !b {
slog.Warn("停车标公里标不能转换正线公里标", "id", s.Common.Id)
2023-09-14 13:58:03 +08:00
continue
}
s.KilometerSystem = mainLineKm
2023-08-08 18:09:13 +08:00
switch s.RefDev.DeviceType {
case graphicData.RelatedRef_Section:
gm.SectionMap[s.RefDev.Id].stopPositions = append(gm.SectionMap[s.RefDev.Id].stopPositions, s)
}
}
// 坡度Map
slopeMap := make(map[graphicData.Direction]map[string]*graphicData.KilometerSystem)
for _, s := range gd.SlopeKiloMarker {
2023-09-14 13:58:03 +08:00
handleSlopeCurvaturesMap(gm.CoordinateConvertorMap, s.Common.Id, s.KilometerSystem, slopeMap)
}
// 曲度Map
curvatureMap := make(map[graphicData.Direction]map[string]*graphicData.KilometerSystem)
for _, c := range gd.CurvatureKiloMarker {
2023-09-14 13:58:03 +08:00
handleSlopeCurvaturesMap(gm.CoordinateConvertorMap, c.Common.Id, c.KilometerSystem, curvatureMap)
}
if len(slopeMap) != 0 || len(curvatureMap) != 0 {
for _, s := range gm.SectionMap {
handleSectionSlopeCurvaturesMap(s, slopeMap, func(sec *buildCalcSectionStruct) map[string]*graphicData.KilometerSystem { return sec.slopes })
handleSectionSlopeCurvaturesMap(s, curvatureMap, func(sec *buildCalcSectionStruct) map[string]*graphicData.KilometerSystem { return sec.curvatures })
}
for _, t := range gm.TurnoutMap {
// A点坡度
handleTurnoutSlopeCurvaturesMap(graphicData.RelatedRef_A, t, slopeMap,
func(sw *buildCalcTurnoutStruct) map[graphicData.RelatedRef_DevicePort]map[string]*graphicData.KilometerSystem {
return sw.slopes
})
// B点坡度
handleTurnoutSlopeCurvaturesMap(graphicData.RelatedRef_B, t, slopeMap,
func(sw *buildCalcTurnoutStruct) map[graphicData.RelatedRef_DevicePort]map[string]*graphicData.KilometerSystem {
return sw.slopes
})
// A点曲度
handleTurnoutSlopeCurvaturesMap(graphicData.RelatedRef_A, t, curvatureMap,
func(sw *buildCalcTurnoutStruct) map[graphicData.RelatedRef_DevicePort]map[string]*graphicData.KilometerSystem {
return sw.curvatures
})
// B点曲度
handleTurnoutSlopeCurvaturesMap(graphicData.RelatedRef_B, t, curvatureMap,
func(sw *buildCalcTurnoutStruct) map[graphicData.RelatedRef_DevicePort]map[string]*graphicData.KilometerSystem {
return sw.curvatures
})
}
}
2023-08-07 15:05:37 +08:00
return gm, startPoints
}
2023-09-14 13:58:03 +08:00
// 根据道岔公里标列表,获取道岔公里标并且生成公里标转换对象
func queryTurnoutKmAndGenerateConvertor(gm *buildCalcStruct, kilometers []*graphicData.KilometerSystem) *graphicData.KilometerSystem {
if len(kilometers) == 0 {
return nil
}
var ks []*graphicData.KilometerSystem
var rk *graphicData.KilometerSystem
for _, k := range kilometers {
if judgeKilometerVaild(k) {
ks = append(ks, k)
if k.CoordinateSystem == mainLineType {
rk = k
}
}
}
l := len(ks)
if rk == nil && l > 0 {
rk = ks[0]
}
if l < 2 {
return rk
}
for i, si := range ks {
for j := i + 1; j < l; j++ {
sj := ks[j]
if si.CoordinateSystem == sj.CoordinateSystem {
continue
}
key := generateConvertorKey(si.CoordinateSystem, sj.CoordinateSystem)
if gm.CoordinateConvertorMap[key] != nil {
continue
}
gm.CoordinateConvertorMap[key] = &coordinateConvertor{
ConfigType: si.CoordinateSystem,
ConfigCoordinate: si.Kilometer,
ConvertorType: sj.CoordinateSystem,
ConvertorCoordinate: sj.Kilometer,
}
}
}
return rk
}
// 根据计轴公里标生成公里标转换对象
func convertorCoordinateByAxleCounting(gm *buildCalcStruct, axleCounts []*graphicData.AxleCounting) {
if len(gm.TurnoutMap) == 0 {
return
}
for _, a := range axleCounts {
if len(a.AxleCountingRef) == 0 {
continue
}
if !judgeKilometerVaild(a.KilometerSystem) {
continue
}
axleKM := a.KilometerSystem
var sameKM, diffKM *graphicData.KilometerSystem
for _, r := range a.AxleCountingRef {
if r.DeviceType != graphicData.RelatedRef_Turnout {
continue
}
t := gm.TurnoutMap[r.Id]
if t == nil {
continue
}
if t.CrossKilometerSystem.CoordinateSystem == axleKM.CoordinateSystem {
sameKM = t.CrossKilometerSystem
} else {
diffKM = t.CrossKilometerSystem
}
}
if sameKM == nil || diffKM == nil {
continue
}
key := generateConvertorKey(sameKM.CoordinateSystem, diffKM.CoordinateSystem)
if gm.CoordinateConvertorMap[key] != nil {
continue
}
// 计轴与相同坐标系岔心之间差值
diffValue := axleKM.Kilometer - sameKM.Kilometer
// 俩岔心到计轴的距离相同,所以另一坐标系的公里标相减差值就是计轴在另一个坐标系的位置
// a - x = y - b (x,y为计轴在两坐标系上的坐标)
convertKilometer := diffKM.Kilometer - diffValue
// 求出坐标系0点位置
gm.CoordinateConvertorMap[key] = &coordinateConvertor{
ConfigType: axleKM.CoordinateSystem,
ConfigCoordinate: axleKM.Kilometer,
ConvertorType: diffKM.CoordinateSystem,
ConvertorCoordinate: convertKilometer,
}
}
}
2023-08-07 17:21:03 +08:00
// 获取link的路径信息
func getGraphicLinkPath(gm *buildCalcStruct, startPointQueue *list.List) map[int][]*graphicData.RelatedRef {
handleMap := make(map[string]bool)
resultMap := make(map[int][]*graphicData.RelatedRef)
id := 1
for i := startPointQueue.Front(); i != nil; i = i.Next() {
relatedRef := i.Value.(*graphicData.RelatedRef)
// 起始连接点,判断选择走向
var refInfo *graphicData.RelatedRef
var axleInfo *graphicData.AxleCounting
if relatedRef.DeviceType == graphicData.RelatedRef_Section {
2023-08-08 18:09:13 +08:00
axleInfo = gm.SectionMap[relatedRef.Id].axlePoints[relatedRef.DevicePort]
refInfo = getRelatePointInfo(reflect.ValueOf(gm.SectionMap[relatedRef.Id]).Elem(), relatedRef.DevicePort)
2023-08-07 17:21:03 +08:00
} else {
2023-08-08 18:09:13 +08:00
axleInfo = gm.TurnoutMap[relatedRef.Id].axlePoints[relatedRef.DevicePort]
refInfo = getRelatePointInfo(reflect.ValueOf(gm.TurnoutMap[relatedRef.Id]).Elem(), relatedRef.DevicePort)
2023-08-07 17:21:03 +08:00
}
// 查看是否已经被处理过的ID计轴信息为空时表示道岔将ID排序后存入
var handleId string
if axleInfo == nil {
ids := []string{relatedRef.Id, refInfo.Id}
sort.Strings(ids)
handleId = strings.Join(ids, "_")
} else {
handleId = axleInfo.Common.Id
}
if handleMap[handleId] {
continue
}
handleMap[handleId] = true
pathRefArr := []*graphicData.RelatedRef{refInfo}
// 循环查找结束点
loopRelateRef := relatedRef
for loopRelateRef != nil {
pathRefArr = append(pathRefArr, loopRelateRef)
2023-08-07 17:21:03 +08:00
switch loopRelateRef.DeviceType {
case graphicData.RelatedRef_Section:
section := gm.SectionMap[loopRelateRef.Id]
2023-08-08 18:09:13 +08:00
axleInfo = section.axlePoints[loopRelateRef.DevicePort]
2023-08-07 17:21:03 +08:00
if loopRelateRef.DevicePort == graphicData.RelatedRef_A {
loopRelateRef = section.Data.PbRef
} else {
loopRelateRef = section.Data.PaRef
}
case graphicData.RelatedRef_Turnout:
2023-08-08 10:40:24 +08:00
turnout := gm.TurnoutMap[loopRelateRef.Id]
2023-08-08 18:09:13 +08:00
axleInfo = turnout.axlePoints[loopRelateRef.DevicePort]
2023-08-07 17:21:03 +08:00
loopRelateRef = nil
}
2023-08-08 10:40:24 +08:00
if axleInfo != nil { // 放入处理的计轴,防止倒过来重复处理
handleMap[axleInfo.Common.Id] = true
}
2023-08-07 17:21:03 +08:00
}
resultMap[id] = pathRefArr
id++ // ID自增
}
return resultMap
}
2023-08-07 15:05:37 +08:00
// 获取本连接点上一个连接信息以及计轴信息
2023-08-08 18:09:13 +08:00
func getRelatePointInfo(v reflect.Value, p graphicData.RelatedRef_DevicePort) *graphicData.RelatedRef {
2023-08-07 15:05:37 +08:00
var relateInfo reflect.Value
// 放入计轴点
switch p {
case graphicData.RelatedRef_A:
relateInfo = v.FieldByName("Data").Elem().FieldByName("PaRef")
case graphicData.RelatedRef_B:
relateInfo = v.FieldByName("Data").Elem().FieldByName("PbRef")
case graphicData.RelatedRef_C:
relateInfo = v.FieldByName("Data").Elem().FieldByName("PcRef")
}
2023-08-08 18:09:13 +08:00
return relateInfo.Interface().(*graphicData.RelatedRef)
2023-08-07 15:05:37 +08:00
}
2023-08-08 10:40:24 +08:00
// 获取起始端的
func getStartKilometer(gm *buildCalcStruct, ref *graphicData.RelatedRef) (int64, int32) {
switch ref.DeviceType {
case graphicData.RelatedRef_Section:
section := gm.SectionMap[ref.Id]
2023-08-08 18:09:13 +08:00
var resultKilometer = int64(math.MaxInt64)
for _, p := range section.axlePoints {
if resultKilometer > p.KilometerSystem.Kilometer {
resultKilometer = p.KilometerSystem.Kilometer
}
2023-08-08 10:40:24 +08:00
}
2023-08-08 18:09:13 +08:00
if resultKilometer == math.MaxInt64 {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: "区段公里标数据出错"})
2023-08-08 10:40:24 +08:00
}
2023-08-08 18:09:13 +08:00
return resultKilometer, 0
2023-08-08 10:40:24 +08:00
case graphicData.RelatedRef_Turnout:
turnout := gm.TurnoutMap[ref.Id]
2023-09-14 13:58:03 +08:00
if !judgeKilometerVaild(turnout.CrossKilometerSystem) {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: "道岔岔心无正线公里标"})
2023-08-08 10:40:24 +08:00
}
return turnout.CrossKilometerSystem.Kilometer, 0
}
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: "错误的设备类型类型"})
}
2023-09-14 13:58:03 +08:00
// 转换正线公里标
func convertorMainLineKM(convertorMap map[string]*coordinateConvertor, k *graphicData.KilometerSystem) (*graphicData.KilometerSystem, bool, bool) {
if !judgeKilometerVaild(k) {
return k, false, false
}
if k.CoordinateSystem == mainLineType {
return k, true, true
}
key := generateConvertorKey(mainLineType, k.CoordinateSystem)
convertor := convertorMap[key]
if convertor == nil {
return nil, true, false
}
kilometer := convertor.ConvertorKilometer(k, mainLineType)
return &graphicData.KilometerSystem{
Kilometer: kilometer,
CoordinateSystem: mainLineType,
Direction: k.Direction,
}, true, true
}
func judgeKilometerVaild(k *graphicData.KilometerSystem) bool {
return k != nil && k.CoordinateSystem != "" && k.Kilometer != 0
}
// 判断公里标k1 是否在这k2,k3个范围内
func judgeKilometerInRange(k1, k2, k3 *graphicData.KilometerSystem) bool {
2023-09-14 13:58:03 +08:00
if judgeKilometerVaild(k1) && judgeKilometerVaild(k2) && judgeKilometerVaild(k3) {
start, end := k2, k3
if k2.Kilometer > k3.Kilometer {
start, end = k3, k2
}
return k1.Kilometer > start.Kilometer && k1.Kilometer < end.Kilometer
}
return false
}
// 处理道岔坡度、曲度信息
2023-09-14 13:58:03 +08:00
func handleSlopeCurvaturesMap(convertorMap map[string]*coordinateConvertor,
id string, kms []*graphicData.KilometerSystem, m map[graphicData.Direction]map[string]*graphicData.KilometerSystem) {
for _, k := range kms {
2023-09-14 13:58:03 +08:00
mainLineKm, v, b := convertorMainLineKM(convertorMap, k)
if !v {
continue
}
if !b {
slog.Warn("坡度、曲度公里标不能转换正线公里标", "id", id)
2023-08-31 16:16:18 +08:00
continue
}
kmMap := m[k.Direction]
if kmMap == nil {
kmMap = make(map[string]*graphicData.KilometerSystem)
m[k.Direction] = kmMap
}
2023-09-14 13:58:03 +08:00
kmMap[id] = mainLineKm
}
}
func handleTurnoutSlopeCurvaturesMap(port graphicData.RelatedRef_DevicePort,
t *buildCalcTurnoutStruct,
scmap map[graphicData.Direction]map[string]*graphicData.KilometerSystem,
f func(*buildCalcTurnoutStruct) map[graphicData.RelatedRef_DevicePort]map[string]*graphicData.KilometerSystem) {
point := t.axlePoints[port]
2023-08-31 16:16:18 +08:00
if point == nil {
return
}
m := f(t)
m[port] = make(map[string]*graphicData.KilometerSystem)
kmMap := scmap[point.KilometerSystem.Direction]
var idArr []string
for k, v := range kmMap {
if judgeKilometerInRange(v, point.KilometerSystem, t.CrossKilometerSystem) {
m[port][k] = v
idArr = append(idArr, k)
}
}
2023-08-31 16:16:18 +08:00
for _, id := range idArr {
delete(kmMap, id)
}
}
func handleSectionSlopeCurvaturesMap(s *buildCalcSectionStruct,
scmap map[graphicData.Direction]map[string]*graphicData.KilometerSystem,
f func(*buildCalcSectionStruct) map[string]*graphicData.KilometerSystem) {
pointA := s.axlePoints[graphicData.RelatedRef_A]
pointB := s.axlePoints[graphicData.RelatedRef_B]
if pointA == nil || pointB == nil {
return
}
m := f(s)
kmMap := scmap[pointA.KilometerSystem.Direction]
2023-08-31 16:16:18 +08:00
var idArr []string
for k, v := range kmMap {
if judgeKilometerInRange(v, pointA.KilometerSystem, pointB.KilometerSystem) {
m[k] = v
idArr = append(idArr, k)
}
}
for _, id := range idArr {
delete(kmMap, id)
}
}