-
Notifications
You must be signed in to change notification settings - Fork 12
/
fork.go
91 lines (81 loc) · 2.19 KB
/
fork.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package main
import (
"math"
"github.com/unixpickle/model3d/model2d"
"github.com/unixpickle/model3d/model3d"
"github.com/unixpickle/model3d/toolbox3d"
)
const (
ForkLength = 5.0
ForkDip = 0.5
ForkMaxWidth = 1.0
ForkTipWidth = 0.2
ForkThickness = 0.1
ForkProngLength = 1.5 * ForkLength / 5
ForkNumProngs = 4
)
type ForkSolid struct {
HeightCurve model2d.BezierCurve
WidthCurve model2d.BezierCurve
MinVal model3d.Coord3D
MaxVal model3d.Coord3D
}
func NewForkSolid() *ForkSolid {
c := model2d.BezierCurve{
model2d.Coord{X: 0, Y: 0},
model2d.Coord{X: ForkProngLength, Y: -ForkDip * 2},
model2d.Coord{X: 3 * ForkLength / 5, Y: 0},
model2d.Coord{X: 3 * ForkLength / 5, Y: 0},
model2d.Coord{X: ForkLength, Y: 0},
}
_, minZ := (&toolbox3d.LineSearch{Stops: 1000}).Minimize(0, 1, func(t float64) float64 {
return c.Eval(t).Y
})
wc := model2d.BezierCurve{
model2d.Coord{X: 0, Y: ForkMaxWidth / 2},
model2d.Coord{X: ForkProngLength, Y: ForkMaxWidth / 2},
model2d.Coord{X: ForkProngLength, Y: ForkMaxWidth / 2},
model2d.Coord{X: 1.1 * ForkProngLength, Y: ForkMaxWidth / 2},
model2d.Coord{X: 1.5 * ForkProngLength, Y: ForkTipWidth / 2},
model2d.Coord{X: 1.5 * ForkProngLength, Y: ForkTipWidth / 2},
model2d.Coord{X: ForkLength, Y: ForkTipWidth / 2},
}
return &ForkSolid{
HeightCurve: c,
WidthCurve: wc,
MinVal: model3d.XYZ(0, -ForkMaxWidth/2, minZ),
MaxVal: model3d.XYZ(ForkLength, ForkMaxWidth/2, ForkThickness),
}
}
func (f *ForkSolid) Min() model3d.Coord3D {
return f.MinVal
}
func (f *ForkSolid) Max() model3d.Coord3D {
return f.MaxVal
}
func (f *ForkSolid) Contains(c model3d.Coord3D) bool {
if !model3d.InBounds(f, c) {
return false
}
zMin := f.HeightCurve.EvalX(c.X)
if c.Z < zMin || c.Z > zMin+ForkThickness {
return false
}
width := f.WidthCurve.EvalX(c.X)
if math.Abs(c.Y) > width {
return false
}
if c.X < ForkProngLength {
prongWidth := width / 8 * math.Sqrt(1-(ForkProngLength-c.X)/ForkProngLength)
for i := 0.0; i < 4; i++ {
minY := -(width - width/8)
maxY := -minY
prongY := minY + i*(maxY-minY)/3
if math.Abs(c.Y-prongY) < prongWidth {
return true
}
}
return false
}
return true
}