|
|
|
@@ -19,6 +19,8 @@ var ( |
|
|
|
|
|
|
|
// ErrRelativePointRecursion is returned when a points are relative to itself. |
|
|
|
ErrRelativePointRecursion = errors.New("point cannot be relative to itself") |
|
|
|
|
|
|
|
ErrInvalidArguments = errors.New("invalid arguments to call function") |
|
|
|
) |
|
|
|
|
|
|
|
// Points contains a map with points. |
|
|
|
@@ -40,52 +42,50 @@ var ErrInvalidPointID = errors.New("type cannot be converted to a PointID") |
|
|
|
func (p Points) Functions(pat *pattern.Pattern) map[string]govaluate.ExpressionFunction { |
|
|
|
return map[string]govaluate.ExpressionFunction{ |
|
|
|
"DistanceBetween": func(args ...interface{}) (interface{}, error) { |
|
|
|
id0, err := toPointID(args[0]) |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("parsing args[0] to pointID: %w", err) |
|
|
|
if len(args) != 2 { |
|
|
|
return nil, fmt.Errorf("function DistanceBetween() requires 2 arguments: %w", |
|
|
|
ErrInvalidArguments) |
|
|
|
} |
|
|
|
|
|
|
|
id1, err := toPointID(args[1]) |
|
|
|
points, err := p.getOrCreateFromArgs(pat, args...) |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("parsing args[0] to pointID: %w", err) |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
|
|
|
|
p0, err := p.getOrCreate(id0, pat, 0) |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("get or create point %q: %w", id0, err) |
|
|
|
return points[0].Position().Distance(points[1].Position()), nil |
|
|
|
}, |
|
|
|
"AngleBetween": func(args ...interface{}) (interface{}, error) { |
|
|
|
if len(args) != 2 { |
|
|
|
return nil, fmt.Errorf("function AngleBetween() requires 2 arguments: %w", |
|
|
|
ErrInvalidArguments) |
|
|
|
} |
|
|
|
|
|
|
|
p1, err := p.getOrCreate(id1, pat, 0) |
|
|
|
points, err := p.getOrCreateFromArgs(pat, args...) |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("get or create point %q: %w", id1, err) |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
|
|
|
|
return p0.Position().Distance(p1.Position()), nil |
|
|
|
return points[0].Vector().AngleBetween(points[1].Vector()), nil |
|
|
|
}, |
|
|
|
"AngleBetween": func(args ...interface{}) (interface{}, error) { |
|
|
|
id0, err := toPointID(args[0]) |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("parsing args[0] to pointID: %w", err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
id1, err := toPointID(args[1]) |
|
|
|
func (p Points) getOrCreateFromArgs(pat *pattern.Pattern, args ...interface{}) ([]point.Point, error) { |
|
|
|
points := make([]point.Point, 0, len(args)) |
|
|
|
for i, arg := range args { |
|
|
|
id, err := toPointID(arg) |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("parsing args[0] to pointID: %w", err) |
|
|
|
return nil, fmt.Errorf("parsing args[%d] to pointID: %w", i, err) |
|
|
|
} |
|
|
|
|
|
|
|
p0, err := p.getOrCreate(id0, pat, 0) |
|
|
|
newPoint, err := p.getOrCreate(id, pat, 0) |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("get or create point %q: %w", id0, err) |
|
|
|
return nil, fmt.Errorf("get or create point %q: %w", id, err) |
|
|
|
} |
|
|
|
|
|
|
|
p1, err := p.getOrCreate(id1, pat, 0) |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("get or create point %q: %w", id1, err) |
|
|
|
points = append(points, newPoint) |
|
|
|
} |
|
|
|
|
|
|
|
return p0.Vector().AngleBetween(p1.Vector()), nil |
|
|
|
}, |
|
|
|
} |
|
|
|
return points, nil |
|
|
|
} |
|
|
|
|
|
|
|
func toPointID(arg interface{}) (point.ID, error) { |
|
|
|
@@ -111,9 +111,19 @@ type BetweenPoint struct { |
|
|
|
func (p Points) evaluationFunctions() map[string]govaluate.ExpressionFunction { |
|
|
|
return map[string]govaluate.ExpressionFunction{ |
|
|
|
"acos": func(args ...interface{}) (interface{}, error) { |
|
|
|
if len(args) != 1 { |
|
|
|
return nil, fmt.Errorf("function acos() requires 1 argument: %w", |
|
|
|
ErrInvalidArguments) |
|
|
|
} |
|
|
|
|
|
|
|
return math.Acos(args[0].(float64)), nil |
|
|
|
}, |
|
|
|
"atan2": func(args ...interface{}) (interface{}, error) { |
|
|
|
if len(args) != 2 { |
|
|
|
return nil, fmt.Errorf("function atan2() requires 2 arguments: %w", |
|
|
|
ErrInvalidArguments) |
|
|
|
} |
|
|
|
|
|
|
|
return math.Atan2(args[0].(float64), args[1].(float64)), nil |
|
|
|
}, |
|
|
|
} |
|
|
|
|