161 lines
3.4 KiB
Go
161 lines
3.4 KiB
Go
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)
|
||
}
|