diff --git a/examples/README.md b/examples/README.md index 246c894..c2de1ec 100644 --- a/examples/README.md +++ b/examples/README.md @@ -3,11 +3,20 @@ Click on image to go to code directory. +## Metric spacers M3,M4,M6,M8,M16 + +| Example | Execution Time | File size | +|---|---|---| +|[Metric spacers M3,M4,M6,M8,M16](metric-spacers)|1s|9451kB| + +[![Metric spacers M3,M4,M6,M8,M16](fig/metric-spacers.png)](metric-spacers) + + ## ADZ Nagano sensor cover | Example | Execution Time | File size | |---|---|---| -|[ADZ Nagano sensor cover](adz-sensor-cover)|1s|10MB| +|[ADZ Nagano sensor cover](adz-sensor-cover)|0.5s|10MB| [![ADZ Nagano sensor cover](fig/adz-sensor-cover.png)](adz-sensor-cover) @@ -25,7 +34,7 @@ Click on image to go to code directory. | Example | Execution Time | File size | |---|---|---| -|[ATX Bench power supply mod](atx-bench-supply)|1s|4540kB| +|[ATX Bench power supply mod](atx-bench-supply)|0.5s|4540kB| [![ATX Bench power supply mod](fig/atx-bench-supply.png)](atx-bench-supply) diff --git a/examples/fig/metric-spacers.png b/examples/fig/metric-spacers.png new file mode 100644 index 0000000..4ddf86c Binary files /dev/null and b/examples/fig/metric-spacers.png differ diff --git a/examples/generate_examples.go b/examples/generate_examples.go index ae764c2..2e87eaf 100644 --- a/examples/generate_examples.go +++ b/examples/generate_examples.go @@ -36,6 +36,12 @@ var examples = []struct { ExecutionTime string }{ // Add new examples here! + { + Name: "Metric spacers M3,M4,M6,M8,M16", + Dir: "metric-spacers", + resultSTL: "spacers.stl", + view: defaultView, + }, { Name: "ADZ Nagano sensor cover", Dir: "adz-sensor-cover", diff --git a/examples/metric-spacers/spacers.go b/examples/metric-spacers/spacers.go new file mode 100644 index 0000000..bc866b1 --- /dev/null +++ b/examples/metric-spacers/spacers.go @@ -0,0 +1,66 @@ +package main + +import ( + "math" + + "github.com/soypat/sdf" + "github.com/soypat/sdf/form3" + "github.com/soypat/sdf/form3/obj3/thread" + "github.com/soypat/sdf/helpers/matter" + "github.com/soypat/sdf/render" + "gonum.org/v1/gonum/spatial/r3" +) + +type spacer struct { + // Metric diameter. + D float64 + // Height of spacer. + H float64 +} + +func main() { + spacers := []spacer{ + {D: 3, H: 7}, + {D: 3, H: 12}, + {D: 4, H: 7}, + {D: 6, H: 30}, + {D: 8, H: 30}, + {D: 16, H: 10}, + } + var sdfs []sdf.SDF3 + var x float64 + for i := range spacers { + s, err := spacers[i].sdf(matter.PLA) + if err != nil { + panic(err) + } + s = sdf.Transform3D(s, sdf.Translate3D(r3.Vec{X: x})) + sdfs = append(sdfs, s) + x += spacers[i].D * 3 + } + s := sdf.Union3D(sdfs...) + err := render.CreateSTL("spacers.stl", render.NewOctreeRenderer(s, 300)) + if err != nil { + panic(err) + } +} + +func (s spacer) sdf(material matter.Material) (sdf.SDF3, error) { + const tol = 0.03 + holeCorrected := material.InternalDimScale(s.D * (1 + tol)) + ftf := math.Ceil(holeCorrected*1.4) - .15 // Face to face hex distance + hexRadius := getHexRadiusFromFTF(ftf) + sp, err := thread.HexHead(hexRadius, s.H, "") + if err != nil { + return nil, err + } + hole, err := form3.Cylinder(s.H, holeCorrected/2, 0) + if err != nil { + return nil, err + } + return sdf.Difference3D(sp, hole), nil +} + +func getHexRadiusFromFTF(ftf float64) (radius float64) { + return ftf / math.Cos(30.*math.Pi/180.) / 2 +} diff --git a/helpers/matter/3dprint.go b/helpers/matter/3dprint.go index df13776..51b8420 100644 --- a/helpers/matter/3dprint.go +++ b/helpers/matter/3dprint.go @@ -2,12 +2,22 @@ package matter import "github.com/soypat/sdf" +type Material interface { + Scale(s sdf.SDF3) sdf.SDF3 + InternalDimScale(real float64) float64 +} + var ( // PLA (polylactic acid) is the most widely used plastic filament material in 3D printing. - PLA = ViscousMaterial{shrink: 0.2e-2, pullShrink: .45} // 0.2% shrinkage + PLA = Viscoelastic{shrink: 0.3e-2, pullShrink: .45} // 0.3% shrinkage ) -type ViscousMaterial struct { +type Ideal struct{} + +func (Ideal) Scale(s sdf.SDF3) sdf.SDF3 { return s } +func (Ideal) InternalDimScale(real float64) float64 { return real } + +type Viscoelastic struct { // shrink is the thermal contraction shrinkage of a material once the material // cools to room temperature after the heated bed is turned off. shrink float64 @@ -16,13 +26,12 @@ type ViscousMaterial struct { } // Scale scales a 3D -func (m ViscousMaterial) Scale(s sdf.SDF3) sdf.SDF3 { - scale := 1 / (1 - m.shrink) // is this correct? - return sdf.ScaleUniform3D(s, scale) +func (m Viscoelastic) Scale(s sdf.SDF3) sdf.SDF3 { + return sdf.ScaleUniform3D(s, 1+m.shrink) } -func (m ViscousMaterial) InternalDimScale(real float64) float64 { +func (m Viscoelastic) InternalDimScale(real float64) float64 { if real <= 0 { panic("InternalDimScale only works for non-zero dimensions") }