package point import ( "math" "git.wtrh.nl/patterns/gopatterns/pkg/position" "git.wtrh.nl/patterns/gopatterns/pkg/util" "git.wtrh.nl/patterns/gopatterns/pkg/vector" "github.com/tdewolff/canvas" ) // RelativePoint implements Point and defines a position that is relative to a different Point. type RelativePoint struct { draw bool name string point Point relativeOffset position.Position id util.ID hide bool } // Name returns the name of a point. func (r *RelativePoint) Name() string { return r.name } // Done returns the relativePoint as interface. func (r *RelativePoint) Done() Point { //nolint:ireturn return r } // MarkWith sets the ID of the point. func (r *RelativePoint) MarkWith(n util.ID) *RelativePoint { r.id = n if r.name == "" { r.name = string(n) } return r } // Position calculates and returns the absolute [position.Position]. func (r *RelativePoint) Position() position.Position { p := r.point.Position() return p.Add(r.relativeOffset) } // Matrix calculates and returns the [canvas.Matrix] of a point. func (r *RelativePoint) Matrix() canvas.Matrix { return r.point.Matrix().Translate(r.relativeOffset.Vector.Values()).Rotate(r.relativeOffset.Rotation / math.Pi * 180) } // Vector calculates and returns the absolute [vector.Vector]. func (r *RelativePoint) Vector() vector.Vector { return r.Position().Vector } // ID returns the point ID. func (r *RelativePoint) ID() util.ID { return r.id } // NewRelativePointWithVector returns a new RelativePoint. func NewRelativePointWithVector(point Point, p vector.Vector, id util.ID) *RelativePoint { return &RelativePoint{ point: point, relativeOffset: position.Position{Vector: p}, id: id, name: string(id), } } // NewRelativePoint returns a new RelativePoint. func NewRelativePoint(point Point) *RelativePoint { return &RelativePoint{ point: point, } } // NewRotationPoint returns a new RelativePoint with a specific rotation. func NewRotationPoint(point Point, a float64, id util.ID) *RelativePoint { p := &RelativePoint{ point: point, relativeOffset: position.Position{ Vector: vector.Vector{}, Rotation: a, }, name: string(id), id: id, } return p } // WithXOffset sets the x value for the relative offset. func (r *RelativePoint) WithXOffset(value float64) *RelativePoint { r.relativeOffset.Vector.X = value return r } // WithYOffset sets the y value for the relative offset. func (r *RelativePoint) WithYOffset(value float64) *RelativePoint { r.relativeOffset.Vector.Y = value return r } // WithRotationOffset sets the angle for the relative offset. func (r *RelativePoint) WithRotationOffset(value float64) *RelativePoint { r.relativeOffset.Rotation = value return r } // NewRelativePointBelow returns a RelativePoint distance f below another Point. func NewRelativePointBelow(point Point, f float64, id util.ID) *RelativePoint { return NewRelativePointWithVector(point, vector.Vector{X: 0, Y: -f}, id) } // NewRelativePointAbove returns a RelativePoint distance f above another Point. func NewRelativePointAbove(point Point, f float64, id util.ID) *RelativePoint { return NewRelativePointWithVector(point, vector.Vector{X: 0, Y: f}, id) } // NewRelativePointLeft returns a RelativePoint distance f left of another Point. func NewRelativePointLeft(point Point, f float64, id util.ID) *RelativePoint { return NewRelativePointWithVector(point, vector.Vector{X: -f, Y: 0}, id) } // NewRelativePointRight returns a RelativePoint distance f right of another Point. func NewRelativePointRight(point Point, f float64, id util.ID) *RelativePoint { return NewRelativePointWithVector(point, vector.Vector{X: f, Y: 0}, id) } // Draw returns if the point should be drawn. func (r *RelativePoint) Draw() bool { return r.draw } // SetDraw indicates that the point should be drawn. func (r *RelativePoint) SetDraw() { r.draw = true } // UnsetDraw indicates that the point should not be drawn. func (r *RelativePoint) UnsetDraw() { r.draw = true } // Hide returns if the point must remain hidden. func (r *RelativePoint) Hide() bool { return r.hide } // SetHide indicates that the must be hidden. func (r *RelativePoint) SetHide() { r.hide = true }