rts-sim-testing-service/ts/simulation/wayside/memory/wayside_memory_generate.go
2023-10-26 17:16:07 +08:00

786 lines
28 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package memory
import (
"container/list"
"fmt"
"log/slog"
"math"
"reflect"
"sort"
"strings"
"joylink.club/bj-rtsts-server/dto"
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
)
// 参与计算的坡度与曲度均为正线公里标,如果有其他坐标系需要转换
var mainLineType = "MAIN_LINE"
// 参与计算结构体信息
type buildCalcStruct struct {
AxlePointMap map[string]*graphicData.AxleCounting
TurnoutMap map[string]*buildCalcTurnoutStruct
SectionMap map[string]*buildCalcSectionStruct
CoordinateConvertorMap map[string]*coordinateConvertor
}
// 参与计算link时的区段结构体
type buildCalcSectionStruct struct {
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 // 曲度公里标
}
// 参与计算的
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 // 曲度公里标
}
// 坐标转换结构体
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
}
}
// 根据地图信息生成calcLink数据
func BuildCalculateLinkData(gd *graphicData.RtssGraphicStorage) []*graphicData.CalculateLink {
gm, startPointQueue := getGraphicDataDeviceMap(gd)
// 这里linkPath是排过序的公里标大小
linkPathMap := getGraphicLinkPath(gm, startPointQueue)
// 根据路径开始包装结果数据
var resultArr []*graphicData.CalculateLink
for id, pathArr := range linkPathMap {
item := &graphicData.CalculateLink{
Common: &graphicData.CommonInfo{},
Index: int32(id),
Points: []*graphicData.Point{},
Length: 0,
DevicePositions: []*graphicData.CalculateLink_DevicePosition{},
}
allTurnout := true
prevKm, offset := getStartKilometer(gm, pathArr[0])
devicePosistionMap := make(map[string]*graphicData.CalculateLink_DevicePosition)
for index, refVal := range pathArr {
if refVal.DeviceType == graphicData.RelatedRef_Section {
allTurnout = false
section := gm.SectionMap[refVal.Id]
// 计算长度
item.Length = item.Length + calcGraphicLenBySection(section)
// 放入设备偏移
offset, prevKm = getGraphicSectionRefDevices(refVal, devicePosistionMap, section, offset, prevKm)
} else {
allTurnout = allTurnout && true
turnout := gm.TurnoutMap[refVal.Id]
// 计算长度
item.Length = item.Length + calcGraphicLenByTurnout(turnout, refVal.DevicePort)
// 放入设备偏移
offset, prevKm = getGraphicTurnoutRefDevices(refVal, devicePosistionMap, turnout, offset, prevKm)
// 道岔时左右端直接赋值
if index == 0 {
item.ARelatedRef = refVal
} else {
item.BRelatedRef = refVal
}
}
}
for _, v := range devicePosistionMap {
item.DevicePositions = append(item.DevicePositions, v)
}
sort.SliceStable(item.DevicePositions, func(i, j int) bool {
return item.DevicePositions[i].Offset < item.DevicePositions[j].Offset
})
// 如果全部为道岔,则长度使用岔心减岔心
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)))
}
resultArr = append(resultArr, item)
}
return resultArr
}
// 计算区段长度
func calcGraphicLenBySection(section *buildCalcSectionStruct) int32 {
if len(section.axlePoints) != 2 {
slog.Warn("区段端点位置缺失", "id", section.Data.Common.Id)
return 0
}
var length int64 // 两端公里标相减即可
for _, a := range section.axlePoints {
if !judgeKilometerVaild(a.KilometerSystem) {
return 0
}
length = a.KilometerSystem.Kilometer - length
}
return int32(math.Abs(float64(length)))
}
// 计算道岔端长度
func calcGraphicLenByTurnout(turnout *buildCalcTurnoutStruct, p graphicData.RelatedRef_DevicePort) int32 {
endPoint := turnout.axlePoints[p]
if endPoint == nil || !judgeKilometerVaild(endPoint.KilometerSystem) {
slog.Warn("道岔对应端口【%s】数据无计轴", "turnoutId", turnout.Data.Common.Id, "port", p.String())
return 0
}
if !judgeKilometerVaild(turnout.CrossKilometerSystem) {
slog.Warn("道岔数据错误,岔心公里标为空", "turnoutId", turnout.Data.Common.Id)
return 0
}
start := turnout.CrossKilometerSystem.Kilometer
end := endPoint.KilometerSystem.Kilometer
return int32(math.Abs(float64(end - start)))
}
// 获取关于区段的设备信息
func getGraphicSectionRefDevices(refVal *graphicData.RelatedRef, deviceMap map[string]*graphicData.CalculateLink_DevicePosition,
section *buildCalcSectionStruct, offset int32, prevKm int64) (int32, int64) {
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 {
resultOff := o + int32(math.Abs(float64(p.KilometerSystem.Kilometer-pk)))
resultPK := p.KilometerSystem.Kilometer
d[p.Common.Id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: p.Common.Id,
Offset: resultOff,
DeviceType: graphicData.RelatedRef_AxleCounting.String(),
}
return resultOff, resultPK
}
return o, pk
}
// 查看连接点
point := section.axlePoints[refVal.DevicePort]
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]
offsetCalc, prevKmCalc = dealFunc(point, deviceMap, offsetCalc, prevKmCalc)
// 处理区段上的设备
startPoint := section.axlePoints[refVal.DevicePort]
if startPoint != nil {
sppk := startPoint.KilometerSystem.Kilometer // 相对起点的公里标
spof := deviceMap[startPoint.Common.Id].Offset // 相对的起点offset
// 信号机信息
for _, s := range section.signals {
if judgeKilometerVaild(s.KilometerSystem) && deviceMap[s.Common.Id] == nil {
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 {
if judgeKilometerVaild(s.KilometerSystem) && deviceMap[s.Common.Id] == nil {
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 {
if judgeKilometerVaild(t.KilometerSystem) && deviceMap[t.Common.Id] == nil {
deviceMap[t.Common.Id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: t.Common.Id,
Offset: spof + int32(math.Abs(float64(t.KilometerSystem.Kilometer-sppk))),
DeviceType: "Transponder",
}
}
}
// 坡度
for id, s := range section.slopes {
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 {
if judgeKilometerVaild(c) && deviceMap[id] == nil {
deviceMap[id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: id,
Offset: spof + int32(math.Abs(float64(c.Kilometer-sppk))),
DeviceType: "curvatures",
}
}
}
}
return offsetCalc, prevKmCalc
}
// 获取关于道岔的设备信息
func getGraphicTurnoutRefDevices(refVal *graphicData.RelatedRef, deviceMap map[string]*graphicData.CalculateLink_DevicePosition, turnout *buildCalcTurnoutStruct, offset int32, prevKm int64) (int32, int64) {
// 目前只放入岔心位置
if turnout.CrossKilometerSystem != nil && deviceMap[turnout.Data.Common.Id] == nil {
offsetCalc := offset + int32(math.Abs(float64(turnout.CrossKilometerSystem.Kilometer-prevKm)))
prevKmCalc := turnout.CrossKilometerSystem.Kilometer
deviceMap[turnout.Data.Common.Id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: turnout.Data.Common.Id,
Offset: offsetCalc,
DeviceType: graphicData.RelatedRef_Turnout.String(),
}
// 查看是否存在连接计轴
point := turnout.axlePoints[refVal.DevicePort]
if point != nil && judgeKilometerVaild(point.KilometerSystem) && deviceMap[point.Common.Id] == nil {
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]
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",
}
}
// 处理道岔上的应答器
transponders := turnout.transponders[refVal.DevicePort]
for _, t := range transponders {
if judgeKilometerVaild(t.KilometerSystem) && deviceMap[t.Common.Id] == nil {
deviceMap[t.Common.Id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: t.Common.Id,
Offset: offset + int32(math.Abs(float64(t.KilometerSystem.Kilometer-prevKm))),
DeviceType: "Transponder",
}
}
}
// 坡度
sm := turnout.slopes[refVal.DevicePort]
for id, s := range sm {
if judgeKilometerVaild(s) && deviceMap[id] == nil {
deviceMap[id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: id,
Offset: offset + int32(math.Abs(float64(s.Kilometer-prevKm))),
DeviceType: "slopes",
}
}
}
// 曲度
cm := turnout.curvatures[refVal.DevicePort]
for id, c := range cm {
if judgeKilometerVaild(c) && deviceMap[id] == nil {
deviceMap[id] = &graphicData.CalculateLink_DevicePosition{
DeviceId: id,
Offset: offset + int32(math.Abs(float64(c.Kilometer-prevKm))),
DeviceType: "curvatures",
}
}
}
return offsetCalc, prevKmCalc
}
return offset, prevKm
}
// 获取link的起始点和包装数据结构方便查找以道岔的各分支的连接点为起点
func getGraphicDataDeviceMap(gd *graphicData.RtssGraphicStorage) (*buildCalcStruct, *list.List) {
gm := &buildCalcStruct{
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),
}
}
// 起始点列表
startPoints := list.New()
for _, t := range gd.Turnouts {
// 根据道岔公里标列表,获取道岔公里标并且生成公里标转换对象
op := queryTurnoutKmAndGenerateConvertor(gm, t.KilometerSystem)
if t.PaRef != nil {
startPoints.PushBack(t.PaRef)
}
if t.PbRef != nil {
startPoints.PushBack(t.PbRef)
}
if t.PcRef != nil {
startPoints.PushBack(t.PcRef)
}
gm.TurnoutMap[t.Common.Id] = &buildCalcTurnoutStruct{
Data: t,
CrossKilometerSystem: op,
axlePoints: make(map[graphicData.RelatedRef_DevicePort]*graphicData.AxleCounting, 3),
transponders: make(map[graphicData.RelatedRef_DevicePort][]*graphicData.Transponder),
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),
}
}
// 处理坐标转换对象
convertorCoordinateByAxleCounting(gm, gd.AxleCountings)
for tid, turnoutInfo := range gm.TurnoutMap {
mainLineKm, v, b := convertorMainLineKM(gm.CoordinateConvertorMap, turnoutInfo.CrossKilometerSystem)
if !v {
slog.Warn("道岔公里标缺失", "turnoutId", tid)
continue
}
if !b {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: fmt.Sprintf("道岔[%s]公里标不能转换正线公里标", tid)})
}
turnoutInfo.CrossKilometerSystem = mainLineKm
}
// 计轴点关联到对应的区段,道岔上
for _, a := range gd.AxleCountings {
mainLineKm, v, b := convertorMainLineKM(gm.CoordinateConvertorMap, a.KilometerSystem)
if !v {
slog.Warn("计轴点公里标缺失", "axleId", a.Common.Id)
continue
}
if !b {
slog.Warn("计轴点[%s]公里标不能转换正线公里标", "axleId", a.Common.Id)
continue
}
a.KilometerSystem = mainLineKm
gm.AxlePointMap[a.Common.Id] = a
for _, r := range a.AxleCountingRef {
if r.DeviceType == graphicData.RelatedRef_Section {
gm.SectionMap[r.Id].axlePoints[r.DevicePort] = a
} else if r.DeviceType == graphicData.RelatedRef_Turnout {
gm.TurnoutMap[r.Id].axlePoints[r.DevicePort] = a
}
}
}
// 信号机关联到对应区段或道岔上
for _, s := range gd.Signals {
mainLineKm, v, b := convertorMainLineKM(gm.CoordinateConvertorMap, s.KilometerSystem)
if !v {
continue
}
if !b {
slog.Warn("信号机公里标不能转换正线公里标", "signalId", s.Common.Id)
continue
}
s.KilometerSystem = mainLineKm
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 {
mainLineKm, v, b := convertorMainLineKM(gm.CoordinateConvertorMap, t.KilometerSystem)
if !v {
continue
}
if !b {
slog.Warn("应答器公里标不能转换正线公里标", "id", t.Common.Id)
continue
}
t.KilometerSystem = mainLineKm
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 {
mainLineKm, v, b := convertorMainLineKM(gm.CoordinateConvertorMap, s.KilometerSystem)
if !v {
continue
}
if !b {
slog.Warn("停车标公里标不能转换正线公里标", "id", s.Common.Id)
continue
}
s.KilometerSystem = mainLineKm
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 {
handleSlopeCurvaturesMap(gm.CoordinateConvertorMap, s.Common.Id, s.KilometerSystem, slopeMap)
}
// 曲度Map
curvatureMap := make(map[graphicData.Direction]map[string]*graphicData.KilometerSystem)
for _, c := range gd.CurvatureKiloMarker {
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
})
}
}
return gm, startPoints
}
// 根据道岔公里标列表,获取道岔公里标并且生成公里标转换对象
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,
}
}
}
// 获取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 {
axleInfo = gm.SectionMap[relatedRef.Id].axlePoints[relatedRef.DevicePort]
refInfo = getRelatePointInfo(reflect.ValueOf(gm.SectionMap[relatedRef.Id]).Elem(), relatedRef.DevicePort)
} else {
axleInfo = gm.TurnoutMap[relatedRef.Id].axlePoints[relatedRef.DevicePort]
refInfo = getRelatePointInfo(reflect.ValueOf(gm.TurnoutMap[relatedRef.Id]).Elem(), relatedRef.DevicePort)
}
// 查看是否已经被处理过的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)
switch loopRelateRef.DeviceType {
case graphicData.RelatedRef_Section:
section := gm.SectionMap[loopRelateRef.Id]
axleInfo = section.axlePoints[loopRelateRef.DevicePort]
if loopRelateRef.DevicePort == graphicData.RelatedRef_A {
loopRelateRef = section.Data.PbRef
} else {
loopRelateRef = section.Data.PaRef
}
case graphicData.RelatedRef_Turnout:
turnout := gm.TurnoutMap[loopRelateRef.Id]
axleInfo = turnout.axlePoints[loopRelateRef.DevicePort]
loopRelateRef = nil
}
if axleInfo != nil { // 放入处理的计轴,防止倒过来重复处理
handleMap[axleInfo.Common.Id] = true
}
}
resultMap[id] = pathRefArr
id++ // ID自增
}
return resultMap
}
// 获取本连接点上一个连接信息以及计轴信息
func getRelatePointInfo(v reflect.Value, p graphicData.RelatedRef_DevicePort) *graphicData.RelatedRef {
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")
}
return relateInfo.Interface().(*graphicData.RelatedRef)
}
// 获取起始端的
func getStartKilometer(gm *buildCalcStruct, ref *graphicData.RelatedRef) (int64, int32) {
switch ref.DeviceType {
case graphicData.RelatedRef_Section:
section := gm.SectionMap[ref.Id]
var resultKilometer = int64(math.MaxInt64)
for _, p := range section.axlePoints {
if resultKilometer > p.KilometerSystem.Kilometer {
resultKilometer = p.KilometerSystem.Kilometer
}
}
if resultKilometer == math.MaxInt64 {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: "区段公里标数据出错"})
}
return resultKilometer, 0
case graphicData.RelatedRef_Turnout:
turnout := gm.TurnoutMap[ref.Id]
if !judgeKilometerVaild(turnout.CrossKilometerSystem) {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: "道岔岔心无正线公里标"})
}
return turnout.CrossKilometerSystem.Kilometer, 0
}
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: "错误的设备类型类型"})
}
// 转换正线公里标
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 {
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
}
// 处理道岔坡度、曲度信息
func handleSlopeCurvaturesMap(convertorMap map[string]*coordinateConvertor,
id string, kms []*graphicData.KilometerSystem, m map[graphicData.Direction]map[string]*graphicData.KilometerSystem) {
for _, k := range kms {
mainLineKm, v, b := convertorMainLineKM(convertorMap, k)
if !v {
continue
}
if !b {
slog.Warn("坡度、曲度公里标不能转换正线公里标", "id", id)
continue
}
kmMap := m[k.Direction]
if kmMap == nil {
kmMap = make(map[string]*graphicData.KilometerSystem)
m[k.Direction] = kmMap
}
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]
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)
}
}
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]
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)
}
}