2024-06-07 18:38:38 +08:00
|
|
|
|
package model
|
|
|
|
|
|
2024-07-01 19:49:24 +08:00
|
|
|
|
import (
|
2024-07-02 18:30:12 +08:00
|
|
|
|
"fmt"
|
2024-07-01 19:49:24 +08:00
|
|
|
|
"io"
|
2024-07-10 18:09:16 +08:00
|
|
|
|
"math"
|
2024-07-01 19:49:24 +08:00
|
|
|
|
)
|
2024-06-17 19:45:38 +08:00
|
|
|
|
|
|
|
|
|
type RR = io.Writer
|
|
|
|
|
|
|
|
|
|
// 轨道
|
2024-07-10 18:09:16 +08:00
|
|
|
|
// 默认坐标系为以A端为起点,B端为终点的单轴坐标系
|
2024-06-07 18:38:38 +08:00
|
|
|
|
type Link interface {
|
2024-07-02 18:30:12 +08:00
|
|
|
|
TwoPortsPipeElement
|
|
|
|
|
IsEquals(pla *PipeLink, plb *PipeLink) bool
|
2024-07-10 18:09:16 +08:00
|
|
|
|
// 获取轨道长度,单位:毫米mm
|
|
|
|
|
GetLength() int64
|
2024-06-17 19:45:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-10 18:09:16 +08:00
|
|
|
|
// 轨道连接点(使用的是道岔岔心),然后有三个方向A/B/C,还是使用PipePort枚举,但表示的含义是方向,而不是道岔的三个端口
|
2024-06-17 19:45:38 +08:00
|
|
|
|
type LinkNode interface {
|
|
|
|
|
Turnout() Turnout
|
2024-07-02 18:30:12 +08:00
|
|
|
|
ThreePortsPipeElement
|
2024-06-17 19:45:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-10 18:09:16 +08:00
|
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 18:20:11 +08:00
|
|
|
|
var _ Link = (*LinkImpl)(nil)
|
|
|
|
|
var _ LinkNode = (*LinkNodeImpl)(nil)
|
|
|
|
|
|
2024-06-17 19:45:38 +08:00
|
|
|
|
type LinkImpl struct {
|
2024-07-02 18:30:12 +08:00
|
|
|
|
*TwoPortsPipeElementImpl
|
2024-07-10 18:09:16 +08:00
|
|
|
|
len int64
|
2024-06-17 19:45:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type LinkNodeImpl struct {
|
2024-06-27 19:59:13 +08:00
|
|
|
|
turnout Turnout
|
2024-07-02 18:30:12 +08:00
|
|
|
|
*ThreePortsPipeElementImpl
|
2024-06-17 19:45:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-02 18:30:12 +08:00
|
|
|
|
func NewLink(pla *PipeLink, plb *PipeLink) *LinkImpl {
|
|
|
|
|
uid := buildLinkUid(pla, plb)
|
2024-06-17 19:45:38 +08:00
|
|
|
|
return &LinkImpl{
|
2024-07-02 18:30:12 +08:00
|
|
|
|
TwoPortsPipeElementImpl: &TwoPortsPipeElementImpl{
|
2024-06-27 19:59:13 +08:00
|
|
|
|
uid: uid,
|
|
|
|
|
},
|
2024-06-17 19:45:38 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-01 19:49:24 +08:00
|
|
|
|
func NewLinkNode(turnout Turnout) *LinkNodeImpl {
|
|
|
|
|
if turnout == nil {
|
|
|
|
|
panic("构造LinkNode错误: 道岔不能为空")
|
|
|
|
|
}
|
2024-06-17 19:45:38 +08:00
|
|
|
|
return &LinkNodeImpl{
|
|
|
|
|
turnout: turnout,
|
2024-07-02 18:30:12 +08:00
|
|
|
|
ThreePortsPipeElementImpl: &ThreePortsPipeElementImpl{
|
2024-06-27 19:59:13 +08:00
|
|
|
|
uid: turnout.Uid(),
|
|
|
|
|
},
|
2024-06-17 19:45:38 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-02 18:30:12 +08:00
|
|
|
|
func (l *LinkImpl) IsEquals(pla *PipeLink, plb *PipeLink) bool {
|
|
|
|
|
return l.uid == buildLinkUid(pla, plb) || l.uid == buildLinkUid(plb, pla)
|
2024-07-01 19:49:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-10 18:09:16 +08:00
|
|
|
|
func (l *LinkImpl) GetLength() int64 {
|
|
|
|
|
return l.len
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (l *LinkImpl) SetLength(len int64) {
|
|
|
|
|
l.len = len
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-17 19:45:38 +08:00
|
|
|
|
func (n *LinkNodeImpl) Turnout() Turnout {
|
|
|
|
|
return n.turnout
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-02 18:30:12 +08:00
|
|
|
|
func buildLinkUid(pla *PipeLink, plb *PipeLink) string {
|
|
|
|
|
if pla == nil && plb == nil {
|
|
|
|
|
panic("构造link Uid错误: pla和plb不能同时为空")
|
2024-06-17 19:45:38 +08:00
|
|
|
|
}
|
2024-07-02 18:30:12 +08:00
|
|
|
|
if pla == nil {
|
|
|
|
|
return fmt.Sprintf("end->%s(%s)", plb.Pipe.Uid(), plb.Port)
|
2024-06-17 19:45:38 +08:00
|
|
|
|
}
|
2024-07-02 18:30:12 +08:00
|
|
|
|
if plb == nil {
|
|
|
|
|
return fmt.Sprintf("%s(%s)->end", pla.Pipe.Uid(), pla.Port)
|
2024-06-17 19:45:38 +08:00
|
|
|
|
}
|
2024-07-02 18:30:12 +08:00
|
|
|
|
return fmt.Sprintf("%s(%s)->%s(%s)", pla.Pipe.Uid(), pla.Port, plb.Pipe.Uid(), plb.Port)
|
2024-06-07 18:38:38 +08:00
|
|
|
|
}
|