@ -2,12 +2,12 @@ package memory
import (
"fmt"
"math"
"sort"
"strconv"
"strings"
"sync"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/repository"
proto2 "joylink.club/rtsssimulation/repository/model/proto"
@ -17,7 +17,6 @@ import (
"joylink.club/bj-rtsts-server/dto"
"joylink.club/bj-rtsts-server/sys_error"
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/protos/state"
)
var (
@ -96,18 +95,6 @@ func QueryGiId(name string) int32 {
return value . ( int32 )
}
// 根据区段, 道岔偏移量返回linkID和link相对偏移量
func QueryEcsLinkByDeviceInfo ( repo * repository . Repository , mapId int32 , status * state . TrainState ) ( int32 , int64 , bool , bool , int64 ) {
id := status . HeadDeviceId
if status . DevicePort == "" {
uid := QueryUidByMidAndComId ( mapId , id , & graphicData . Section { } )
return sectionMapToEcsLink ( repo , uid , status )
} else {
uid := QueryUidByMidAndComId ( mapId , id , & graphicData . Turnout { } )
return turnoutMapToEcsLink ( repo , uid , status )
}
}
func GetStorageIBPMapData ( mapCode string ) * graphicData . IBPGraphicStorage {
// 处理关联的IBP盘信息
if mapCode == "" {
@ -124,116 +111,39 @@ func GetStorageIBPMapData(mapCode string) *graphicData.IBPGraphicStorage {
return ibpMapData . ( * graphicData . IBPGraphicStorage )
}
// 根据物理区段上的偏移量( 基于区段A端) , 找到所在link的linkId与偏移量
func sectionMapToEcsLink ( repo * repository . Repository , id string , status * state . TrainState ) ( int32 , int64 , bool , bool , int64 ) {
runDirection := status . RunDirection
section := repo . FindPhysicalSection ( id )
if section == nil {
panic ( sys_error . New ( fmt . Sprintf ( "地图不存在uid:%s缓存" , id ) ) )
}
ao , bo := section . ALinkPosition ( ) . Offset ( ) , section . BLinkPosition ( ) . Offset ( )
// 检查区段长度是否足够放下列车
status . HeadOffset = checkDeviceContainTrain ( status . HeadOffset , status . TrainLength , bo - ao , id )
link := section . ALinkPosition ( ) . Link ( )
// 是否从A到B, 统一坐标
ak , bk := convertRepoBaseKm ( repo , section . AKilometer ( ) ) , convertRepoBaseKm ( repo , section . BKilometer ( ) )
akv , bkv := ak . Value , bk . Value
// 上行
var up , abDirection bool
if runDirection {
abDirection = akv < bkv
if abDirection {
up = ao < bo
} else {
up = ao > bo
}
} else {
abDirection = akv > bkv
if abDirection {
up = ao < bo
} else {
up = ao > bo
}
}
linkId , _ := strconv . Atoi ( link . Identity . Id ( ) )
trainKilometer := concertTrainKilometer ( akv , status . HeadOffset , up )
if ao < bo {
return int32 ( linkId ) , ao + status . HeadOffset , up , abDirection , trainKilometer
} else {
return int32 ( linkId ) , ao - status . HeadOffset , up , abDirection , trainKilometer
}
}
// 根据道岔上的偏移量( 基于岔心位置) , 找到所在link的linkId与偏移量
func turnoutMapToEcsLink ( repo * repository . Repository , id string , status * state . TrainState ) ( int32 , int64 , bool , bool , int64 ) {
port , runDirection := status . DevicePort , status . RunDirection
turnout := repo . FindTurnout ( id )
if turnout == nil {
panic ( sys_error . New ( fmt . Sprintf ( "不存在道岔【uid:%s】" , id ) ) )
}
var portPosition * repository . LinkPosition
var crossKm , portKm * proto2 . Kilometer
switch port {
case "A" :
portPosition = turnout . FindLinkPositionByPort ( proto2 . Port_A )
portKm = turnout . GetTurnoutKm ( proto2 . Port_A )
case "B" :
portPosition = turnout . FindLinkPositionByPort ( proto2 . Port_B )
portKm = turnout . GetTurnoutKm ( proto2 . Port_B )
case "C" :
portPosition = turnout . FindLinkPositionByPort ( proto2 . Port_C )
portKm = turnout . GetTurnoutKm ( proto2 . Port_C )
default :
panic ( sys_error . New ( fmt . Sprintf ( "无效端口【%s】偏移量" , port ) ) )
}
// 岔心公里标
crossKm = turnout . GetTurnoutKm ( proto2 . Port_None )
portKm , err := repo . ConvertKilometer ( portKm , crossKm . CoordinateSystem )
// 转换成统一坐标公里标
func convertRepoBaseKm ( r * repository . Repository , km * proto2 . Kilometer ) * proto2 . Kilometer {
k , err := r . ConvertKilometer ( km , r . GetCoordinateInfo ( ) . Coordinate )
if err != nil {
panic ( sys_error . New ( "公里标转换出错" , err ) )
}
// 检查link偏移
status . HeadOffset = checkDeviceContainTrain ( status . HeadOffset , status . TrainLength , crossKm . Value - portKm . Value , id )
// 关联link
link := portPosition . Link ( )
isStart := link . ARelation ( ) . Device ( ) . Id ( ) == id
up := runDirection
if ( portKm . Value > crossKm . Value ) != isStart {
up = ! runDirection
}
pointTo := ( portKm . Value > crossKm . Value ) == runDirection
trainKilometer := concertTrainKilometer ( crossKm . Value , status . HeadOffset , pointTo )
linkId , _ := strconv . Atoi ( link . Identity . Id ( ) )
if isStart {
return int32 ( linkId ) , status . HeadOffset , up , pointTo , trainKilometer
} else {
// 道岔长度
turnoutLen := int64 ( math . Abs ( float64 ( portKm . Value - crossKm . Value ) ) )
return int32 ( linkId ) , portPosition . Offset ( ) + turnoutLen - status . HeadOffset , up , pointTo , trainKilometer
panic ( sys_error . New ( fmt . Sprintf ( "公里标转换【%s->%s】错误" , km . CoordinateSystem , r . GetCoordinateInfo ( ) . Coordinate ) ) )
}
return k
}
// 根据linkID和link相对偏移量返回区段, 道岔偏移量
// 设备ID、端口、偏移量、上下行、AB走向
func QueryDeviceByCalcLink ( repo * repository . Repository , id string , offset int64 , up bool ) (
deviceId , port string , deviceOffset int64 , runDirection , pointTo bool , km int64 ) {
link := repo . FindLink ( id )
// 根据传入link、偏移、link运行方向, 查找所在设备信息
// 入参: 仿真、linkId、link偏移量、link运行方向
// 输出: linkId、设备Id、设备端口、link偏移量、设备上偏移量、偏移量对应的公里标
func CalcInitializeLink ( sim * VerifySimulation , linkId string , offset int64 , up bool ) (
outLinkId , deviceId , port string , outLinkOffset , deviceOffset int64 , km * proto2 . Kilometer ) {
link := sim . Repo . FindLink ( linkId )
if link == nil {
panic ( dto . ErrorDto { Code : dto . DataNotExist , Message : fmt . Sprintf ( "未找到link【%s】" , id ) } )
}
if offset > link . Length ( ) {
panic ( dto . ErrorDto { Code : dto . DataNotExist , Message : fmt . Sprintf ( "偏移【%d】超出link范围【%d】" , offset , link . Length ( ) ) } )
panic ( sys_error . New ( fmt . Sprintf ( "未找到link【%s】" , linkId ) ) )
}
// 获取计算link与所在偏移
outLinkId , outLinkOffset = findCalcLinkIdAndOffset ( sim , link , offset )
calcLink := sim . Repo . FindLink ( outLinkId )
// 判断是否在道岔上
onTurnout , isA := isOnLinkTurnout ( link , offset )
onTurnout , isA := isOnLinkTurnout ( calcLink , outLinkOffset )
if onTurnout {
return ecsLinkMapToTurnout ( repo , isA , offset , up , link )
deviceId , port , deviceOffset , km = calcTurnoutOffset ( sim . Repo , calcLink , isA , outLinkOffset , up )
} else {
return ecsLinkMapToSection ( repo , offset , up , link )
deviceId , port , deviceOffset , km = calcSectionOffset ( sim . Repo , calcLink , outLinkOffset , up )
}
// 输出当前所在设备、端口、设备偏移
return
}
// 是否在link的道岔上
// 列车是否在link的道岔上
func isOnLinkTurnout ( link * repository . Link , offset int64 ) ( bool , bool ) {
aTp := link . ARelation ( )
var turnoutOffset int64
@ -251,57 +161,123 @@ func isOnLinkTurnout(link *repository.Link, offset int64) (bool, bool) {
return false , false
}
// 处理在道岔上link映射
func ecsLinkMapToTurnout ( repo * repository . Repository , isA bool , offset int64 , up bool , link * repository . Link ) (
deviceId , port string , deviceOffset int64 , runDirection , pointTo bool , km int64 ) {
// 查找最终的linkId与link偏移
// 入参: 仿真、link、link偏移量
// 输出: linkId、link偏移量
func findCalcLinkIdAndOffset ( sim * VerifySimulation , link * repository . Link , offset int64 ) ( string , int64 ) {
if 0 <= offset && offset <= link . Length ( ) {
return link . Id ( ) , offset
}
// 超出端、超出长度
tp , length := link . ARelation ( ) , 0 - offset
if offset > 0 {
tp , length = link . BRelation ( ) , offset - link . Length ( )
}
if tp == nil {
panic ( sys_error . New ( "列车偏移超出link位置" ) )
}
nextPort := getTurnoutNextPort ( sim , tp )
if nextPort == proto2 . Port_None {
panic ( sys_error . New ( "列车偏移超出link位置" ) )
}
var nextLink * repository . Link
var isB bool
// 寻找匹配到的link
for _ , l := range sim . Repo . LinkList ( ) {
if l . ARelation ( ) != nil && l . ARelation ( ) . Port ( ) == nextPort && l . ARelation ( ) . Device ( ) . Id ( ) == tp . Device ( ) . Id ( ) {
nextLink = l
break
}
if l . BRelation ( ) != nil && l . BRelation ( ) . Port ( ) == nextPort && l . BRelation ( ) . Device ( ) . Id ( ) == tp . Device ( ) . Id ( ) {
nextLink = l
isB = true
break
}
}
// 没有找到连接信息,说明已经到尽头找不到位置
if nextLink == nil {
panic ( sys_error . New ( fmt . Sprintf ( "未找到对应的link信息, linkId=%s, offset=%d" , link . Id ( ) , offset ) ) )
}
// 下个link偏移
nextOffset := length
if isB {
nextOffset = nextLink . Length ( ) - length
}
return findCalcLinkIdAndOffset ( sim , nextLink , nextOffset )
}
// 根据当前link端, 寻找下一个link连接端端口
// 入参:仿真、道岔端口
// 输出:道岔端口
func getTurnoutNextPort ( sim * VerifySimulation , tp * repository . TurnoutPort ) proto2 . Port {
entry , ok := entity . GetEntityByUid ( sim . World , tp . Device ( ) . Id ( ) )
if ! ok {
panic ( sys_error . New ( fmt . Sprintf ( "道岔不存在: World id=%d,道岔id=%s" , sim . World . Id ( ) , tp . Device ( ) . Id ( ) ) ) )
}
if ! entry . HasComponent ( component . TurnoutPositionType ) {
panic ( sys_error . New ( fmt . Sprintf ( "道岔没有TurnoutPosition组件: World id=%d,道岔id=%s" , sim . World . Id ( ) , tp . Device ( ) . Id ( ) ) ) )
}
// 获取定反数据
pos := component . TurnoutPositionType . Get ( entry )
switch tp . Port ( ) {
case proto2 . Port_A :
if pos . Dw {
return proto2 . Port_B
} else {
return proto2 . Port_C
}
case proto2 . Port_B :
if pos . Dw {
return proto2 . Port_A
} else {
return proto2 . Port_None
}
case proto2 . Port_C :
if pos . Dw {
return proto2 . Port_None
} else {
return proto2 . Port_A
}
}
panic ( sys_error . New ( fmt . Sprintf ( "非法端口:端口=%s" , tp . Port ( ) . String ( ) ) ) )
}
// 计算link offset 在道岔上的位置
// 入参: 仿真Repository、link、是否从A端开始、link偏移量、link运行方向
// 输出: 设备Id、设备所在端口、设备偏移量、公里标信息( 地图主坐标系)
func calcTurnoutOffset ( repo * repository . Repository , link * repository . Link , isA bool , offset int64 , up bool ) (
deviceId , port string , deviceOffset int64 , km * proto2 . Kilometer ) {
tp := link . ARelation ( )
if ! isA {
tp = link . BRelation ( )
}
// 设备ID
deviceId = tp . Turnout ( ) . Id ( )
tpOffset := tp . Turnout ( ) . FindLinkPositionByPort ( tp . Port ( ) ) . Offset ( )
crossKmInfo , portKmInfo := tp . Turnout ( ) . GetTurnoutKm ( proto2 . Port_None ) , tp . Turnout ( ) . GetTurnoutKm ( tp . Port ( ) )
portKmInfo , err := repo . ConvertKilometer ( portKmInfo , crossKmInfo . CoordinateSystem )
if err != nil {
panic ( err )
}
crossKm , portKm := crossKmInfo . Value , portKmInfo . Value
// 端口信息
port = tp . Port ( ) . String ( )
// 设备上的偏移量
if isA {
deviceOffset = tpOffset - ( tpOffset - offset )
pointTo = ! up
deviceOffset = offset
} else {
deviceOffset = link . Length ( ) - offset
pointTo = up
}
// 查询公里标大于端口公里标
if crossKm > portKm {
km = crossKm - deviceOffset
// 公里标计算
crossKmInfo := convertRepoBaseKm ( repo , tp . Turnout ( ) . GetTurnoutKm ( proto2 . Port_None ) )
portKmInfo := convertRepoBaseKm ( repo , tp . Turnout ( ) . GetTurnoutKm ( tp . Port ( ) ) )
km = & proto2 . Kilometer { CoordinateSystem : crossKmInfo . CoordinateSystem }
if crossKmInfo . Value > portKmInfo . Value {
km . Value = crossKmInfo . Value - deviceOffset
} else {
km = crossKm + deviceOffset
}
if up && isA { // link offset 趋大, A端岔心 ---> 边界
runDirection = crossKm < portKm
} else if up && ! isA { // link offset 趋大, B端边界 ---> 岔心
runDirection = crossKm > portKm
} else if ! up && isA { // link offset 趋小, A端边界 ---> 岔心
runDirection = crossKm > portKm
} else { // link offset 趋小, B端岔心 ---> 边界
runDirection = crossKm < portKm
}
switch tp . Port ( ) {
case proto2 . Port_A :
port = "A"
case proto2 . Port_B :
port = "B"
case proto2 . Port_C :
port = "C"
km . Value = crossKmInfo . Value + deviceOffset
}
return
}
// 处理在道岔上link映射
func ecsLinkMapToSection ( repo * repository . Repository , offset int64 , up bool , link * repository . Link ) (
deviceId , port string , deviceOffset int64 , runDirection , pointTo bool , km int64 ) {
// 计算link offset 在区段上的位置
// 入参: 仿真Repository、link、link偏移量、link运行方向
// 输出: 设备Id、设备所在端口、设备偏移量、公里标信息( 地图主坐标系)
func calcSectionOffset ( repo * repository . Repository , link * repository . Link , offset int64 , up bool ) (
deviceId , port string , deviceOffset int64 , km * proto2 . Kilometer ) {
var section * repository . PhysicalSection
for _ , s := range link . PhysicalSections ( ) {
ao , bo := s . ALinkPosition ( ) . Offset ( ) , s . BLinkPosition ( ) . Offset ( )
@ -311,72 +287,258 @@ func ecsLinkMapToSection(repo *repository.Repository, offset int64, up bool, lin
}
}
if section == nil {
panic ( dto. ErrorDto { Code : dto . DataNotExist , Message : fmt . Sprintf ( "未找到link设备偏移【%d】" , offset ) } )
panic ( sys_error. New ( fmt . Sprintf ( "未找到link设备偏移【%d】" , offset ) ) )
}
// 元素ID
deviceId = section . Id ( )
// link偏移变大方向
ao , bo := section . ALinkPosition ( ) . Offset ( ) , section . BLinkPosition ( ) . Offset ( )
ak , bk := convertRepoBaseKm ( repo , section . AKilometer ( ) ) , convertRepoBaseKm ( repo , section . BKilometer ( ) )
akv , bkv := ak . Value , bk . Value
if up {
if ao < bo {
runDirection = akv < bkv
} else {
runDirection = akv > bkv
}
} else {
if ao > bo {
runDirection = akv < bkv
} else {
runDirection = akv > bkv
}
}
pointTo = runDirection == ( akv < bkv )
// a点偏移 大于 b点偏移
ao , bo := section . ALinkPosition ( ) . Offset ( ) , section . BLinkPosition ( ) . Offset ( )
if ao > bo {
deviceOffset = ao - offset
} else {
deviceOffset = offset - ao
}
// a点公里标 大于 b点公里标
if akv > bkv {
km = akv - deviceOffset
ak , bk := convertRepoBaseKm ( repo , section . AKilometer ( ) ) , convertRepoBaseKm ( repo , section . BKilometer ( ) )
km = & proto2 . Kilometer { CoordinateSystem : ak . CoordinateSystem }
if ak . Value > bk . Value {
km . Value = ak . Value - deviceOffset
} else {
km = akv + deviceOffset
km . Value = ak . Value + deviceOffset
}
return
}
// 查找列车的公里标
func concertTrainKilometer ( kilometer , offset int64 , tendTo bool ) int64 {
if tendTo {
return kilometer - offset
// 根据设备查找link
// 入参: 设备ID、端口、设备偏移
// 输出: linkId、link偏移
func QueryLinkAndOffsetByDevice ( repo * repository . Repository , uid , port string , offset int64 ) ( linkId string , linkOffset int64 ) {
if port == "" {
linkId , linkOffset = sectionToLink ( repo , uid , offset )
} else {
return kilometer + offset
linkId , linkOffset = turnoutToLink ( repo , uid , port , offset )
}
return
}
// 根据区段设备查找link
// 入参: 仿真Repository、设备ID、设备偏移
// 输出: linkId、link偏移、公里标
func sectionToLink ( repo * repository . Repository , uid string , offset int64 ) ( string , int64 ) {
section := repo . FindPhysicalSection ( uid )
if section == nil {
panic ( sys_error . New ( fmt . Sprintf ( "地图不存在uid:%s缓存" , uid ) ) )
}
ao , bo := section . ALinkPosition ( ) . Offset ( ) , section . BLinkPosition ( ) . Offset ( )
if ao < bo {
return section . ALinkPosition ( ) . Link ( ) . Id ( ) , ao + offset
} else {
return section . ALinkPosition ( ) . Link ( ) . Id ( ) , ao - offset
}
}
// 转换成统一坐标公里标
func convertRepoBaseKm ( r * repository . Repository , km * proto2 . Kilometer ) * proto2 . Kilometer {
k , err := r . ConvertKilometer ( km , r . GetCoordinateInfo ( ) . Coordinate )
if err != nil {
panic ( err )
// 根据道岔设备查找link
// 入参: 仿真Repository、道岔设备ID、道岔端口、设备偏移
// 输出: linkId、link偏移
func turnoutToLink ( repo * repository . Repository , uid , port string , offset int64 ) ( string , int64 ) {
turnout := repo . FindTurnout ( uid )
if turnout == nil {
panic ( sys_error . New ( fmt . Sprintf ( "不存在道岔【uid:%s】" , uid ) ) )
}
var portPosition * repository . LinkPosition
switch port {
case "A" :
portPosition = turnout . FindLinkPositionByPort ( proto2 . Port_A )
case "B" :
portPosition = turnout . FindLinkPositionByPort ( proto2 . Port_B )
case "C" :
portPosition = turnout . FindLinkPositionByPort ( proto2 . Port_C )
default :
panic ( sys_error . New ( fmt . Sprintf ( "无效端口【%s】偏移量" , port ) ) )
}
// 关联link
link := portPosition . Link ( )
isStart := link . ARelation ( ) . Device ( ) . Id ( ) == uid
if isStart {
return link . Id ( ) , offset
} else {
return link . Id ( ) , link . Length ( ) - offset
}
return k
}
// 检查列车是否可以放到设备上
func checkDeviceContainTrain ( offset , trainLen , deviceLen int64 , deviceName string ) int64 {
l := int64 ( math . Abs ( float64 ( deviceLen ) ) )
if offset > l {
panic ( sys_error . New ( fmt . Sprintf ( "偏移【%d】超出【%s】范围【%d】" , offset , deviceName , l ) ) )
// 根据设备信息、上下行, 获取link运行方向, ab指向
// 入参: 仿真Repository、uid、端口、上下行
// 输出: link运行方向、设备上的指向
func QueryUpAndABByDevice ( repo * repository . Repository , uid , port string , runDirection bool ) ( up , ab bool ) {
if port == "" {
up , ab = runDirectionSectionToUpAndAB ( repo , uid , runDirection )
} else {
up , ab = runDirectionTurnoutToUpAndAB ( repo , uid , port , runDirection )
}
if trainLen > offset { // 如果列车长度超过设置offset
offset = trainLen
return
}
if offset > l {
panic ( sys_error . New ( fmt . Sprintf ( "列车长度【%d】超出【%s】范围【%d】" , trainLen , deviceName , l ) ) )
// 根据区段及上下行, 获取link运行方向, ab指向
// 入参: 仿真Repository、区段UID、上下行
// 输出: link运行方向、设备上的指向
func runDirectionSectionToUpAndAB ( repo * repository . Repository , id string , runDirection bool ) ( up , ab bool ) {
section := repo . FindPhysicalSection ( id )
if section == nil {
panic ( sys_error . New ( fmt . Sprintf ( "地图不存在uid:%s缓存" , id ) ) )
}
return offset
ao , bo := section . ALinkPosition ( ) . Offset ( ) , section . BLinkPosition ( ) . Offset ( )
// 是否从A到B, 统一坐标
ak , bk := convertRepoBaseKm ( repo , section . AKilometer ( ) ) , convertRepoBaseKm ( repo , section . BKilometer ( ) )
ab = ( runDirection == ( ak . Value <= bk . Value ) )
up = ( ab == ( ao < bo ) )
return
}
// 根据区段及上下行, 获取link运行方向, ab指向
// 入参: 仿真Repository、道岔UID、道岔端口、上下行
// 输出: link运行方向, 设备上的指向
func runDirectionTurnoutToUpAndAB ( repo * repository . Repository , id , port string , runDirection bool ) ( up , ab bool ) {
turnout := repo . FindTurnout ( id )
if turnout == nil {
panic ( sys_error . New ( fmt . Sprintf ( "不存在道岔【uid:%s】" , id ) ) )
}
var portKm * proto2 . Kilometer
var portPosition * repository . LinkPosition
switch port {
case "A" :
portKm = convertRepoBaseKm ( repo , turnout . GetTurnoutKm ( proto2 . Port_A ) )
portPosition = turnout . FindLinkPositionByPort ( proto2 . Port_A )
case "B" :
portKm = convertRepoBaseKm ( repo , turnout . GetTurnoutKm ( proto2 . Port_B ) )
portPosition = turnout . FindLinkPositionByPort ( proto2 . Port_B )
case "C" :
portKm = convertRepoBaseKm ( repo , turnout . GetTurnoutKm ( proto2 . Port_C ) )
portPosition = turnout . FindLinkPositionByPort ( proto2 . Port_C )
default :
panic ( sys_error . New ( fmt . Sprintf ( "无效端口【%s】偏移量" , port ) ) )
}
// 岔心公里标
crossKm := convertRepoBaseKm ( repo , turnout . GetTurnoutKm ( proto2 . Port_None ) )
// 是否是link的起始断点
isStart := ( portPosition . Link ( ) . ARelation ( ) != nil && portPosition . Link ( ) . ARelation ( ) . Device ( ) . Id ( ) == id )
up = runDirection
if ( portKm . Value > crossKm . Value ) != isStart {
up = ! runDirection
}
ab = ( portKm . Value > crossKm . Value ) == runDirection
return
}
// 根据设备以及link运行方向, 获取上下行、设备上的运行指向
// 入参: 仿真Repository、道岔UID、道岔端口、上下行
// 输出: link运行方向, 设备上的指向
func QueryDirectionAndABByDevice ( repo * repository . Repository , uid , port string , up bool ) ( runDirection , ab bool ) {
if port == "" {
runDirection , ab = upSectionToDirectionAndAB ( repo , uid , up )
} else {
runDirection , ab = upTurnoutToDirectionAndAB ( repo , uid , port , up )
}
return
}
// 根据区段以及link运行方向, 获取上下行、设备上的运行指向
// 入参: 仿真Repository、道岔UID、道岔端口、上下行
// 输出: link运行方向, 设备上的指向
func upSectionToDirectionAndAB ( repo * repository . Repository , uid string , up bool ) ( runDirection , ab bool ) {
section := repo . FindPhysicalSection ( uid )
if section == nil {
panic ( sys_error . New ( fmt . Sprintf ( "地图不存在uid:%s缓存" , uid ) ) )
}
// a点偏移、b点偏移
ao , bo := section . ALinkPosition ( ) . Offset ( ) , section . BLinkPosition ( ) . Offset ( )
// a点公里标、b点公里标
ak , bk := convertRepoBaseKm ( repo , section . AKilometer ( ) ) , convertRepoBaseKm ( repo , section . BKilometer ( ) )
if up {
runDirection = ( ( ao < bo ) == ( ak . Value < bk . Value ) )
} else {
runDirection = ( ( ao > bo ) == ( ak . Value < bk . Value ) )
}
ab = ( runDirection == ( ak . Value < bk . Value ) )
return
}
// 根据道岔以及link运行方向, 获取上下行、设备上的运行指向
// 入参: 仿真Repository、道岔UID、道岔端口、上下行
// 输出: link运行方向, 设备上的指向
func upTurnoutToDirectionAndAB ( repo * repository . Repository , uid , port string , up bool ) ( runDirection , ab bool ) {
turnout := repo . FindTurnout ( uid )
if turnout == nil {
panic ( sys_error . New ( fmt . Sprintf ( "不存在道岔【uid:%s】" , uid ) ) )
}
var port_enum proto2 . Port
switch port {
case "A" :
port_enum = proto2 . Port_A
case "B" :
port_enum = proto2 . Port_B
case "C" :
port_enum = proto2 . Port_C
default :
panic ( sys_error . New ( fmt . Sprintf ( "无效端口【%s】偏移量" , port ) ) )
}
tpo := turnout . FindLinkPositionByPort ( port_enum )
isA := tpo . Link ( ) . ARelation ( ) != nil && tpo . Link ( ) . ARelation ( ) . Device ( ) . Id ( ) == uid
crossKmInfo := convertRepoBaseKm ( repo , turnout . GetTurnoutKm ( proto2 . Port_None ) )
portKmInfo := convertRepoBaseKm ( repo , turnout . GetTurnoutKm ( port_enum ) )
if isA {
ab = ! up
runDirection = ( up == ( crossKmInfo . Value < portKmInfo . Value ) )
} else {
ab = up
runDirection = ( up == ( crossKmInfo . Value > portKmInfo . Value ) )
}
return
}
// 根据设备获取列车公里标
// 入参: 仿真Repository、UID、端口、上下行、link偏移
// 输出:公里标信息
func CalcTrainKilometer ( repo * repository . Repository , uid , port string , runDirection bool , offset int64 ) (
km * proto2 . Kilometer ) {
if port == "" {
km = sectionOffsetToKilometer ( repo , uid , runDirection , offset )
} else {
km = turnoutOffsetToKilometer ( repo , uid , runDirection , offset )
}
return
}
// 获取区段的上公里标
// 入参: 仿真Repository、UID、上下行、link偏移
// 输出:公里标信息
func sectionOffsetToKilometer ( repo * repository . Repository , uid string , runDirection bool , offset int64 ) ( km * proto2 . Kilometer ) {
section := repo . FindPhysicalSection ( uid )
if section == nil {
panic ( sys_error . New ( fmt . Sprintf ( "地图不存在uid:%s缓存" , uid ) ) )
}
km = convertRepoBaseKm ( repo , section . AKilometer ( ) )
if runDirection {
km . Value = km . Value + offset
} else {
km . Value = km . Value - offset
}
return
}
// 获取道岔的公里标
// 入参: 仿真Repository、UID、上下行、link偏移
// 输出:公里标信息
func turnoutOffsetToKilometer ( repo * repository . Repository , uid string , runDirection bool , offset int64 ) ( km * proto2 . Kilometer ) {
turnout := repo . FindTurnout ( uid )
if turnout == nil {
panic ( sys_error . New ( fmt . Sprintf ( "不存在道岔【uid:%s】" , uid ) ) )
}
// 岔心公里标
km = convertRepoBaseKm ( repo , turnout . GetTurnoutKm ( proto2 . Port_None ) )
if runDirection {
km . Value = km . Value + offset
} else {
km . Value = km . Value - offset
}
return
}