From 8ef4bd432aa5cf97481525ef9cb0c71d76a7984b Mon Sep 17 00:00:00 2001 From: soypat Date: Sun, 15 May 2022 14:39:22 -0300 Subject: [PATCH] add thread package --- .gitignore | 1 + README.md | 2 + examples/README.md | 2 +- examples/atx-bench-supply/atx.go | 4 +- examples/npt-flange/flange.go | 11 +- form2/obj2/thread.go | 314 ------------------ form3/obj3/bolt.go | 75 ----- form3/obj3/nut.go | 47 --- form3/obj3/obj3.go | 24 -- form3/obj3/standoff.go | 2 +- form3/obj3/thread/acme.go | 45 +++ form3/obj3/thread/ansibuttress.go | 46 +++ form3/obj3/thread/basic.go | 52 +++ form3/obj3/thread/bolt.go | 75 +++++ form3/obj3/{hex.go => thread/hexhead.go} | 26 +- form3/obj3/thread/iso.go | 61 ++++ form3/obj3/{ => thread}/knurl.go | 48 ++- form3/obj3/thread/legacy_test.go | 234 +++++++++++++ form3/obj3/thread/npt.go | 72 ++++ form3/obj3/thread/nut.go | 79 +++++ form3/obj3/thread/parameters.go | 26 ++ form3/obj3/thread/plasticbuttress.go | 45 +++ .../{must3/screw.go => obj3/thread/thread.go} | 64 ++-- form3/obj3/thread/uts.go | 25 ++ form3/screw.go | 25 -- render/3mf_test.go | 2 + render/form3_test.go | 20 +- render/internal_test.go | 8 +- render/kdrender.go | 206 ------------ render/kdrender_test.go | 213 +++++++++++- render/render_test.go | 19 +- render/stl_test.go | 1 + render/testdata/defactoBolt.png | Bin 86762 -> 87037 bytes sdf3.go | 8 +- 34 files changed, 1112 insertions(+), 770 deletions(-) delete mode 100644 form2/obj2/thread.go delete mode 100644 form3/obj3/bolt.go delete mode 100644 form3/obj3/nut.go delete mode 100644 form3/obj3/obj3.go create mode 100644 form3/obj3/thread/acme.go create mode 100644 form3/obj3/thread/ansibuttress.go create mode 100644 form3/obj3/thread/basic.go create mode 100644 form3/obj3/thread/bolt.go rename form3/obj3/{hex.go => thread/hexhead.go} (65%) create mode 100644 form3/obj3/thread/iso.go rename form3/obj3/{ => thread}/knurl.go (65%) create mode 100644 form3/obj3/thread/legacy_test.go create mode 100644 form3/obj3/thread/npt.go create mode 100644 form3/obj3/thread/nut.go create mode 100644 form3/obj3/thread/parameters.go create mode 100644 form3/obj3/thread/plasticbuttress.go rename form3/{must3/screw.go => obj3/thread/thread.go} (54%) create mode 100644 form3/obj3/thread/uts.go delete mode 100644 form3/screw.go delete mode 100644 render/kdrender.go diff --git a/.gitignore b/.gitignore index 56e162b..51e0346 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ # Exclude CPU and memory profiles *.prof +*.pprof *.png # Exclude all png files except for test files diff --git a/README.md b/README.md index 1a3631c..4b8d946 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,8 @@ Advantages of soypat/sdf: - Uses gonum's `spatial` package - `sdfx` has own vector types with methods which [hurt code legibility](https://github.com/deadsy/sdfx/issues/48) - `spatial` types from gonum library with correct Triangle degeneracy calculation. `deadsy/sdfx`'s Degenerate calculation is incorrect. +- Idiomatic [`thread`](./form3/obj3/thread/thread.go) package. Define arbitrary threads with ease using `Threader` interface. + - `deadsy/sdfx` defines threads with strings i.e. `"M16x2"`. `sdf` Defines threads with types corresponding to standards. i.e: `thread.ISO{D:16, P:2}`, which defines an M16x2 ISO thread. ## Contributing diff --git a/examples/README.md b/examples/README.md index fb2d751..246c894 100644 --- a/examples/README.md +++ b/examples/README.md @@ -25,7 +25,7 @@ Click on image to go to code directory. | Example | Execution Time | File size | |---|---|---| -|[ATX Bench power supply mod](atx-bench-supply)|0.5s|4540kB| +|[ATX Bench power supply mod](atx-bench-supply)|1s|4540kB| [![ATX Bench power supply mod](fig/atx-bench-supply.png)](atx-bench-supply) diff --git a/examples/atx-bench-supply/atx.go b/examples/atx-bench-supply/atx.go index 5c8408f..3488e46 100644 --- a/examples/atx-bench-supply/atx.go +++ b/examples/atx-bench-supply/atx.go @@ -59,12 +59,12 @@ func main() { // Begin working on regulated step-down block regOut = sdf.Array2D(bananaPlugSmall, sdf.V2i{2, 1}, r2.Vec{bananaSpacing, bananaSpacing}) - bplugX := bbSize(regBlock.Bounds()).X + bplugX := bbSize(regOut.Bounds()).X vDisp := sdf.Transform2D(voltageDisplay, sdf.Translate2d(r2.Vec{bplugX / 2, vDispH/2 + bananaSpacing/2})) regOut = sdf.Union2D(regOut, vDisp) regOut = sdf.Transform2D(regOut, sdf.Translate2d(r2.Vec{-atxW/2 - bplugX/2 + vDispW/2 + 12, atxH/2 - 12 - vDispH/2 - bananaSpacing})) // Create mound for step up outputs. - regSz := bbSize(regBlock.Bounds()) + regSz := bbSize(regOut.Bounds()) regBlock = form2.Box(r2.Vec{regSz.X + regBlockMargin, regSz.Y + regBlockMargin}, regBlockMargin/2) regBlock = sdf.Transform2D(regBlock, sdf.Translate2d(bbCenter(regOut.Bounds()))) regBlock = sdf.Difference2D(regBlock, regOut) diff --git a/examples/npt-flange/flange.go b/examples/npt-flange/flange.go index 0b5be28..2328a9f 100644 --- a/examples/npt-flange/flange.go +++ b/examples/npt-flange/flange.go @@ -3,7 +3,7 @@ package main import ( "github.com/soypat/sdf" form3 "github.com/soypat/sdf/form3/must3" - "github.com/soypat/sdf/form3/obj3" + "github.com/soypat/sdf/form3/obj3/thread" "github.com/soypat/sdf/render" "gonum.org/v1/gonum/spatial/r3" ) @@ -14,18 +14,19 @@ const ( internalDiameter = 1.5 / 2. flangeH = 7 / 25.4 flangeD = 60. / 25.4 - thread = "npt_1/2" // internal diameter scaling. plaScale = 1.03 ) func main() { var ( + npt thread.NPT flange sdf.SDF3 ) - pipe, err := obj3.Nut(obj3.NutParms{ - Thread: thread, - Style: obj3.CylinderCircular, + npt.SetFromNominal(1.0 / 2.0) + pipe, err := thread.Nut(thread.NutParms{ + Thread: npt, + Style: thread.NutCircular, }) if err != nil { panic(err) diff --git a/form2/obj2/thread.go b/form2/obj2/thread.go deleted file mode 100644 index e7d1d3b..0000000 --- a/form2/obj2/thread.go +++ /dev/null @@ -1,314 +0,0 @@ -package obj2 - -import ( - "fmt" - "log" - "math" - - "github.com/soypat/sdf" - "github.com/soypat/sdf/form2/must2" -) - -// Screws -// Screws are made by taking a 2D thread profile, rotating it about the z-axis and -// spiralling it upwards as we move along z. -// -// The 2D thread profiles are a polygon of a single thread centered on the y-axis with -// the x-axis as the screw axis. Most thread profiles are symmetric about the y-axis -// but a few aren't (E.g. buttress threads) so in general we build the profile of -// an entire pitch period. -// -// This code doesn't deal with thread tolerancing. If you want threads to fit properly -// the radius of the thread will need to be tweaked (+/-) to give internal/external thread -// clearance. - -// Thread Database - lookup standard screw threads by name - -// ThreadParameters stores the values that define a thread. -type ThreadParameters struct { - Name string // name of screw thread - Radius float64 // nominal major radius of screw - Pitch float64 // thread to thread distance of screw - Taper float64 // thread taper (radians) - HexFlat2Flat float64 // hex head flat to flat distance - Units string // "inch" or "mm" -} - -type threadDatabase map[string]ThreadParameters - -var threadDB = initThreadLookup() - -// UTSAdd adds a Unified Thread Standard to the thread database. -// diameter is screw major diameter. -// tpi is threads per inch. -// ftof is hex head flat to flat distance. -func (m threadDatabase) UTSAdd(name string, diameter float64, tpi float64, ftof float64) { - if ftof <= 0 { - log.Panicf("bad flat to flat distance for thread \"%s\"", name) - } - t := ThreadParameters{} - t.Name = name - t.Radius = diameter / 2.0 - t.Pitch = 1.0 / tpi - t.HexFlat2Flat = ftof - t.Units = "inch" - m[name] = t -} - -// ISOAdd adds an ISO Thread Standard to the thread database. -func (m threadDatabase) ISOAdd( - name string, // thread name - diameter float64, // screw major diamater - pitch float64, // thread pitch - ftof float64, // hex head flat to flat distance -) { - if ftof <= 0 { - log.Panicf("bad flat to flat distance for thread \"%s\"", name) - } - t := ThreadParameters{} - t.Name = name - t.Radius = diameter / 2.0 - t.Pitch = pitch - t.HexFlat2Flat = ftof - t.Units = "mm" - m[name] = t -} - -// NPTAdd adds an National Pipe Thread to the thread database. -func (m threadDatabase) NPTAdd( - name string, // thread name - diameter float64, // screw major diameter - tpi float64, // threads per inch - ftof float64, // hex head flat to flat distance -) { - if ftof <= 0 { - log.Panicf("bad flat to flat distance for thread \"%s\"", name) - } - t := ThreadParameters{} - t.Name = name - t.Radius = diameter / 2.0 - t.Pitch = 1.0 / tpi - t.Taper = math.Atan(1.0 / 32.0) - t.HexFlat2Flat = ftof - t.Units = "inch" - m[name] = t -} - -// initThreadLookup adds a collection of standard threads to the thread database. -func initThreadLookup() threadDatabase { - m := make(threadDatabase) - // UTS Coarse - m.UTSAdd("unc_1/4", 1.0/4.0, 20, 7.0/16.0) - m.UTSAdd("unc_5/16", 5.0/16.0, 18, 1.0/2.0) - m.UTSAdd("unc_3/8", 3.0/8.0, 16, 9.0/16.0) - m.UTSAdd("unc_7/16", 7.0/16.0, 14, 5.0/8.0) - m.UTSAdd("unc_1/2", 1.0/2.0, 13, 3.0/4.0) - m.UTSAdd("unc_9/16", 9.0/16.0, 12, 13.0/16.0) - m.UTSAdd("unc_5/8", 5.0/8.0, 11, 15.0/16.0) - m.UTSAdd("unc_3/4", 3.0/4.0, 10, 9.0/8.0) - m.UTSAdd("unc_7/8", 7.0/8.0, 9, 21.0/16.0) - m.UTSAdd("unc_1", 1.0, 8, 3.0/2.0) - // UTS Fine - m.UTSAdd("unf_1/4", 1.0/4.0, 28, 7.0/16.0) - m.UTSAdd("unf_5/16", 5.0/16.0, 24, 1.0/2.0) - m.UTSAdd("unf_3/8", 3.0/8.0, 24, 9.0/16.0) - m.UTSAdd("unf_7/16", 7.0/16.0, 20, 5.0/8.0) - m.UTSAdd("unf_1/2", 1.0/2.0, 20, 3.0/4.0) - m.UTSAdd("unf_9/16", 9.0/16.0, 18, 13.0/16.0) - m.UTSAdd("unf_5/8", 5.0/8.0, 18, 15.0/16.0) - m.UTSAdd("unf_3/4", 3.0/4.0, 16, 9.0/8.0) - m.UTSAdd("unf_7/8", 7.0/8.0, 14, 21.0/16.0) - m.UTSAdd("unf_1", 1.0, 12, 3.0/2.0) - - // National Pipe Thread. Face to face distance taken from ASME B16.11 Plug Manufacturer (mm) - m.NPTAdd("npt_1/8", 0.405, 27, 11.2*InchesPerMillimetre) - m.NPTAdd("npt_1/4", 0.540, 18, 15.7*InchesPerMillimetre) - m.NPTAdd("npt_3/8", 0.675, 18, 17.5*InchesPerMillimetre) - m.NPTAdd("npt_1/2", 0.840, 14, 22.4*InchesPerMillimetre) - m.NPTAdd("npt_3/4", 1.050, 14, 26.9*InchesPerMillimetre) - m.NPTAdd("npt_1", 1.315, 11.5, 35.1*InchesPerMillimetre) - m.NPTAdd("npt_1_1/4", 1.660, 11.5, 44.5*InchesPerMillimetre) - m.NPTAdd("npt_1_1/2", 1.900, 11.5, 50.8*InchesPerMillimetre) - m.NPTAdd("npt_2", 2.375, 11.5, 63.5*InchesPerMillimetre) - m.NPTAdd("npt_2_1/2", 2.875, 8, 76.2*InchesPerMillimetre) - m.NPTAdd("npt_3", 3.500, 8, 88.9*InchesPerMillimetre) - m.NPTAdd("npt_4", 4.500, 8, 117.3*InchesPerMillimetre) - - // ISO Coarse - m.ISOAdd("M1x0.25", 1, 0.25, 1.75) // ftof? - m.ISOAdd("M1.2x0.25", 1.2, 0.25, 2.0) // ftof? - m.ISOAdd("M1.6x0.35", 1.6, 0.35, 3.2) - m.ISOAdd("M2x0.4", 2, 0.4, 4) - m.ISOAdd("M2.5x0.45", 2.5, 0.45, 5) - m.ISOAdd("M3x0.5", 3, 0.5, 6) - m.ISOAdd("M4x0.7", 4, 0.7, 7) - m.ISOAdd("M5x0.8", 5, 0.8, 8) - m.ISOAdd("M6x1", 6, 1, 10) - m.ISOAdd("M8x1.25", 8, 1.25, 13) - m.ISOAdd("M10x1.5", 10, 1.5, 17) - m.ISOAdd("M12x1.75", 12, 1.75, 19) - m.ISOAdd("M16x2", 16, 2, 24) - m.ISOAdd("M20x2.5", 20, 2.5, 30) - m.ISOAdd("M24x3", 24, 3, 36) - m.ISOAdd("M30x3.5", 30, 3.5, 46) - m.ISOAdd("M36x4", 36, 4, 55) - m.ISOAdd("M42x4.5", 42, 4.5, 65) - m.ISOAdd("M48x5", 48, 5, 75) - m.ISOAdd("M56x5.5", 56, 5.5, 85) - m.ISOAdd("M64x6", 64, 6, 95) - // ISO Fine - m.ISOAdd("M1x0.2", 1, 0.2, 1.75) // ftof? - m.ISOAdd("M1.2x0.2", 1.2, 0.2, 2.0) // ftof? - m.ISOAdd("M1.6x0.2", 1.6, 0.2, 3.2) - m.ISOAdd("M2x0.25", 2, 0.25, 4) - m.ISOAdd("M2.5x0.35", 2.5, 0.35, 5) - m.ISOAdd("M3x0.35", 3, 0.35, 6) - m.ISOAdd("M4x0.5", 4, 0.5, 7) - m.ISOAdd("M5x0.5", 5, 0.5, 8) - m.ISOAdd("M6x0.75", 6, 0.75, 10) - m.ISOAdd("M8x1", 8, 1, 13) - m.ISOAdd("M10x1.25", 10, 1.25, 17) - m.ISOAdd("M12x1.5", 12, 1.5, 19) - m.ISOAdd("M16x1.5", 16, 1.5, 24) - m.ISOAdd("M20x2", 20, 2, 30) - m.ISOAdd("M24x2", 24, 2, 36) - m.ISOAdd("M30x2", 30, 2, 46) - m.ISOAdd("M36x3", 36, 3, 55) - m.ISOAdd("M42x3", 42, 3, 65) - m.ISOAdd("M48x3", 48, 3, 75) - m.ISOAdd("M56x4", 56, 4, 85) - m.ISOAdd("M64x4", 64, 4, 95) - return m -} - -// ThreadLookup lookups the parameters for a thread by name. -func ThreadLookup(name string) (ThreadParameters, error) { - if t, ok := threadDB[name]; ok { - return t, nil - } - return ThreadParameters{}, fmt.Errorf("thread \"%s\" not found", name) -} - -// HexRadius returns the hex head radius. -func (t *ThreadParameters) HexRadius() float64 { - return t.HexFlat2Flat / (2.0 * math.Cos(30*math.Pi/180)) -} - -// HexHeight returns the hex head height (empirical). -func (t *ThreadParameters) HexHeight() float64 { - return 2.0 * t.HexRadius() * (5.0 / 12.0) -} - -// Thread Profiles - -// AcmeThread returns the 2d profile for an acme thread. -// radius is radius of thread. pitch is thread-to-thread distance. -func AcmeThread(radius float64, pitch float64) sdf.SDF2 { - - h := radius - 0.5*pitch - theta := d2r(29.0 / 2.0) - delta := 0.25 * pitch * math.Tan(theta) - xOfs0 := 0.25*pitch - delta - xOfs1 := 0.25*pitch + delta - - acme := must2.NewPolygon() - acme.Add(radius, 0) - acme.Add(radius, h) - acme.Add(xOfs1, h) - acme.Add(xOfs0, radius) - acme.Add(-xOfs0, radius) - acme.Add(-xOfs1, h) - acme.Add(-radius, h) - acme.Add(-radius, 0) - - return must2.Polygon(acme.Vertices()) -} - -// ISOThread returns the 2d profile for an ISO/UTS thread. -// https://en.wikipedia.org/wiki/ISO_metric_screw_thread -// https://en.wikipedia.org/wiki/Unified_Thread_Standard -// radius is radius of thread. pitch is thread-to-thread distance. -// external (or internal) thread -func ISOThread(radius float64, pitch float64, external bool) sdf.SDF2 { - theta := d2r(30.0) - h := pitch / (2.0 * math.Tan(theta)) - rMajor := radius - r0 := rMajor - (7.0/8.0)*h - - iso := must2.NewPolygon() - if external { - rRoot := (pitch / 8.0) / math.Cos(theta) - xOfs := (1.0 / 16.0) * pitch - iso.Add(pitch, 0) - iso.Add(pitch, r0+h) - iso.Add(pitch/2.0, r0).Smooth(rRoot, 5) - iso.Add(xOfs, rMajor) - iso.Add(-xOfs, rMajor) - iso.Add(-pitch/2.0, r0).Smooth(rRoot, 5) - iso.Add(-pitch, r0+h) - iso.Add(-pitch, 0) - } else { - rMinor := r0 + (1.0/4.0)*h - rCrest := (pitch / 16.0) / math.Cos(theta) - xOfs := (1.0 / 8.0) * pitch - iso.Add(pitch, 0) - iso.Add(pitch, rMinor) - iso.Add(pitch/2-xOfs, rMinor) - iso.Add(0, r0+h).Smooth(rCrest, 5) - iso.Add(-pitch/2+xOfs, rMinor) - iso.Add(-pitch, rMinor) - iso.Add(-pitch, 0) - } - return must2.Polygon(iso.Vertices()) -} - -// ANSIButtressThread returns the 2d profile for an ANSI 45/7 buttress thread. -// https://en.wikipedia.org/wiki/Buttress_thread -// AMSE B1.9-1973 -// radius is radius of thread. pitch is thread-to-thread distance. -func ANSIButtressThread(radius float64, pitch float64) sdf.SDF2 { - t0 := math.Tan(d2r(45.0)) - t1 := math.Tan(d2r(7.0)) - b := 0.6 // thread engagement - - h0 := pitch / (t0 + t1) - h1 := ((b / 2.0) * pitch) + (0.5 * h0) - hp := pitch / 2.0 - - tp := must2.NewPolygon() - tp.Add(pitch, 0) - tp.Add(pitch, radius) - tp.Add(hp-((h0-h1)*t1), radius) - tp.Add(t0*h0-hp, radius-h1).Smooth(0.0714*pitch, 5) - tp.Add((h0-h1)*t0-hp, radius) - tp.Add(-pitch, radius) - tp.Add(-pitch, 0) - - return must2.Polygon(tp.Vertices()) -} - -// PlasticButtressThread returns the 2d profile for a screw top style plastic buttress thread. -// Similar to ANSI 45/7 - but with more corner rounding -// radius is radius of thread. pitch is thread-to-thread distance. -func PlasticButtressThread(radius float64, pitch float64) sdf.SDF2 { - t0 := math.Tan(d2r(45.0)) - t1 := math.Tan(d2r(7.0)) - b := 0.6 // thread engagement - - h0 := pitch / (t0 + t1) - h1 := ((b / 2.0) * pitch) + (0.5 * h0) - hp := pitch / 2.0 - - tp := must2.NewPolygon() - tp.Add(pitch, 0) - tp.Add(pitch, radius) - tp.Add(hp-((h0-h1)*t1), radius).Smooth(0.05*pitch, 5) - tp.Add(t0*h0-hp, radius-h1).Smooth(0.15*pitch, 5) - tp.Add((h0-h1)*t0-hp, radius).Smooth(0.15*pitch, 5) - tp.Add(-pitch, radius) - tp.Add(-pitch, 0) - - return must2.Polygon(tp.Vertices()) -} -func d2r(degrees float64) float64 { return degrees * math.Pi / 180. } -func r2d(radians float64) float64 { return radians / math.Pi * 180. } diff --git a/form3/obj3/bolt.go b/form3/obj3/bolt.go deleted file mode 100644 index 439482c..0000000 --- a/form3/obj3/bolt.go +++ /dev/null @@ -1,75 +0,0 @@ -package obj3 - -import ( - "github.com/soypat/sdf" - "github.com/soypat/sdf/form2/obj2" - form3 "github.com/soypat/sdf/form3/must3" - "gonum.org/v1/gonum/spatial/r3" -) - -// Bolts: Screws, nuts etc. - -// BoltParms defines the parameters for a bolt. -type BoltParms struct { - Thread string // name of thread - Style CylinderStyle // head style "hex" or "knurl" - Tolerance float64 // subtract from external thread radius - TotalLength float64 // threaded length + shank length - ShankLength float64 // non threaded length -} - -// Bolt returns a simple bolt suitable for 3d printing. -func Bolt(k BoltParms) (s sdf.SDF3, err error) { - // validate parameters - t, err := obj2.ThreadLookup(k.Thread) - if err != nil { - panic(err) - } - if k.TotalLength < 0 { - panic("TotalLength < 0") - } - if k.ShankLength < 0 { - panic("ShankLength < 0") - } - if k.Tolerance < 0 { - panic("Tolerance < 0") - } - - // head - var head sdf.SDF3 - hr := t.HexRadius() - hh := t.HexHeight() - switch k.Style { - case CylinderHex: - head, _ = HexHead(hr, hh, "b") - case CylinderKnurl: - head, _ = KnurledHead(hr, hh, hr*0.25) - default: - panic("unknown style for bolt " + k.Style.String()) - } - - // shank - shankLength := k.ShankLength + hh/2 - shankOffset := shankLength / 2 - var shank sdf.SDF3 = form3.Cylinder(shankLength, t.Radius, hh*0.08) - shank = sdf.Transform3D(shank, sdf.Translate3D(r3.Vec{0, 0, shankOffset})) - - // external thread - threadLength := k.TotalLength - k.ShankLength - if threadLength < 0 { - threadLength = 0 - } - var thread sdf.SDF3 - if threadLength != 0 { - r := t.Radius - k.Tolerance - threadOffset := threadLength/2 + shankLength - isoThread := obj2.ISOThread(r, t.Pitch, true) - thread = form3.Screw(isoThread, threadLength, t.Taper, t.Pitch, 1) - // chamfer the thread - thread = form3.ChamferedCylinder(thread, 0, 0.5) - - thread = sdf.Transform3D(thread, sdf.Translate3D(r3.Vec{0, 0, threadOffset})) - } - - return sdf.Union3D(head, shank, thread), nil // TODO error handling -} diff --git a/form3/obj3/nut.go b/form3/obj3/nut.go deleted file mode 100644 index 39b6654..0000000 --- a/form3/obj3/nut.go +++ /dev/null @@ -1,47 +0,0 @@ -package obj3 - -import ( - "github.com/soypat/sdf" - "github.com/soypat/sdf/form2/obj2" - form3 "github.com/soypat/sdf/form3/must3" -) - -// NutParms defines the parameters for a nut. -type NutParms struct { - Thread string // name of thread - Style CylinderStyle - Tolerance float64 // add to internal thread radius -} - -// Nut returns a simple nut suitable for 3d printing. -func Nut(k NutParms) (s sdf.SDF3, err error) { - if k.Tolerance < 0 { - panic("Tolerance < 0") - } - // validate parameters - t, err := obj2.ThreadLookup(k.Thread) - if err != nil { - panic(err) - } - - // nut body - var nut sdf.SDF3 - nr := t.HexRadius() - nh := t.HexHeight() - switch k.Style { - case CylinderHex: // TODO error handling - nut, _ = HexHead(nr, nh, "tb") - case CylinderKnurl: - nut, _ = KnurledHead(nr, nh, nr*0.25) - case CylinderCircular: - nut = form3.Cylinder(nh, nr*1.1, 0) - default: - panic("passed argument CylinderStyle not defined for Nut") - } - - // internal thread - isoThread := obj2.ISOThread(t.Radius+k.Tolerance, t.Pitch, false) - - thread := form3.Screw(isoThread, nh, t.Taper, t.Pitch, 1) - return sdf.Difference3D(nut, thread), err // TODO error handling -} diff --git a/form3/obj3/obj3.go b/form3/obj3/obj3.go deleted file mode 100644 index 5ce60d8..0000000 --- a/form3/obj3/obj3.go +++ /dev/null @@ -1,24 +0,0 @@ -package obj3 - -type CylinderStyle int - -const ( - _ CylinderStyle = iota - CylinderCircular - CylinderHex - CylinderKnurl -) - -func (c CylinderStyle) String() (str string) { - switch c { - case CylinderCircular: - str = "circular" - case CylinderHex: - str = "hex" - case CylinderKnurl: - str = "knurl" - default: - str = "unknown" - } - return str -} diff --git a/form3/obj3/standoff.go b/form3/obj3/standoff.go index 1c0cb29..e0a2b36 100644 --- a/form3/obj3/standoff.go +++ b/form3/obj3/standoff.go @@ -52,7 +52,7 @@ func pillarWeb(k StandoffParams) sdf.SDF3 { w.Add(0, k.WebHeight) p := form2.Polygon(w.Vertices()) s := sdf.Extrude3D(p, k.WebWidth) - m := sdf.Translate3D(r3.Vec{0, 0, -0.5 * k.PillarHeight}).Mul(sdf.RotateX(d2r(90.0))) + m := sdf.Translate3D(r3.Vec{0, 0, -0.5 * k.PillarHeight}).Mul(sdf.RotateX(90.0 * math.Pi / 180.)) return sdf.Transform3D(s, m) } diff --git a/form3/obj3/thread/acme.go b/form3/obj3/thread/acme.go new file mode 100644 index 0000000..0c9e044 --- /dev/null +++ b/form3/obj3/thread/acme.go @@ -0,0 +1,45 @@ +package thread + +import ( + "math" + + "github.com/soypat/sdf" + "github.com/soypat/sdf/form2/must2" +) + +// Acme is a trapezoidal thread form. https://en.wikipedia.org/wiki/Trapezoidal_thread_form +type Acme struct { + // D is the thread nominal diameter. + D float64 + // P is the thread pitch. + P float64 +} + +var _ Threader = Acme{} // Compile time check of interface implementation. + +func (acme Acme) Parameters() Parameters { + return basic{D: acme.D, P: acme.P}.Parameters() +} + +// AcmeThread returns the 2d profile for an acme thread. +// radius is radius of thread. pitch is thread-to-thread distance. +func (acme Acme) Thread() (sdf.SDF2, error) { + radius := acme.D / 2 + h := radius - 0.5*acme.P + theta := (29.0 / 2.0) * math.Pi / 180.0 + delta := 0.25 * acme.P * math.Tan(theta) + xOfs0 := 0.25*acme.P - delta + xOfs1 := 0.25*acme.P + delta + + poly := must2.NewPolygon() + poly.Add(radius, 0) + poly.Add(radius, h) + poly.Add(xOfs1, h) + poly.Add(xOfs0, radius) + poly.Add(-xOfs0, radius) + poly.Add(-xOfs1, h) + poly.Add(-radius, h) + poly.Add(-radius, 0) + + return must2.Polygon(poly.Vertices()), nil +} diff --git a/form3/obj3/thread/ansibuttress.go b/form3/obj3/thread/ansibuttress.go new file mode 100644 index 0000000..5cecc24 --- /dev/null +++ b/form3/obj3/thread/ansibuttress.go @@ -0,0 +1,46 @@ +package thread + +import ( + "math" + + "github.com/soypat/sdf" + "github.com/soypat/sdf/form2/must2" +) + +type ANSIButtress struct { + // D is the thread nominal diameter. + D float64 + // P is the thread pitch. + P float64 +} + +var _ Threader = ANSIButtress{} // Compile time check of interface implementation. + +func (butt ANSIButtress) Parameters() Parameters { + return basic{D: butt.D, P: butt.P}.Parameters() +} + +// ANSIButtressThread returns the 2d profile for an ANSI 45/7 buttress thread. +// https://en.wikipedia.org/wiki/Buttress_thread +// AMSE B1.9-1973 +// radius is radius of thread. pitch is thread-to-thread distance. +func (ansi ANSIButtress) Thread() (sdf.SDF2, error) { + radius := ansi.D / 2 + t0 := math.Tan(45.0 * math.Pi / 180) + t1 := math.Tan(7.0 * math.Pi / 180) + b := 0.6 // thread engagement + + h0 := ansi.P / (t0 + t1) + h1 := ((b / 2.0) * ansi.P) + (0.5 * h0) + hp := ansi.P / 2.0 + + tp := must2.NewPolygon() + tp.Add(ansi.P, 0) + tp.Add(ansi.P, radius) + tp.Add(hp-((h0-h1)*t1), radius) + tp.Add(t0*h0-hp, radius-h1).Smooth(0.0714*ansi.P, 5) + tp.Add((h0-h1)*t0-hp, radius) + tp.Add(-ansi.P, radius) + tp.Add(-ansi.P, 0) + return must2.Polygon(tp.Vertices()), nil +} diff --git a/form3/obj3/thread/basic.go b/form3/obj3/thread/basic.go new file mode 100644 index 0000000..2c06ebc --- /dev/null +++ b/form3/obj3/thread/basic.go @@ -0,0 +1,52 @@ +package thread + +import "math" + +// basic is a building block for most threads. +type basic struct { + // D is the thread nominal diameter [mm]. + D float64 + // P is the thread pitch [mm]. + P float64 +} + +func (b basic) Parameters() Parameters { + radius := b.D / 2 + return Parameters{ + Name: "basic", + Radius: radius, + Pitch: b.P, + Starts: 1, + Taper: 0, + HexF2F: metricf2f(radius), + } +} + +// Metric hex Flat to flat dimension [mm]. +var metricF2FTable = []float64{1.75, 2, 3.2, 4, 5, 6, 7, 8, 10, 13, 17, 19, 24, 30, 36, 46, 55, 65, 75, 85, 95} + +// metricf2f gets a reasonable hex flat-to-flat dimension +// for a metric screw of nominal radius. +func metricf2f(radius float64) float64 { + var estF2F float64 + switch { + case radius < 1.2/2: + estF2F = 3.2 * radius + case radius < 3.8/2: + estF2F = 4.5 * radius + case radius < 4.2/2: + estF2F = 4. * radius + default: + estF2F = 3.5 * radius + } + if math.Abs(radius-56/2) < 1 { + estF2F = 86 + } + for i := len(metricF2FTable) - 1; i >= 0; i-- { + v := metricF2FTable[i] + if estF2F-1e-2 > v { + return v + } + } + return metricF2FTable[0] +} diff --git a/form3/obj3/thread/bolt.go b/form3/obj3/thread/bolt.go new file mode 100644 index 0000000..e6a8459 --- /dev/null +++ b/form3/obj3/thread/bolt.go @@ -0,0 +1,75 @@ +package thread + +import ( + "errors" + + "github.com/soypat/sdf" + "github.com/soypat/sdf/form3/must3" + "gonum.org/v1/gonum/spatial/r3" +) + +// BoltParms defines the parameters for a bolt. +type BoltParms struct { + Thread Threader + Style NutStyle // head style "hex" or "knurl" + Tolerance float64 // subtract from external thread radius + TotalLength float64 // threaded length + shank length + ShankLength float64 // non threaded length +} + +// Bolt returns a simple bolt suitable for 3d printing. +func Bolt(k BoltParms) (s sdf.SDF3, err error) { + switch { + case k.Thread == nil: + err = errors.New("nil Threader") + case k.TotalLength < 0: + err = errors.New("total length < 0") + case k.ShankLength >= k.TotalLength: + err = errors.New("shank length must be less than total length") + case k.ShankLength < 0: + err = errors.New("shank length < 0") + case k.Tolerance < 0: + err = errors.New("tolerance < 0") + } + param := k.Thread.Parameters() + // head + var head sdf.SDF3 + + hr := param.HexRadius() + hh := param.HexHeight() + if hr <= 0 || hh <= 0 { + return nil, errors.New("bad hex head dimension") + } + switch k.Style { + case NutHex: + head, _ = HexHead(hr, hh, "b") + case NutKnurl: + head, _ = KnurledHead(hr, hh, hr*0.25) + default: + return nil, errors.New("unknown style for bolt: " + k.Style.String()) + } + + // shank + shankLength := k.ShankLength + hh/2 + shankOffset := shankLength / 2 + var shank sdf.SDF3 = must3.Cylinder(shankLength, param.Radius, hh*0.08) + shank = sdf.Transform3D(shank, sdf.Translate3D(r3.Vec{X: 0, Y: 0, Z: shankOffset})) + + // external thread + threadLength := k.TotalLength - k.ShankLength + if threadLength < 0 { + threadLength = 0 + } + var thread sdf.SDF3 + if threadLength != 0 { + thread, err = Screw(threadLength, k.Thread) + if err != nil { + return nil, err + } + // chamfer the thread + thread = must3.ChamferedCylinder(thread, 0, 0.5) + threadOffset := threadLength/2 + shankLength + thread = sdf.Transform3D(thread, sdf.Translate3D(r3.Vec{X: 0, Y: 0, Z: threadOffset})) + } + return sdf.Union3D(head, shank, thread), nil +} diff --git a/form3/obj3/hex.go b/form3/obj3/thread/hexhead.go similarity index 65% rename from form3/obj3/hex.go rename to form3/obj3/thread/hexhead.go index 9d5e363..937ab59 100644 --- a/form3/obj3/hex.go +++ b/form3/obj3/thread/hexhead.go @@ -1,11 +1,11 @@ -package obj3 +package thread import ( "math" "github.com/soypat/sdf" - form2 "github.com/soypat/sdf/form2/must2" - form3 "github.com/soypat/sdf/form3/must3" + "github.com/soypat/sdf/form2" + "github.com/soypat/sdf/form3" "gonum.org/v1/gonum/spatial/r3" ) @@ -16,20 +16,30 @@ import ( func HexHead(radius float64, height float64, round string) (s sdf.SDF3, err error) { // basic hex body cornerRound := radius * 0.08 - hex2d := form2.Polygon(form2.Nagon(6, radius-cornerRound)) + nagon, err := form2.Nagon(6, radius-cornerRound) + if err != nil { + return nil, err + } + hex2d, err := form2.Polygon(nagon) + if err != nil { + return nil, err + } hex2d = sdf.Offset2D(hex2d, cornerRound) var hex3d sdf.SDF3 = sdf.Extrude3D(hex2d, height) // round out the top and/or bottom as required if round != "" { topRound := radius * 1.6 - d := radius * math.Cos(d2r(30)) - sphere3d := form3.Sphere(topRound) + d := radius * math.Cos(30.0*math.Pi/180.0) + sphere3d, err := form3.Sphere(topRound) + if err != nil { + return nil, err + } zOfs := math.Sqrt(topRound*topRound-d*d) - height/2 if round == "t" || round == "tb" { - hex3d = sdf.Intersect3D(hex3d, sdf.Transform3D(sphere3d, sdf.Translate3D(r3.Vec{0, 0, -zOfs}))) + hex3d = sdf.Intersect3D(hex3d, sdf.Transform3D(sphere3d, sdf.Translate3D(r3.Vec{X: 0, Y: 0, Z: -zOfs}))) } if round == "b" || round == "tb" { - hex3d = sdf.Intersect3D(hex3d, sdf.Transform3D(sphere3d, sdf.Translate3D(r3.Vec{0, 0, zOfs}))) + hex3d = sdf.Intersect3D(hex3d, sdf.Transform3D(sphere3d, sdf.Translate3D(r3.Vec{X: 0, Y: 0, Z: zOfs}))) } } return hex3d, nil // TODO error handling. diff --git a/form3/obj3/thread/iso.go b/form3/obj3/thread/iso.go new file mode 100644 index 0000000..44fc9ed --- /dev/null +++ b/form3/obj3/thread/iso.go @@ -0,0 +1,61 @@ +package thread + +import ( + "math" + + "github.com/soypat/sdf" + "github.com/soypat/sdf/form2/must2" +) + +// ISO is a standardized thread. +// Pitch is usually the number following the diameter +// i.e: for M16x2 the pitch is 2mm +type ISO struct { + // D is the thread nominal diameter [mm]. + D float64 + // P is the thread pitch [mm]. + P float64 + // Is external or internal thread. Ext set to true means external thread. + Ext bool +} + +var _ Threader = ISO{} // Compile time check of interface implementation. + +func (iso ISO) Parameters() Parameters { + b := basic{D: iso.D, P: iso.P} + return b.Parameters() +} + +func (iso ISO) Thread() (sdf.SDF2, error) { + radius := iso.D / 2 + theta := 30.0 * math.Pi / 180. + h := iso.P / (2.0 * math.Tan(theta)) + rMajor := radius + r0 := rMajor - (7.0/8.0)*h + + poly := must2.NewPolygon() + if iso.Ext { + rRoot := (iso.P / 8.0) / math.Cos(theta) + xOfs := (1.0 / 16.0) * iso.P + poly.Add(iso.P, 0) + poly.Add(iso.P, r0+h) + poly.Add(iso.P/2.0, r0).Smooth(rRoot, 5) + poly.Add(xOfs, rMajor) + poly.Add(-xOfs, rMajor) + poly.Add(-iso.P/2.0, r0).Smooth(rRoot, 5) + poly.Add(-iso.P, r0+h) + poly.Add(-iso.P, 0) + } else { + rMinor := r0 + (1.0/4.0)*h + rCrest := (iso.P / 16.0) / math.Cos(theta) + xOfs := (1.0 / 8.0) * iso.P + poly.Add(iso.P, 0) + poly.Add(iso.P, rMinor) + poly.Add(iso.P/2-xOfs, rMinor) + poly.Add(0, r0+h).Smooth(rCrest, 5) + poly.Add(-iso.P/2+xOfs, rMinor) + poly.Add(-iso.P, rMinor) + poly.Add(-iso.P, 0) + } + return must2.Polygon(poly.Vertices()), nil +} diff --git a/form3/obj3/knurl.go b/form3/obj3/thread/knurl.go similarity index 65% rename from form3/obj3/knurl.go rename to form3/obj3/thread/knurl.go index 56f77bb..f9603f9 100644 --- a/form3/obj3/knurl.go +++ b/form3/obj3/thread/knurl.go @@ -1,11 +1,11 @@ -package obj3 +package thread import ( "math" "github.com/soypat/sdf" - form2 "github.com/soypat/sdf/form2/must2" - form3 "github.com/soypat/sdf/form3/must3" + "github.com/soypat/sdf/form2" + "github.com/soypat/sdf/form3" ) // Knurled Cylinders @@ -20,10 +20,11 @@ type KnurlParams struct { Pitch float64 // knurl pitch Height float64 // knurl height Theta float64 // knurl helix angle + starts int } -// knurlProfile returns a 2D knurl profile. -func knurlProfile(k KnurlParams) sdf.SDF2 { +// Thread implements the Threader interface. +func (k KnurlParams) Thread() (sdf.SDF2, error) { knurl := form2.NewPolygon() knurl.Add(k.Pitch/2, 0) knurl.Add(k.Pitch/2, k.Radius) @@ -34,8 +35,16 @@ func knurlProfile(k KnurlParams) sdf.SDF2 { return form2.Polygon(knurl.Vertices()) } +// Parameters implements the Threader interface. +func (k KnurlParams) Parameters() Parameters { + p := ISO{D: k.Radius * 2, P: k.Pitch, Ext: true}.Parameters() + p.Starts = k.starts + return p +} + // Knurl returns a knurled cylinder. func Knurl(k KnurlParams) (s sdf.SDF3, err error) { + // TODO fix error handling. if k.Length <= 0 { panic("Length <= 0") } @@ -51,17 +60,22 @@ func Knurl(k KnurlParams) (s sdf.SDF3, err error) { if k.Theta < 0 { panic("Theta < 0") } - if k.Theta >= d2r(90) { + if k.Theta >= 90.*math.Pi/180. { panic("Theta >= 90") } // Work out the number of starts using the desired helix angle. - n := int(2 * math.Pi * k.Radius * math.Tan(k.Theta) / k.Pitch) - // build the knurl profile. - knurl2d := knurlProfile(k) + k.starts = int(2 * math.Pi * k.Radius * math.Tan(k.Theta) / k.Pitch) // create the left/right hand spirals - knurl0_3d := form3.Screw(knurl2d, k.Length, 0, k.Pitch, n) - knurl1_3d := form3.Screw(knurl2d, k.Length, 0, k.Pitch, -n) - return sdf.Intersect3D(knurl0_3d, knurl1_3d), err // TODO error handling + knurl0_3d, err := Screw(k.Length, k) + if err != nil { + return nil, err + } + k.starts *= -1 + knurl1_3d, err := Screw(k.Length, k) + if err != nil { + return nil, err + } + return sdf.Intersect3D(knurl0_3d, knurl1_3d), nil } // KnurledHead returns a generic cylindrical knurled head. @@ -73,15 +87,15 @@ func KnurledHead(radius float64, height float64, pitch float64) (s sdf.SDF3, err Radius: radius, Pitch: pitch, Height: pitch * 0.3, - Theta: d2r(45), + Theta: 45.0 * math.Pi / 180, } knurl, err := Knurl(k) if err != nil { return s, err } - cylinder := form3.Cylinder(height, radius, cylinderRound) + cylinder, err := form3.Cylinder(height, radius, cylinderRound) + if err != nil { + return nil, err + } return sdf.Union3D(cylinder, knurl), err } - -func d2r(degrees float64) float64 { return degrees * math.Pi / 180. } -func r2d(radians float64) float64 { return radians / math.Pi * 180. } diff --git a/form3/obj3/thread/legacy_test.go b/form3/obj3/thread/legacy_test.go new file mode 100644 index 0000000..324419f --- /dev/null +++ b/form3/obj3/thread/legacy_test.go @@ -0,0 +1,234 @@ +package thread + +import ( + "fmt" + "log" + "math" + "sort" + "strings" + "testing" +) + +func TestMetricF2F(t *testing.T) { + var threads byF2F + for _, v := range threadDB { + threads = append(threads, v) + } + sort.Sort(threads) + // lookup := make(map[float64]struct{}) + for _, v := range threads { + if v.Name[0] != 'M' { + continue + } + v.Name = strings.Replace(v.Name, ".", "", 1) + f2f := v.HexFlat2Flat * v.toMM() + radius := v.Radius * v.toMM() + estf2f := metricf2f(radius) + if estf2f != f2f { + t.Errorf("%s\tf2f=%.3g\test=%.3g", v.Name, f2f, estf2f) + } + // t.Logf("%s\tk=%.3g\tr=%.3g\tf2f=%.3g\testf2f=%.3g", v.Name, f2f/radius, radius, f2f, estf2f) + } +} + +type byRadius []threadParameters +type byF2F []threadParameters +type byName []threadParameters + +func (b byName) Less(i, j int) bool { return b[i].Name < b[j].Name } +func (b byName) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b byName) Len() int { return len(b) } +func (b byRadius) Less(i, j int) bool { + return b[i].Radius*b[i].toMM() < b[j].Radius*b[j].toMM() +} +func (b byRadius) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b byRadius) Len() int { return len(b) } +func (b byF2F) Less(i, j int) bool { + return b[i].HexFlat2Flat*b[i].toMM() < b[j].HexFlat2Flat*b[j].toMM() +} +func (b byF2F) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b byF2F) Len() int { return len(b) } + +// Thread Database - lookup standard screw threads by name + +// threadParameters stores the values that define a thread. +type threadParameters struct { + Name string // name of screw thread + Radius float64 // nominal major radius of screw + Pitch float64 // thread to thread distance of screw + Taper float64 // thread taper (radians) + HexFlat2Flat float64 // hex head flat to flat distance + Units string // "inch" or "mm" +} + +func (t threadParameters) toMM() float64 { + if t.Units == "inches" || t.Units == "inch" { + return 25.4 + } + return 1.0 +} + +type threadDatabase map[string]threadParameters + +var threadDB = initThreadLookup() + +// UTSAdd adds a Unified Thread Standard to the thread database. +// diameter is screw major diameter. +// tpi is threads per inch. +// ftof is hex head flat to flat distance. +func (m threadDatabase) UTSAdd(name string, diameter float64, tpi float64, ftof float64) { + if ftof <= 0 { + log.Panicf("bad flat to flat distance for thread \"%s\"", name) + } + t := threadParameters{} + t.Name = name + t.Radius = diameter / 2.0 + t.Pitch = 1.0 / tpi + t.HexFlat2Flat = ftof + t.Units = "inch" + m[name] = t +} + +// ISOAdd adds an ISO Thread Standard to the thread database. +func (m threadDatabase) ISOAdd( + name string, // thread name + diameter float64, // screw major diamater + pitch float64, // thread pitch + ftof float64, // hex head flat to flat distance +) { + if ftof <= 0 { + log.Panicf("bad flat to flat distance for thread \"%s\"", name) + } + t := threadParameters{} + t.Name = name + t.Radius = diameter / 2.0 + t.Pitch = pitch + t.HexFlat2Flat = ftof + t.Units = "mm" + m[name] = t +} + +// NPTAdd adds an National Pipe Thread to the thread database. +func (m threadDatabase) NPTAdd( + name string, // thread name + diameter float64, // screw major diameter + tpi float64, // threads per inch + ftof float64, // hex head flat to flat distance +) { + if ftof <= 0 { + log.Panicf("bad flat to flat distance for thread \"%s\"", name) + } + t := threadParameters{} + t.Name = name + t.Radius = diameter / 2.0 + t.Pitch = 1.0 / tpi + t.Taper = math.Atan(1.0 / 32.0) + t.HexFlat2Flat = ftof + t.Units = "inch" + m[name] = t +} + +// initThreadLookup adds a collection of standard threads to the thread database. +func initThreadLookup() threadDatabase { + m := make(threadDatabase) + // UTS Coarse + m.UTSAdd("unc_1/4", 1.0/4.0, 20, 7.0/16.0) + m.UTSAdd("unc_5/16", 5.0/16.0, 18, 1.0/2.0) + m.UTSAdd("unc_3/8", 3.0/8.0, 16, 9.0/16.0) + m.UTSAdd("unc_7/16", 7.0/16.0, 14, 5.0/8.0) + m.UTSAdd("unc_1/2", 1.0/2.0, 13, 3.0/4.0) + m.UTSAdd("unc_9/16", 9.0/16.0, 12, 13.0/16.0) + m.UTSAdd("unc_5/8", 5.0/8.0, 11, 15.0/16.0) + m.UTSAdd("unc_3/4", 3.0/4.0, 10, 9.0/8.0) + m.UTSAdd("unc_7/8", 7.0/8.0, 9, 21.0/16.0) + m.UTSAdd("unc_1", 1.0, 8, 3.0/2.0) + // UTS Fine + m.UTSAdd("unf_1/4", 1.0/4.0, 28, 7.0/16.0) + m.UTSAdd("unf_5/16", 5.0/16.0, 24, 1.0/2.0) + m.UTSAdd("unf_3/8", 3.0/8.0, 24, 9.0/16.0) + m.UTSAdd("unf_7/16", 7.0/16.0, 20, 5.0/8.0) + m.UTSAdd("unf_1/2", 1.0/2.0, 20, 3.0/4.0) + m.UTSAdd("unf_9/16", 9.0/16.0, 18, 13.0/16.0) + m.UTSAdd("unf_5/8", 5.0/8.0, 18, 15.0/16.0) + m.UTSAdd("unf_3/4", 3.0/4.0, 16, 9.0/8.0) + m.UTSAdd("unf_7/8", 7.0/8.0, 14, 21.0/16.0) + m.UTSAdd("unf_1", 1.0, 12, 3.0/2.0) + const inchesPerMM = 1.0 / 25.4 + // National Pipe Thread. Face to face distance taken from ASME B16.11 Plug Manufacturer (mm) + m.NPTAdd("npt_1/8", 0.405, 27, 11.2*inchesPerMM) + m.NPTAdd("npt_1/4", 0.540, 18, 15.7*inchesPerMM) + m.NPTAdd("npt_3/8", 0.675, 18, 17.5*inchesPerMM) + m.NPTAdd("npt_1/2", 0.840, 14, 22.4*inchesPerMM) + m.NPTAdd("npt_3/4", 1.050, 14, 26.9*inchesPerMM) + m.NPTAdd("npt_1", 1.315, 11.5, 35.1*inchesPerMM) + m.NPTAdd("npt_1_1/4", 1.660, 11.5, 44.5*inchesPerMM) + m.NPTAdd("npt_1_1/2", 1.900, 11.5, 50.8*inchesPerMM) + m.NPTAdd("npt_2", 2.375, 11.5, 63.5*inchesPerMM) + m.NPTAdd("npt_2_1/2", 2.875, 8, 76.2*inchesPerMM) + m.NPTAdd("npt_3", 3.500, 8, 88.9*inchesPerMM) + m.NPTAdd("npt_4", 4.500, 8, 117.3*inchesPerMM) + + // ISO Coarse + m.ISOAdd("M1x0.25", 1, 0.25, 1.75) // ftof? + m.ISOAdd("M1.2x0.25", 1.2, 0.25, 2.0) // ftof? + m.ISOAdd("M1.6x0.35", 1.6, 0.35, 3.2) + m.ISOAdd("M2x0.4", 2, 0.4, 4) + m.ISOAdd("M2.5x0.45", 2.5, 0.45, 5) + m.ISOAdd("M3x0.5", 3, 0.5, 6) + m.ISOAdd("M4x0.7", 4, 0.7, 7) + m.ISOAdd("M5x0.8", 5, 0.8, 8) + m.ISOAdd("M6x1", 6, 1, 10) + m.ISOAdd("M8x1.25", 8, 1.25, 13) + m.ISOAdd("M10x1.5", 10, 1.5, 17) + m.ISOAdd("M12x1.75", 12, 1.75, 19) + m.ISOAdd("M16x2", 16, 2, 24) + m.ISOAdd("M20x2.5", 20, 2.5, 30) + m.ISOAdd("M24x3", 24, 3, 36) + m.ISOAdd("M30x3.5", 30, 3.5, 46) + m.ISOAdd("M36x4", 36, 4, 55) + m.ISOAdd("M42x4.5", 42, 4.5, 65) + m.ISOAdd("M48x5", 48, 5, 75) + m.ISOAdd("M56x5.5", 56, 5.5, 85) + m.ISOAdd("M64x6", 64, 6, 95) + // ISO Fine + m.ISOAdd("M1x0.2", 1, 0.2, 1.75) // ftof? + m.ISOAdd("M1.2x0.2", 1.2, 0.2, 2.0) // ftof? + m.ISOAdd("M1.6x0.2", 1.6, 0.2, 3.2) + m.ISOAdd("M2x0.25", 2, 0.25, 4) + m.ISOAdd("M2.5x0.35", 2.5, 0.35, 5) + m.ISOAdd("M3x0.35", 3, 0.35, 6) + m.ISOAdd("M4x0.5", 4, 0.5, 7) + m.ISOAdd("M5x0.5", 5, 0.5, 8) + m.ISOAdd("M6x0.75", 6, 0.75, 10) + m.ISOAdd("M8x1", 8, 1, 13) + m.ISOAdd("M10x1.25", 10, 1.25, 17) + m.ISOAdd("M12x1.5", 12, 1.5, 19) + m.ISOAdd("M16x1.5", 16, 1.5, 24) + m.ISOAdd("M20x2", 20, 2, 30) + m.ISOAdd("M24x2", 24, 2, 36) + m.ISOAdd("M30x2", 30, 2, 46) + m.ISOAdd("M36x3", 36, 3, 55) + m.ISOAdd("M42x3", 42, 3, 65) + m.ISOAdd("M48x3", 48, 3, 75) + m.ISOAdd("M56x4", 56, 4, 85) + m.ISOAdd("M64x4", 64, 4, 95) + return m +} + +// lookup lookups the parameters for a thread by name. +func lookup(name string) (threadParameters, error) { + if t, ok := threadDB[name]; ok { + return t, nil + } + return threadParameters{}, fmt.Errorf("thread \"%s\" not found", name) +} + +// HexRadius returns the hex head radius. +func (t *threadParameters) HexRadius() float64 { + return t.HexFlat2Flat / (2.0 * math.Cos(30*math.Pi/180)) +} + +// HexHeight returns the hex head height (empirical). +func (t *threadParameters) HexHeight() float64 { + return 2.0 * t.HexRadius() * (5.0 / 12.0) +} diff --git a/form3/obj3/thread/npt.go b/form3/obj3/thread/npt.go new file mode 100644 index 0000000..b01f270 --- /dev/null +++ b/form3/obj3/thread/npt.go @@ -0,0 +1,72 @@ +package thread + +import ( + "errors" + "math" + + "github.com/soypat/sdf" +) + +type NPT struct { + // D is the thread nominal diameter. + D float64 + // threads per inch. 1.0/TPI gives pitch. + TPI float64 + // Flat-to-flat hex distance. + // Can be set by SetFromNominal with a standard value. + F2F float64 +} + +var _ Threader = NPT{} // Compile time check of interface implementation. + +func (npt NPT) Parameters() Parameters { + p := ISO{D: npt.D, P: 1.0 / npt.TPI}.Parameters() + p.Name = "NPT" + p.Taper = math.Atan(1.0 / 32.0) // standard NPT taper. + if npt.F2F > 0 { + p.HexF2F = npt.F2F + } + return p +} + +func (npt NPT) Thread() (sdf.SDF2, error) { + return ISO{D: npt.D, P: 1.0 / npt.TPI}.Thread() +} + +type nptSpec struct { + N float64 // Nominal measurement (usually a fraction of inch) + D float64 // screw major diameter + tpi float64 // threads per inch + ftof float64 // hex head flat to flat distance +} + +var nptLookupTable = []nptSpec{ + {N: 1.0 / 8.0, D: 0.405, tpi: 27, ftof: 11.2 / 25.4}, + {N: 1.0 / 4.0, D: 0.540, tpi: 18, ftof: 15.7 / 25.4}, + {N: 3.0 / 8.0, D: 0.675, tpi: 18, ftof: 17.5 / 25.4}, + {N: 1.0 / 2.0, D: 0.840, tpi: 14, ftof: 22.4 / 25.4}, + {N: 3.0 / 4.0, D: 1.050, tpi: 14, ftof: 26.9 / 25.4}, + {N: 1.0, D: 1.315, tpi: 11.5, ftof: 35.1 / 25.4}, + {N: 1 + 1.0/4.0, D: 1.660, tpi: 11.5, ftof: 44.5 / 25.4}, + {N: 1 + 1.0/2.0, D: 1.900, tpi: 11.5, ftof: 50.8 / 25.4}, + {N: 2, D: 2.375, tpi: 11.5, ftof: 63.5 / 25.4}, + {N: 2 + 1.0/2.0, D: 2.875, tpi: 8, ftof: 76.2 / 25.4}, + {N: 3, D: 3.500, tpi: 8, ftof: 88.9 / 25.4}, + {N: 4, D: 4.500, tpi: 8, ftof: 117.3 / 25.4}, +} + +// SetFromNominal sets NPT thread dimensions from a nominal measurement +// which usually takes the form of inch fractions. i.e: +// npt.SetFromNominal(1.0/8.0) // sets NPT 1/8 +func (npt *NPT) SetFromNominal(nominalDimension float64) error { + const lookupTol = 1. / 32. + for _, a := range nptLookupTable { + if math.Abs(a.N-nominalDimension) < lookupTol { + npt.D = a.D + npt.F2F = a.ftof + npt.TPI = a.tpi + return nil + } + } + return errors.New("nominal measurement not found") +} diff --git a/form3/obj3/thread/nut.go b/form3/obj3/thread/nut.go new file mode 100644 index 0000000..94da430 --- /dev/null +++ b/form3/obj3/thread/nut.go @@ -0,0 +1,79 @@ +package thread + +import ( + "errors" + + "github.com/soypat/sdf" + "github.com/soypat/sdf/form3/must3" +) + +type NutStyle int + +const ( + _ NutStyle = iota + NutCircular + NutHex + NutKnurl +) + +func (c NutStyle) String() (str string) { + switch c { + case NutCircular: + str = "circular" + case NutHex: + str = "hex" + case NutKnurl: + str = "knurl" + default: + str = "unknown" + } + return str +} + +// NutParms defines the parameters for a nut. +type NutParms struct { + Thread Threader + Style NutStyle + Tolerance float64 // add to internal thread radius +} + +// Nut returns a simple nut suitable for 3d printing. +func Nut(k NutParms) (s sdf.SDF3, err error) { + switch { + case k.Thread == nil: + err = errors.New("nil threader") + case k.Tolerance < 0: + err = errors.New("tolerance < 0") + } + if err != nil { + return nil, err + } + + params := k.Thread.Parameters() + // nut body + var nut sdf.SDF3 + nr := params.HexRadius() + nh := params.HexHeight() + if nr <= 0 || nh <= 0 { + return nil, errors.New("bad hex nut dimensions") + } + switch k.Style { + case NutHex: // TODO error handling + nut, err = HexHead(nr, nh, "tb") + case NutKnurl: + nut, err = KnurledHead(nr, nh, nr*0.25) + case NutCircular: + nut = must3.Cylinder(nh, nr*1.1, 0) + default: + err = errors.New("passed argument CylinderStyle not defined for Nut") + } + if err != nil { + return nil, err + } + // internal thread + thread, err := Screw(nh, k.Thread) + if err != nil { + return nil, err + } + return sdf.Difference3D(nut, thread), nil +} diff --git a/form3/obj3/thread/parameters.go b/form3/obj3/thread/parameters.go new file mode 100644 index 0000000..80182e9 --- /dev/null +++ b/form3/obj3/thread/parameters.go @@ -0,0 +1,26 @@ +package thread + +import "math" + +type Parameters struct { + Name string // name of screw thread + Radius float64 // nominal major radius of screw + Pitch float64 // thread to thread distance of screw + Starts int // number of threads + Taper float64 // thread taper (radians) + HexF2F float64 // hex head flat to flat distance +} + +// HexRadius returns the hex head radius. +func (t Parameters) HexRadius() float64 { + return t.HexF2F / (2.0 * math.Cos(30*math.Pi/180)) +} + +// HexHeight returns the hex head height (empirical). +func (t Parameters) HexHeight() float64 { + return 2.0 * t.HexRadius() * (5.0 / 12.0) +} + +// Imperial hex Flat to flat dimension [mm]. +// Face to face distance taken from ASME B16.11 Plug Manufacturer (mm) +// var imperialF2FTable = []float64{11.2, 15.7, 17.5, 22.4, 26.9, 35.1, 44.5, 50.8, 63.5, 76.2, 88.9, 117.3} diff --git a/form3/obj3/thread/plasticbuttress.go b/form3/obj3/thread/plasticbuttress.go new file mode 100644 index 0000000..70cd084 --- /dev/null +++ b/form3/obj3/thread/plasticbuttress.go @@ -0,0 +1,45 @@ +package thread + +import ( + "math" + + "github.com/soypat/sdf" + "github.com/soypat/sdf/form2/must2" +) + +type PlasticButtress struct { + // D is the thread nominal diameter. + D float64 + // P is the thread pitch. + P float64 +} + +var _ Threader = PlasticButtress{} // Compile time check of interface implementation. + +func (butt PlasticButtress) Parameters() Parameters { + return basic{D: butt.D, P: butt.P}.Parameters() +} + +// Thread returns the 2d profile for a screw top style plastic buttress thread. +// Similar to ANSI 45/7 - but with more corner rounding +// radius is radius of thread. pitch is thread-to-thread distance. +func (butt PlasticButtress) Thread() (sdf.SDF2, error) { + radius := butt.D / 2 + t0 := math.Tan(45.0 * math.Pi / 180) + t1 := math.Tan(7.0 * math.Pi / 180) + b := 0.6 // thread engagement + + h0 := butt.P / (t0 + t1) + h1 := ((b / 2.0) * butt.P) + (0.5 * h0) + hp := butt.P / 2.0 + + tp := must2.NewPolygon() + tp.Add(butt.P, 0) + tp.Add(butt.P, radius) + tp.Add(hp-((h0-h1)*t1), radius).Smooth(0.05*butt.P, 5) + tp.Add(t0*h0-hp, radius-h1).Smooth(0.15*butt.P, 5) + tp.Add((h0-h1)*t0-hp, radius).Smooth(0.15*butt.P, 5) + tp.Add(-butt.P, radius) + tp.Add(-butt.P, 0) + return must2.Polygon(tp.Vertices()), nil +} diff --git a/form3/must3/screw.go b/form3/obj3/thread/thread.go similarity index 54% rename from form3/must3/screw.go rename to form3/obj3/thread/thread.go index 661d1b8..e72f1cf 100644 --- a/form3/must3/screw.go +++ b/form3/obj3/thread/thread.go @@ -1,6 +1,7 @@ -package must3 +package thread import ( + "errors" "math" "github.com/soypat/sdf" @@ -8,6 +9,29 @@ import ( "gonum.org/v1/gonum/spatial/r3" ) +// Screws +// Screws are made by taking a 2D thread profile, rotating it about the z-axis and +// spiralling it upwards as we move along z. +// +// The 2D thread profiles are a polygon of a single thread centered on the y-axis with +// the x-axis as the screw axis. Most thread profiles are symmetric about the y-axis +// but a few aren't (E.g. buttress threads) so in general we build the profile of +// an entire pitch period. +// +// This code doesn't deal with thread tolerancing. If you want threads to fit properly +// the radius of the thread will need to be tweaked (+/-) to give internal/external thread +// clearance. + +type Threader interface { + Thread() (sdf.SDF2, error) + Parameters() Parameters +} + +type ScrewParameters struct { + Length float64 + Taper float64 +} + // screw is a 3d screw form. type screw struct { thread sdf.SDF2 // 2D thread profile @@ -24,36 +48,32 @@ type screw struct { // - thread taper angle (radians) // - pitch thread to thread distance // - number of thread starts (< 0 for left hand threads) -func Screw(thread sdf.SDF2, length float64, taper float64, pitch float64, starts int) sdf.SDF3 { +func Screw(length float64, thread Threader) (sdf.SDF3, error) { if thread == nil { - panic("thread == nil") + return nil, errors.New("nil threader") } if length <= 0 { - panic("length <= 0") + return nil, errors.New("need greater than zero length") } - if taper < 0 { - panic("taper < 0") - } - if taper >= math.Pi*0.5 { - panic("taper >= Pi * 0.5") - } - if pitch <= 0 { - panic("pitch <= 0") + tsdf, err := thread.Thread() + if err != nil { + return nil, err } + params := thread.Parameters() s := screw{} - s.thread = thread - s.pitch = pitch + s.thread = tsdf + s.pitch = params.Pitch s.length = length / 2 - s.taper = taper - s.lead = -pitch * float64(starts) + s.taper = params.Taper + s.lead = -s.pitch * float64(params.Starts) // Work out the bounding box. // The max-y axis of the sdf2 bounding box is the radius of the thread. bb := s.thread.Bounds() r := bb.Max.Y // add the taper increment - r += s.length * math.Tan(taper) - s.bb = r3.Box{r3.Vec{X: -r, Y: -r, Z: -s.length}, r3.Vec{X: r, Y: r, Z: s.length}} - return &s + r += s.length * math.Tan(s.taper) + s.bb = r3.Box{Min: r3.Vec{X: -r, Y: -r, Z: -s.length}, Max: r3.Vec{X: r, Y: r, Z: s.length}} + return &s, nil } // Evaluate returns the minimum distance to a 3d screw form. @@ -82,3 +102,9 @@ func (s *screw) Evaluate(p r3.Vec) float64 { func (s *screw) Bounds() r3.Box { return s.bb } + +func sawTooth(x, period float64) float64 { + x += period / 2 + t := x / period + return period*(t-math.Floor(t)) - period/2 +} diff --git a/form3/obj3/thread/uts.go b/form3/obj3/thread/uts.go new file mode 100644 index 0000000..fb671bc --- /dev/null +++ b/form3/obj3/thread/uts.go @@ -0,0 +1,25 @@ +package thread + +import "github.com/soypat/sdf" + +// Unified thread standard. +// Example: UNC 1/4 with external threading would be +// UTS{D:1.0/4.0, TPI:20, Ext: true} +type UTS struct { + D float64 + TPI float64 + // External or internal thread. + Ext bool +} + +var _ Threader = UTS{} // Interface implementation. + +func (uts UTS) Parameters() Parameters { + p := basic{D: uts.D, P: 1.0 / uts.TPI}.Parameters() + // TODO(soypat) add imperial hex flat-to-flat. See NPT for what that could look like. + return p +} + +func (uts UTS) Thread() (sdf.SDF2, error) { + return ISO{D: uts.D, P: 1.0 / uts.TPI, Ext: uts.Ext}.Thread() +} diff --git a/form3/screw.go b/form3/screw.go deleted file mode 100644 index 75a0a2f..0000000 --- a/form3/screw.go +++ /dev/null @@ -1,25 +0,0 @@ -package form3 - -import ( - "runtime/debug" - - "github.com/soypat/sdf" - "github.com/soypat/sdf/form3/must3" -) - -// screw returns a screw SDF3. -// - length of screw -// - thread taper angle (radians) -// - pitch thread to thread distance -// - number of thread starts (< 0 for left hand threads) -func screw(thread sdf.SDF2, length, taper, pitch float64, starts int) (s sdf.SDF3, err error) { - defer func() { - if a := recover(); a != nil { - err = &shapeErr{ - panicObj: a, - stack: string(debug.Stack()), - } - } - }() - return must3.Screw(thread, length, taper, pitch, starts), err -} diff --git a/render/3mf_test.go b/render/3mf_test.go index 2988359..48663ef 100644 --- a/render/3mf_test.go +++ b/render/3mf_test.go @@ -1,6 +1,7 @@ package render_test import ( + "os" "testing" "github.com/soypat/sdf/form3" @@ -10,6 +11,7 @@ import ( func Test3MF(t *testing.T) { const path = "box.3mf" + defer os.Remove(path) box, _ := form3.Box(r3.Vec{X: 1, Y: 1, Z: 1}, .1) err := render.Create3MF(path, render.NewOctreeRenderer(box, 10)) if err != nil { diff --git a/render/form3_test.go b/render/form3_test.go index 99f3a97..b91d39b 100644 --- a/render/form3_test.go +++ b/render/form3_test.go @@ -10,7 +10,7 @@ import ( "github.com/soypat/sdf" form2 "github.com/soypat/sdf/form2/must2" form3 "github.com/soypat/sdf/form3/must3" - "github.com/soypat/sdf/form3/obj3" + "github.com/soypat/sdf/form3/obj3/thread" "github.com/soypat/sdf/internal/d3" "github.com/soypat/sdf/render" "gonum.org/v1/gonum/spatial/r3" @@ -126,14 +126,24 @@ func hexToSTL(t testing.TB, filename string) { } func boltToSTL(t testing.TB, filename string) { - object, _ := obj3.Bolt(obj3.BoltParms{ - Thread: "M16x2", - Style: obj3.CylinderHex, + object, err := thread.Bolt(thread.BoltParms{ + Thread: thread.ISO{D: 16, P: 2}, // M16x2 + Style: thread.NutHex, Tolerance: 0.1, TotalLength: 60.0, ShankLength: 10.0, }) - err := render.CreateSTL(filename, render.NewOctreeRenderer(object, quality)) + if err != nil { + t.Fatal(err) + } + // object, _ = obj3.Bolt(obj3.BoltParms{ + // Thread: "M16x2", + // Style: obj3.CylinderHex, + // Tolerance: 0.1, + // TotalLength: 60.0, + // ShankLength: 10.0, + // }) + err = render.CreateSTL(filename, render.NewOctreeRenderer(object, quality)) if err != nil { t.Fatal(err) } diff --git a/render/internal_test.go b/render/internal_test.go index 12f8ef0..4383eeb 100644 --- a/render/internal_test.go +++ b/render/internal_test.go @@ -5,7 +5,7 @@ import ( "errors" "testing" - "github.com/soypat/sdf/form3/obj3" + "github.com/soypat/sdf/form3/obj3/thread" "github.com/soypat/sdf/internal/d3" "gonum.org/v1/gonum/spatial/r3" ) @@ -28,9 +28,9 @@ func TestSTLWriteReadback(t *testing.T) { quality = 200 tol = 1e-5 ) - s0, _ := obj3.Bolt(obj3.BoltParms{ - Thread: "M16x2", - Style: obj3.CylinderHex, + s0, _ := thread.Bolt(thread.BoltParms{ + Thread: thread.ISO{D: 16, P: 2}, // M16x2 + Style: thread.NutHex, Tolerance: 0.1, TotalLength: 40., ShankLength: 10.0, diff --git a/render/kdrender.go b/render/kdrender.go deleted file mode 100644 index c4a4ed6..0000000 --- a/render/kdrender.go +++ /dev/null @@ -1,206 +0,0 @@ -package render - -import ( - "math" - - "github.com/soypat/sdf" - "github.com/soypat/sdf/internal/d3" - "gonum.org/v1/gonum/spatial/kdtree" - "gonum.org/v1/gonum/spatial/r3" -) - -var ( - _ sdf.SDF3 = kdSDF{} - _ kdtree.Interface = kdTriangles{} - _ kdtree.Bounder = kdTriangles{} -) - -func NewKDSDF(model []Triangle3) sdf.SDF3 { - mykd := make(kdTriangles, len(model)) - // var min, max r3.Vec - for i := range mykd { - tri := kdTriangle(model[i]) - mykd[i] = tri - // triMin := d3.MinElem(tri.V[2], d3.MinElem(tri.V[0], tri.V[1])) - // triMax := d3.MaxElem(tri.V[2], d3.MaxElem(tri.V[0], tri.V[1])) - // min = d3.MinElem(triMin, min) - // max = d3.MaxElem(triMax, max) - } - tree := kdtree.New(mykd, true) - // tree.Root.Bounding = &kdtree.Bounding{ - // Min: kdTriangle{V: [3]r3.Vec{min, min, min}}, - // Max: kdTriangle{V: [3]r3.Vec{max, max, max}}, - // } - return kdSDF{ - tree: *tree, - } -} - -type kdSDF struct { - tree kdtree.Tree -} - -func (s kdSDF) Evaluate(v r3.Vec) float64 { - const eps = 1e-3 - // do some ad-hoc math with the triangle normal ???? - triangle := s.Nearest(v) - minDist := math.MaxFloat64 - // Find closest vertex - closest := r3.Vec{} - for i := 0; i < 3; i++ { - vDist := r3.Norm(r3.Sub(v, triangle[i])) - if vDist < minDist { - closest = triangle[i] - minDist = vDist - } - } - if minDist < eps { - return 0 - } - pointDir := r3.Sub(v, closest) - n := triangle.Normal() - alpha := math.Acos(r3.Cos(n, pointDir)) - return math.Copysign(minDist, math.Pi/2-alpha) -} - -// Get nearest triangle to point. -func (s kdSDF) Nearest(v r3.Vec) kdTriangle { - got, _ := s.tree.Nearest(kdTriangle{v, v, v}) - // do some ad-hoc math with the triangle normal ???? - return got.(kdTriangle) -} - -func (s kdSDF) Bounds() r3.Box { - bb := s.tree.Root.Bounding - if bb == nil { - panic("got nil bounding box?") - } - tMin := bb.Min.(kdTriangle) - tMax := bb.Max.(kdTriangle) - return r3.Box{ - Min: d3.MinElem(tMin[2], d3.MinElem(tMin[0], tMin[1])), - Max: d3.MaxElem(tMax[2], d3.MaxElem(tMax[0], tMax[1])), - } -} - -type kdTriangles []kdTriangle - -type kdTriangle Triangle3 - -func (k kdTriangles) Index(i int) kdtree.Comparable { - return k[i] -} - -// Len returns the length of the list. -func (k kdTriangles) Len() int { return len(k) } - -// Pivot partitions the list based on the dimension specified. -func (k kdTriangles) Pivot(d kdtree.Dim) int { - p := kdPlane{dim: int(d), triangles: k} - return kdtree.Partition(p, kdtree.MedianOfMedians(p)) - return 0 -} - -// Slice returns a slice of the list using zero-based half -// open indexing equivalent to built-in slice indexing. -func (k kdTriangles) Slice(start, end int) kdtree.Interface { - return k[start:end] -} - -func (k kdTriangles) Bounds() *kdtree.Bounding { - max := r3.Vec{-math.MaxFloat64, -math.MaxFloat64, -math.MaxFloat64} - min := r3.Vec{math.MaxFloat64, math.MaxFloat64, math.MaxFloat64} - for _, tri := range k { - tbounds := tri.Bounds() - tmin := tbounds.Min.(kdTriangle) - tmax := tbounds.Max.(kdTriangle) - min = d3.MinElem(min, tmin[0]) - max = d3.MaxElem(max, tmax[0]) - } - return &kdtree.Bounding{ - Min: kdTriangle{min, min, min}, - Max: kdTriangle{max, max, max}, - } -} - -// Compare returns the signed distance of a from the plane passing through -// b and perpendicular to the dimension d. -// -// Given c = a.Compare(b, d): -// c = a_d - b_d -func (a kdTriangle) Compare(b kdtree.Comparable, d kdtree.Dim) float64 { - return kdComp(a, b.(kdTriangle), int(d)) -} - -// Dims returns the number of dimensions described in the Comparable. -func (k kdTriangle) Dims() int { - return 3 -} - -// Distance returns the squared Euclidean distance between the receiver and -// the parameter. -func (a kdTriangle) Distance(b kdtree.Comparable) float64 { - return kdDist(a, b.(kdTriangle)) -} - -func (a kdTriangle) Bounds() *kdtree.Bounding { - min := d3.MinElem(a[2], d3.MinElem(a[0], a[1])) - max := d3.MaxElem(a[2], d3.MaxElem(a[0], a[1])) - return &kdtree.Bounding{ - Min: kdTriangle{min, min, min}, - Max: kdTriangle{max, max, max}, - } -} - -func (a kdTriangle) Normal() r3.Vec { - v := Triangle3(a) - return v.Normal() -} - -// c = a.dim - b.dim -func kdComp(a, b kdTriangle, dim int) (c float64) { - switch dim { - case 0: - c = (a[0].X + a[1].X + a[2].X) - (b[0].X + b[1].X + b[2].X) - case 1: - c = (a[0].Y + a[1].Y + a[2].Y) - (b[0].Y + b[1].Y + b[2].Y) - case 2: - c = (a[0].Z + a[1].Z + a[2].Z) - (b[0].Z + b[1].Z + b[2].Z) - } - return c / 3 -} - -// returns euclidean squared norm distance between triangle centroids. -func kdDist(a, b kdTriangle) (c float64) { - ac := kdCentroid(a) - bc := kdCentroid(b) - return r3.Norm2(r3.Sub(ac, bc)) -} - -func kdCentroid(a kdTriangle) r3.Vec { - v := r3.Vec{ - X: a[0].X + a[1].X + a[2].X, - Y: a[0].Y + a[1].Y + a[2].Y, - Z: a[0].Z + a[1].Z + a[2].Z, - } - return r3.Scale(1./3., v) -} - -type kdPlane struct { - dim int - triangles kdTriangles -} - -func (p kdPlane) Less(i, j int) bool { - return kdComp(p.triangles[i], p.triangles[j], p.dim) < 0 -} -func (p kdPlane) Swap(i, j int) { - p.triangles[i], p.triangles[j] = p.triangles[j], p.triangles[i] -} -func (p kdPlane) Len() int { - return len(p.triangles) -} -func (p kdPlane) Slice(start, end int) kdtree.SortSlicer { - p.triangles = p.triangles[start:end] - return p -} diff --git a/render/kdrender_test.go b/render/kdrender_test.go index be781d2..bc96601 100644 --- a/render/kdrender_test.go +++ b/render/kdrender_test.go @@ -1,11 +1,14 @@ -package render_test +package render import ( + "math" "testing" "time" + "github.com/soypat/sdf" "github.com/soypat/sdf/form3" - "github.com/soypat/sdf/render" + "github.com/soypat/sdf/internal/d3" + "gonum.org/v1/gonum/spatial/kdtree" "gonum.org/v1/gonum/spatial/r3" ) @@ -23,20 +26,216 @@ func TestKDSDF(t *testing.T) { // t.Fatal(err) // } // stlToPNG(t, "kd_before.stl", "kd_before.png", defaultView) - model, err := render.RenderAll(render.NewOctreeRenderer(s, quality)) + model, err := RenderAll(NewOctreeRenderer(s, quality)) if err != nil { t.Fatal(err) } - t.Error(len(model), "triangles") - kdf := render.NewKDSDF(model) - t.Error(kdf.Bounds()) + t.Log(len(model), "triangles") + kdf := NewKDSDF(model) + t.Log(kdf.Bounds()) start := time.Now() outside := kdf.Evaluate(r3.Vec{2, 0, 0}) // evaluate point outside bounds inside := kdf.Evaluate(r3.Vec{0, 0, 0}) // evaluate point inside bounds surface := kdf.Evaluate(r3.Vec{1, 0, 0}) // evaluate point on surface - t.Errorf("outside:%.2g, inside:%.2g, surface:%.2g in %s", outside, inside, surface, time.Since(start)) + t.Logf("outside:%.2g, inside:%.2g, surface:%.2g in %s", outside, inside, surface, time.Since(start)) // render.CreateSTL("kd_after.stl", render.NewOctreeRenderer(sdf, quality/6)) // stlToPNG(t, "kd_after.stl", "kd_after.png", defaultView) } + +var ( + _ sdf.SDF3 = kdSDF{} + _ kdtree.Interface = kdTriangles{} + _ kdtree.Bounder = kdTriangles{} +) + +func NewKDSDF(model []Triangle3) sdf.SDF3 { + mykd := make(kdTriangles, len(model)) + // var min, max r3.Vec + for i := range mykd { + tri := kdTriangle(model[i]) + mykd[i] = tri + // triMin := d3.MinElem(tri.V[2], d3.MinElem(tri.V[0], tri.V[1])) + // triMax := d3.MaxElem(tri.V[2], d3.MaxElem(tri.V[0], tri.V[1])) + // min = d3.MinElem(triMin, min) + // max = d3.MaxElem(triMax, max) + } + tree := kdtree.New(mykd, true) + // tree.Root.Bounding = &kdtree.Bounding{ + // Min: kdTriangle{V: [3]r3.Vec{min, min, min}}, + // Max: kdTriangle{V: [3]r3.Vec{max, max, max}}, + // } + return kdSDF{ + tree: *tree, + } +} + +type kdSDF struct { + tree kdtree.Tree +} + +func (s kdSDF) Evaluate(v r3.Vec) float64 { + const eps = 1e-3 + // do some ad-hoc math with the triangle normal ???? + triangle := s.Nearest(v) + minDist := math.MaxFloat64 + // Find closest vertex + closest := r3.Vec{} + for i := 0; i < 3; i++ { + vDist := r3.Norm(r3.Sub(v, triangle[i])) + if vDist < minDist { + closest = triangle[i] + minDist = vDist + } + } + if minDist < eps { + return 0 + } + pointDir := r3.Sub(v, closest) + n := triangle.Normal() + alpha := math.Acos(r3.Cos(n, pointDir)) + return math.Copysign(minDist, math.Pi/2-alpha) +} + +// Get nearest triangle to point. +func (s kdSDF) Nearest(v r3.Vec) kdTriangle { + got, _ := s.tree.Nearest(kdTriangle{v, v, v}) + // do some ad-hoc math with the triangle normal ???? + return got.(kdTriangle) +} + +func (s kdSDF) Bounds() r3.Box { + bb := s.tree.Root.Bounding + if bb == nil { + panic("got nil bounding box?") + } + tMin := bb.Min.(kdTriangle) + tMax := bb.Max.(kdTriangle) + return r3.Box{ + Min: d3.MinElem(tMin[2], d3.MinElem(tMin[0], tMin[1])), + Max: d3.MaxElem(tMax[2], d3.MaxElem(tMax[0], tMax[1])), + } +} + +type kdTriangles []kdTriangle + +type kdTriangle Triangle3 + +func (k kdTriangles) Index(i int) kdtree.Comparable { + return k[i] +} + +// Len returns the length of the list. +func (k kdTriangles) Len() int { return len(k) } + +// Pivot partitions the list based on the dimension specified. +func (k kdTriangles) Pivot(d kdtree.Dim) int { + p := kdPlane{dim: int(d), triangles: k} + return kdtree.Partition(p, kdtree.MedianOfMedians(p)) + return 0 +} + +// Slice returns a slice of the list using zero-based half +// open indexing equivalent to built-in slice indexing. +func (k kdTriangles) Slice(start, end int) kdtree.Interface { + return k[start:end] +} + +func (k kdTriangles) Bounds() *kdtree.Bounding { + max := r3.Vec{-math.MaxFloat64, -math.MaxFloat64, -math.MaxFloat64} + min := r3.Vec{math.MaxFloat64, math.MaxFloat64, math.MaxFloat64} + for _, tri := range k { + tbounds := tri.Bounds() + tmin := tbounds.Min.(kdTriangle) + tmax := tbounds.Max.(kdTriangle) + min = d3.MinElem(min, tmin[0]) + max = d3.MaxElem(max, tmax[0]) + } + return &kdtree.Bounding{ + Min: kdTriangle{min, min, min}, + Max: kdTriangle{max, max, max}, + } +} + +// Compare returns the signed distance of a from the plane passing through +// b and perpendicular to the dimension d. +// +// Given c = a.Compare(b, d): +// c = a_d - b_d +func (a kdTriangle) Compare(b kdtree.Comparable, d kdtree.Dim) float64 { + return kdComp(a, b.(kdTriangle), int(d)) +} + +// Dims returns the number of dimensions described in the Comparable. +func (k kdTriangle) Dims() int { + return 3 +} + +// Distance returns the squared Euclidean distance between the receiver and +// the parameter. +func (a kdTriangle) Distance(b kdtree.Comparable) float64 { + return kdDist(a, b.(kdTriangle)) +} + +func (a kdTriangle) Bounds() *kdtree.Bounding { + min := d3.MinElem(a[2], d3.MinElem(a[0], a[1])) + max := d3.MaxElem(a[2], d3.MaxElem(a[0], a[1])) + return &kdtree.Bounding{ + Min: kdTriangle{min, min, min}, + Max: kdTriangle{max, max, max}, + } +} + +func (a kdTriangle) Normal() r3.Vec { + v := Triangle3(a) + return v.Normal() +} + +// c = a.dim - b.dim +func kdComp(a, b kdTriangle, dim int) (c float64) { + switch dim { + case 0: + c = (a[0].X + a[1].X + a[2].X) - (b[0].X + b[1].X + b[2].X) + case 1: + c = (a[0].Y + a[1].Y + a[2].Y) - (b[0].Y + b[1].Y + b[2].Y) + case 2: + c = (a[0].Z + a[1].Z + a[2].Z) - (b[0].Z + b[1].Z + b[2].Z) + } + return c / 3 +} + +// returns euclidean squared norm distance between triangle centroids. +func kdDist(a, b kdTriangle) (c float64) { + ac := kdCentroid(a) + bc := kdCentroid(b) + return r3.Norm2(r3.Sub(ac, bc)) +} + +func kdCentroid(a kdTriangle) r3.Vec { + v := r3.Vec{ + X: a[0].X + a[1].X + a[2].X, + Y: a[0].Y + a[1].Y + a[2].Y, + Z: a[0].Z + a[1].Z + a[2].Z, + } + return r3.Scale(1./3., v) +} + +type kdPlane struct { + dim int + triangles kdTriangles +} + +func (p kdPlane) Less(i, j int) bool { + return kdComp(p.triangles[i], p.triangles[j], p.dim) < 0 +} +func (p kdPlane) Swap(i, j int) { + p.triangles[i], p.triangles[j] = p.triangles[j], p.triangles[i] +} +func (p kdPlane) Len() int { + return len(p.triangles) +} +func (p kdPlane) Slice(start, end int) kdtree.SortSlicer { + p.triangles = p.triangles[start:end] + return p +} diff --git a/render/render_test.go b/render/render_test.go index cab97f4..0ba87e4 100644 --- a/render/render_test.go +++ b/render/render_test.go @@ -7,7 +7,7 @@ import ( "github.com/deadsy/sdfx/obj" sdfxrender "github.com/deadsy/sdfx/render" - "github.com/soypat/sdf/form3/obj3" + "github.com/soypat/sdf/form3/obj3/thread" "github.com/soypat/sdf/internal/d3" "github.com/soypat/sdf/render" "gonum.org/v1/gonum/spatial/r3" @@ -38,9 +38,11 @@ func BenchmarkSDFXBolt(b *testing.B) { func BenchmarkBolt(b *testing.B) { const output = "our_bolt.stl" - object, _ := obj3.Bolt(obj3.BoltParms{ - Thread: "npt_1/2", - Style: obj3.CylinderHex, + npt := thread.NPT{} + npt.SetFromNominal(1.0 / 2.0) + object, _ := thread.Bolt(thread.BoltParms{ + Thread: npt, // M16x2 + Style: thread.NutHex, Tolerance: 0.1, TotalLength: 20, ShankLength: 10, @@ -51,7 +53,7 @@ func BenchmarkBolt(b *testing.B) { } } -func TestStressProfile(t *testing.T) { +func testStressProfile(t *testing.T) { const stlName = "stress.stl" startProf(t, "stress.prof") stlStressTest(t, stlName) @@ -66,13 +68,14 @@ func TestStressProfile(t *testing.T) { } func stlStressTest(t testing.TB, filename string) { - object, _ := obj3.Bolt(obj3.BoltParms{ - Thread: "M16x2", - Style: obj3.CylinderHex, + object, _ := thread.Bolt(thread.BoltParms{ + Thread: thread.ISO{D: 16, P: 2}, // M16x2 + Style: thread.NutHex, Tolerance: 0.1, TotalLength: 60.0, ShankLength: 10.0, }) + err := render.CreateSTL(filename, render.NewOctreeRenderer(object, 500)) if err != nil { t.Fatal(err) diff --git a/render/stl_test.go b/render/stl_test.go index 36e668d..2bb4b65 100644 --- a/render/stl_test.go +++ b/render/stl_test.go @@ -19,6 +19,7 @@ func TestSTLCreateWriteRead(t *testing.T) { if err != nil { t.Fatal(err) } + defer os.Remove("box.stl") bfile, err := io.ReadAll(fp) if err != nil { t.Fatal(err) diff --git a/render/testdata/defactoBolt.png b/render/testdata/defactoBolt.png index dd183e8f9d93fd35519359e5504302bc963da6eb..b90ed174e347ca9a91d1b59df8aadd7c38db330b 100644 GIT binary patch literal 87037 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

