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) } }