package model import ( "fmt" "io" "math" ) type RR = io.Writer // 轨道 // 默认坐标系为以A端为起点,B端为终点的单轴坐标系 type Link interface { TwoPortsPipeElement IsEquals(pla *PipeLink, plb *PipeLink) bool // 获取轨道长度,单位:毫米mm GetLength() int64 } // 轨道连接点(使用的是道岔岔心),然后有三个方向A/B/C,还是使用PipePort枚举,但表示的含义是方向,而不是道岔的三个端口 type LinkNode interface { Turnout() Turnout ThreePortsPipeElement } type LinkDirection int const ( LinkDirectionB2A LinkDirection = -1 LinkDirectionA2B LinkDirection = 1 ) // link位置 type LinkPosition struct { link Link pos int64 } func NewLinkPosition(link Link, pos int64) *LinkPosition { return &LinkPosition{ link: link, pos: pos, } } func (lp *LinkPosition) Link() Link { return lp.link } func (lp *LinkPosition) Position() int64 { return lp.pos } func (lp *LinkPosition) IsIn(linkRange LinkRange) bool { return lp.link.Uid() == linkRange.link.Uid() && lp.IsInRange(linkRange.start, linkRange.end) } func (lp *LinkPosition) IsInRange(a int64, b int64) bool { start := int64(math.Min(float64(a), float64(b))) end := int64(math.Max(float64(a), float64(b))) return lp.pos >= start && lp.pos <= end } // 移动位置 func (lp *LinkPosition) Move(len uint32, direction LinkDirection) (overflow bool) { lp.pos += int64(len) * int64(direction) if lp.pos > lp.link.GetLength() || lp.pos < 0 { overflow = true } return } // link范围 type LinkRange struct { link Link start int64 end int64 } // 构造link范围 // link: 轨道 不能为nil // a: 起始位置,b: 结束位置,单位:毫米mm,a和b不能相等 func NewLinkRange(link Link, a int64, b int64) *LinkRange { if link == nil { panic("构造LinkRange错误: link不能为空") } if a == b { panic("构造LinkRange错误: a和b不能相等") } start := int64(math.Min(float64(a), float64(b))) end := int64(math.Max(float64(a), float64(b))) return &LinkRange{ link: link, start: start, end: end, } } var _ Link = (*LinkImpl)(nil) var _ LinkNode = (*LinkNodeImpl)(nil) type LinkImpl struct { *TwoPortsPipeElementImpl len int64 } type LinkNodeImpl struct { turnout Turnout *ThreePortsPipeElementImpl } func NewLink(pla *PipeLink, plb *PipeLink) *LinkImpl { uid := buildLinkUid(pla, plb) return &LinkImpl{ TwoPortsPipeElementImpl: &TwoPortsPipeElementImpl{ uid: uid, }, } } func NewLinkNode(turnout Turnout) *LinkNodeImpl { if turnout == nil { panic("构造LinkNode错误: 道岔不能为空") } return &LinkNodeImpl{ turnout: turnout, ThreePortsPipeElementImpl: &ThreePortsPipeElementImpl{ uid: turnout.Uid(), }, } } func (l *LinkImpl) IsEquals(pla *PipeLink, plb *PipeLink) bool { return l.uid == buildLinkUid(pla, plb) || l.uid == buildLinkUid(plb, pla) } func (l *LinkImpl) GetLength() int64 { return l.len } func (l *LinkImpl) SetLength(len int64) { l.len = len } func (n *LinkNodeImpl) Turnout() Turnout { return n.turnout } func buildLinkUid(pla *PipeLink, plb *PipeLink) string { if pla == nil && plb == nil { panic("构造link Uid错误: pla和plb不能同时为空") } if pla == nil { return fmt.Sprintf("end->%s(%s)", plb.Pipe.Uid(), plb.Port) } if plb == nil { return fmt.Sprintf("%s(%s)->end", pla.Pipe.Uid(), pla.Port) } return fmt.Sprintf("%s(%s)->%s(%s)", pla.Pipe.Uid(), pla.Port, plb.Pipe.Uid(), plb.Port) }