!WwpGWjH*^spbAhiy#BFf=!bKD#4* zOZ{7F>2@`dQJbr!{$@_0SuTK`b$Gjhj^3efOiVXgE=}89Bxj{+tn(no zq6%5wl{3zIjql*f13>Eg4ii<(lC&c9QeOt}r;*o50&OidPwK6L6wV!&hhO^+42;;* zFC88>-VxLWT^7izobTxfKfjN5JLS=SAn&$ty{D=X)8^rfUC&`c_SlvMKGQpIoUT^m z(w#JkM!m9d7Q%M{_AYX_zd<2dP|_*%tgyA*3qj6XfH__EZME&Ni5XcC^XbNgR%yy% zW&yD8#TAPJe-(yiJ?V~f9+BMybuzQ&#int>}_m17COilNLRmD2AUHkN<(0( z)0}VU$JnQ>r-um=WY9C&j>;KSjQ`O#0c3w}m9lT3c^_6II7ST{&27YH>DnC0EDOF= z&iBo0bA-5Cuyt7!=#KZ*^>;n{J>tt&$A>XP#^w!JO^moWqi?ds`BK-$FE9|>orjrL z893(h#L{NREJHA&02ze)StL;1HFO@}`;d@rVoQ*LmEtV*dyvP{Mo)iRf|P+oG?Nmf zIsUb^&w|N=>-Q4>(DI zVXvQ6s!MYST#z9-@PhUsX+sWzx3H{1u=Hyt8^VLVWfFXp?BvO`u$DHLgKb5Z9EPdl z4ItE#xuHhSDqo@5{z{iJP_W`}>pD~iRd(GIKU93#p#Qg78Ile%NIKgwYa}x@e#j%) znZh3iP$WAdSw>JG<>n8{O_$Ip-zArHIIX48S_!KT635U^LhPJ|L1IcYN!XS>PAcz5 zKAX-CKE(wlWiM9OGW99Jy2#QEi;^P78f)7HjYxBD2~%uwP=lK2J($e!e5J+i4>zd4 z-0nT*rC$VKFgqH^qt@a3i08KCH-0Ras*#>&U4*w!T7az8zz147qc4QX}1S} zZ1OWIg)y~ypI5veaw~atoiWpjf{#M54Hxth@LP-`cP9~59~XfA{zn$7x6B|6(>`CR z>pP<`00JslKkZr3e06}5xah)3ue5>~`LTy>7>}Vp%3oZI*V5X}#99>gV~Sr?#J%;2 znwbU;X12fjK>1l`d32U(q1SIwt5kHg%e*&G^41tm-8n}Ag&MrK@}#fpM50=nRwR~@ zSoZZkFRtkY1Pz2++|yYU6T~^=peSA*C>;3j*tReXss>pzr;6eRK$R(DIag zg$l-|1W(L1rABolZ%CtUT}E2={4y48)4M>>q;ZjNlSfWT7?UK-DY=q0d3AM`;S@3X z3-l61OTXFUQZeh)`N0#E^cn%&`Gk02EbzM61#!&>91x*5mOSw&An^_JJoI?lw7gZN z-S)qvdpEbZ-s(bf^}AU{J}gWbb}it4F7V4U@5z84R(weaGk;Ziprixe`FNMII{F0}L4GqR!_uZpzkBx2beKCl&*-Ul2AgRliW%Qboi8D$0938DRVqQ^ek8g)4b zd(`04Z+1*}_cZ{daR zesIVD4eRjL>TIzyiZ7W~NZtsYt&03XDhP~jn@L7LsPwuJe-#@p)J8cLF0w{fw)4V@ z?GBG^xq=oxj@<2$`E%sjY;%ZZ-})azS50+R1=(Lowi|bW3b5bW)y7XK`JE}cT;7mC zlXe9$QT}{ux4C1pO&k6rJ@WU315+z;d(zg-kmaaj zBln{A*u?CokHgQcgk69jzcE!Za`co=b+Wcy#lZ)aiSK{#S+ynkL^0mh<^lV-FrYACBQPad+|3s}fqEJe=EbLIFvsJ5cWT9Tvt;<*6<2h)j!3By;VH52 z)lt^Ov+G*1Qtt#<>E{zXUy&q~9|Z5-dYLn_wl(oE7TC0bYqjW=Q*lOJNA^exB#z{# z-aNAn=+-ym{lZIF$(>pIYvKMiD(TYzN^X1e;TFnAKMoJNr4TD*1hi9_t*o^Lt^tSZ zG+TcBoO06a!`J=;RN@hY*kb|2-D=u(5~ixG7Dk^n0?CHJQ+%`MVo%2^ z1!l}J(M+jys2$Tt*dxYPB7bB%+H;dP)z>dc8!IG+xV5T;Y&zPpEw;7_X&uW^K1)$! zFXA4W0c*$7?l#`IcPbycX;k0jH?inPQJ}OD9)$B!BASQEQJ^y{!~VYwIlsuWn*@2g z^;1odz*xT|T+lyBDGydYs9;!HubsWN#V8?r`Kbb|_`=YB@k`!1*0}ayD&8Q;(~rXUvE{)H7pKF7)5Ea#q6l;uX|xRz+tyFV~Ag< zbkAyaQ|IjluE*?Dxqe1g+rv4hy|eB=YV~81Y7dO>t{~weF31f$XOScgT4^HJ7A*fl zNtSlAe?gtt8=)aXq@i&=t0jnx`oX~$%RmQ0*1%4RF^8&+w;tw{bZ&tPoFf6I8A-H2 z5BeQaC-hd4&uT`Z>W_x%Rz73A9eEt?zV-;!Qr`9N5fxM>oB23r-qRY&N0a<$hn{d+eR}4w^zH=HMW&+ zM~Xp@*o9m-NNk;3Lyv_m(8o5z!o5dCdht5e4v95d^An!KZPQF?*Y!g|qTyv+=PlPw zUK767XBXLYUu9T|Rk1x86_M_;uHPH9)LfMrDIn?6Jrt(pe|YbL!L6`n)TJ&b&4lC5 zwYC1z`iwYL>^dP6vaUEAds=SD-?wUX#JBGK%(tXq3762IwRuW9CUSa1*e-U(5Bsh@ zmB2TNaBjE1CQ}ew9UB~u8Av%3dt(@#!w=YT&wXdwZ$~B9Hu^nk#5@o75jP@NN^K8i zJn8mfJ{JkLG`(Mmdb`;cFb|t|(mXKsvPD;@9=SnQoCQ6XAKXeyD-Wrr3NM)-pT2GW z`Hg_UEd|E_&kzh&!N#=}So(Gm8SE8A9eAU4m*2B#A z)A}D{Scs%2gMwvyOV=NVAOkALZI>P+@h4PgN-0WpBQqHnJ%pf{{9%=ZP!ET2B(LTm zq&Q~ zQb01bzm@@4izAJo)9paVvyYJp%-*jji!o#=uRFhF=K|yy1U!%)?sN+y2T%7!8HtOWIv{8CkTK|dQ-U%8hxU7 zhxox78`<}l{bVM>gMS+ZlG*2%=bsfKllwk;({?Xf$G=7m8^-BAC!E853A_C|8>N*P0ci~jdu)%Cjid46_q8`ky$^cigcMkuejA} zm7OL03P2mPQRbU`cAE<`lYoVzTO#wu0`9yMdeHv3fnwRdVPqA87O$W;EA zyLFt4kg1jLyC^la)H9W#!2``opcRU&tsbq@I+R)7yAh$pkEo8OwRNZqj<~$;Vne{@ zIJtd?#pj1+E-ewvkhB6M)%0Io8@&iz=+*9$9a|UHZo%$IDC;|a!ILnpHqfCGa;iQ zs)S!$lj_*-EIzMJY_6vyf^o8%M2fEyp;^0Kcy{pcv1ji+^(z2Y^7Q@usgeaPPt%2Y zx^#O5LCG{F(nw7lERW&R4P+5|FDHzvxyZ>zg54pso7I;pwL!*_dLmU)kUH{7)|bXxZ6*; z>{x5F^U3z9nemkc`PQ|q4Hk|XQ7*OBueGPFaFVLVj@V#NrovfKPrUK^KeE;3<*1^J z1TX=TN5FX#`Y& z5vI7}zA;KCj(*O3r6u#E^krQ8xRActZcOPd z11Yg5ar8l{)JOk{Jp1>m=GCRSxiUskSy_=4E0P+%RBevh@L8%Jpwcp|uB+T(;nw$N zAF8-w_AF^@S`@pz&9bYhT9HF2CIr7RG;b`yXKM1SRb2~J#z#Q#%8G_ooxIcL(fT*` zUQuO(T%JY~GrMT%6E!}z?CSmJT#fVF#40e}{ZD%Y_~lc=A9%JuTBgSr#Kzc+Ts!&H zR#4B;b4auy^&fd$-)xV<$&N;w`%fQ+X}r?Dst&2{9FCjoc-}Hw4N<>=qL0|ltWLkL zua`6pHcs>7C76X!@qXy%R5nHa$X`z9mTOUdH<8n${FxSl>J9w$INaI5`<2a7i{Bn# zg@UY-a=|{cUX{{XAwg~0B#FiW#t-1pdC7G-fCouJ@`Ej8T>7UW`QiH+_P*X=`|TIjn|H|SS_Y=#hZB7 ztaII?e?!qNdimXRSXP7DmAi|zV*=`a)I2ZOt=lkJPa8|h3yav_1h`*r zd7PUK!Q*M>+4kn${_@6OpWc$4^m#ko=sveTtTxj;lW$OJ($OxJm44mvmF~TRUtS$_ zCT8zVsu{HN6=vL4@9_1MCGbj3cls?d`7jU>l>C^@t5%$VYxgMP{Gm+1Ez4gif?0cN za>g_Qs9`JH4sQTb1ltP!-}Prb{h=gos*1iSrw^;?$!olK;qKXEEnh>E#b=QdL{_j$ zNf!KF>z+V)r_=BZv*$nM=Qa!JWh8kkuRY1xr`_+q>DW?6Mt)o=8tHJmBmRTwCNTz& zVw!oag-W7p`n{Wc0})%m6a{c8n%k5E>0Q#h$~XK}=hdt38}}^2L{?S%I*1e20oT%Q zP+-Bze10oSBSTIFogW{@=j3{;UonIk6}Y7LLZnrb#T(fvfddnp*~Ty%Wg~0-Auf!qOK&DS4OCF zKnvWs6wXeE{&jwG%k}3_S*PY>^T8qHU9&IB8ex0l9PJ<^PLGa!Tw$>K4Re_LrCG?Y zCQG;x5AN$ntc-PGyHIS(ay!l6we3jx73ZLXUEc7th4j+v_lV*tR==GMKJm{gFIsN- z?LU4_i+5<*rx)^SyzEDprq)Ff@GH2#X3l@w(0lvzMC`!<@8vp`=%`Z|N1D$(ZAX_3 zAuUxaZ+jEuIbVXKR)jhETI)ZG5oRaWht&uIb`3szCmO?Eq?FR=BoF1_8N6kbjJWaE zkFo6zQyDgzJ3gK-+$M)RQ5tq7?;pivLooiGC7t&75C8R~s_ouZ_4i|PC8dui{iBAQ z?myQEljW?cx{Y%Pyh&AX@kW&yqiLnjmyXHp3Z}gINBBZVa=`S=qnc_ktQF|V$Pv5E z14Ry~9fH;xPVSDh_DYzt?Gi8D^5*!Y{Mhw(WfZTu{>NK;&e^E6m8DlNUFF&V`T{HD z33p2}sA!wkx2+hHH2C-$^5(xL75NaJYq>yb(JQ+0R_UF$5kk2*Id*e!Q}Mgbi?-LT zvWL2gQ|`fp`Qq}oQv;$%!&{~6awkj2>d)&|N9}a7g~w1(f8MzS#=IPG_cy#-ix1T%xI!lXHzEpcBeyd#a5VDJ<4R+CkM{zdTcL^TJ4Yy>)oF6T` zw~D`^8W~iQpDl#6$Opwx+;w|Jmv2ezkl#0-($AP}h*st14tHE%6a~0y9uS2L?m0I0 zcmCa@qa^dzGmnH|-IUO6P!sSEXv!KEtBNfx&EEdzTl&qh@AbA=mDVMCy~;!FPoMuy zQDOea=p*v^6y`ecwUQeWnEYuQ@ZGPu@}rU!_#G{F1>RnWH+gogRKL)c$j~aQfjQpl zB=(D*bWTEc$Bzb>F2NK3?Q}8t`!)X?$jAL3C0hQUA18Vgn_zhUAzz8qxa-G^<@(bQ z-FBVldU`T>o_Swx=0CGM=T(MvDrxj}7misF=rH|Y4!IRAp!TCMLG@3X6tYmHeH#2& z)6L9>=kGVvSy?Ycel+Eb%1;Mh5mkH+_=A|QJ~GHOZRW!6Ztd6x@f1_=u4V-4p3?1O zuT7FZ2_Y+Q`|RJrNB@(D%vB@z`i}kl+T$iCSCHP7F(4RS`hS@E>aZxk=WRa*prVKY zA_x)!lDgoMf*>JMg5**nv2=GTC4%HC3(_UIAh9&8bS^0%-OW-L)_n@%y??`{gM9RvS$klpQTNa*TSE?VK~bAhzW|d1 zX?N?r(afGY(&Uq>NL7+a&F<3ItLudN=)xbu{x;T5p}cSt5LpM~a%@|O$C7hzxY@SA zSvY$B=iY(8kBqi@daN^c`A6{kyqB6}Bf<94LT2mHBapY&`3#Hw#joRc$RYgk0#rO* zw{(&$ZCsRP-28Phna$^Z45&!9mRyKVY#ylv55SOQb@ZQEUrdc>Ix$X zMZ`VS?^}G!KWNwZVXy4#=*l|IFF#M35VwQ#D!H7w@Zo6@40y~d>UU&SSDw35)E@79 zOM~^+6bcMBl5H!+A;%x~qGe2X<~IC3pMNHAa@Q?_DwI0+wYCwS(Tq_lN{n}0Sbyzi zlv007SpbjsP>xtN@i2h_dbnkFWaVIVe%v#!;W@i`n7UykT{IgI`GR7#OO0;Z=}lh z<{&Ft(BEeN(NfIDFKQRa2-l;H^bnd=0@9l4RR`kIlIxJEkASs}_xcOiT>atn=Zj$! z%Cv)nx)h1zEtAv+ZQnuzxoPy13SX0z(-=)c^}dQE*WzOX+BP*$0-pe#>cE#bJq0v? z0+;0Zl9nxlI5Fyvmd;%Z1|`*%2@(a@vvZd#1ywg^&FG#SIqDtj(kYZIRyg^j$|vKM zJw4-(WSdip`bN#}mokZaFCHzY7ozyY1Tp#}f*$z9_P*!r+Fp58EA3_;AdpA9Xz`#a zVaeM-TsKCwD>-b#Y{9N8s$o`JP;*u-x`4d`EJ+DcCbt;;qR z2YYuOnel$+IeEC6Q-rjk9~sCmxgp`0!MxtYYH35x?*Cpkwo<`=OvuACzTK|M&UCML zp!%fUuJ}Z;T>b94&j9Afo2jr~&V?J2o@vMvGnk$#->CxO14u24S9Yp|VwGQjMKf13R zm@+x}y$ZRO+)|E^w2%ixj?dg8Nt;?;4+dL@vE~F^t&6`f?WGWMRL(PCF7EFVL~$M4 z6S58EfZ=diDaD0G(yicAvqZ=K`t|}m92!bGhrEum%e>9Xmmo1r577EJLX2nO=6Y)Oe-rq(7`!1 zy{nz2{cO>un-yCU@LT*HVkZ;Bn}YceF(rHs})4?mfbaDRI?j3obNHWz3q z^$W7O;k&H}GxbqJbLMQ6MFNvgfRF3%oVu;B>E%iV&#|%QMNdls7gkv);Ztp1e7jl9 zXH%7Ovy`&Y3UWx#j*o>-XsYvf_3R2&Bk}L4Nxig1O~!?) zD-{AZo6`93_T9!F@7j`*y4BK_zS+Lqk({$*`}5zDzd|yV%QMbRJA2tdE>#a4 zyRo?^AVPZyQ}NsAF`T@G?OiPY$HP+YwEq~5jP##Ni!v&bPOrO=Dt^dy!34xzTYD{$uxFhUGIwI& z<+#?o1~_$RbZJr9&UauQi?i>e_LO5ldkZATXYDpX!g-V9N?zrJZKM*YJB2o_CRUOp zn)b0Svt!aKgs0bzjTRwissBmdr=-S$8E{FLzKdu%Cs4vg3_C>%-?MmLk@Y6Po>`3? z7n;)74lcq>+8Amx1SONfWzBbYnQNkqE%S+bIPy`85*JI?x^+=+F^{=K^nu=#*S4^L z`$cz5%Wl&(T^(YSe1q+yEZGY*v#3X>_Pu?0+M0A4d9w;p$2Pn(w2kOy9NUX#->J5R z&LCe$g3^23k_#ihwrTNVpuFQ&QMt5XG~8!y_1J-0dSXICMkcI=c`opR*8#7&=Qd0fI$182N?f%U1Rm*&Gi*#C6 zK2h?9O(XM<%k#M`QcWGrdYPue}rpUfT z<5cAMc5dE_%mY8fLllMDGFYLAEu@65*5Kv(rMjf+Y+mZtpGP6KwvDTga>u!%T%Rh) zz#M%PPR%-llYy-Bk)0&RMG6V(vE8rsr6G+@{0rnB1k|41o*G@ZQfU9Ddb~d&EOBMK z7gbLFWw80ZJk4k7peSVlimF?rOjuoH$@mKDqW1&?xX2zj-4T9zp|mdr5Oh!u<)!j zEyizv;PZ4dPmvpd%IRNOD=a`Ac2w7fu;nyp$oqXB@_8rk?vOiM{H0RtA$P`ObE-nu zi6|$2b(Lw-3RSs8V-4EWjCKX1+uzD>l*Sc=&o|%md1v`~CRqC=WhwKUscPjel*F@l zF%1UKx&5iog1;fO&SUOXn5Q4+4F)X6#>PChRxRUu3?|%c3U%YT*|I~4ojKn2iQtVz zA9@TuM@DIjUEoV*y1y0A-!d6A6DABdL90K8B#$9mz*tpAA^*k1U8;j|nEOW=WLENx z;>ldbfXDjBR!AxbALZdBD?UA&w-v@ITD{Rvpw!oRz1~1-UM%nV2&VhLA!M^P@A+cz zBV63MnW4CEC<+|5iWxg0vk4u@%5`$axDl3w1&?mgU z>w9*8vi&ncm!3>uZqdZv+FrP|@ZG}Y=KC2|E)3K;2>3z=1TOuxeaOLPvbYfZN>tq1 zu&Xj|DTbyr1jtq^FEn}I-5ZsB1zV|+9F0|5(xYd&fIRu2BkFtqK&0hv!NqM^8N z{W?(^#ma4WADu^!t|&x5^)2?Qm)@ z4Ub%!nPWTqq)4!5S|{^f!DlbKilp;8mie#IJl8$G{c=tvX}UKM9E(8uUCio{GIshZ zf$e=F;FAFhpeO@-4$S?x`QP0Gk($PtV+1G8e0+1=d;SuWa2>XH3Kl7n?;Ks(>*eJJ zQ8f0%j!v5TOOk~6MyA}4SIC;nIr)TJc3;b+RVJLp#cA!m0AlNl(^YzZAb3Z113B0- zbkGD;8FN9%goP^`AQ#Qs)^`^S>U>jjCLQ1EZF=)~f^jeAKbCCN9G5Io?{qm}-g;+A z!G?9)Uej2A27|~OY&ykLkt0j_LT0TKoU{{(VOG()_~nzGxaCS&-(4Bd-Ok66D$o5o z^lk-)NP=7(oWMfDj-Hoe#9tu0N9jLFmV!Nut&_w;XL+Z7M$)FiaoAJ)&TYN@KP2QnL&j5_h2=av88u2jWPZYZMCmqw;kleLh)-LAozb=Ak zk&w?APze0co|U04NQ4{Guy?0m`OB{4JAZF<$sd4t7L%(n+kMRyVz5RePPK|;rv=l3 zwSI>SiiLY7ItkDDV-R(nDe3xozde6+rR;Hqomkrp0tKSjArxh~)h!|9s#r)A_x+h= z|AZf<)ZMZT`4|i!L#SN0s`k*>69Jdv?avuMM%7x^;yG{j?aK?mr%uNypL_7}Z%6`* z`^UI{@4C>v;t0Rn6fBT31s|g^~*%c{f>-=&E>WRmjv`p;!Df) z*86DrKnz5e{y?~7Cf1<5{8(!K-Lf(N!XU)@r~z@Hw-j-`&cSubzudjj7I&P7By}@* zN0hg%9QN7J^~6v}z^g>outc@xCPPkP_cg{l_wSpK=#6KPBa28GPtD6eRU-l)k7%Oo zPY}6oc@TQe6fRM{8>f>RHiTYWP|$h9(${Q$v{u}ZcC#t9Go?~rD3}>8AzSN`E(7@6 z1~OT!wKm){s$6McYevP@HV-+%yR#-bsaIVzc33< zKFM!Osn!Gs94JOid1-|rOtgIx8OFV4M*HK>GGM_|A`=KB(U12sV(m#VUnQt@u6~DU z{|?uj=y=!%$p2QsSDy{pSoJ8i%JY667N%pu5lRDeed@ z_ob(24{vPP+=h}xDVo-YI9Kh)@y*uzzhFA<5GSbBE>wmz@9?gx7(X zOI4OOC%{mUzn)zs$R+c~7`lH(b@DB9G%lPsqkjm_S=?TlO;I_R_868oXEI3L-V15kPakgQcw%l^B*r#RTy1ojmr1Q$Xe^90RVnm7M3z@N`bV_Q z{YUxGU#?~dgR$=JZjmZ=afFv_rrbeH{GM4KGmaw^%4v~e$L*1KPO~)8cugI<)24KP* z5aIqpS5Up)@OFv92(|fu)sWHmJ0su(Qpk00Br83oJE+Vc(l8c;t<}oLsURe|= zG2D?NbQbyl#|((B70cZ$O@A=O_&A=0$U!A1mrE=TTd*_Gh1O6QNN|*MH)OezJ?3XK@U?E2*B2mZ3#OjdZ5O-=WC^ zEgul4U2lF`X@9#l-Ihq>0s*~dY1*cxSS>0!_-^H?UtI(nHtX@FDbzg!Yu;Wq%sQCF zoPqg2J^PMB3v0&Y4>g%CEOaC$%P_xRELg%`Fr)Y437`MZNmwzMeFN!!9wLn;E}R?H z>!fi4Dv68ysO}xNZ`>OvOCU2b{S&oFgSsc;(HUu$NK;Fh9>RfXy zWOaHncqc#bIFz-mfF+-7MAYoH_lOfZ^z{3u>r<6Lj8a9Inc_(()2daW`_#xPKkYNI zIAZivTP!dl2*5)uPiN}_U#H&qmFx7r`}Qw8Ui3=P-63_3O2~C+{ORSQb^M=`z2vV1 ze;YB$$SW@rGYCa)wPU~KBQF@hB7~^xZD^Q=tDbiF%QKlj+HnjKTa+1-f#z+}C)!f5 zi*02QFH%~IYR>mj5SRBX3u|`2`tGdEG%_c7)7Lm^>DpSlrq4cV9u=;p#op?8M$xD- zUtn#EFe#aL^;uo|CV%PFw!i#CzQgfx9yO~!k4t+Ap(xjj`L+B~N~WreC0q>dUU28t zXrRv1n^4#wPuGcXv<$T)D1krRSgy)xSgfdY?_H`+m=i92Eoa?Vh;+rn|cy0ff%yozGn zQH^5q(0{9Ft@(nZwLRS?N+fH}JV`=Fhv4HS<_mB6d6owMkF`r(OtCK@^9!xIzSgjy zPPzI{FX-v_I5X%dMJSxNC0544TWK&zWJ6gd&#O=zezdBF9SR=fok~ay!;6q&+IW}U zFvR0$u018?6m7Jj`vSBqydH~;X7t5ib5{2bo!gf@`n=OK2-x|7`)>X$>e-%R=lwQTjNICtIw3f)BH%yU={Y_ltLza~!M*Tn?f4yV2d$lnei`9n(o_s4{MCq|bCRxM~W zQ#dGIpG-~&PW9^e(#;{rO=Q|qi=ES8$&9kXl0?ZM#O=sovPNZXHd5mG0>P(w?(nw>ajKlF4Lw5$!koF!A!l0_}QL2TSt**gl1#pBD|$GKLC=eYu&B5z)< zdoftHeodBl5=L>wwkz&q=o*@~IZ*mocX(`!e74ODLp)k3S!;^?@a4n0RiUs zHBzBY9PM7W;-~$bXB$tvUSpSNEZlCzeF7#dfXLlY65t*+lN0h7nxd<4_1fjizUCr3W1AxP7nY1t*14mlpZpTA4pZi+g2yjqsU#(c29yFqBzp)e8qe&2bF;IE*;(q5t z-v4%pke%zSB8R+WT)i|jepoMa(rS!rFiUe-lY(m#hYU`nu+Xz0)pj}x7WjA=<0)=c zm*?JT=XkU@8!TgI6=(sLt+u|<$y}_GQxE6APJ*alN3$D^{h&Ree7t5bF}pi5LktMES`4(MxXZ-ynGH|O%$gF7T_Xpe z2EW59<@`(DD*5=k@IRxK%M6MLM+~j7Fs4mVOfsb)oy&~<+g$RhV(3Nx!RCi1MWt%}X4rsa`qR}&vi_Uw zYV(WGCS%P#^EUN$jPC8B^IWd)4nS$xVJkmqDJF&HnOPTZXwNeipTS5Y6M9R(HQfbv z0a(_?a5}#XlqkI^{{Prq`GW0UC!g4E-{eApq(o&^Ib(YAhR@RG< zEG+HulTtO+Hj5^~cvde4u!k39qCM|QJ85zy#zU@aJ*z#;*d4&-D3L?eKq4JU{iK@D zTAy1_-9@YO(pgP;Zs{iqbarKY(S5)fz$rxKKIp*hALBP?3KKBevYgE6iOsJrZ-+XU z9j~|n)dkwN#Jr)NpE58};~VvJ0T1zjFRX(gWf&A{bmvmd_Jh`59)Eg<1aR54`3+O0 zZMjg`W;ic8_QIvsRvoMQakM|C1@9RJmW)ouCYQ1}+9K)|(^z+v$d~!KNgb-GegY+mR{RV*tGb zn<;eA9X@nd6#YBekuT?gE#Rd*Jy~b&{%wD_Fqg zKV_GcOpa&|k55~L{AZD;2$oCJAH%mlzmzDr+%)1AvoJ=n6M#IK+jX~(g27VbJ9%tu z6!3^W@tbM)R&2b~GJB-hT${)^DU?7S-lnXa=Yyekw(bYInT_y^-it>8m)rs>1LQ8r4F#?OpHyE zM>5-Gt|o8hxtZ8(pN)D|&?_rMmy$k`UCf+wvzg_e)6g$n(lg&fI5Y7cCHA&9^? zSv_RnwJ@RIaH|av={#ZO>c9=JF0y`5wr5z_c*{3YTf71?qhY_UueT6LemjDsIzx-3 z!=z*UR~HSxra0EC)KdeLK=x4m_OioJ1#-}J#qmgwg%mx`Ke1dLTbQxjc!N$r(?F{I zIIiK^lY>H=?Wp?3blNGxhl;5gI?u!9;CLB@?^xOx{4mn2+U@?{BBugd2~LCrMZ^*Z z1df4L4BzDcf-)g@-hm; zb_~^W|5D9OkJX@*%5N{&;$|^~9c3tVt|dAjTp(IyE{!h+vU_B*gwC5TUf>eFYsC5y z%781GYEB*};tL&`Wre?KcrsF9yUU*FW0Y>FvZl*bvM~nzsjNl+1{>8Ie)&iUmW(f} zhwhrA4Bf&&-RGrrci8h}Ib=qzmftBJ7$08i71Q%ehMlGY3o{90Qo~j0wah)Dc#zYXjIg zU3xeLCLCAzXyjWu*k9Ynei1pTbP4})E00}GBz@2S$Dnu07CtRf*qGqydw@c8c~W75&!C4-rMbSJ+nU5s9~im|85 zFPSBy>0Ia>HQo#RFHC$63>PeIVxR6zezHdmOpJ}=r>*N6=gp?OFIRJKcrTW(uxxieqtfiAxCT)H zCqC6YtB~w?{xVXxYRU(o;=cRg3-?F^zaWj$6g1&esYznkJ50o%M9*)R?hV}KENi)v zdkq9XFrZ)IS()AHho%|}CjnwCWckpLt)98{ZW2*I9O9$WH?rYcHjIl8sMQdb>#xE4 z+b&OyBN9lH0enmMc%7=`@akE9!T%3St@ARjh@uuKyOtm1?p~$+OAI}?2sz{oFxyqx zvh>|4&mE3LGKW$h4>Za9n_41vhYcp*1cm5`-8=X!%nhTVrUF1f;Bx$BdG%3)3yvU; zXFGH|=xABqzAO$476k5`#Kdv;Y;Z5p?2@8YBnI=;&%>y-!Td@Pq-dv~-kDdU-!oYix|H9WMevzhtBnO|c6?F|?% z#%GCOIM(26-b=)fuSmAZ1Y1~hvjUZ=nnl|p8DF`h+cR2e1KByrzV+E3LmWARu2d#V zB$U#%E?~t^*|j6gXrw$%I*#17rT1Ep%&P<2Ut zg_~}Q+e3R4xBvTyR!hB8jJeFW5zv%iNs)6yGKI)KzMKt%DSL+dKENaZ-e}(yUK|6e zXm<$`C$V&)+ftw`baOBSzz8_HO9!p-{2nVW&+wb~|5q21a0iO(TJ?8j0Ajn)@`VC# z;dZs#*&e3c7Y4I^VqS4?+{!+m$>&XY2cgwtdd0>kKx$nh?5fXsXq~r*lx4!3Qr!-0a_v@bDYQxs;3Trw({Vgx*mssS$sYI;^AKnsSJ!7WN-v$C7G^MIJ;G+|t=z8KAwI6209!BWThtD7{P%_JZ>wVjD2&&o?8 zJB?>Q=c{W^f1i8rn#^f$y5a`${$k3~cF!oxebyUyHFQ^~aBsStb)dj`H11l9=tHz` zyBTOy+&&qi=b4SLJ%%FpPIB=|%zIdgS8j+UVWkeNUx) zp->Szn#_NFv`7wA4xZdDbfZI=(S6~(l5z{j@H0L!Kuv0i?;Qt*sU2#AemY0ImVy}Q-z0YXPeU_?DYJsLdbk7 zCc0)-=v+3eOM+J8WMa}OGql41-6s=Nw)E_3)^6G){SRvr+B=>*yygsWT3S{k&R@voMFP|N9E zUxavVF1E@$&Ii4R?c&@;v)1P(KRfYXt43@RIK@T9L{HYIh<7a4NAQial=@yZ{QlQx z0X5&EYnd@}MrgYw7x%}Q_auMutnJE|U$UYzw>)93vKI(###Md)ai3QYK#j_$savPt zrpa!;>K-{_(p!UkYeXeTqZpV!!I8*{Rv6KmdDcylD6KD~SM85vc^R1MD~2+&-FJ>w zH+OheL)bv=G$!Mk#2=_A@C=(Kz@fbwWI0Tm;#5+|sp;wZnOiVmE;jH5DUzLG27YF+2h+Ey z0Z4IK>|D2i=sa2VF;%S3SJXd%=FZ9L{^PdcY0v?<11@A2t{7N>#XSF@| zK3*a+_He;VdI%$Bl`LyEsy$z^I?@v^zpSg9ng6OiK3q8iU@N8t&)rc!*3~K!qCZe3 zdt`y3I_hyr6E^07H=|8k-+nv{D4-UF6NL?9C9a>3(hy%`Xt^n}KCibD>7;Ha&Y z7qa-v-ATuOd}Y7KH)Y}FR<$eZb_JWP-pn|x;5gDYZTOVHr8{<6_z$Z2^sg5@;^))f zgw@;_QHCKNYV&$fsq%Zkj=WGzBhF@OPtjgI4!rf)g4}YUtBh99vXU6uukuRaE$xoS z55=TPeNJA@*|o)U#%L-l2Ms3HkSs0UC^aC_tBaAiQ7Tyu@|m5Uq0~NLRy#PHZ}qLJ zlsw({_c#BlZA902>vjN%T@L^Eue5w^M>;xtQcL#OS;g^s2t@A}lYj`ng)%>yS-yZH z4;%nL+PRu@yT@+n=*I%8ySr*^K2k^Ou=yA*0><@lsX=TC1L=wc{Y`2s5_sfdg6-a>AD0~jP777^;puA21O&Icm zCU=73*%D9kH8y~CeEEacvg8Z;W@1M3hd^=&i35Rp$m6A-i*C0VuN5R1czX}{lFt8; zgj8$+{^M1&bHZAa8-~+j&b4uRQq2>7OgZvUp zn^kVJ!*sJ_@o?L`=*Q00d(>V!@iFBV0gGy%jd^k5>bFWc`k_XheAe4v?$C;!A({Md zZ=Lx`g<8NDlbeY&+}WSs@aQ-zu6SER>#gE zn2*`8c8DV>R8+nd&9qupIiwx?s%7ebk{T#?$@C4Wjhy z#D8*uHKgYA>eb7P2<{l}3+A9iayGSsvQe`>v_$8T?a7!g-j)|9b-G>W{uMXw?$_?J zqDu=F8dOkoDCFp2Nf+?C+-C+=>Oy>P3|oHaOIIGVK$G`6qMYkZM^t`{&|XnLIu|2? zlb4+ZC^0-MVRfU1s8KUCQ;$ixv;EWI_a`AhW}^~>95Vi9DbT&~tUx{Z%ZeR1aUrUh z7b2QI_s&zeRUM8L}FzaEsx%Op0PpyiqLbT2m{X7N%qHF9qj`R<-g zZw_wgQ#qaZ$$c?F4$a^BMT@(Y+bU7fS95FkG$f_)Yh#GLjp-Q`jHCb(69mYW#MjHj z@Z~-}D}`sZ@$_HZM1I*Ew9FLL&1XjRx^t=BE)CX|NL89{r8?HcyIzK~F<}a+LafL+ zLlce17ri_VC~d)QtpYZBkJ1bo1>f-WC<_HCVfC-mkPLlSm3vbFj?a{!bGR+)w)Fhv zik}gj8XJA@+OMk%wDN$cmhw~k%*gx}*K!lq@!Hb?3&u7ofd~(bY2sOX+fUFx5lr?? zXtF?gr-n&y^BCy1OEa~E$PR$5-q~Jv{2eZ|b*+R1tQoJl0;f+k!%EfHG! zwda~3oiqaCPu5EhE68tCqPtsg;Ep#|b9y3PPWfpmDipK*OU-d+;;uG}eJoX;@rEKm zJ#RO+KiNRBs_D$1*|?G$apppFf8*}R!dy=nPP0dqhMnh)spKn~UrZA}ZV4=U33-Ff zpU|N_Nmf}VylgfB4((GmfZ)&dBwWu*{}c%Vv`Z^1W-XU`?F%tB_ks3In?--_zssThuT#4#8TdNmn>8mf>IrOS zt=hHWM-j5@LbRVvwChtFW}A1N?iRY@FS>hx#QR6IU1f{q`bU?MV2=&{gW25;AL4PD zult34&ed|@;yEWLC7}iv!`|2hBwxQjW!^mU0OnTc9diZTP=)9Pq29UAVQ0%e5T^Mk z6~jpx4*3}7B7lZGiaH0l<#)Y|x|+w3$dE>>Z~3c#vSPEp+!wVzxBq^6pRMuBVT(rf zZiTG4&J;a=SxkV#*mL^tF(3NPzheQAb=)Bm=ntM6kc$b28nP{JLz!O5yrE&glgq#P zRY`W>$9;g$59?8t%X=yy6+zJ*^UIRog^Vi^7{D%YqT1fxzO~@HBofRn-|tG8w!}HD z)M*Z$SmlZ6tXUNLYkX0JIqvhFsZ#!R-gUmUzy2-Vu)vcwEqjVF&G@m;EJ7iAo32!; zqyTyX9iq(TLPUClKKA0IV-Aup#c{w0`BeU=VAXTc@_l~h`Le%PYF$0giu5i01AUtrvK@OP8z_&1VV^<(o_utnjg=FUq&LC$u~UN< z-gQ$2>RB6HR{K)p<)g2vljcLCDRA0_$nBB^a5wA z;syC?zcn^{^Xn9X=J^sWTljUQMweZ*?}jG>p^tXME!x(ZJ^jIbMR)a$m7&qu>t*Y^ zuX9Uk!D6D^aIkpAUVoSYz9?C6Gx^L$QS4vp1|EFFm^-T{0p$2Se>RfOESda#cgoye zfv;#hiwX)exymwVzW9n`m79*H+;~d|c3`^|2O=-lX2Q}#^*=p)1+;NEq$498+~Jot zPc&_-ezaU!=#ijKCQ(^#*xgZpQGLSUG#Kzvn?3NXLZ4l49}-0=So()ZzZaNAaFE)4 zfWf}3Ej0;NJ}L)h@oe~=)ulgf{>dENiVqGo0&IYm!{`UFm1Z@~W<$_jS$z1_@9rep zBprL^uaj^=6B?jcpy!56#Yq@`kl$c-9jFLu37^3>yRo#~rS0QU3yJM5(U9NLues#n z;HFJOqmRP{y%%lF5~&pLVZtWojSqoYExb4S(tD=tr#66==$BFy#4Ts0Z`at6&2F4r z-@ZEn4aUyVVH8U4PbA5JX7zhFPWSwM=HF8ct1TZ`g6#3Ne&;FQV+&Wmz0>VOXqRvG zX|%}`td9u8IvD3rb-<}z$aKf~epD&ycj%5M#C#T7;_JL>;Lsf8D?t~dTy#`C$HlN4 zeu5D{dPB@vvz$CxJ_%m#W2iOkS6CF`yuQIu5j#e_v|1Q;;~jqgtEgWDD?yXBU;F!c z+#kJ`=zoN-l&6OA2+|uYJ~Gsn|Cp&dPa(jm?Ibm9JyF3DE#*9)%g5L~I?CrLte6!=03Tv-Y7p9p2jj5xfG5%rXqt%QN zk53HBkRzS);$5ydC~=ZNJ;_4dddt~$_>z@q4ZF~BYZ5mzO^OT$1z_V!iavb)vO z-LjFsFB1{0OKx2{;%3u>Iv`MQQ~;CY7wCbW@KHR9xQ5d4S!2tOyDBsO%wMq7#?VJ8 z5gxg$#*1S=TNA~1lDPmZ5#VUr0AJ~>*S zsOdam6P+JZ1d^(A)1I?Q=j^Ub$j(b*cS)acMQD zp0pW5qz&=L=G>QaZ))Y-Ht3cWEGcWzvOWp|McVNE9zCju^aMRomAezj$_ZX}M0Xoz zeO0{W3jB8wR&+3XV%NPX;7&w#0?x2Z4yId>595!d@nb$+H#9T-mC7!et`ns&x zIxCUX9yL65y+?e-W-G>`lq~J+y*V1QHl+o+dse#sZ=1mJvbAZkHv5ZTF15>yb7jaq z?YV!F4(JIMcSpSEbA>|6u~}^`Z!FOClO=~0?WF*s4CqgF3+rk4E$`HC>;4YcBe}mf zwsCk0=o{2*^h23CSW8mwW2g7$n=*TLSCWaDs{-2%3o>JS??~`b;zYdEZa0IMb=`Dn z8#)5Js~x;Z=L(kdbCL2LKY#Od6Wxa1j-3Uf3UaIO>UUpeW<=w%U|jc=#xF~%5mzl$ zF|HCo7x5cHv1 zCstX2VuN9s1^xZg>*xWfeu?}?Z6Imp@!H)xku^ZsDtg1EH?0v1>H3HEn6L1oW`N#7 zg)Rzt@AJ-ABX@3E!wPM{GUBk7p&%`_ma|=gtZC{1Mo?K?*8=U%PrsMK~d# zwoE?R z?Iob;SE_Uymqh+0#P0`f9(&jK_H`#IsqsVIaW()gP;H+Rpx=rDxD@2P$3iJ_2%@8A z9{i5%Sp3kyCqewUYwAcAXt2T*09kBgcICo@DfGP;QX~AAAyH2`i4v#Ao)i54$6OR# zz5P5HXhPOS&RAaTZIfBSKcNt8tHeHG2qJ}*x%%u(^oOrcs}x zDxxl|+_6hZmQER)Z@}K*}v0FCgoejum#1n)+48+`N_L z$;7~^2Wgu)UIM-cm*`tc%q$--?xelr*gK@9w3WxpCJjnZ^Spbu`T2j3caqA8ag1UN z$p9>?a@?fu6c(?wa}joU(`X}h#=wl;ySeloN#}PJkXfv<%++3@%_&{GYtGu4M#De6 zVYRNI&GJl$Mhw?D{Aqc$yzckd*eUsyHibX(1%`B&>(wG@(ceM-*CDB6gRjZVJNK{I z%>UU*(!Y(u7HrR9rU|&9#F&#`8FA#Hrl0+gk~z&?2jdT7cSa0%;-8p8=eqa5jV<)t zL%^&&KwLcLpTU~wF8L&+(^loz1K9`)rF0w4t?#i6J{x-xxTDSZ#PAJV%Tn;mg%{)I zNgmXJeG4#Ml~1AZm9NLlN><~~mf&CGM8Ab?q2kWY71j*hr=^{hC84RY|N z!CK-w$BTbVi2>S`m6G51l8=vhz9wV5V1i8b`cHx`r zHk*F!AP$S&|d8Doq_6O6lkAb$-gdHkmGAA-?b_mM z_$!xi2oo~1feBV(f3#URs-O}hXm!GqChGjSf?tT~OaFWo;>9WH8cv=uL%)PeNfyJ# z@8_0{YU~R348Or;>`ghUg^Oc9 zp3Xw4UUxXP=lwrO?Y6E)JSx)N*a}qZmS%7P16p2vW0`q7EZ5BPvl=ka*D8j@p1n4E z)OeI3r&}ij8ukPV7poq-@(3WsD-Unx)h!g)RMd|2n6BVdi?(ur?tS6_1HQ6F%k>5K ze+MO-Ab$;&pDQJUyeW3M=$(AO2-xTE{usM8~ z#6YCX!`S-Zd})Ch{z)qnWsvBHs4wYp64eU}h43!Rvp~o7kC^>nL8WOYr4s|G5W9Bg zqp{pY^>Yc~&~(|>P7hWNANpDVzy`YR{P**OfTnb&7GSz2Qx}5TpX=ANC3to5qC%)c zq&sHOMmR|wTGb>-1OXXa524l|E`dCccIgAM+WHP>{8y7+d;PHc^CC3Y50u?No`d?q zr|bWJNp1dF!)*Xtk+gZ>7D>P-fy=wmCf5}@9osh*sgAOIZdh6C7wb}d2iiv44HAvj zdJLU&siQ|m=RqH92;RCR+*Fbl;oZ*BRhvx!Asu$#RZ`=+tByQCD1HBd-;Em-maCyz zI=WRmtWr2wVOQZRx!}d$0zAnLP^&9{F@5=Z)pR@Umxh&5{!1?SqS?%coqLJrGF3H( z{id4_k#1=MC0()>M&0tQ0n{43!A?ilB}5j>IXFOOleCXF%G~_MrpTUblw*5ES%C66 z^^Rgc@`I(ge>ZAa^1`PF#Y6^ABE6Ni2mB*`(_~^FqkG~|1%)`S(8#?cGk2QdHDPtlDA}iP$@~???5!zCXTy$RDmNkLNkh zbI!TXeVCGg?-YL3Aj+W#(94JSLUJrTb8_u-_w=`h5H7HB;mQHGVmFjc zvA0Sp?Q>o4-JP%Wi>R%dr5)mIerbxEuAuuM@yVZFMY+EWCr+e06OO-Lq%Ojm#IWr} zD8q3_yPNWfG%TF2CS2|1p}}m3!LqlD`th|EIcHzwp8LVPp*i-dg3noc3GE5iWq!(d zRtzep6Geh5)IVF3`?khWqmd}3t{ylZ1~OTl?BHT8L*P-y$LIZy`_%B|>4|-&T0I=n zDIjjT2Tj+0ma4jl14w}Fn5BMui1P(Hp%}fWDjo*AD$@EG9mG9-+5gbrO}ZVV6iOJ9 zXeB&%jGl{6zR*c#-fM`jQgLQa3;-OM*7`v9;IdtD3 zrO%%Ft?ByoEWw-JoqwgjBq=w9i2iNYTYI5y_L`N-qgXy?A)xi~XwBr(Q`eobo#M8Q zp}35DwWFKUEhmV%rObsBU@?hJj>@2(uHNm*uD*+rz}r5}7Dvex{XS*{ExZ2GaA&ah_Q`{jxLE<$oseDyC3!zlrXl7bym)tXNpGdx{tzTP==yiI; zkcY<|11UM(Xv!mu`X?t?^naO|%%EZi0`$UxMnd4P1gm5nh2bRGu=LtYr*0(!h5$IzJj?yEd#Bk%=hB^NN6#I<<+LpeH1iyQ;8XkX*e0(}>?Y5Z z43od$XgBU|-ux6LGeT}Dsumd?YBOK`?a=7og>>@$NBj&1jm}X$tMyiTnoeRUdYeCUGZq`VKdxWRTRyRz`l4bZZ<5-0WB$ut|Efu= z$}?$H643}&!x6Yfu$O6d8HoW~4K_oqmI0-22PNJ)+}0=rm*UVLj~_n-9T**tfN^$TiUVU{-2YX|{9bj=GqZn3i(lnueMcz~6c9EX2bR!A6}!Ra5y$ zpE1f_{%odm1z%Q}z~1eR%&&RNX&cC&pB`8n=A1uED(s%It0^1XN}xNBD!yUIykuJ_ zpk;L@ba(4fP&mC2x=cXvBScIA}W^e;3i7pB&wq3Fd*(LT*HRXSKLib|G zP;JAQQOOn$U4Mw-{q=_cV0EgCNV$mLvS??1DyF{WJwM_g@O3#e#Mn#ZN}wch#K#vF z!dFFZ)B82t0P59&Of5*@>V6{paXvi1bnX=Q5i2Aa+1vGEQ}E(h)>qro>^=wD{o5S` zNpuTLPL_O;NtLiZM);%@4krRzzPS-N_Wb$!7>7L*$^{));F?fcxJkeG-1gCiqx9qB zJ$pxas&xInJ=`9qMA<@eWCL4R$I(E4xGoK9&^n4_giKCvr6}^Z`A4qWuJ0&K4&N0` zAhADPO4UQ`&2xqc&FLqy%S4bq@X=m{4M}Y6g}=z?9eU#4BV@0=e(>ON^+p!>GWP^vWQQ6p(vjfIf{*xx1oSz% zVKM($@srL~UIjW%0 zw8UrHPoC5yywqhK_$0_SJjS1~-K5akYUCe-B#VPK|I9>kp1bG#oO(x`?`o{icDfJr z#OnS{|3g2yW8(VN&Fmk4D(}P_2!S4=#+=NQ;vIyN#OqfjdX^*L9-W1LKIVGI*e%Bk zg>-wjxT~ootf4A7!A07gU7@<_lwiT9;3nm<>d0@uktr^&5oGqToDc|o#W*Dkg50Cy zMarflkgt)AYR%A!xn;$$lJT#YWu(u{2ev3_l^AfxNvEUlY^VJI?<|yAPELHNg?8a* zhpsZv!AdPh?uuyv!?bd!hMD|vQx(2GlF6L5RZ2Tf^SUI?s}$iYb(QTSOIvTQb8WG7 zw6?MN;dL9n?L}%1& zGPG8!?G{DTstk*xg_lx|Iti_79dZ|(%OV|HLfHI5uUSCOBxB!3o9fzVF62SYBHt=T z>dB547RG4V31BY5SOm7~_L*Xq{nWzvwp@I7#w`Nm=FegVmk$nn4aa*VtO&TpNJfLy zp`0;+3nBkl9iL2W2k?*NEhi8s$g@iBe#U=ZKAuv~_*s z8_0o4{8;n97-S$GX30)S+nu@MrWU3c|}nvmO=Y2CqZ!{^8DE zX!?^wCAG!6oDVE_z7wqm%54}bA!&umjZ8$DXM2YU+C=Hi)5iqg7AvMRll33*Q{(=a zH=j;eqQ%7t6$zTz4wrqa{nvQvW}TzZ@KCUXfxuH(Ix~E?)!iDsXctnynR}$ZtAj(Y z+mWS?%)JDH`zhdM2U_;uG-mE#$)4*-rHwHgTKGlPIen|pKQs_`-qSkVHW-6x6Jp{X zm@fAyF*eJZzdgV%zT|`$*`4aA6;{uI$GIT}uV_##Qc2Cr(RdWIcZjdjpVeNQJ7e&5K9$l-`&%b%_%OoCN6Reh#%%9eZ;AKuNCfy z8xNbsHkW#)&T6;k=kb^74*-Xkt19NR6Sb!m0SlS9t{VFWpvuW5-iOdrmDmY`tpn8H&VR`X4?c79V z)P&pzVe7DTMgB?Q{-t%;y(#_dA;++)(f53evQXUahz;c1f~W?_?WlABWKx@oT9OF% zctdfJ>oZ-u?7eh_e1UHmK0a#q!g^0Ft&;YMWwsV|+=r)24oNy|2CWK@w(f*QmaZiO0saWRpNP6L!cdGGAF5dW>VaI@K3`i+VG07Y;# zL2kysv`3k!=pKPdH9%pF$!FY;t{VUn2wSdozpooCz+2XvN}Gy~c-+=mNn zAzUC!_>Gh-9DGe9tF!LnR}V)Kx+n5dV7OtOr8jMgfNt+}B~yJ>7Wk{}h1Bfjq2H9` zm}=^co;FL3<(HU-_=M4++*pGOV1NFC%jWkjZjm_d=YcsI!gGDB)7_pOlE$2WZTK#?PRbr;io z(HAqXm5f`_M7(SVLfe4qSVTp?1$-uW!_8-bh5mTC-#?$0V=V#|p?lvL*E9YbQn}Sz zNb|fm>6zSx{y5cFje$ht){Rbx;hi4}``LcLFj*@}(!5wbg7Y@j0Qy=qP?4L|@Lm7S*iOVV%iSMvt7#1;x*hD`m zuF&-K@lC?M&3qvgR_@U;cjrqaza`mQWR6_bKdSHJAzeBKWI(&o>%HQ804LS=Wxsap z1xC-;-0lXtA1W^#XB!jujBh+S-aV1|a~2xZHekz$mVEE!YZ+_Fd_}dNn9qOH;4SXa z|7FE#?_YkQ6wi;bmGb?}Cxn7tr-J!NPrR~4Z&$$DoM|ug$>F2Vx|FyWzINS?$Z#;x zu6kz6snULLI9OOp2)+3vRr6`qcY}a>MJP_YexKd_h`diiX+eA@>3j#guamXuxvfOl4b zWip3uwY`I5?{Z+&2t^b70QZPE1JX_`_`v6>5kq!#4}5*wVYpsWg^8h1ov@@(5R@a# zjvb{M=J3pu-XEy9se)~=?;dxxHCUdebH%Z zRX~@Swzq4hqZ0Ncnq$&Sg4-`g>N@w+cqwoW_>tH1c>XIgzP(0AOO~ik&>og~N8vc| zR~h`77Jr>XQRp#ZNnHp_e@ew{IQ6kQRfDOwV`WAbv?-)!s&s7>VS4L0!)Z#kQ3|Tb z=Qv~t#L728J%^n9*{VO`YgG$_-S4LS+O0QC*6aK@Lh;%a9Upy&FuZ+6%BSqy{ScN~ zvi#n`XXfo|vv{7P=2W{GT#H$k+-l3(SVqXbD>9vAj5AnH>ACZq@1^4nS(!eiV_ICM z8%@gCi07+vo!Orz7~c3V)|Uogpi(Td4=_3xu&~~!qU%9^`wT|q`u1#tO>7+y>qb{8c^Gc z8-@>7`jFNxj?>T0)!)=MA5@Eo-1Iphx;-E*O(WYA2Lh1c6?{unm72rmT|PWntaX)F z)A zU5AqjJuThLksWFCpJMne6;lm_CM$_LhVK!DLTx@oK)mg0Bf{0!KJs(w7e|}GGv2vU zFXv2bHW|I`Z?x+!7GK-j5hYV9_NG~gXJfI_oQ&Dx6#9BNsJg!xt#v{#bod*e`itAl z(iiBu{;N55@e4hj8A$(QW5$qUy5^OgD(Ir-ZW32S|C*oteE+`zQ8MDtmdyx1JfG>L z62f7~ysIfV(IX;Xxz&2}3Bv~<8v2E%+@hW#_LiqJakXriNEFmx4gnB?pQtvM+}GPuoOTPP*}|8UE9r=IVTMYJH#(L zTn3m>R{)G*jjMtx$TOB|A?yZ&OC-HjvOTJv&Duulk$LKg9>r1JkHgg6az-TY5jm5& zYuujD3nc4YOm`8z{X+2W)^)cJx)&iJ$}p>=_DkV?734oz$x(l6+jC!HeIL=eL_aDH%uQ&>2MaSO7TA*5P!&H=54Y z0OhsgXRn&;XnrBJou%ZF!uqu380r=|mvxNKP40&&KTo@u`vZEGqq!E}0@TUd@P_8J z=abI&Y=MFj6G9H|m0aQTOnPqU7*nWESLH`bg!N1Dz*`fq9zgdxlKF_5#sZ{Nz0TiR zE@{#iTkIEbvA+EZ#?h9s2;-omT$hVl6u((`G1Q1* zeZjJVh5zdxqhu8FP8pL-6V}t>>D98)!j&2!-+(7<(7VrxqV9s)sJf78 zO9I3mugt-X$l?j%^N4T>F3=fjZjfFDOS|Nq%9~xGYTw6FmguBits7D* z`ar+qOzl)p@_RFrVI?|-;*mY-G9Kb$#Xu>03hH|~eTCw;)?~?K8_eLu{_gGwH}$Hg z2WPQ>rTto;(ay(}hnrT@j=$xM;~5yufpL{(E)V>cI70?U41=$+;LqYSO(&Swl};*5 zMeqL1W^i9X&M;~s@K4-dx$`Ho3~}Pj%T`Rq;(ObjJu|e7ep;z=mrt0>R&1D(ISoOt zu^sKP-8pC!2Bee|+}t3L%mVl#QuqGEaIshTxdT?wgez`BByBXE=lk(-!_1BN(Swe8 zH|cdxmuny1Zq&sksyr??8VW`g3wkaSHqGRo->{Cfgl>nY?oVDg ze0gH1=T6%M(1Nn_C~Bg`3m-vM(pTdXfX&qe-^w3|XEx87GFsA=P z`zfMcy1|4N&Q%t1V}r9ieC(BpYE~&K^JZsyt$>$ALd8!;H9*S5*4ZkNPiS-~Yr_42 zwEjd<4a)#in@Aaz@7$o?5Yhi+8=j{;MEG(mAQ>NqT2vF$0cHDB>sskfe@(e$@BAMa zO{W4`wv+VT3EMBFJYH=I_30ZA=T%gbIfrFa|6yCKzqBkesf+e@G7-5IoRR)PQxGmB zAN8^~=FMPxbk3@=@AdAl4qm)3Ld|VdlQYkVfi^%E4PWV~JX^aZMs*D30Bs-tMmBnX z&&$b1HK2ahe{0So!b9%0x4VfJMZNf^VrX_jt&_7C_qQ-JZ;Pf9ac(&nE|_=yvXxWz)906Uglqu>omK zl~T>6t=({?8=<=yx&5`8DL-R-Pm5Hk0#2>K-VAa)O}Id8 zy>MN%)wT57Np6JTSl?uFqn`~zbL?ol7&hZajVLIuOM$pPP6n_*ZWCo+8!pvv&J4aY z2;V8aBf>gRSCHfQnXxoF+o1?;0N#E}wB!=uq#jUn8f-)cUrvjCN|W!DqD+AEkzlT( z_0419SPQnfnJ3j8%v)6h{i(>jp3zY7NSk>yhjk|_f{p~{BIWkL`C_oQ(98ig02XHp zlu6{pErPQUqPmdj4r=f(F#`kN?w@I*ZeYtjjS4B=;f`fy$<4myq~#F%qlUs(cZ~nD zT)D=jEvXTzVG#E@VAJ1BuKbQ^qh9+Hqn`Fqc3_{f;qi^Ha(D@{*7WMt^;y|~3t>QW z^=Z3TP2#BLq*MG^TuQuhbK+kn=%?mxTcnuEge$ZcoHgAi;6p52bz5HT-iEjB%opWN z{Ult{P|*_BeAHft?*W8*o4?9Pgb|D_c`c)QdfRP^>e%U|Dp82wQql{73BKRY}Wis1j z?1N5VdNKRK8+dm4d17Ozv|c%0wl-TTXh6+j&zPi{OqD=sIQBK)_hOCST<)09B%7G4 zBkzrr+h`=vMcb$2elzXT=mr5Q-dM;SpAuCH**;#!8Ozgkgn<(~U3)BaDtQt7mY%W? zIyS~~dU7JkuSE2e|A`&X6RH!J_q?x~4T4R>wcHtH)4J+EGn4k!sP4s+U!B%Hw#_c-xh4crxACrm~P~l2R;U`r7@rA-niLDu>pUzz4@imn2wBdL#asQ&u`mo&9Of zXqEn(mo~(~`!`&_P0iUZ`h<$zAS@~p#8_QBn?~aKjkQZbx@Ut7797*H-n&qxc2t6E**Lt5c3G zIQ^=xR(5CKf8_&|wT|m^@{|dCcDBOpy@;F$e@mu5DVpRKNFo0Wgy^K!(l8?2+kpz{ zM`3SB#tu-5ObJXVH>w>q)~4zhKIKYXU9vDlZ!cL$uR@P(+%EG@sp3{Qp+T0!`)UcQ2HVv&|*CIhWY) zFIm`oEtKz9)6W5$utPb%FVjSIenals=R0U*y9(!DKXPgniMBs&;wFm(+x4?b7tb;< z7I24(iE*#bF6C9eaI#CW$;3z7Y_8(s%3+5e#>4h~;##cuJQpg(^7YyoWA^eqzwPbX z`zEBmZGHj+7(!$A-UpdH!u8#r`xyKjpK`TO8lTgy#(`nQ?w{(&UotP;!5o;2QpyIN zCE!91XRJkrUtS*t`E#@6;P1n6U)G(1E$uCDcXPw5ki0~Fz}y0gPLUA$ z5OQDfQr)tDGT9Kd#Un+!Q+d>!7-&CgC!xQ(HyxZMvJz)(eY}8o8r7feCFWo!pIg4~ z_Ql@WXUKzer#aGtIfLB;-2eKBi7K4kkt#I-}j2^RD2PeDZF?5OT%u^=v8 zURLjtO3fS88GSD&<$Q!xK_={2vx#Euyf6373;fKJX|4tbTvnU@Ig=vy+HQdA7xLQ` zT=#HV^~)S5Ihxz-?Fz9~F5zaBW8?sQ$d@OFw zD}30SH6~k9FS3!k$}@ai#3I)tQ_$Mrs-n07lm11X%W*=R?V!Z5;Tz_d!Ij^dsP4#~ zNcQ$7H6xB@5D;j$b}Ne%cNG;}ZzVVih27Ap|(_0l)@h^ z0N014U+@2Hfx7>~wUhI~xWHL`Ur=|eOG0ljC0|{2G*86Zm){S`=oL+o1$vWj9uX}w zS|sOi6}lPqA3Ap|fM@}f>09Mzj@O2jZAMFf+V}Yp?0>oP6*W|y0t>2LDX|EHjFsB& zPE+l^4;ef*um9CdZp{QoQBKywd)QkSuKt=(o?+xNyC*OCuYRTVIUk$ONfpsw9Vi-K zbEs;UE4!zZ`+tn=re2|EE7#L>K>K?=OO8r?bRLnG6GeD)Ti~PjM z0=f7*?ZSYf_afPQMEq#6v{%t+uTr&&-zHHeQ3ZsmyUhQm8p(8;!{54>*vx@w?-Itv zfz7(A_A>O%yI!PHHm+Advc6^}7dKD-@R?5GMQ#OSrhyyHn2j*3ar!eVh zWW)8b{J*!NpX@BZ554eNm;1fhXsf9rTZ_d(rl5sa^C3z*Q%(;b}Bwtz>(8b{3j%(mltA-l9y7g^Z8leAe!7!%XPn*R|tqV%)l-( z7RW2T8VRl6kA|1`gfP`~=T|4EBYlZ<^B&e?t!cp;w^3b)sWETInMQ}>cGh_Gj43%DTa7he}GjuCV!sM;E+qqPJ=TGqms?*v|uRElK%MFA*mn!T8 zq~`S1R`3j7Ik$XPU`M{F``ky{o%>#5A&c)rB7v??iE>Kg>dni*Doz9H=Zy&dIC$aOxd#aR?%BhKuaPZR0$uof1aoK;VcZh0N(s!%LH8t#LfyepU zf{^=H_Kzx$*ByRYz_H{o_xKly5-O4`{wGpaLK{Aq*Jt6O6W2c&rG_)$N4c5>u z+V)!P26=)%E)Q+&1Rw3+f|ohd!opKkrkqrpbcw>4uE>~MT}gqNQsBqQElE)8t%)Sx zHH#zMSzo;q!#PD|tRyK&(1rk{{^gO}qIFj$aQZ#VL@7Fj=X0?RS|c0`F^uu0YQxab zjIN>j0gsaPQLf&!=N15`5FME8XI@wS&=AXGjcTV+iA~rQ=n>BvuLtgj2S(}`9 zTex14|HOLoIbtd~(np21l$-yklgRy&!N?IS zS}N2rWMqb<+V2O;&o_B038r*_U_iw<3L6RY-Nq~tOAtOu$CRN`)o<*-gmeQnEPi?| zTkhQbpvA#_I>saLl+=$)kWW8H)F0lWY61~I>>d2X$5X1

9*#0x0X9(ov9q3k#;j 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 G<^KTs7&h$y diff --git a/sdf3.go b/sdf3.go index 85410fd..cce01c3 100644 --- a/sdf3.go +++ b/sdf3.go @@ -2,6 +2,7 @@ package sdf import ( "math" + "strconv" "github.com/soypat/sdf/internal/d2" "github.com/soypat/sdf/internal/d3" @@ -350,6 +351,9 @@ type transform3 struct { // Transform3D applies a transformation matrix to an SDF3. func Transform3D(sdf SDF3, matrix m44) SDF3 { + if sdf == nil { + panic("nil SDF3 argument") + } s := transform3{} s.sdf = sdf s.matrix = matrix @@ -418,9 +422,9 @@ func Union3D(sdf ...SDF3) SDF3Union { s := union3{ sdf: sdf, } - for _, x := range s.sdf { + for i, x := range s.sdf { if x == nil { - panic("nil sdf argument found") + panic("nil sdf argument (" + strconv.Itoa(i) + ") to Union3D") } } // work out the bounding box