package template import ( "errors" "git.wtrh.nl/patterns/gopatterns/pkg/util" "git.wtrh.nl/patterns/gopatterns/pkg/path" "git.wtrh.nl/patterns/gopatterns/pkg/pattern" "git.wtrh.nl/patterns/gopatterns/pkg/point" ) var ErrLineNotFound = errors.New("required path not found") // Lines contain named lines. type Lines map[util.ID]Line // Line describes a pattern line. type Line struct { Through []util.ID `yaml:"through"` Curve *Curve `yaml:"curve,omitempty"` Style *Style `yaml:"style,omitempty"` } type Style struct { Thickness *float64 `yaml:"thickness,omitempty"` } // Curve describes if a Line curves and if it has start and end constraints. type Curve struct { Start util.ID `yaml:"start,omitempty"` End util.ID `yaml:"end,omitempty"` } func (t Template) templateLine(panelName string, id util.ID) (Line, error) { if id.Panel() != "" { panelName = id.Panel() } panel, err := t.Panel(panelName) if !errors.Is(err, ErrPanelNotFound) { l, ok := panel.Lines[id.Deref()] if ok { return l, nil } } line, ok := t.Lines[id.Deref()] if !ok { return Line{}, ErrLineNotFound } return line, nil } func (t Template) getOrCreateLine(id util.ID, req request, depth int) (path.Path, error) { l, ok := req.lines[id] if ok { return l, nil } newLine, err := t.createLine(id, req, depth+1) if err != nil { return nil, err } req.lines[util.ID(id)] = newLine return newLine, nil } func (t Template) createLine(id util.ID, req request, depth int) (path.Path, error) { line, err := t.templateLine(req.name, id) if err != nil { return nil, err } throughPoints, err := t.getOrCreatePoints(line.Through, req, depth+1) if err != nil { return nil, err } style := path.NewDefaultStyle() if line.Style != nil && line.Style.Thickness != nil { style.Thickness = *line.Style.Thickness } switch { case line.Curve != nil: var start, end point.Point if line.Curve.Start != "" { start, err = t.getOrCreatePoint(line.Curve.Start, req, depth+1) if err != nil { return nil, err } } if line.Curve.End != "" { end, err = t.getOrCreatePoint(line.Curve.End, req, depth+1) if err != nil { return nil, err } } return path.NewSpline(path.SplineOpts{ Start: start, End: end, Points: throughPoints, Style: style, ID: util.ID(id), }), nil default: return path.NewPolygon(throughPoints, style, util.ID(id)), nil } } // Build adds the line to the provided [pattern.Pattern]. func (l Line) Build(pat *pattern.Pattern) error { points := pat.GetPoints(l.Through) for _, p := range points { p.SetDraw() } style := path.NewDefaultStyle() if l.Style != nil && l.Style.Thickness != nil { style.Thickness = *l.Style.Thickness } switch { case l.Curve != nil: pat.AddLine( path.NewSpline(path.SplineOpts{ Start: pat.GetPoint(l.Curve.Start), End: pat.GetPoint(l.Curve.End), Points: points, Style: style, }), ) default: pat.AddLine(path.NewPolygon(points, style, "")) } return nil } // Build adds all the lines to the provided [pattern.Pattern]. func (l Lines) Build(pat *pattern.Pattern) error { for _, line := range l { err := line.Build(pat) if err != nil { return err } } return nil }