This point can be drawn from point A to B and extends from B with an absolute offset.pull/1/head
| @@ -0,0 +1,90 @@ | |||||
| package point | |||||
| import ( | |||||
| "git.wtrh.nl/wouter/gopatterns/pkg/position" | |||||
| "git.wtrh.nl/wouter/gopatterns/pkg/vector" | |||||
| "github.com/tdewolff/canvas" | |||||
| "math" | |||||
| ) | |||||
| // ExtendPoint defines a point on the line between two other points. | |||||
| type ExtendPoint struct { | |||||
| id ID | |||||
| from Point | |||||
| to Point | |||||
| extend float64 | |||||
| name string | |||||
| draw bool | |||||
| hide bool | |||||
| } | |||||
| // NewExtendPoint returns a new ExtendPoint relative to two other points from and to. | |||||
| // The given offset defines where the new point is. | |||||
| // With offset = 0 the new point is a from, offset = 0.5 results in a point exactly in the middle. | |||||
| func NewExtendPoint(from, to Point, extend float64, id ID) *ExtendPoint { | |||||
| return &ExtendPoint{ | |||||
| id: id, | |||||
| from: from, | |||||
| to: to, | |||||
| extend: extend, | |||||
| name: string(id), | |||||
| } | |||||
| } | |||||
| // Position calculates and returns the absolute [position.Position]. | |||||
| func (b *ExtendPoint) Position() position.Position { | |||||
| return position.Position{ | |||||
| Vector: b.to.Vector().Add(b.extendedVector()), | |||||
| Rotation: b.to.Vector().AngleBetween(b.to.Vector()) - math.Pi/2, | |||||
| } | |||||
| } | |||||
| func (b *ExtendPoint) extendedVector() vector.Vector { | |||||
| return b.to.Vector().Subtract(b.from.Vector()).Unit().Multiply(b.extend) | |||||
| } | |||||
| // Vector calculates and returns the absolute [vector.Vector]. | |||||
| func (b *ExtendPoint) Vector() vector.Vector { | |||||
| return b.Position().Vector | |||||
| } | |||||
| // Matrix calculates and returns the [canvas.Matrix] of a point. | |||||
| func (b *ExtendPoint) Matrix() canvas.Matrix { | |||||
| return b.to.Matrix().Translate(b.extendedVector().Values()). | |||||
| Rotate((b.from.Vector().AngleBetween(b.to.Vector()) - math.Pi/2) * 180 / math.Pi) | |||||
| } | |||||
| // ID returns the point ID. | |||||
| func (b *ExtendPoint) ID() ID { | |||||
| return b.id | |||||
| } | |||||
| // Name returns the name of a point. | |||||
| func (b *ExtendPoint) Name() string { | |||||
| return b.name | |||||
| } | |||||
| // Draw returns if the point should be drawn. | |||||
| func (b *ExtendPoint) Draw() bool { | |||||
| return b.draw | |||||
| } | |||||
| // SetDraw indicates that the point should be drawn. | |||||
| func (b *ExtendPoint) SetDraw() { | |||||
| b.draw = true | |||||
| } | |||||
| // UnsetDraw indicates that the point should not be drawn. | |||||
| func (b *ExtendPoint) UnsetDraw() { | |||||
| b.draw = true | |||||
| } | |||||
| // Hide returns if the point must remain hidden. | |||||
| func (b *ExtendPoint) Hide() bool { | |||||
| return b.hide | |||||
| } | |||||
| // SetHide indicates that the must be hidden. | |||||
| func (b *ExtendPoint) SetHide() { | |||||
| b.hide = true | |||||
| } | |||||
| @@ -30,6 +30,7 @@ type Point struct { | |||||
| RelativeTo *point.ID `yaml:"relativeTo,omitempty"` | RelativeTo *point.ID `yaml:"relativeTo,omitempty"` | ||||
| Description string `yaml:"description"` | Description string `yaml:"description"` | ||||
| Between *BetweenPoint `yaml:"between"` | Between *BetweenPoint `yaml:"between"` | ||||
| Extend *ExtendPoint `yaml:"extend"` | |||||
| Hide bool `yaml:"hide"` | Hide bool `yaml:"hide"` | ||||
| } | } | ||||
| @@ -150,6 +151,11 @@ func (p Points) addSingleToPattern(id point.ID, pat *pattern.Pattern, depth int) | |||||
| if err != nil { | if err != nil { | ||||
| return err | return err | ||||
| } | } | ||||
| case templatePoint.Extend != nil: | |||||
| newPoint, err = p.createExtend(id, pat, depth) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| default: | default: | ||||
| x, y, r, err := templatePoint.Position.evaluate(pat.Parameters(), p.Functions(pat)) | x, y, r, err := templatePoint.Position.evaluate(pat.Parameters(), p.Functions(pat)) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -245,3 +251,39 @@ func (p Points) getOrCreate(id point.ID, pat *pattern.Pattern, depth int) (point | |||||
| return createdPoint, nil | return createdPoint, nil | ||||
| } | } | ||||
| func (p Points) createExtend(id point.ID, pat *pattern.Pattern, depth int) (point.Point, error) { | |||||
| newPoint, ok := p[id] | |||||
| if !ok { | |||||
| return nil, ErrPointNotFound | |||||
| } | |||||
| if newPoint.Extend.To == id || newPoint.Extend.From == id || depth > maxRecursionDepth { | |||||
| return nil, ErrRelativePointRecursion | |||||
| } | |||||
| fromPoint, err := p.getOrCreate(newPoint.Extend.From, pat, depth) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| toPoint, err := p.getOrCreate(newPoint.Extend.To, pat, depth) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| params := pat.Parameters() | |||||
| offset, err := newPoint.Extend.Offset.Evaluate(params, p.Functions(pat)) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| return point.NewExtendPoint(fromPoint, toPoint, offset, id), nil | |||||
| } | |||||
| type ExtendPoint struct { | |||||
| From point.ID `yaml:"from"` | |||||
| To point.ID `yaml:"to"` | |||||
| Offset *Value `yaml:"offset"` | |||||
| } | |||||
| @@ -57,6 +57,15 @@ components: | |||||
| $ref: '#/components/schemas/expression' | $ref: '#/components/schemas/expression' | ||||
| hide: | hide: | ||||
| type: bool | type: bool | ||||
| extend: | |||||
| type: object | |||||
| properties: | |||||
| from: | |||||
| $ref: '#/components/schemas/pointID' | |||||
| to: | |||||
| $ref: '#/components/schemas/pointID' | |||||
| offset: | |||||
| $ref: '#/components/schemas/expression' | |||||
| points: | points: | ||||
| type: object | type: object | ||||
| @@ -67,11 +76,11 @@ components: | |||||
| type: object | type: object | ||||
| properties: | properties: | ||||
| y: | y: | ||||
| type: string | |||||
| $ref: '#/components/schemas/expression' | |||||
| x: | x: | ||||
| type: string | |||||
| $ref: '#/components/schemas/expression' | |||||
| rotation: | rotation: | ||||
| type: string | |||||
| $ref: '#/components/schemas/expression' | |||||
| line: | line: | ||||
| type: object | type: object | ||||
| @@ -95,8 +104,8 @@ components: | |||||
| expression: | expression: | ||||
| oneOf: | oneOf: | ||||
| - type: integer | - type: integer | ||||
| - type: number | |||||
| - type: string | - type: string | ||||
| @@ -80,7 +80,7 @@ points: | |||||
| between: | between: | ||||
| from: 16 | from: 16 | ||||
| to: 18 | to: 18 | ||||
| offset: 0.5 | |||||
| absolute: 0.5 | |||||
| 20: | 20: | ||||
| position: | position: | ||||
| x: 20 | x: 20 | ||||
| @@ -87,23 +87,16 @@ points: | |||||
| position: | position: | ||||
| x: -rugbreedte/2 | x: -rugbreedte/2 | ||||
| relativeTo: H | relativeTo: H | ||||
| Nrotated: | |||||
| position: | |||||
| rotation: AngleBetween("N","Q") | |||||
| relativeTo: N | |||||
| V: | V: | ||||
| position: | |||||
| x: DistanceBetween("R","W")-10 | |||||
| relativeTo: Nrotated | |||||
| Rrotated: | |||||
| position: | |||||
| rotation: AngleBetween("R","T") | |||||
| relativeTo: R | |||||
| extend: | |||||
| from: Q | |||||
| to: N | |||||
| offset: -(DistanceBetween("R","W") - 10) | |||||
| W: | W: | ||||
| position: | |||||
| x: DistanceBetween("R","T") + 20 | |||||
| relativeTo: Rrotated | |||||
| extend: | |||||
| from: R | |||||
| to: T | |||||
| offset: 20 | |||||
| panels: | panels: | ||||
| basis: | basis: | ||||