786 lines
28 KiB
Go
786 lines
28 KiB
Go
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)
|
||
}
|
||
}
|