swf2ass-go/types/shapes/PathSegment.go

123 lines
2.5 KiB
Go

package shapes
import (
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/records"
"slices"
)
type PathSegment[T ~float64 | ~int64] []VisitedPoint[T]
func NewPathSegment[T ~float64 | ~int64](start math.Vector2[T]) PathSegment[T] {
return PathSegment[T]{
VisitedPoint[T]{
Pos: start,
IsBezierControl: false,
},
}
}
// Flip
// Flips the direction of the path segment.
// Flash fill paths are dual-sided, with fill style 1 indicating the positive side
// and fill style 0 indicating the negative. We have to flip fill style 0 paths
// in order to link them to fill style 1 paths.
func (s *PathSegment[T]) Flip() {
slices.Reverse(*s)
}
func (s *PathSegment[T]) AddPoint(p VisitedPoint[T]) {
*s = append(*s, p)
}
func (s *PathSegment[T]) Start() math.Vector2[T] {
return (*s)[0].Pos
}
func (s *PathSegment[T]) End() math.Vector2[T] {
return (*s)[len(*s)-1].Pos
}
func (s *PathSegment[T]) IsEmpty() bool {
return len(*s) <= 1
}
func (s *PathSegment[T]) IsClosed() bool {
return s.Start().Equals(s.End())
}
func (s *PathSegment[T]) Swap(o *PathSegment[T]) {
*s, *o = *o, *s
}
func (s *PathSegment[T]) Merge(o PathSegment[T]) {
*s = append(*s, o[1:]...)
}
func (s *PathSegment[T]) TryMerge(o *PathSegment[T], isDirected bool) bool {
if o.End().Equals(s.Start()) {
s.Swap(o)
s.Merge(*o)
return true
} else if s.End().Equals(o.Start()) {
s.Merge(*o)
return true
} else if !isDirected && s.End().Equals(o.End()) {
o.Flip()
s.Merge(*o)
return true
} else if !isDirected && s.Start().Equals(o.Start()) {
o.Flip()
s.Swap(o)
s.Merge(*o)
return true
}
return false
}
func (s *PathSegment[T]) GetShape() (shape Shape) {
if s.IsEmpty() {
panic("not possible")
}
shape = make(Shape, 0, len(*s)-1)
points := *s
next := func() VisitedPoint[T] {
point := points[0]
points = points[1:]
return point
}
lastPos := next().Pos.Float64()
//lastPos := points[0].Pos.Float64()
for len(points) > 0 {
point := next()
if !point.IsBezierControl {
shape = append(shape, records.LineRecord{
To: point.Pos.Float64(),
Start: lastPos,
})
lastPos = point.Pos.Float64()
} else {
if len(points) == 0 {
panic("Bezier without endpoint")
}
end := next()
shape = append(shape, records.QuadraticCurveRecord{
Control: point.Pos.Float64(),
Anchor: end.Pos.Float64(),
Start: lastPos,
})
lastPos = end.Pos.Float64()
}
}
return shape
}