#1 Fix panic on evaluate functions

已合併
wouter 1 年之前 將 1 次代碼提交從 fix-panic-on-evaluate-functions合併至 master
  1. +42
    -32
      pkg/pattern/template/point.go

+ 42
- 32
pkg/pattern/template/point.go 查看文件

@@ -19,6 +19,8 @@ var (


// ErrRelativePointRecursion is returned when a points are relative to itself. // ErrRelativePointRecursion is returned when a points are relative to itself.
ErrRelativePointRecursion = errors.New("point cannot be 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. // 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 { func (p Points) Functions(pat *pattern.Pattern) map[string]govaluate.ExpressionFunction {
return map[string]govaluate.ExpressionFunction{ return map[string]govaluate.ExpressionFunction{
"DistanceBetween": func(args ...interface{}) (interface{}, error) { "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)
}

id1, err := toPointID(args[1])
if err != nil {
return nil, fmt.Errorf("parsing args[0] to pointID: %w", err)
}

p0, err := p.getOrCreate(id0, pat, 0)
if err != nil {
return nil, fmt.Errorf("get or create point %q: %w", id0, err)
if len(args) != 2 {
return nil, fmt.Errorf("function DistanceBetween() requires 2 arguments: %w",
ErrInvalidArguments)
} }


p1, err := p.getOrCreate(id1, pat, 0)
points, err := p.getOrCreateFromArgs(pat, args...)
if err != nil { 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].Position().Distance(points[1].Position()), nil
}, },
"AngleBetween": func(args ...interface{}) (interface{}, error) { "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)
if len(args) != 2 {
return nil, fmt.Errorf("function AngleBetween() requires 2 arguments: %w",
ErrInvalidArguments)
} }


id1, err := toPointID(args[1])
points, err := p.getOrCreateFromArgs(pat, args...)
if err != nil { 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].Vector().AngleBetween(points[1].Vector()), nil
},
}
}


p1, err := p.getOrCreate(id1, pat, 0)
if err != nil {
return nil, fmt.Errorf("get or create point %q: %w", id1, err)
}
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[%d] to pointID: %w", i, err)
}


return p0.Vector().AngleBetween(p1.Vector()), nil
},
newPoint, err := p.getOrCreate(id, pat, 0)
if err != nil {
return nil, fmt.Errorf("get or create point %q: %w", id, err)
}

points = append(points, newPoint)
} }

return points, nil
} }


func toPointID(arg interface{}) (point.ID, error) { func toPointID(arg interface{}) (point.ID, error) {
@@ -111,9 +111,19 @@ type BetweenPoint struct {
func (p Points) evaluationFunctions() map[string]govaluate.ExpressionFunction { func (p Points) evaluationFunctions() map[string]govaluate.ExpressionFunction {
return map[string]govaluate.ExpressionFunction{ return map[string]govaluate.ExpressionFunction{
"acos": func(args ...interface{}) (interface{}, error) { "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 return math.Acos(args[0].(float64)), nil
}, },
"atan2": func(args ...interface{}) (interface{}, error) { "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 return math.Atan2(args[0].(float64), args[1].(float64)), nil
}, },
} }


Loading…
取消
儲存